@adeu/core 1.14.0 → 1.15.1

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/src/mapper.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { DocumentObject } from './docx/bridge.js';
2
- import { Paragraph, Table, Run, DocxEvent } from './docx/primitives.js';
3
- import { findAllDescendants, findChild } from './docx/dom.js';
4
- import { extract_comments_data } from './comments.js';
1
+ import { DocumentObject } from "./docx/bridge.js";
2
+ import { Paragraph, Table, Run, DocxEvent } from "./docx/primitives.js";
3
+ import { findAllDescendants, findChild } from "./docx/dom.js";
4
+ import { extract_comments_data } from "./comments.js";
5
5
  import {
6
6
  _get_style_cache,
7
7
  get_paragraph_prefix,
@@ -12,7 +12,7 @@ import {
12
12
  iter_block_items,
13
13
  iter_document_parts,
14
14
  iter_paragraph_content,
15
- } from './utils/docx.js';
15
+ } from "./utils/docx.js";
16
16
 
17
17
  export interface TextSpan {
18
18
  start: number;
@@ -23,68 +23,81 @@ export interface TextSpan {
23
23
  ins_id?: string | null;
24
24
  del_id?: string | null;
25
25
  hyperlink_id?: string | null;
26
+ comment_ids?: string[];
26
27
  }
27
28
 
28
- export function renumber_snapshot_ids(doc: DocumentObject): [Record<string, string>, Record<string, string>] {
29
+ export function renumber_snapshot_ids(
30
+ doc: DocumentObject,
31
+ ): [Record<string, string>, Record<string, string>] {
29
32
  const chg_remap: Record<string, string> = {};
30
33
  let next_chg = 1;
31
34
  const body_root = doc.element;
32
35
 
33
36
  const chg_elements: Element[] = [];
34
- const all_elements = findAllDescendants(body_root, '*');
37
+ const all_elements = findAllDescendants(body_root, "*");
35
38
  for (const el of all_elements) {
36
- if (el.tagName === 'w:ins' || el.tagName === 'w:del') {
39
+ if (el.tagName === "w:ins" || el.tagName === "w:del") {
37
40
  chg_elements.push(el);
38
41
  }
39
42
  }
40
43
 
41
44
  for (const elem of chg_elements) {
42
- const old_id = elem.getAttribute('w:id');
45
+ const old_id = elem.getAttribute("w:id");
43
46
  if (!old_id) continue;
44
47
  if (chg_remap[old_id]) {
45
- elem.setAttribute('w:id', chg_remap[old_id]);
48
+ elem.setAttribute("w:id", chg_remap[old_id]);
46
49
  continue;
47
50
  }
48
51
  const new_id = next_chg.toString();
49
52
  chg_remap[old_id] = new_id;
50
- elem.setAttribute('w:id', new_id);
53
+ elem.setAttribute("w:id", new_id);
51
54
  next_chg++;
52
55
  }
53
56
 
54
57
  const com_remap: Record<string, string> = {};
55
58
  let next_com = 1;
56
- const comments_part = doc.pkg.parts.find(p => p.contentType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml');
59
+ const comments_part = doc.pkg.parts.find(
60
+ (p) =>
61
+ p.contentType ===
62
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml",
63
+ );
57
64
 
58
65
  if (comments_part) {
59
66
  const comments_root = comments_part._element;
60
- for (const c of findAllDescendants(comments_root, 'w:comment')) {
61
- const old_id = c.getAttribute('w:id');
67
+ for (const c of findAllDescendants(comments_root, "w:comment")) {
68
+ const old_id = c.getAttribute("w:id");
62
69
  if (!old_id) continue;
63
70
  if (com_remap[old_id]) {
64
- c.setAttribute('w:id', com_remap[old_id]);
71
+ c.setAttribute("w:id", com_remap[old_id]);
65
72
  continue;
66
73
  }
67
74
  const new_id = next_com.toString();
68
75
  com_remap[old_id] = new_id;
69
- c.setAttribute('w:id', new_id);
76
+ c.setAttribute("w:id", new_id);
70
77
  next_com++;
71
78
  }
72
79
  }
73
80
 
74
81
  for (const elem of all_elements) {
75
- if (['w:commentReference', 'w:commentRangeStart', 'w:commentRangeEnd'].includes(elem.tagName)) {
76
- const old_id = elem.getAttribute('w:id');
82
+ if (
83
+ [
84
+ "w:commentReference",
85
+ "w:commentRangeStart",
86
+ "w:commentRangeEnd",
87
+ ].includes(elem.tagName)
88
+ ) {
89
+ const old_id = elem.getAttribute("w:id");
77
90
  if (old_id && com_remap[old_id]) {
78
- elem.setAttribute('w:id', com_remap[old_id]);
91
+ elem.setAttribute("w:id", com_remap[old_id]);
79
92
  }
80
93
  }
81
94
  }
82
95
 
83
96
  if (comments_part) {
84
- for (const c of findAllDescendants(comments_part._element, 'w:comment')) {
85
- const parent_id = c.getAttribute('w15:p');
97
+ for (const c of findAllDescendants(comments_part._element, "w:comment")) {
98
+ const parent_id = c.getAttribute("w15:p");
86
99
  if (parent_id && com_remap[parent_id]) {
87
- c.setAttribute('w15:p', com_remap[parent_id]);
100
+ c.setAttribute("w15:p", com_remap[parent_id]);
88
101
  }
89
102
  }
90
103
  }
@@ -97,12 +110,16 @@ export class DocumentMapper {
97
110
  public clean_view: boolean;
98
111
  public original_view: boolean;
99
112
  public comments_map: Record<string, any>;
100
- public full_text: string = '';
113
+ public full_text: string = "";
101
114
  public spans: TextSpan[] = [];
102
115
  public appendix_start_index: number = -1;
103
116
  private _text_chunks: string[] = [];
104
117
 
105
- constructor(doc: DocumentObject, clean_view: boolean = false, original_view: boolean = false) {
118
+ constructor(
119
+ doc: DocumentObject,
120
+ clean_view: boolean = false,
121
+ original_view: boolean = false,
122
+ ) {
106
123
  this.doc = doc;
107
124
  this.clean_view = clean_view;
108
125
  this.original_view = original_view;
@@ -114,23 +131,29 @@ export class DocumentMapper {
114
131
  let current_offset = 0;
115
132
  this.spans = [];
116
133
  this._text_chunks = [];
117
- this.full_text = '';
134
+ this.full_text = "";
118
135
 
119
136
  for (const part of iter_document_parts(this.doc)) {
120
137
  current_offset = this._map_blocks(part, current_offset);
121
138
 
122
- if (this.spans.length > 0 && this.spans[this.spans.length - 1].text !== '\n\n') {
123
- this._add_virtual_text('\n\n', current_offset, null);
139
+ if (
140
+ this.spans.length > 0 &&
141
+ this.spans[this.spans.length - 1].text !== "\n\n"
142
+ ) {
143
+ this._add_virtual_text("\n\n", current_offset, null);
124
144
  current_offset += 2;
125
145
  }
126
146
  }
127
147
 
128
- while (this.spans.length > 0 && this.spans[this.spans.length - 1].text === '\n\n') {
148
+ while (
149
+ this.spans.length > 0 &&
150
+ this.spans[this.spans.length - 1].text === "\n\n"
151
+ ) {
129
152
  this.spans.pop();
130
153
  this._text_chunks.pop();
131
154
  }
132
155
 
133
- this.full_text = this._text_chunks.join('');
156
+ this.full_text = this._text_chunks.join("");
134
157
  this.appendix_start_index = -1;
135
158
  }
136
159
 
@@ -140,12 +163,13 @@ export class DocumentMapper {
140
163
  const part = container.part || container;
141
164
  const [style_cache, default_pstyle] = _get_style_cache(part);
142
165
 
143
- if (c_type === 'NotesPart') {
144
- const header = container.note_type === 'fn' ? '## Footnotes' : '## Endnotes';
166
+ if (c_type === "NotesPart") {
167
+ const header =
168
+ container.note_type === "fn" ? "## Footnotes" : "## Endnotes";
145
169
  const sep = `---\n${header}`;
146
170
  this._add_virtual_text(sep, current, null);
147
171
  current += sep.length;
148
- this._add_virtual_text('\n\n', current, null);
172
+ this._add_virtual_text("\n\n", current, null);
149
173
  current += 2;
150
174
  }
151
175
 
@@ -155,17 +179,18 @@ export class DocumentMapper {
155
179
  for (const item of iter_block_items(container)) {
156
180
  const i_type = item.constructor.name;
157
181
 
158
- if (i_type === 'FootnoteItem') {
182
+ if (i_type === "FootnoteItem") {
159
183
  current = this._map_blocks(item, current);
160
184
  } else if (item instanceof Paragraph) {
161
185
  if (!is_first_para) {
162
- const prev_para = previous_item instanceof Paragraph ? previous_item : null;
163
- this._add_virtual_text('\n\n', current, prev_para);
186
+ const prev_para =
187
+ previous_item instanceof Paragraph ? previous_item : null;
188
+ this._add_virtual_text("\n\n", current, prev_para);
164
189
  current += 2;
165
190
  }
166
191
 
167
192
  let prefix = get_paragraph_prefix(item, style_cache, default_pstyle);
168
- if (is_first_para && c_type === 'FootnoteItem') {
193
+ if (is_first_para && c_type === "FootnoteItem") {
169
194
  prefix = `[^${container.note_type}-${container.id}]: ` + prefix;
170
195
  }
171
196
  if (prefix) {
@@ -173,13 +198,19 @@ export class DocumentMapper {
173
198
  current += prefix.length;
174
199
  }
175
200
 
176
- current = this._map_paragraph_content(item, current, style_cache, default_pstyle);
201
+ current = this._map_paragraph_content(
202
+ item,
203
+ current,
204
+ style_cache,
205
+ default_pstyle,
206
+ );
177
207
  is_first_para = false;
178
208
  previous_item = item;
179
209
  } else if (item instanceof Table) {
180
210
  if (!is_first_para) {
181
- const prev_para = previous_item instanceof Paragraph ? previous_item : null;
182
- this._add_virtual_text('\n\n', current, prev_para);
211
+ const prev_para =
212
+ previous_item instanceof Paragraph ? previous_item : null;
213
+ this._add_virtual_text("\n\n", current, prev_para);
183
214
  current += 2;
184
215
  }
185
216
  current = this._map_table(item, current);
@@ -197,23 +228,23 @@ export class DocumentMapper {
197
228
 
198
229
  for (const row of table.rows) {
199
230
  const tr = row._element;
200
- const trPr = findChild(tr, 'w:trPr');
201
- const ins = trPr ? findChild(trPr, 'w:ins') : null;
202
- const del_node = trPr ? findChild(trPr, 'w:del') : null;
231
+ const trPr = findChild(tr, "w:trPr");
232
+ const ins = trPr ? findChild(trPr, "w:ins") : null;
233
+ const del_node = trPr ? findChild(trPr, "w:del") : null;
203
234
 
204
235
  if (this.clean_view && del_node) continue;
205
236
  if (this.original_view && ins) continue;
206
237
 
207
238
  if (rows_processed > 0) {
208
- this._add_virtual_text('\n', current, null);
239
+ this._add_virtual_text("\n", current, null);
209
240
  current += 1;
210
241
  }
211
242
 
212
243
  if (ins && !this.clean_view && !this.original_view) {
213
- this._add_virtual_text('{++ ', current, null);
244
+ this._add_virtual_text("{++ ", current, null);
214
245
  current += 4;
215
246
  } else if (del_node && !this.clean_view && !this.original_view) {
216
- this._add_virtual_text('{-- ', current, null);
247
+ this._add_virtual_text("{-- ", current, null);
217
248
  current += 4;
218
249
  }
219
250
 
@@ -225,7 +256,7 @@ export class DocumentMapper {
225
256
  seen_cells.add(cell);
226
257
 
227
258
  if (cells_processed > 0) {
228
- this._add_virtual_text(' | ', current, null);
259
+ this._add_virtual_text(" | ", current, null);
229
260
  current += 3;
230
261
  }
231
262
 
@@ -234,11 +265,11 @@ export class DocumentMapper {
234
265
  }
235
266
 
236
267
  if (ins && !this.clean_view && !this.original_view) {
237
- const suffix = ` |Chg:${ins.getAttribute('w:id')}++}`;
268
+ const suffix = ` |Chg:${ins.getAttribute("w:id")}++}`;
238
269
  this._add_virtual_text(suffix, current, null);
239
270
  current += suffix.length;
240
271
  } else if (del_node && !this.clean_view && !this.original_view) {
241
- const suffix = ` |Chg:${del_node.getAttribute('w:id')}--}`;
272
+ const suffix = ` |Chg:${del_node.getAttribute("w:id")}--}`;
242
273
  this._add_virtual_text(suffix, current, null);
243
274
  current += suffix.length;
244
275
  }
@@ -251,11 +282,11 @@ export class DocumentMapper {
251
282
 
252
283
  private _strip_markdown_formatting(text: string): string {
253
284
  let result = text;
254
- result = result.replace(/^#+\s*/gm, '');
255
- result = result.replace(/\*\*(\w[\w\s]*\w|\w{2,})\*\*/g, '$1');
256
- result = result.replace(/__(\w[\w\s]*\w|\w{2,})__/g, '$1');
257
- result = result.replace(/(?<!\w)_(\w[\w\s]*\w|\w{2,})_(?!\w)/g, '$1');
258
- result = result.replace(/(?<!\w)\*(\w[\w\s]*\w|\w{2,})\*(?!\w)/g, '$1');
285
+ result = result.replace(/^#+\s*/gm, "");
286
+ result = result.replace(/\*\*(\w[\w\s]*\w|\w{2,})\*\*/g, "$1");
287
+ result = result.replace(/__(\w[\w\s]*\w|\w{2,})__/g, "$1");
288
+ result = result.replace(/(?<!\w)_(\w[\w\s]*\w|\w{2,})_(?!\w)/g, "$1");
289
+ result = result.replace(/(?<!\w)\*(\w[\w\s]*\w|\w{2,})\*(?!\w)/g, "$1");
259
290
  return result;
260
291
  }
261
292
 
@@ -263,11 +294,17 @@ export class DocumentMapper {
263
294
  paragraph: Paragraph,
264
295
  start_offset: number,
265
296
  style_cache?: any,
266
- default_pstyle?: string | null
297
+ default_pstyle?: string | null,
267
298
  ): number {
268
299
  let current = start_offset;
269
300
 
270
- const span: TextSpan = { start: current, end: current, text: '', run: null, paragraph };
301
+ const span: TextSpan = {
302
+ start: current,
303
+ end: current,
304
+ text: "",
305
+ run: null,
306
+ paragraph,
307
+ };
271
308
  this.spans.push(span);
272
309
 
273
310
  const active_ids = new Set<string>();
@@ -276,10 +313,17 @@ export class DocumentMapper {
276
313
  const active_fmt: Record<string, DocxEvent> = {};
277
314
 
278
315
  let deferred_meta_states: any[] = [];
279
- let current_wrappers: [string, string] = ['', ''];
280
- let current_style: [string, string] = ['', ''];
316
+ let current_wrappers: [string, string] = ["", ""];
317
+ let current_style: [string, string] = ["", ""];
281
318
  let active_hyperlink_id: string | null = null;
282
- let pending_runs: [string, string, Run | null, string | null, string | null][] = [];
319
+ let pending_runs: [
320
+ string,
321
+ string,
322
+ Run | null,
323
+ string | null,
324
+ string | null,
325
+ string[],
326
+ ][] = [];
283
327
 
284
328
  const flush_pending_runs = () => {
285
329
  if (pending_runs.length === 0) return;
@@ -288,14 +332,20 @@ export class DocumentMapper {
288
332
  this._add_virtual_text(s_tok, current, paragraph);
289
333
  current += s_tok.length;
290
334
  }
291
- for (const [kind, txt, r_obj, i_id, d_id] of pending_runs) {
292
- if (kind === 'virtual') {
335
+ for (const [kind, txt, r_obj, i_id, d_id, c_ids] of pending_runs) {
336
+ if (kind === "virtual") {
293
337
  this._add_virtual_text(txt, current, paragraph, active_hyperlink_id);
294
338
  } else {
295
339
  const s: TextSpan = {
296
- start: current, end: current + txt.length, text: txt,
297
- run: r_obj, paragraph, ins_id: i_id || undefined, del_id: d_id || undefined,
298
- hyperlink_id: active_hyperlink_id || undefined
340
+ start: current,
341
+ end: current + txt.length,
342
+ text: txt,
343
+ run: r_obj,
344
+ paragraph,
345
+ ins_id: i_id || undefined,
346
+ del_id: d_id || undefined,
347
+ hyperlink_id: active_hyperlink_id || undefined,
348
+ comment_ids: c_ids.length > 0 ? c_ids : undefined,
299
349
  };
300
350
  this.spans.push(s);
301
351
  this._text_chunks.push(txt);
@@ -310,8 +360,16 @@ export class DocumentMapper {
310
360
  };
311
361
 
312
362
  const items = Array.from(iter_paragraph_content(paragraph));
313
- const is_heading = is_heading_paragraph(paragraph, style_cache, default_pstyle);
314
- const native_heading = is_native_heading(paragraph, style_cache, default_pstyle);
363
+ const is_heading = is_heading_paragraph(
364
+ paragraph,
365
+ style_cache,
366
+ default_pstyle,
367
+ );
368
+ const native_heading = is_native_heading(
369
+ paragraph,
370
+ style_cache,
371
+ default_pstyle,
372
+ );
315
373
  let leading_strip_active = is_heading;
316
374
 
317
375
  for (let i = 0; i < items.length; i++) {
@@ -323,24 +381,24 @@ export class DocumentMapper {
323
381
  const text = get_run_text(item);
324
382
 
325
383
  if (leading_strip_active) {
326
- if (text === '' || /^\s*$/.test(text)) continue;
384
+ if (text === "" || /^\s*$/.test(text)) continue;
327
385
  leading_strip_active = false;
328
386
  }
329
387
 
330
- if (text.includes('\n') && (prefix || suffix)) {
331
- const parts = text.split('\n');
388
+ if (text.includes("\n") && (prefix || suffix)) {
389
+ const parts = text.split("\n");
332
390
  for (let idx = 0; idx < parts.length; idx++) {
333
- if (idx > 0) run_parts.push(['real', '\n', item]);
391
+ if (idx > 0) run_parts.push(["real", "\n", item]);
334
392
  if (parts[idx]) {
335
- if (prefix) run_parts.push(['virtual', prefix, null]);
336
- run_parts.push(['real', parts[idx], item]);
337
- if (suffix) run_parts.push(['virtual', suffix, null]);
393
+ if (prefix) run_parts.push(["virtual", prefix, null]);
394
+ run_parts.push(["real", parts[idx], item]);
395
+ if (suffix) run_parts.push(["virtual", suffix, null]);
338
396
  }
339
397
  }
340
398
  } else {
341
- if (prefix) run_parts.push(['virtual', prefix, null]);
342
- if (text) run_parts.push(['real', text, item]);
343
- if (suffix) run_parts.push(['virtual', suffix, null]);
399
+ if (prefix) run_parts.push(["virtual", prefix, null]);
400
+ if (text) run_parts.push(["real", text, item]);
401
+ if (suffix) run_parts.push(["virtual", suffix, null]);
344
402
  }
345
403
 
346
404
  if (this.clean_view && Object.keys(active_del).length > 0) {
@@ -350,88 +408,154 @@ export class DocumentMapper {
350
408
  // pass
351
409
  }
352
410
 
353
- const full_seg_text = run_parts.map(x => x[1]).join('');
411
+ const full_seg_text = run_parts.map((x) => x[1]).join("");
354
412
  const curr_ins_id = Object.keys(active_ins).pop() || null;
355
413
  const curr_del_id = Object.keys(active_del).pop() || null;
356
414
 
357
- if (full_seg_text && !(this.clean_view && curr_del_id) && !(this.original_view && curr_ins_id)) {
358
- const new_wrappers = (this.clean_view || this.original_view) ? ['', ''] as [string, string] : this._get_wrappers(curr_ins_id, curr_del_id, active_ids, active_fmt);
415
+ if (
416
+ full_seg_text &&
417
+ !(this.clean_view && curr_del_id) &&
418
+ !(this.original_view && curr_ins_id)
419
+ ) {
420
+ const new_wrappers =
421
+ this.clean_view || this.original_view
422
+ ? (["", ""] as [string, string])
423
+ : this._get_wrappers(
424
+ curr_ins_id,
425
+ curr_del_id,
426
+ active_ids,
427
+ active_fmt,
428
+ );
359
429
  const new_style: [string, string] = [prefix, suffix];
360
430
 
361
- if (pending_runs.length > 0 && new_wrappers[0] === current_wrappers[0] && new_wrappers[1] === current_wrappers[1]) {
431
+ if (
432
+ pending_runs.length > 0 &&
433
+ new_wrappers[0] === current_wrappers[0] &&
434
+ new_wrappers[1] === current_wrappers[1]
435
+ ) {
362
436
  let skip_leading_prefix = false;
363
- if (new_style[0] === current_style[0] && new_style[1] === current_style[1] && current_style[0] !== '' &&
364
- pending_runs[pending_runs.length - 1][0] === 'virtual' &&
365
- pending_runs[pending_runs.length - 1][1] === current_style[1]) {
437
+ if (
438
+ new_style[0] === current_style[0] &&
439
+ new_style[1] === current_style[1] &&
440
+ current_style[0] !== "" &&
441
+ pending_runs[pending_runs.length - 1][0] === "virtual" &&
442
+ pending_runs[pending_runs.length - 1][1] === current_style[1]
443
+ ) {
366
444
  pending_runs.pop();
367
445
  skip_leading_prefix = true;
368
446
  }
369
447
 
448
+ const curr_comment_ids = Array.from(active_ids);
370
449
  for (const [kind, txt, r_obj] of run_parts) {
371
- if (skip_leading_prefix && kind === 'virtual' && txt === new_style[0]) {
450
+ if (
451
+ skip_leading_prefix &&
452
+ kind === "virtual" &&
453
+ txt === new_style[0]
454
+ ) {
372
455
  skip_leading_prefix = false;
373
456
  continue;
374
457
  }
375
- pending_runs.push([kind, txt, r_obj, curr_ins_id, curr_del_id]);
458
+ pending_runs.push([
459
+ kind,
460
+ txt,
461
+ r_obj,
462
+ curr_ins_id,
463
+ curr_del_id,
464
+ curr_comment_ids,
465
+ ]);
376
466
  }
377
467
  current_style = new_style;
378
468
  } else {
379
469
  flush_pending_runs();
380
470
  current_wrappers = new_wrappers;
381
471
  current_style = new_style;
472
+ const curr_comment_ids = Array.from(active_ids);
382
473
  for (const [kind, txt, r_obj] of run_parts) {
383
- pending_runs.push([kind, txt, r_obj, curr_ins_id, curr_del_id]);
474
+ pending_runs.push([
475
+ kind,
476
+ txt,
477
+ r_obj,
478
+ curr_ins_id,
479
+ curr_del_id,
480
+ curr_comment_ids,
481
+ ]);
384
482
  }
385
483
  }
386
484
  }
387
485
 
388
486
  if (!this.clean_view && !this.original_view) {
389
- const has_meta = Object.keys(active_ins).length > 0 || Object.keys(active_del).length > 0 || active_ids.size > 0 || Object.keys(active_fmt).length > 0;
487
+ const has_meta =
488
+ Object.keys(active_ins).length > 0 ||
489
+ Object.keys(active_del).length > 0 ||
490
+ active_ids.size > 0 ||
491
+ Object.keys(active_fmt).length > 0;
390
492
  if (has_meta) {
391
- deferred_meta_states.push([{...active_ins}, {...active_del}, new Set(active_ids), {...active_fmt}]);
493
+ deferred_meta_states.push([
494
+ { ...active_ins },
495
+ { ...active_del },
496
+ new Set(active_ids),
497
+ { ...active_fmt },
498
+ ]);
392
499
  }
393
500
 
394
501
  let should_defer = false;
395
- const is_redline = curr_ins_id !== null || curr_del_id !== null || Object.keys(active_fmt).length > 0;
502
+ const has_any_meta =
503
+ curr_ins_id !== null ||
504
+ curr_del_id !== null ||
505
+ Object.keys(active_fmt).length > 0 ||
506
+ active_ids.size > 0;
396
507
 
397
- if (is_redline) {
508
+ if (has_any_meta) {
398
509
  let j = i + 1;
399
- let next_is_redline = false;
510
+ let next_has_meta = false;
400
511
  let temp_ins_count = Object.keys(active_ins).length;
401
512
  let temp_del_count = Object.keys(active_del).length;
402
513
  let temp_fmt_count = Object.keys(active_fmt).length;
514
+ const temp_comment_ids = new Set(active_ids);
403
515
 
404
516
  while (j < items.length) {
405
517
  const next_item = items[j];
406
518
  if (next_item instanceof Run) {
407
519
  if (!get_run_text(next_item)) {
408
- j++; continue;
520
+ j++;
521
+ continue;
409
522
  }
410
- if (temp_ins_count > 0 || temp_del_count > 0 || temp_fmt_count > 0) {
411
- next_is_redline = true;
523
+ if (
524
+ temp_ins_count > 0 ||
525
+ temp_del_count > 0 ||
526
+ temp_fmt_count > 0 ||
527
+ temp_comment_ids.size > 0
528
+ ) {
529
+ next_has_meta = true;
412
530
  }
413
531
  break;
414
532
  } else {
415
533
  const ev = next_item as DocxEvent;
416
- if (ev.type === 'ins_start') temp_ins_count++;
417
- else if (ev.type === 'ins_end') temp_ins_count = Math.max(0, temp_ins_count - 1);
418
- else if (ev.type === 'del_start') temp_del_count++;
419
- else if (ev.type === 'del_end') temp_del_count = Math.max(0, temp_del_count - 1);
420
- else if (ev.type === 'fmt_start') temp_fmt_count++;
421
- else if (ev.type === 'fmt_end') temp_fmt_count = Math.max(0, temp_fmt_count - 1);
534
+ if (ev.type === "ins_start") temp_ins_count++;
535
+ else if (ev.type === "ins_end")
536
+ temp_ins_count = Math.max(0, temp_ins_count - 1);
537
+ else if (ev.type === "del_start") temp_del_count++;
538
+ else if (ev.type === "del_end")
539
+ temp_del_count = Math.max(0, temp_del_count - 1);
540
+ else if (ev.type === "fmt_start") temp_fmt_count++;
541
+ else if (ev.type === "fmt_end")
542
+ temp_fmt_count = Math.max(0, temp_fmt_count - 1);
543
+ else if (ev.type === "start") temp_comment_ids.add(ev.id);
544
+ else if (ev.type === "end") temp_comment_ids.delete(ev.id);
422
545
  }
423
546
  j++;
424
547
  }
425
548
 
426
- if (next_is_redline) should_defer = true;
549
+ if (next_has_meta) should_defer = true;
427
550
  }
428
551
 
429
552
  if (!should_defer && deferred_meta_states.length > 0) {
430
- const meta_block = this._build_merged_meta_block(deferred_meta_states);
553
+ const meta_block =
554
+ this._build_merged_meta_block(deferred_meta_states);
431
555
  if (meta_block) {
432
556
  flush_pending_runs();
433
- current_wrappers = ['', ''];
434
- current_style = ['', ''];
557
+ current_wrappers = ["", ""];
558
+ current_style = ["", ""];
435
559
  const full_meta = `{>>${meta_block}<<}`;
436
560
  this._add_virtual_text(full_meta, current, paragraph);
437
561
  current += full_meta.length;
@@ -443,57 +567,57 @@ export class DocumentMapper {
443
567
  const ev = item as DocxEvent;
444
568
  leading_strip_active = false;
445
569
  flush_pending_runs();
446
- current_wrappers = ['', ''];
447
- current_style = ['', ''];
448
-
449
- if (ev.type === 'start') active_ids.add(ev.id);
450
- else if (ev.type === 'end') active_ids.delete(ev.id);
451
- else if (ev.type === 'ins_start') active_ins[ev.id] = ev;
452
- else if (ev.type === 'ins_end') delete active_ins[ev.id];
453
- else if (ev.type === 'del_start') active_del[ev.id] = ev;
454
- else if (ev.type === 'del_end') delete active_del[ev.id];
455
- else if (ev.type === 'fmt_start') active_fmt[ev.id] = ev;
456
- else if (ev.type === 'fmt_end') delete active_fmt[ev.id];
457
- else if (ev.type === 'footnote' || ev.type === 'endnote') {
570
+ current_wrappers = ["", ""];
571
+ current_style = ["", ""];
572
+
573
+ if (ev.type === "start") active_ids.add(ev.id);
574
+ else if (ev.type === "end") active_ids.delete(ev.id);
575
+ else if (ev.type === "ins_start") active_ins[ev.id] = ev;
576
+ else if (ev.type === "ins_end") delete active_ins[ev.id];
577
+ else if (ev.type === "del_start") active_del[ev.id] = ev;
578
+ else if (ev.type === "del_end") delete active_del[ev.id];
579
+ else if (ev.type === "fmt_start") active_fmt[ev.id] = ev;
580
+ else if (ev.type === "fmt_end") delete active_fmt[ev.id];
581
+ else if (ev.type === "footnote" || ev.type === "endnote") {
458
582
  flush_pending_runs();
459
- current_wrappers = ['', ''];
460
- current_style = ['', ''];
461
- const prefix_str = ev.type === 'footnote' ? 'fn' : 'en';
583
+ current_wrappers = ["", ""];
584
+ current_style = ["", ""];
585
+ const prefix_str = ev.type === "footnote" ? "fn" : "en";
462
586
  const txt = `[^${prefix_str}-${ev.id}]`;
463
587
  this._add_virtual_text(txt, current, paragraph);
464
588
  current += txt.length;
465
- } else if (ev.type === 'hyperlink_start') {
589
+ } else if (ev.type === "hyperlink_start") {
466
590
  flush_pending_runs();
467
- current_wrappers = ['', ''];
468
- current_style = ['', ''];
469
- this._add_virtual_text('[', current, paragraph, ev.id);
591
+ current_wrappers = ["", ""];
592
+ current_style = ["", ""];
593
+ this._add_virtual_text("[", current, paragraph, ev.id);
470
594
  current += 1;
471
595
  active_hyperlink_id = ev.id;
472
- } else if (ev.type === 'hyperlink_end') {
596
+ } else if (ev.type === "hyperlink_end") {
473
597
  flush_pending_runs();
474
- current_wrappers = ['', ''];
475
- current_style = ['', ''];
598
+ current_wrappers = ["", ""];
599
+ current_style = ["", ""];
476
600
  const txt = `](${ev.date})`;
477
601
  this._add_virtual_text(txt, current, paragraph, ev.id);
478
602
  current += txt.length;
479
603
  active_hyperlink_id = null;
480
- } else if (ev.type === 'xref_start') {
604
+ } else if (ev.type === "xref_start") {
481
605
  flush_pending_runs();
482
- current_wrappers = ['', ''];
483
- current_style = ['', ''];
484
- this._add_virtual_text('[~', current, paragraph);
606
+ current_wrappers = ["", ""];
607
+ current_style = ["", ""];
608
+ this._add_virtual_text("[~", current, paragraph);
485
609
  current += 2;
486
- } else if (ev.type === 'xref_end') {
610
+ } else if (ev.type === "xref_end") {
487
611
  flush_pending_runs();
488
- current_wrappers = ['', ''];
489
- current_style = ['', ''];
612
+ current_wrappers = ["", ""];
613
+ current_style = ["", ""];
490
614
  const txt = `~](#${ev.id})`;
491
615
  this._add_virtual_text(txt, current, paragraph);
492
616
  current += txt.length;
493
- } else if (ev.type === 'bookmark') {
617
+ } else if (ev.type === "bookmark") {
494
618
  flush_pending_runs();
495
- current_wrappers = ['', ''];
496
- current_style = ['', ''];
619
+ current_wrappers = ["", ""];
620
+ current_style = ["", ""];
497
621
  const txt = `{#${ev.id}}`;
498
622
  this._add_virtual_text(txt, current, paragraph);
499
623
  current += txt.length;
@@ -515,11 +639,17 @@ export class DocumentMapper {
515
639
  return current;
516
640
  }
517
641
 
518
- private _get_wrappers(ins_id: string | null, del_id: string | null, active_ids: Set<string>, active_fmt: Record<string, DocxEvent>): [string, string] {
519
- if (del_id) return ['{--', '--}'];
520
- if (ins_id) return ['{++', '++}'];
521
- if (active_ids.size > 0 || Object.keys(active_fmt).length > 0) return ['{==', '==}'];
522
- return ['', ''];
642
+ private _get_wrappers(
643
+ ins_id: string | null,
644
+ del_id: string | null,
645
+ active_ids: Set<string>,
646
+ active_fmt: Record<string, DocxEvent>,
647
+ ): [string, string] {
648
+ if (del_id) return ["{--", "--}"];
649
+ if (ins_id) return ["{++", "++}"];
650
+ if (active_ids.size > 0 || Object.keys(active_fmt).length > 0)
651
+ return ["{==", "==}"];
652
+ return ["", ""];
523
653
  }
524
654
 
525
655
  private _build_merged_meta_block(states_list: any[]): string {
@@ -528,26 +658,32 @@ export class DocumentMapper {
528
658
  const seen_sigs = new Set<string>();
529
659
 
530
660
  for (const [ins_map, del_map, comments_set, fmt_map] of states_list) {
531
- for (const [uid, meta] of Object.entries(ins_map as Record<string, DocxEvent>)) {
661
+ for (const [uid, meta] of Object.entries(
662
+ ins_map as Record<string, DocxEvent>,
663
+ )) {
532
664
  const sig = `Chg:${uid}`;
533
665
  if (!seen_sigs.has(sig)) {
534
- const auth = meta.author || 'Unknown';
666
+ const auth = meta.author || "Unknown";
535
667
  change_lines.push(`[${sig} insert] ${auth}`);
536
668
  seen_sigs.add(sig);
537
669
  }
538
670
  }
539
- for (const [uid, meta] of Object.entries(del_map as Record<string, DocxEvent>)) {
671
+ for (const [uid, meta] of Object.entries(
672
+ del_map as Record<string, DocxEvent>,
673
+ )) {
540
674
  const sig = `Chg:${uid}`;
541
675
  if (!seen_sigs.has(sig)) {
542
- const auth = meta.author || 'Unknown';
676
+ const auth = meta.author || "Unknown";
543
677
  change_lines.push(`[${sig} delete] ${auth}`);
544
678
  seen_sigs.add(sig);
545
679
  }
546
680
  }
547
- for (const [uid, meta] of Object.entries(fmt_map as Record<string, DocxEvent>)) {
681
+ for (const [uid, meta] of Object.entries(
682
+ fmt_map as Record<string, DocxEvent>,
683
+ )) {
548
684
  const sig = `Chg:${uid}`;
549
685
  if (!seen_sigs.has(sig)) {
550
- const auth = meta.author || 'Unknown';
686
+ const auth = meta.author || "Unknown";
551
687
  change_lines.push(`[${sig} format] ${auth}`);
552
688
  seen_sigs.add(sig);
553
689
  }
@@ -568,24 +704,33 @@ export class DocumentMapper {
568
704
  }
569
705
  }
570
706
 
571
- return [...change_lines, ...comment_lines].join('\n');
707
+ return [...change_lines, ...comment_lines].join("\n");
572
708
  }
573
709
 
574
- private _add_virtual_text(text: string, offset: number, context_paragraph: Paragraph | null, hyperlink_id: string | null = null) {
710
+ private _add_virtual_text(
711
+ text: string,
712
+ offset: number,
713
+ context_paragraph: Paragraph | null,
714
+ hyperlink_id: string | null = null,
715
+ ) {
575
716
  const span: TextSpan = {
576
717
  start: offset,
577
718
  end: offset + text.length,
578
719
  text,
579
720
  run: null,
580
721
  paragraph: context_paragraph,
581
- hyperlink_id: hyperlink_id || undefined
722
+ hyperlink_id: hyperlink_id || undefined,
582
723
  };
583
724
  this.spans.push(span);
584
725
  this._text_chunks.push(text);
585
726
  }
586
727
 
587
728
  private _replace_smart_quotes(text: string): string {
588
- return text.replace(/“/g, '"').replace(/”/g, '"').replace(/‘/g, "'").replace(/’/g, "'");
729
+ return text
730
+ .replace(/“/g, '"')
731
+ .replace(/”/g, '"')
732
+ .replace(/‘/g, "'")
733
+ .replace(/’/g, "'");
589
734
  }
590
735
 
591
736
  private _make_fuzzy_regex(target_text: string): string {
@@ -594,10 +739,11 @@ export class DocumentMapper {
594
739
 
595
740
  const parts: string[] = [];
596
741
  const token_pattern = /(\[_+\])|(\s+)|(['"])|([.,;:\/])/g;
597
-
742
+
598
743
  let last_idx = 0;
599
744
  let match;
600
- const escapeRegExp = (str: string) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
745
+ const escapeRegExp = (str: string) =>
746
+ str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
601
747
 
602
748
  while ((match = token_pattern.exec(target_text)) !== null) {
603
749
  const literal = target_text.substring(last_idx, match.index);
@@ -609,18 +755,18 @@ export class DocumentMapper {
609
755
  const g_punct = match[4];
610
756
 
611
757
  if (g_placeholder) {
612
- parts.push('\\[_+\\]');
758
+ parts.push("\\[_+\\]");
613
759
  } else if (g_space) {
614
- parts.push('(?:\\*\\*|__|\\*|_)?');
615
- parts.push('\\s+');
616
- parts.push('(?:\\*\\*|__|\\*|_)?');
760
+ parts.push("(?:\\*\\*|__|\\*|_)?");
761
+ parts.push("\\s+");
762
+ parts.push("(?:\\*\\*|__|\\*|_)?");
617
763
  } else if (g_quote) {
618
- if (g_quote === "'") parts.push('[\u2018\u2019\']');
764
+ if (g_quote === "'") parts.push("[\u2018\u2019']");
619
765
  else parts.push('["\u201c\u201d]');
620
766
  } else if (g_punct) {
621
- parts.push('(?:\\*\\*|__|\\*|_)?');
767
+ parts.push("(?:\\*\\*|__|\\*|_)?");
622
768
  parts.push(escapeRegExp(g_punct));
623
- parts.push('(?:\\*\\*|__|\\*|_)?');
769
+ parts.push("(?:\\*\\*|__|\\*|_)?");
624
770
  }
625
771
 
626
772
  last_idx = token_pattern.lastIndex;
@@ -629,10 +775,22 @@ export class DocumentMapper {
629
775
  const remaining = target_text.substring(last_idx);
630
776
  if (remaining) parts.push(escapeRegExp(remaining));
631
777
 
632
- return parts.join('');
778
+ return parts.join("");
633
779
  }
634
780
 
635
- public find_match_index(target_text: string): [number, number] {
781
+ public find_match_index(
782
+ target_text: string,
783
+ is_regex: boolean = false,
784
+ ): [number, number] {
785
+ if (is_regex) {
786
+ try {
787
+ const pattern = new RegExp(target_text);
788
+ const match = pattern.exec(this.full_text);
789
+ if (match) return [match.index, match[0].length];
790
+ } catch (e) {}
791
+ return [-1, 0];
792
+ }
793
+
636
794
  let start_idx = this.full_text.indexOf(target_text);
637
795
  if (start_idx !== -1) return [start_idx, target_text.length];
638
796
 
@@ -656,26 +814,49 @@ export class DocumentMapper {
656
814
  return [-1, 0];
657
815
  }
658
816
 
659
- public find_all_match_indices(target_text: string): [number, number][] {
817
+ public find_all_match_indices(
818
+ target_text: string,
819
+ is_regex: boolean = false,
820
+ ): [number, number][] {
660
821
  if (!target_text) return [];
661
- const escapeRegExp = (str: string) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
662
822
 
663
- let matches = [...this.full_text.matchAll(new RegExp(escapeRegExp(target_text), 'g'))];
664
- if (matches.length > 0) return matches.map(m => [m.index!, m[0].length]);
823
+ if (is_regex) {
824
+ try {
825
+ const pattern = new RegExp(target_text, "g");
826
+ const matches = [...this.full_text.matchAll(pattern)];
827
+ if (matches.length > 0)
828
+ return matches.map((m) => [m.index!, m[0].length]);
829
+ } catch (e) {}
830
+ return [];
831
+ }
832
+ const escapeRegExp = (str: string) =>
833
+ str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
834
+
835
+ let matches = [
836
+ ...this.full_text.matchAll(new RegExp(escapeRegExp(target_text), "g")),
837
+ ];
838
+ if (matches.length > 0) return matches.map((m) => [m.index!, m[0].length]);
665
839
 
666
840
  const norm_full = this._replace_smart_quotes(this.full_text);
667
841
  const norm_target = this._replace_smart_quotes(target_text);
668
- matches = [...norm_full.matchAll(new RegExp(escapeRegExp(norm_target), 'g'))];
669
- if (matches.length > 0) return matches.map(m => [m.index!, m[0].length]);
842
+ matches = [
843
+ ...norm_full.matchAll(new RegExp(escapeRegExp(norm_target), "g")),
844
+ ];
845
+ if (matches.length > 0) return matches.map((m) => [m.index!, m[0].length]);
670
846
 
671
847
  const stripped_target = this._strip_markdown_formatting(target_text);
672
- matches = [...this.full_text.matchAll(new RegExp(escapeRegExp(stripped_target), 'g'))];
673
- if (matches.length > 0) return matches.map(m => [m.index!, m[0].length]);
848
+ matches = [
849
+ ...this.full_text.matchAll(
850
+ new RegExp(escapeRegExp(stripped_target), "g"),
851
+ ),
852
+ ];
853
+ if (matches.length > 0) return matches.map((m) => [m.index!, m[0].length]);
674
854
 
675
855
  try {
676
- const pattern = new RegExp(this._make_fuzzy_regex(target_text), 'g');
856
+ const pattern = new RegExp(this._make_fuzzy_regex(target_text), "g");
677
857
  matches = [...this.full_text.matchAll(pattern)];
678
- if (matches.length > 0) return matches.map(m => [m.index!, m[0].length]);
858
+ if (matches.length > 0)
859
+ return matches.map((m) => [m.index!, m[0].length]);
679
860
  } catch (e) {}
680
861
 
681
862
  return [];
@@ -687,39 +868,69 @@ export class DocumentMapper {
687
868
  return this._resolve_runs_at_range(start_idx, start_idx + length);
688
869
  }
689
870
 
690
- public find_target_runs_by_index(start_index: number, length: number, rebuild_map = true): Run[] {
691
- return this._resolve_runs_at_range(start_index, start_index + length, rebuild_map);
871
+ public find_target_runs_by_index(
872
+ start_index: number,
873
+ length: number,
874
+ rebuild_map = true,
875
+ ): Run[] {
876
+ return this._resolve_runs_at_range(
877
+ start_index,
878
+ start_index + length,
879
+ rebuild_map,
880
+ );
692
881
  }
693
882
 
694
- public get_virtual_spans_in_range(start_index: number, length: number): TextSpan[] {
883
+ public get_virtual_spans_in_range(
884
+ start_index: number,
885
+ length: number,
886
+ ): TextSpan[] {
695
887
  const end_index = start_index + length;
696
- return this.spans.filter(s => s.run === null && s.text === '\n\n' && s.start >= start_index && s.end <= end_index);
888
+ return this.spans.filter(
889
+ (s) =>
890
+ s.run === null &&
891
+ s.text === "\n\n" &&
892
+ s.start >= start_index &&
893
+ s.end <= end_index,
894
+ );
697
895
  }
698
896
 
699
- private _resolve_runs_at_range(start_idx: number, end_idx: number, rebuild_map = true): Run[] {
700
- const affected_spans = this.spans.filter(s => s.end > start_idx && s.start < end_idx);
897
+ private _resolve_runs_at_range(
898
+ start_idx: number,
899
+ end_idx: number,
900
+ rebuild_map = true,
901
+ ): Run[] {
902
+ const affected_spans = this.spans.filter(
903
+ (s) => s.end > start_idx && s.start < end_idx,
904
+ );
701
905
  if (affected_spans.length === 0) return [];
702
906
 
703
- const working_runs = affected_spans.filter(s => s.run !== null).map(s => s.run!);
907
+ const working_runs = affected_spans
908
+ .filter((s) => s.run !== null)
909
+ .map((s) => s.run!);
704
910
  if (working_runs.length === 0) return [];
705
911
 
706
912
  let dom_modified = false;
707
913
 
708
- const first_real_span = affected_spans.find(s => s.run !== null);
914
+ const first_real_span = affected_spans.find((s) => s.run !== null);
709
915
  let start_split_adjustment = 0;
710
916
 
711
917
  if (first_real_span) {
712
918
  const local_start = start_idx - first_real_span.start;
713
919
  if (local_start > 0) {
714
920
  const idx_in_working = 0;
715
- const [, right_run] = this._split_run_at_index(working_runs[idx_in_working], local_start);
921
+ const [, right_run] = this._split_run_at_index(
922
+ working_runs[idx_in_working],
923
+ local_start,
924
+ );
716
925
  working_runs[idx_in_working] = right_run;
717
926
  dom_modified = true;
718
927
  start_split_adjustment = local_start;
719
928
  }
720
929
  }
721
930
 
722
- const last_real_span = [...affected_spans].reverse().find(s => s.run !== null);
931
+ const last_real_span = [...affected_spans]
932
+ .reverse()
933
+ .find((s) => s.run !== null);
723
934
 
724
935
  if (last_real_span) {
725
936
  const is_same_run = first_real_span === last_real_span;
@@ -746,8 +957,11 @@ export class DocumentMapper {
746
957
  return working_runs;
747
958
  }
748
959
 
749
- public get_insertion_anchor(index: number, rebuild_map = true): [Run | null, Paragraph | null] {
750
- const preceding = this.spans.filter(s => s.end === index);
960
+ public get_insertion_anchor(
961
+ index: number,
962
+ rebuild_map = true,
963
+ ): [Run | null, Paragraph | null] {
964
+ const preceding = this.spans.filter((s) => s.end === index);
751
965
  if (preceding.length > 0) {
752
966
  for (let i = preceding.length - 1; i >= 0; i--) {
753
967
  if (preceding[i].run) return [preceding[i].run, preceding[i].paragraph];
@@ -757,7 +971,9 @@ export class DocumentMapper {
757
971
  }
758
972
  }
759
973
 
760
- const containing = this.spans.filter(s => s.start < index && index < s.end);
974
+ const containing = this.spans.filter(
975
+ (s) => s.start < index && index < s.end,
976
+ );
761
977
  if (containing.length > 0) {
762
978
  const span = containing[0];
763
979
  if (span.run === null) {
@@ -767,7 +983,7 @@ export class DocumentMapper {
767
983
  return [null, span.paragraph];
768
984
  } else {
769
985
  const offset = index - span.start;
770
- const [left, ] = this._split_run_at_index(span.run, offset);
986
+ const [left] = this._split_run_at_index(span.run, offset);
771
987
  if (rebuild_map) this._build_map();
772
988
  return [left, span.paragraph];
773
989
  }
@@ -779,16 +995,18 @@ export class DocumentMapper {
779
995
  return [null, null];
780
996
  }
781
997
 
782
- const preceding_gap = this.spans.filter(s => s.end < index);
998
+ const preceding_gap = this.spans.filter((s) => s.end < index);
783
999
  if (preceding_gap.length > 0) {
784
1000
  for (let i = preceding_gap.length - 1; i >= 0; i--) {
785
- if (preceding_gap[i].run) return [preceding_gap[i].run, preceding_gap[i].paragraph];
1001
+ if (preceding_gap[i].run)
1002
+ return [preceding_gap[i].run, preceding_gap[i].paragraph];
786
1003
  }
787
1004
  for (let i = preceding_gap.length - 1; i >= 0; i--) {
788
- if (preceding_gap[i].paragraph) return [null, preceding_gap[i].paragraph];
1005
+ if (preceding_gap[i].paragraph)
1006
+ return [null, preceding_gap[i].paragraph];
789
1007
  }
790
1008
  }
791
-
1009
+
792
1010
  return [null, null];
793
1011
  }
794
1012
 
@@ -803,7 +1021,10 @@ export class DocumentMapper {
803
1021
  this._set_run_text_elements(new_r_element, right_text);
804
1022
 
805
1023
  if (run._element.parentNode) {
806
- run._element.parentNode.insertBefore(new_r_element, run._element.nextSibling);
1024
+ run._element.parentNode.insertBefore(
1025
+ new_r_element,
1026
+ run._element.nextSibling,
1027
+ );
807
1028
  }
808
1029
 
809
1030
  const new_run = new Run(new_r_element, run._parent);
@@ -814,7 +1035,10 @@ export class DocumentMapper {
814
1035
  const to_remove: Element[] = [];
815
1036
  for (let i = 0; i < r_element.childNodes.length; i++) {
816
1037
  const child = r_element.childNodes[i] as Element;
817
- if (child.nodeType === 1 && ['w:t', 'w:delText', 'w:br', 'w:cr', 'w:tab'].includes(child.tagName)) {
1038
+ if (
1039
+ child.nodeType === 1 &&
1040
+ ["w:t", "w:delText", "w:br", "w:cr", "w:tab"].includes(child.tagName)
1041
+ ) {
818
1042
  to_remove.push(child);
819
1043
  }
820
1044
  }
@@ -824,18 +1048,23 @@ export class DocumentMapper {
824
1048
 
825
1049
  const doc = r_element.ownerDocument;
826
1050
  if (doc) {
827
- const new_t = doc.createElement('w:t');
1051
+ const new_t = doc.createElement("w:t");
828
1052
  new_t.textContent = new_text;
829
1053
  if (new_text.trim() !== new_text) {
830
- new_t.setAttribute('xml:space', 'preserve');
1054
+ new_t.setAttribute("xml:space", "preserve");
831
1055
  }
832
1056
  r_element.appendChild(new_t);
833
1057
  }
834
1058
  }
835
1059
 
836
- public get_context_at_range(start_idx: number, end_idx: number): TextSpan | null {
837
- const real_spans = this.spans.filter(s => s.run && s.end > start_idx && s.start < end_idx);
1060
+ public get_context_at_range(
1061
+ start_idx: number,
1062
+ end_idx: number,
1063
+ ): TextSpan | null {
1064
+ const real_spans = this.spans.filter(
1065
+ (s) => s.run && s.end > start_idx && s.start < end_idx,
1066
+ );
838
1067
  if (real_spans.length > 0) return real_spans[0];
839
1068
  return null;
840
1069
  }
841
- }
1070
+ }