@adeu/core 1.14.0 → 1.15.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/src/ingest.ts CHANGED
@@ -1,15 +1,25 @@
1
- import { DocumentObject } from './docx/bridge.js';
2
- import { Paragraph, Table, Run, DocxEvent } from './docx/primitives.js';
3
- import {
4
- _get_style_cache, get_paragraph_prefix, is_heading_paragraph, is_native_heading,
5
- get_run_style_markers, get_run_text, apply_formatting_to_segments,
6
- iter_block_items, iter_document_parts, iter_paragraph_content
7
- } from './utils/docx.js';
8
- import { findChild } from './docx/dom.js';
9
- import { build_structural_appendix } from './domain.js';
10
- import { extract_comments_data } from './comments.js';
11
-
12
- export async function extractTextFromBuffer(buffer: Buffer, cleanView = false): Promise<string> {
1
+ import { DocumentObject } from "./docx/bridge.js";
2
+ import { Paragraph, Table, Run, DocxEvent } from "./docx/primitives.js";
3
+ import {
4
+ _get_style_cache,
5
+ get_paragraph_prefix,
6
+ is_heading_paragraph,
7
+ is_native_heading,
8
+ get_run_style_markers,
9
+ get_run_text,
10
+ apply_formatting_to_segments,
11
+ iter_block_items,
12
+ iter_document_parts,
13
+ iter_paragraph_content,
14
+ } from "./utils/docx.js";
15
+ import { findChild } from "./docx/dom.js";
16
+ import { build_structural_appendix } from "./domain.js";
17
+ import { extract_comments_data } from "./comments.js";
18
+
19
+ export async function extractTextFromBuffer(
20
+ buffer: Buffer,
21
+ cleanView = false,
22
+ ): Promise<string> {
13
23
  const doc = await DocumentObject.load(buffer);
14
24
  return _extractTextFromDoc(doc, cleanView) as string;
15
25
  }
@@ -28,7 +38,13 @@ export function _extractTextFromDoc(
28
38
 
29
39
  for (const part of iter_document_parts(doc)) {
30
40
  const part_cursor = full_text.length > 0 ? cursor + 2 : cursor;
31
- const part_text = _extract_blocks(part, comments_map, cleanView, part_cursor, return_paragraph_offsets ? paragraph_offsets : undefined);
41
+ const part_text = _extract_blocks(
42
+ part,
43
+ comments_map,
44
+ cleanView,
45
+ part_cursor,
46
+ return_paragraph_offsets ? paragraph_offsets : undefined,
47
+ );
32
48
  if (part_text) {
33
49
  if (full_text.length > 0) cursor += 2;
34
50
  full_text.push(part_text);
@@ -36,7 +52,7 @@ export function _extractTextFromDoc(
36
52
  }
37
53
  }
38
54
 
39
- let base_text = full_text.join('\n\n');
55
+ let base_text = full_text.join("\n\n");
40
56
 
41
57
  if (includeAppendix) {
42
58
  const appendix = build_structural_appendix(doc, base_text);
@@ -54,7 +70,7 @@ function _extract_blocks(
54
70
  comments_map: any,
55
71
  cleanView: boolean,
56
72
  cursor: number,
57
- paragraph_offsets?: Map<any, [number, number]>
73
+ paragraph_offsets?: Map<any, [number, number]>,
58
74
  ): string {
59
75
  const part = container.part || container;
60
76
  const [style_cache, default_pstyle] = _get_style_cache(part);
@@ -64,8 +80,9 @@ function _extract_blocks(
64
80
  let is_first_block = true;
65
81
  let is_first_para = true;
66
82
 
67
- if (container.constructor && container.constructor.name === 'NotesPart') {
68
- const header = container.note_type === 'fn' ? '## Footnotes' : '## Endnotes';
83
+ if (container.constructor && container.constructor.name === "NotesPart") {
84
+ const header =
85
+ container.note_type === "fn" ? "## Footnotes" : "## Endnotes";
69
86
  const sep = `---\n${header}`;
70
87
  blocks.push(sep);
71
88
  local_cursor += sep.length;
@@ -76,8 +93,14 @@ function _extract_blocks(
76
93
  if (!is_first_block) local_cursor += 2;
77
94
  const block_start = local_cursor;
78
95
 
79
- if (item.constructor.name === 'FootnoteItem') {
80
- const fn_text = _extract_blocks(item, comments_map, cleanView, block_start, paragraph_offsets);
96
+ if (item.constructor.name === "FootnoteItem") {
97
+ const fn_text = _extract_blocks(
98
+ item,
99
+ comments_map,
100
+ cleanView,
101
+ block_start,
102
+ paragraph_offsets,
103
+ );
81
104
  if (fn_text) {
82
105
  blocks.push(fn_text);
83
106
  local_cursor = block_start + fn_text.length;
@@ -87,10 +110,16 @@ function _extract_blocks(
87
110
  }
88
111
  } else if (item instanceof Paragraph) {
89
112
  let prefix = get_paragraph_prefix(item, style_cache, default_pstyle);
90
- if (is_first_para && container.constructor.name === 'FootnoteItem') {
113
+ if (is_first_para && container.constructor.name === "FootnoteItem") {
91
114
  prefix = `[^${container.note_type}-${container.id}]: ` + prefix;
92
115
  }
93
- const p_text = build_paragraph_text(item, comments_map, cleanView, style_cache, default_pstyle);
116
+ const p_text = build_paragraph_text(
117
+ item,
118
+ comments_map,
119
+ cleanView,
120
+ style_cache,
121
+ default_pstyle,
122
+ );
94
123
  const full_block = prefix + p_text;
95
124
  blocks.push(full_block);
96
125
  if (paragraph_offsets) {
@@ -100,7 +129,13 @@ function _extract_blocks(
100
129
  is_first_para = false;
101
130
  is_first_block = false;
102
131
  } else if (item instanceof Table) {
103
- const table_text = extract_table(item, comments_map, cleanView, block_start, paragraph_offsets);
132
+ const table_text = extract_table(
133
+ item,
134
+ comments_map,
135
+ cleanView,
136
+ block_start,
137
+ paragraph_offsets,
138
+ );
104
139
  if (table_text) {
105
140
  blocks.push(table_text);
106
141
  local_cursor = block_start + table_text.length;
@@ -112,7 +147,7 @@ function _extract_blocks(
112
147
  }
113
148
  }
114
149
 
115
- return blocks.join('\n\n');
150
+ return blocks.join("\n\n");
116
151
  }
117
152
 
118
153
  export function extract_table(
@@ -120,7 +155,7 @@ export function extract_table(
120
155
  comments_map: any,
121
156
  cleanView: boolean,
122
157
  cursor: number,
123
- paragraph_offsets?: Map<any, [number, number]>
158
+ paragraph_offsets?: Map<any, [number, number]>,
124
159
  ): string {
125
160
  const rows_text: string[] = [];
126
161
  let rows_processed = 0;
@@ -130,15 +165,16 @@ export function extract_table(
130
165
  const cell_texts: string[] = [];
131
166
  const seen_cells = new Set();
132
167
 
133
- const trPr = findChild(row._element, 'w:trPr');
134
- const ins = trPr ? findChild(trPr, 'w:ins') : null;
135
- const del_node = trPr ? findChild(trPr, 'w:del') : null;
168
+ const trPr = findChild(row._element, "w:trPr");
169
+ const ins = trPr ? findChild(trPr, "w:ins") : null;
170
+ const del_node = trPr ? findChild(trPr, "w:del") : null;
136
171
 
137
172
  if (cleanView && del_node) continue;
138
173
 
139
174
  const row_start = local_cursor + (rows_processed > 0 ? 1 : 0);
140
- const wrapper_prefix_len = (!cleanView && ins) ? 4 : (!cleanView && del_node) ? 4 : 0;
141
-
175
+ const wrapper_prefix_len =
176
+ !cleanView && ins ? 4 : !cleanView && del_node ? 4 : 0;
177
+
142
178
  let cell_cursor = row_start + wrapper_prefix_len;
143
179
  let first_cell = true;
144
180
 
@@ -147,18 +183,25 @@ export function extract_table(
147
183
  seen_cells.add(cell);
148
184
 
149
185
  if (!first_cell) cell_cursor += 3;
150
-
151
- const cell_content = _extract_blocks(cell, comments_map, cleanView, cell_cursor, paragraph_offsets);
186
+
187
+ const cell_content = _extract_blocks(
188
+ cell,
189
+ comments_map,
190
+ cleanView,
191
+ cell_cursor,
192
+ paragraph_offsets,
193
+ );
152
194
  cell_texts.push(cell_content);
153
195
  cell_cursor += cell_content.length;
154
196
  first_cell = false;
155
197
  }
156
198
 
157
- let row_str = cell_texts.join(' | ');
199
+ let row_str = cell_texts.join(" | ");
158
200
 
159
201
  if (!cleanView) {
160
- if (ins) row_str = `{++ ${row_str} |Chg:${ins.getAttribute('w:id')}++}`;
161
- else if (del_node) row_str = `{-- ${row_str} |Chg:${del_node.getAttribute('w:id')}--}`;
202
+ if (ins) row_str = `{++ ${row_str} |Chg:${ins.getAttribute("w:id")}++}`;
203
+ else if (del_node)
204
+ row_str = `{-- ${row_str} |Chg:${del_node.getAttribute("w:id")}--}`;
162
205
  }
163
206
 
164
207
  rows_text.push(row_str);
@@ -166,12 +209,15 @@ export function extract_table(
166
209
  rows_processed++;
167
210
  }
168
211
 
169
- return rows_text.join('\n');
212
+ return rows_text.join("\n");
170
213
  }
171
214
 
172
215
  export function build_paragraph_text(
173
- paragraph: Paragraph, comments_map: any, cleanView: boolean,
174
- style_cache?: any, default_pstyle?: string | null
216
+ paragraph: Paragraph,
217
+ comments_map: any,
218
+ cleanView: boolean,
219
+ style_cache?: any,
220
+ default_pstyle?: string | null,
175
221
  ): string {
176
222
  const parts: string[] = [];
177
223
  const active_ins: Record<string, DocxEvent> = {};
@@ -180,13 +226,21 @@ export function build_paragraph_text(
180
226
  const active_fmt: Record<string, DocxEvent> = {};
181
227
  const deferred_meta_states: any[] = [];
182
228
 
183
- let pending_text = '';
184
- let current_wrappers: [string, string] = ['', ''];
185
- let current_style: [string, string] = ['', ''];
229
+ let pending_text = "";
230
+ let current_wrappers: [string, string] = ["", ""];
231
+ let current_style: [string, string] = ["", ""];
186
232
 
187
233
  const items = Array.from(iter_paragraph_content(paragraph));
188
- const is_heading = is_heading_paragraph(paragraph, style_cache, default_pstyle);
189
- const native_heading = is_native_heading(paragraph, style_cache, default_pstyle);
234
+ const is_heading = is_heading_paragraph(
235
+ paragraph,
236
+ style_cache,
237
+ default_pstyle,
238
+ );
239
+ const native_heading = is_native_heading(
240
+ paragraph,
241
+ style_cache,
242
+ default_pstyle,
243
+ );
190
244
  let leading_strip_active = is_heading;
191
245
 
192
246
  for (let i = 0; i < items.length; i++) {
@@ -205,68 +259,117 @@ export function build_paragraph_text(
205
259
 
206
260
  const seg = apply_formatting_to_segments(text, prefix, suffix);
207
261
  if (seg) {
208
- const new_wrappers = cleanView ? ['', ''] as [string, string] : _get_wrappers(active_ins, active_del, active_comments, active_fmt);
262
+ const new_wrappers = cleanView
263
+ ? (["", ""] as [string, string])
264
+ : _get_wrappers(active_ins, active_del, active_comments, active_fmt);
209
265
  const new_style: [string, string] = [prefix, suffix];
210
266
 
211
- if (pending_text && new_wrappers[0] === current_wrappers[0] && new_wrappers[1] === current_wrappers[1]) {
212
- if (new_style[0] === current_style[0] && new_style[1] === current_style[1] && current_style[0] !== '' &&
213
- pending_text.endsWith(current_style[1]) && seg.startsWith(new_style[0])) {
214
- pending_text = pending_text.slice(0, -current_style[1].length) + seg.slice(new_style[0].length);
267
+ if (
268
+ pending_text &&
269
+ new_wrappers[0] === current_wrappers[0] &&
270
+ new_wrappers[1] === current_wrappers[1]
271
+ ) {
272
+ if (
273
+ new_style[0] === current_style[0] &&
274
+ new_style[1] === current_style[1] &&
275
+ current_style[0] !== "" &&
276
+ pending_text.endsWith(current_style[1]) &&
277
+ seg.startsWith(new_style[0])
278
+ ) {
279
+ pending_text =
280
+ pending_text.slice(0, -current_style[1].length) +
281
+ seg.slice(new_style[0].length);
215
282
  } else {
216
283
  pending_text += seg;
217
284
  }
218
285
  current_style = new_style;
219
286
  } else {
220
- if (pending_text) parts.push(`${current_wrappers[0]}${pending_text}${current_wrappers[1]}`);
287
+ if (pending_text)
288
+ parts.push(
289
+ `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,
290
+ );
221
291
  pending_text = seg;
222
292
  current_wrappers = new_wrappers;
223
293
  current_style = new_style;
224
294
  }
225
295
 
226
296
  if (!cleanView) {
227
- const has_meta = Object.keys(active_ins).length > 0 || Object.keys(active_del).length > 0 || active_comments.size > 0 || Object.keys(active_fmt).length > 0;
297
+ const has_meta =
298
+ Object.keys(active_ins).length > 0 ||
299
+ Object.keys(active_del).length > 0 ||
300
+ active_comments.size > 0 ||
301
+ Object.keys(active_fmt).length > 0;
228
302
  if (has_meta) {
229
- deferred_meta_states.push([{...active_ins}, {...active_del}, new Set(active_comments), {...active_fmt}]);
303
+ deferred_meta_states.push([
304
+ { ...active_ins },
305
+ { ...active_del },
306
+ new Set(active_comments),
307
+ { ...active_fmt },
308
+ ]);
230
309
  }
231
310
 
232
311
  let should_defer = false;
233
- const is_redline = Object.keys(active_ins).length > 0 || Object.keys(active_del).length > 0 || Object.keys(active_fmt).length > 0;
312
+ const has_any_meta =
313
+ Object.keys(active_ins).length > 0 ||
314
+ Object.keys(active_del).length > 0 ||
315
+ Object.keys(active_fmt).length > 0 ||
316
+ active_comments.size > 0;
234
317
 
235
- if (is_redline) {
318
+ if (has_any_meta) {
236
319
  let j = i + 1;
237
- let next_is_redline = false;
320
+ let next_has_meta = false;
238
321
  let temp_ins = Object.keys(active_ins).length;
239
322
  let temp_del = Object.keys(active_del).length;
240
323
  let temp_fmt = Object.keys(active_fmt).length;
324
+ const temp_comments = new Set(active_comments);
241
325
 
242
326
  while (j < items.length) {
243
327
  const next_item = items[j];
244
328
  if (next_item instanceof Run) {
245
- if (!get_run_text(next_item)) { j++; continue; }
246
- if (temp_ins > 0 || temp_del > 0 || temp_fmt > 0) next_is_redline = true;
329
+ if (!get_run_text(next_item)) {
330
+ j++;
331
+ continue;
332
+ }
333
+ if (
334
+ temp_ins > 0 ||
335
+ temp_del > 0 ||
336
+ temp_fmt > 0 ||
337
+ temp_comments.size > 0
338
+ )
339
+ next_has_meta = true;
247
340
  break;
248
341
  } else {
249
342
  const ev = next_item as DocxEvent;
250
- if (ev.type === 'ins_start') temp_ins++;
251
- else if (ev.type === 'ins_end') temp_ins = Math.max(0, temp_ins - 1);
252
- else if (ev.type === 'del_start') temp_del++;
253
- else if (ev.type === 'del_end') temp_del = Math.max(0, temp_del - 1);
254
- else if (ev.type === 'fmt_start') temp_fmt++;
255
- else if (ev.type === 'fmt_end') temp_fmt = Math.max(0, temp_fmt - 1);
343
+ if (ev.type === "ins_start") temp_ins++;
344
+ else if (ev.type === "ins_end")
345
+ temp_ins = Math.max(0, temp_ins - 1);
346
+ else if (ev.type === "del_start") temp_del++;
347
+ else if (ev.type === "del_end")
348
+ temp_del = Math.max(0, temp_del - 1);
349
+ else if (ev.type === "fmt_start") temp_fmt++;
350
+ else if (ev.type === "fmt_end")
351
+ temp_fmt = Math.max(0, temp_fmt - 1);
352
+ else if (ev.type === "start") temp_comments.add(ev.id);
353
+ else if (ev.type === "end") temp_comments.delete(ev.id);
256
354
  }
257
355
  j++;
258
356
  }
259
- if (next_is_redline) should_defer = true;
357
+ if (next_has_meta) should_defer = true;
260
358
  }
261
359
 
262
360
  if (!should_defer && deferred_meta_states.length > 0) {
263
- const meta_block = _build_merged_meta_block(deferred_meta_states, comments_map);
361
+ const meta_block = _build_merged_meta_block(
362
+ deferred_meta_states,
363
+ comments_map,
364
+ );
264
365
  if (meta_block) {
265
366
  if (pending_text) {
266
- parts.push(`${current_wrappers[0]}${pending_text}${current_wrappers[1]}`);
267
- pending_text = '';
268
- current_wrappers = ['', ''];
269
- current_style = ['', ''];
367
+ parts.push(
368
+ `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,
369
+ );
370
+ pending_text = "";
371
+ current_wrappers = ["", ""];
372
+ current_style = ["", ""];
270
373
  }
271
374
  parts.push(`{>>${meta_block}<<}`);
272
375
  }
@@ -277,124 +380,167 @@ export function build_paragraph_text(
277
380
  } else {
278
381
  const ev = item as DocxEvent;
279
382
  leading_strip_active = false;
280
-
281
- if (!['ins_start', 'ins_end', 'del_start', 'del_end', 'fmt_start', 'fmt_end'].includes(ev.type)) {
383
+
384
+ if (
385
+ ![
386
+ "ins_start",
387
+ "ins_end",
388
+ "del_start",
389
+ "del_end",
390
+ "fmt_start",
391
+ "fmt_end",
392
+ ].includes(ev.type)
393
+ ) {
282
394
  if (pending_text) {
283
- parts.push(`${current_wrappers[0]}${pending_text}${current_wrappers[1]}`);
284
- pending_text = '';
285
- current_wrappers = ['', ''];
286
- current_style = ['', ''];
395
+ parts.push(
396
+ `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,
397
+ );
398
+ pending_text = "";
399
+ current_wrappers = ["", ""];
400
+ current_style = ["", ""];
287
401
  }
288
402
  }
289
403
 
290
- if (ev.type === 'start') active_comments.add(ev.id);
291
- else if (ev.type === 'end') active_comments.delete(ev.id);
292
- else if (ev.type === 'ins_start') active_ins[ev.id] = ev;
293
- else if (ev.type === 'ins_end') delete active_ins[ev.id];
294
- else if (ev.type === 'del_start') active_del[ev.id] = ev;
295
- else if (ev.type === 'del_end') delete active_del[ev.id];
296
- else if (ev.type === 'fmt_start') active_fmt[ev.id] = ev;
297
- else if (ev.type === 'fmt_end') delete active_fmt[ev.id];
298
- else if (ev.type === 'footnote' || ev.type === 'endnote') {
404
+ if (ev.type === "start") active_comments.add(ev.id);
405
+ else if (ev.type === "end") active_comments.delete(ev.id);
406
+ else if (ev.type === "ins_start") active_ins[ev.id] = ev;
407
+ else if (ev.type === "ins_end") delete active_ins[ev.id];
408
+ else if (ev.type === "del_start") active_del[ev.id] = ev;
409
+ else if (ev.type === "del_end") delete active_del[ev.id];
410
+ else if (ev.type === "fmt_start") active_fmt[ev.id] = ev;
411
+ else if (ev.type === "fmt_end") delete active_fmt[ev.id];
412
+ else if (ev.type === "footnote" || ev.type === "endnote") {
299
413
  if (pending_text) {
300
- parts.push(`${current_wrappers[0]}${pending_text}${current_wrappers[1]}`);
301
- pending_text = '';
302
- current_wrappers = ['', ''];
303
- current_style = ['', ''];
414
+ parts.push(
415
+ `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,
416
+ );
417
+ pending_text = "";
418
+ current_wrappers = ["", ""];
419
+ current_style = ["", ""];
304
420
  }
305
- parts.push(`[^${ev.type === 'footnote' ? 'fn' : 'en'}-${ev.id}]`);
306
- } else if (ev.type === 'hyperlink_start') {
421
+ parts.push(`[^${ev.type === "footnote" ? "fn" : "en"}-${ev.id}]`);
422
+ } else if (ev.type === "hyperlink_start") {
307
423
  if (pending_text) {
308
- parts.push(`${current_wrappers[0]}${pending_text}${current_wrappers[1]}`);
309
- pending_text = '';
310
- current_wrappers = ['', ''];
311
- current_style = ['', ''];
424
+ parts.push(
425
+ `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,
426
+ );
427
+ pending_text = "";
428
+ current_wrappers = ["", ""];
429
+ current_style = ["", ""];
312
430
  }
313
- parts.push('[');
314
- } else if (ev.type === 'hyperlink_end') {
431
+ parts.push("[");
432
+ } else if (ev.type === "hyperlink_end") {
315
433
  if (pending_text) {
316
- parts.push(`${current_wrappers[0]}${pending_text}${current_wrappers[1]}`);
317
- pending_text = '';
318
- current_wrappers = ['', ''];
319
- current_style = ['', ''];
434
+ parts.push(
435
+ `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,
436
+ );
437
+ pending_text = "";
438
+ current_wrappers = ["", ""];
439
+ current_style = ["", ""];
320
440
  }
321
441
  parts.push(`](${ev.date})`);
322
- } else if (ev.type === 'xref_start') {
442
+ } else if (ev.type === "xref_start") {
323
443
  if (pending_text) {
324
- parts.push(`${current_wrappers[0]}${pending_text}${current_wrappers[1]}`);
325
- pending_text = '';
326
- current_wrappers = ['', ''];
327
- current_style = ['', ''];
444
+ parts.push(
445
+ `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,
446
+ );
447
+ pending_text = "";
448
+ current_wrappers = ["", ""];
449
+ current_style = ["", ""];
328
450
  }
329
- parts.push('[~');
330
- } else if (ev.type === 'xref_end') {
451
+ parts.push("[~");
452
+ } else if (ev.type === "xref_end") {
331
453
  if (pending_text) {
332
- parts.push(`${current_wrappers[0]}${pending_text}${current_wrappers[1]}`);
333
- pending_text = '';
334
- current_wrappers = ['', ''];
335
- current_style = ['', ''];
454
+ parts.push(
455
+ `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,
456
+ );
457
+ pending_text = "";
458
+ current_wrappers = ["", ""];
459
+ current_style = ["", ""];
336
460
  }
337
461
  parts.push(`~](#${ev.id})`);
338
- } else if (ev.type === 'bookmark') {
462
+ } else if (ev.type === "bookmark") {
339
463
  if (pending_text) {
340
- parts.push(`${current_wrappers[0]}${pending_text}${current_wrappers[1]}`);
341
- pending_text = '';
342
- current_wrappers = ['', ''];
343
- current_style = ['', ''];
464
+ parts.push(
465
+ `${current_wrappers[0]}${pending_text}${current_wrappers[1]}`,
466
+ );
467
+ pending_text = "";
468
+ current_wrappers = ["", ""];
469
+ current_style = ["", ""];
344
470
  }
345
471
  parts.push(`{#${ev.id}}`);
346
472
  }
347
473
  }
348
474
  }
349
475
 
350
- if (pending_text) parts.push(`${current_wrappers[0]}${pending_text}${current_wrappers[1]}`);
476
+ if (pending_text)
477
+ parts.push(`${current_wrappers[0]}${pending_text}${current_wrappers[1]}`);
351
478
 
352
479
  if (deferred_meta_states.length > 0) {
353
- const meta_block = _build_merged_meta_block(deferred_meta_states, comments_map);
480
+ const meta_block = _build_merged_meta_block(
481
+ deferred_meta_states,
482
+ comments_map,
483
+ );
354
484
  if (meta_block) parts.push(`{>>${meta_block}<<}`);
355
485
  }
356
486
 
357
- return parts.join('');
487
+ return parts.join("");
358
488
  }
359
489
 
360
- function _get_wrappers(ins: any, del: any, comments: Set<string>, fmt: any): [string, string] {
361
- if (Object.keys(del).length > 0) return ['{--', '--}'];
362
- if (Object.keys(ins).length > 0) return ['{++', '++}'];
363
- if (comments.size > 0 || Object.keys(fmt).length > 0) return ['{==', '==}'];
364
- return ['', ''];
490
+ function _get_wrappers(
491
+ ins: any,
492
+ del: any,
493
+ comments: Set<string>,
494
+ fmt: any,
495
+ ): [string, string] {
496
+ if (Object.keys(del).length > 0) return ["{--", "--}"];
497
+ if (Object.keys(ins).length > 0) return ["{++", "++}"];
498
+ if (comments.size > 0 || Object.keys(fmt).length > 0) return ["{==", "==}"];
499
+ return ["", ""];
365
500
  }
366
501
 
367
- function _build_merged_meta_block(states_list: any[], comments_map: any): string {
502
+ function _build_merged_meta_block(
503
+ states_list: any[],
504
+ comments_map: any,
505
+ ): string {
368
506
  const change_lines: string[] = [];
369
507
  const comment_lines: string[] = [];
370
508
  const seen_sigs = new Set<string>();
371
509
 
372
510
  for (const [ins_map, del_map, comments_set, fmt_map] of states_list) {
373
- for (const [uid, meta] of Object.entries(ins_map as Record<string, DocxEvent>)) {
511
+ for (const [uid, meta] of Object.entries(
512
+ ins_map as Record<string, DocxEvent>,
513
+ )) {
374
514
  const sig = `Chg:${uid}`;
375
515
  if (!seen_sigs.has(sig)) {
376
- change_lines.push(`[${sig} insert] ${meta.author || 'Unknown'}`);
516
+ change_lines.push(`[${sig} insert] ${meta.author || "Unknown"}`);
377
517
  seen_sigs.add(sig);
378
518
  }
379
519
  }
380
- for (const [uid, meta] of Object.entries(del_map as Record<string, DocxEvent>)) {
520
+ for (const [uid, meta] of Object.entries(
521
+ del_map as Record<string, DocxEvent>,
522
+ )) {
381
523
  const sig = `Chg:${uid}`;
382
524
  if (!seen_sigs.has(sig)) {
383
- change_lines.push(`[${sig} delete] ${meta.author || 'Unknown'}`);
525
+ change_lines.push(`[${sig} delete] ${meta.author || "Unknown"}`);
384
526
  seen_sigs.add(sig);
385
527
  }
386
528
  }
387
- for (const [uid, meta] of Object.entries(fmt_map as Record<string, DocxEvent>)) {
529
+ for (const [uid, meta] of Object.entries(
530
+ fmt_map as Record<string, DocxEvent>,
531
+ )) {
388
532
  const sig = `Chg:${uid}`;
389
533
  if (!seen_sigs.has(sig)) {
390
- change_lines.push(`[${sig} format] ${meta.author || 'Unknown'}`);
534
+ change_lines.push(`[${sig} format] ${meta.author || "Unknown"}`);
391
535
  seen_sigs.add(sig);
392
536
  }
393
537
  }
394
538
 
395
539
  // Threaded Comment Resolution Tree
396
540
  const children_map: Record<string, string[]> = {};
397
- for (const [c_id, data] of Object.entries(comments_map as Record<string, any>)) {
541
+ for (const [c_id, data] of Object.entries(
542
+ comments_map as Record<string, any>,
543
+ )) {
398
544
  const p_id = data.parent_id;
399
545
  if (p_id) {
400
546
  if (!children_map[p_id]) children_map[p_id] = [];
@@ -415,7 +561,11 @@ function _build_merged_meta_block(states_list: any[], comments_map: any): string
415
561
  seen_sigs.add(sig);
416
562
 
417
563
  if (children_map[cid]) {
418
- const children = children_map[cid].sort((a, b) => (comments_map[a]?.date || '').localeCompare(comments_map[b]?.date || ''));
564
+ const children = children_map[cid].sort((a, b) =>
565
+ (comments_map[a]?.date || "").localeCompare(
566
+ comments_map[b]?.date || "",
567
+ ),
568
+ );
419
569
  for (const child_id of children) {
420
570
  render_comment(child_id);
421
571
  }
@@ -428,5 +578,5 @@ function _build_merged_meta_block(states_list: any[], comments_map: any): string
428
578
  }
429
579
  }
430
580
 
431
- return [...change_lines, ...comment_lines].join('\n');
432
- }
581
+ return [...change_lines, ...comment_lines].join("\n");
582
+ }