@adeu/core 1.13.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/dist/index.cjs +2215 -1789
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -12
- package/dist/index.d.ts +7 -12
- package/dist/index.js +2215 -1789
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/comment_dedup.test.ts +269 -0
- package/src/domain.test.ts +280 -77
- package/src/domain.ts +146 -46
- package/src/engine.bugs.test.ts +20 -0
- package/src/engine.qa.test.ts +162 -0
- package/src/engine.ts +302 -89
- package/src/ingest.ts +283 -133
- package/src/mapper.ts +425 -196
- package/src/models.ts +2 -0
- package/src/repro_heading_bug.test.ts +174 -0
- package/src/search_write_engine.test.ts +112 -0
package/src/ingest.ts
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
|
-
import { DocumentObject } from
|
|
2
|
-
import { Paragraph, Table, Run, DocxEvent } from
|
|
3
|
-
import {
|
|
4
|
-
_get_style_cache,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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(
|
|
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(
|
|
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 ===
|
|
68
|
-
const header =
|
|
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 ===
|
|
80
|
-
const fn_text = _extract_blocks(
|
|
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 ===
|
|
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(
|
|
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(
|
|
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(
|
|
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,
|
|
134
|
-
const ins = trPr ? findChild(trPr,
|
|
135
|
-
const del_node = trPr ? findChild(trPr,
|
|
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 =
|
|
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(
|
|
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(
|
|
161
|
-
else if (del_node)
|
|
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(
|
|
212
|
+
return rows_text.join("\n");
|
|
170
213
|
}
|
|
171
214
|
|
|
172
215
|
export function build_paragraph_text(
|
|
173
|
-
paragraph: Paragraph,
|
|
174
|
-
|
|
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(
|
|
189
|
-
|
|
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
|
|
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 (
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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)
|
|
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 =
|
|
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([
|
|
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
|
|
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 (
|
|
318
|
+
if (has_any_meta) {
|
|
236
319
|
let j = i + 1;
|
|
237
|
-
let
|
|
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)) {
|
|
246
|
-
|
|
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 ===
|
|
251
|
-
else if (ev.type ===
|
|
252
|
-
|
|
253
|
-
else if (ev.type ===
|
|
254
|
-
else if (ev.type ===
|
|
255
|
-
|
|
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 (
|
|
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(
|
|
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(
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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 (
|
|
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(
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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 ===
|
|
291
|
-
else if (ev.type ===
|
|
292
|
-
else if (ev.type ===
|
|
293
|
-
else if (ev.type ===
|
|
294
|
-
else if (ev.type ===
|
|
295
|
-
else if (ev.type ===
|
|
296
|
-
else if (ev.type ===
|
|
297
|
-
else if (ev.type ===
|
|
298
|
-
else if (ev.type ===
|
|
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(
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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 ===
|
|
306
|
-
} else if (ev.type ===
|
|
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(
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
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 ===
|
|
431
|
+
parts.push("[");
|
|
432
|
+
} else if (ev.type === "hyperlink_end") {
|
|
315
433
|
if (pending_text) {
|
|
316
|
-
parts.push(
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
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 ===
|
|
442
|
+
} else if (ev.type === "xref_start") {
|
|
323
443
|
if (pending_text) {
|
|
324
|
-
parts.push(
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
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 ===
|
|
451
|
+
parts.push("[~");
|
|
452
|
+
} else if (ev.type === "xref_end") {
|
|
331
453
|
if (pending_text) {
|
|
332
|
-
parts.push(
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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 ===
|
|
462
|
+
} else if (ev.type === "bookmark") {
|
|
339
463
|
if (pending_text) {
|
|
340
|
-
parts.push(
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
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)
|
|
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(
|
|
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(
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
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(
|
|
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(
|
|
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 ||
|
|
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(
|
|
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 ||
|
|
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(
|
|
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 ||
|
|
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(
|
|
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) =>
|
|
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(
|
|
432
|
-
}
|
|
581
|
+
return [...change_lines, ...comment_lines].join("\n");
|
|
582
|
+
}
|