docrev 0.9.4 → 0.9.6
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/lib/commands/comments.d.ts.map +1 -1
- package/dist/lib/commands/comments.js +19 -27
- package/dist/lib/commands/comments.js.map +1 -1
- package/dist/lib/commands/context.d.ts +1 -0
- package/dist/lib/commands/context.d.ts.map +1 -1
- package/dist/lib/commands/context.js +1 -2
- package/dist/lib/commands/context.js.map +1 -1
- package/dist/lib/commands/file-ops.d.ts +11 -0
- package/dist/lib/commands/file-ops.d.ts.map +1 -0
- package/dist/lib/commands/file-ops.js +301 -0
- package/dist/lib/commands/file-ops.js.map +1 -0
- package/dist/lib/commands/index.d.ts +9 -1
- package/dist/lib/commands/index.d.ts.map +1 -1
- package/dist/lib/commands/index.js +17 -1
- package/dist/lib/commands/index.js.map +1 -1
- package/dist/lib/commands/merge-resolve.d.ts +12 -0
- package/dist/lib/commands/merge-resolve.d.ts.map +1 -0
- package/dist/lib/commands/merge-resolve.js +318 -0
- package/dist/lib/commands/merge-resolve.js.map +1 -0
- package/dist/lib/commands/preview.d.ts +11 -0
- package/dist/lib/commands/preview.d.ts.map +1 -0
- package/dist/lib/commands/preview.js +138 -0
- package/dist/lib/commands/preview.js.map +1 -0
- package/dist/lib/commands/project-info.d.ts +11 -0
- package/dist/lib/commands/project-info.d.ts.map +1 -0
- package/dist/lib/commands/project-info.js +187 -0
- package/dist/lib/commands/project-info.js.map +1 -0
- package/dist/lib/commands/quality.d.ts +11 -0
- package/dist/lib/commands/quality.d.ts.map +1 -0
- package/dist/lib/commands/quality.js +384 -0
- package/dist/lib/commands/quality.js.map +1 -0
- package/dist/lib/commands/sections.d.ts +3 -2
- package/dist/lib/commands/sections.d.ts.map +1 -1
- package/dist/lib/commands/sections.js +4 -723
- package/dist/lib/commands/sections.js.map +1 -1
- package/dist/lib/commands/sync.d.ts +11 -0
- package/dist/lib/commands/sync.d.ts.map +1 -0
- package/dist/lib/commands/sync.js +441 -0
- package/dist/lib/commands/sync.js.map +1 -0
- package/dist/lib/commands/text-ops.d.ts +11 -0
- package/dist/lib/commands/text-ops.d.ts.map +1 -0
- package/dist/lib/commands/text-ops.js +357 -0
- package/dist/lib/commands/text-ops.js.map +1 -0
- package/dist/lib/commands/utilities.d.ts +2 -4
- package/dist/lib/commands/utilities.d.ts.map +1 -1
- package/dist/lib/commands/utilities.js +3 -1605
- package/dist/lib/commands/utilities.js.map +1 -1
- package/dist/lib/commands/word-tools.d.ts +11 -0
- package/dist/lib/commands/word-tools.d.ts.map +1 -0
- package/dist/lib/commands/word-tools.js +272 -0
- package/dist/lib/commands/word-tools.js.map +1 -0
- package/dist/lib/comment-realign.d.ts.map +1 -1
- package/dist/lib/comment-realign.js +0 -7
- package/dist/lib/comment-realign.js.map +1 -1
- package/dist/lib/dependencies.d.ts.map +1 -1
- package/dist/lib/dependencies.js +11 -23
- package/dist/lib/dependencies.js.map +1 -1
- package/dist/lib/diff-engine.d.ts +25 -0
- package/dist/lib/diff-engine.d.ts.map +1 -0
- package/dist/lib/diff-engine.js +354 -0
- package/dist/lib/diff-engine.js.map +1 -0
- package/dist/lib/git.d.ts.map +1 -1
- package/dist/lib/git.js +18 -28
- package/dist/lib/git.js.map +1 -1
- package/dist/lib/import.d.ts +37 -117
- package/dist/lib/import.d.ts.map +1 -1
- package/dist/lib/import.js +10 -1039
- package/dist/lib/import.js.map +1 -1
- package/dist/lib/merge.d.ts.map +1 -1
- package/dist/lib/merge.js +29 -117
- package/dist/lib/merge.js.map +1 -1
- package/dist/lib/pdf-comments.d.ts.map +1 -1
- package/dist/lib/pdf-comments.js +1 -13
- package/dist/lib/pdf-comments.js.map +1 -1
- package/dist/lib/pptx-themes.d.ts.map +1 -1
- package/dist/lib/pptx-themes.js +0 -403
- package/dist/lib/pptx-themes.js.map +1 -1
- package/dist/lib/protect-restore.d.ts.map +1 -1
- package/dist/lib/protect-restore.js +34 -36
- package/dist/lib/protect-restore.js.map +1 -1
- package/dist/lib/restore-references.d.ts +35 -0
- package/dist/lib/restore-references.d.ts.map +1 -0
- package/dist/lib/restore-references.js +188 -0
- package/dist/lib/restore-references.js.map +1 -0
- package/dist/lib/slides.d.ts.map +1 -1
- package/dist/lib/slides.js +0 -35
- package/dist/lib/slides.js.map +1 -1
- package/dist/lib/trackchanges.d.ts.map +1 -1
- package/dist/lib/trackchanges.js +1 -11
- package/dist/lib/trackchanges.js.map +1 -1
- package/dist/lib/tui.d.ts +36 -45
- package/dist/lib/tui.d.ts.map +1 -1
- package/dist/lib/tui.js +92 -108
- package/dist/lib/tui.js.map +1 -1
- package/dist/lib/undo.d.ts +3 -4
- package/dist/lib/undo.d.ts.map +1 -1
- package/dist/lib/undo.js +0 -7
- package/dist/lib/undo.js.map +1 -1
- package/dist/lib/utils.d.ts +12 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +26 -0
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/word-extraction.d.ts +77 -0
- package/dist/lib/word-extraction.d.ts.map +1 -0
- package/dist/lib/word-extraction.js +515 -0
- package/dist/lib/word-extraction.js.map +1 -0
- package/dist/lib/wordcomments.d.ts.map +1 -1
- package/dist/lib/wordcomments.js +1 -8
- package/dist/lib/wordcomments.js.map +1 -1
- package/dist/package.json +137 -0
- package/lib/commands/comments.ts +20 -25
- package/lib/commands/context.ts +1 -2
- package/lib/commands/file-ops.ts +372 -0
- package/lib/commands/index.ts +24 -0
- package/lib/commands/merge-resolve.ts +378 -0
- package/lib/commands/preview.ts +178 -0
- package/lib/commands/project-info.ts +244 -0
- package/lib/commands/quality.ts +517 -0
- package/lib/commands/sections.ts +3 -857
- package/lib/commands/sync.ts +536 -0
- package/lib/commands/text-ops.ts +449 -0
- package/lib/commands/utilities.ts +62 -2066
- package/lib/commands/word-tools.ts +340 -0
- package/lib/comment-realign.ts +0 -8
- package/lib/dependencies.ts +12 -20
- package/lib/diff-engine.ts +465 -0
- package/lib/git.ts +24 -31
- package/lib/import.ts +78 -1348
- package/lib/merge.ts +42 -132
- package/lib/pdf-comments.ts +2 -14
- package/lib/pptx-themes.ts +0 -413
- package/lib/protect-restore.ts +48 -44
- package/lib/restore-references.ts +240 -0
- package/lib/slides.ts +0 -37
- package/lib/trackchanges.ts +1 -12
- package/lib/{tui.js → tui.ts} +139 -126
- package/lib/undo.ts +3 -12
- package/lib/utils.ts +28 -0
- package/lib/word-extraction.ts +666 -0
- package/lib/wordcomments.ts +1 -9
- package/package.json +1 -1
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-extraction reference restoration and comment parsing
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { readImageRegistry } from './image-registry.js';
|
|
6
|
+
|
|
7
|
+
// ============================================
|
|
8
|
+
// Type Definitions
|
|
9
|
+
// ============================================
|
|
10
|
+
|
|
11
|
+
export interface RestoreCrossrefResult {
|
|
12
|
+
text: string;
|
|
13
|
+
restored: number;
|
|
14
|
+
messages: string[];
|
|
15
|
+
restoredLabels: Set<string>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RestoreImagesResult {
|
|
19
|
+
text: string;
|
|
20
|
+
restored: number;
|
|
21
|
+
messages: string[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ============================================
|
|
25
|
+
// Functions
|
|
26
|
+
// ============================================
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Parse visible comment markers from Word text
|
|
30
|
+
*/
|
|
31
|
+
export function parseVisibleComments(text: string): Array<{ author: string; text: string; position: number }> {
|
|
32
|
+
const comments: Array<{ author: string; text: string; position: number }> = [];
|
|
33
|
+
const pattern = /\[([^\]:]+):\s*([^\]]+)\]/g;
|
|
34
|
+
|
|
35
|
+
let match;
|
|
36
|
+
while ((match = pattern.exec(text)) !== null) {
|
|
37
|
+
comments.push({
|
|
38
|
+
author: match[1].trim(),
|
|
39
|
+
text: match[2].trim(),
|
|
40
|
+
position: match.index,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return comments;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Convert visible comments to CriticMarkup format
|
|
49
|
+
*/
|
|
50
|
+
export function convertVisibleComments(text: string): string {
|
|
51
|
+
return text.replace(/\[([^\]:]+):\s*([^\]]+)\]/g, '{>>$1: $2<<}');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Restore pandoc-crossref figure/table references from Word-rendered format
|
|
56
|
+
*/
|
|
57
|
+
export function restoreCrossrefFromWord(
|
|
58
|
+
text: string,
|
|
59
|
+
projectDir: string,
|
|
60
|
+
restoredLabels: Set<string> | null = null
|
|
61
|
+
): RestoreCrossrefResult {
|
|
62
|
+
const messages: string[] = [];
|
|
63
|
+
let restored = 0;
|
|
64
|
+
let result = text;
|
|
65
|
+
|
|
66
|
+
const registry = readImageRegistry(projectDir);
|
|
67
|
+
|
|
68
|
+
if (!restoredLabels) {
|
|
69
|
+
restoredLabels = new Set<string>();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Pattern 1: [Figure]{.mark} [N]{.mark}
|
|
73
|
+
result = result.replace(/\[(Figure|Table|Fig\.?)\]\{\.mark\}\s*\[(\d+|S\d+)\]\{\.mark\}/gi, (match, type, num) => {
|
|
74
|
+
const prefix = type.toLowerCase().startsWith('tab') ? 'tbl' : 'fig';
|
|
75
|
+
if (registry) {
|
|
76
|
+
const entry = registry.byNumber?.get(`${prefix}:${num}`);
|
|
77
|
+
if (entry && entry.label) {
|
|
78
|
+
restored++;
|
|
79
|
+
return `@${prefix}:${entry.label}`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
restored++;
|
|
83
|
+
messages.push(`Restored ${type} ${num} (no label found, using placeholder)`);
|
|
84
|
+
return `@${prefix}:fig${num}`;
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Pattern 2: Plain "Figure N" or "Fig. N"
|
|
88
|
+
result = result.replace(/(?<!!)\b(Figure|Fig\.?|Table|Tbl\.?)\s+(\d+|S\d+)\b(?!\s*:)/gi, (match, type, num) => {
|
|
89
|
+
const prefix = type.toLowerCase().startsWith('tab') ? 'tbl' : 'fig';
|
|
90
|
+
if (registry) {
|
|
91
|
+
const entry = registry.byNumber?.get(`${prefix}:${num}`);
|
|
92
|
+
if (entry && entry.label) {
|
|
93
|
+
restored++;
|
|
94
|
+
return `@${prefix}:${entry.label}`;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return match;
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Pattern 3: Remove duplicate plain-text captions
|
|
101
|
+
result = result.replace(/(\!\[[^\]]+\]\([^)]+\)(?:\{[^}]*\})?)\s*\n+\s*(?:Figure|Fig\.?|Table|Tbl\.?)\s+\d+[:\.]?\s*[^\n]+/gi, '$1');
|
|
102
|
+
|
|
103
|
+
// Pattern 4: Clean up image captions that start with "Figure N: "
|
|
104
|
+
result = result.replace(/!\[(Figure|Fig\.?|Table|Tbl\.?)\s+(\d+|S\d+)[:\.]?\s*([^\]]*)\]\(([^)]+)\)(?:\{[^}]*\})?/gi,
|
|
105
|
+
(match, type, num, caption, imgPath) => {
|
|
106
|
+
const prefix = type.toLowerCase().startsWith('tab') ? 'tbl' : 'fig';
|
|
107
|
+
const labelKey = `${prefix}:${num}`;
|
|
108
|
+
|
|
109
|
+
if (registry) {
|
|
110
|
+
const entry = registry.byNumber?.get(labelKey);
|
|
111
|
+
if (entry) {
|
|
112
|
+
if (restoredLabels!.has(labelKey)) {
|
|
113
|
+
messages.push(`Skipped duplicate ${prefix}:${entry.label} (already restored)`);
|
|
114
|
+
return ``;
|
|
115
|
+
}
|
|
116
|
+
restoredLabels!.add(labelKey);
|
|
117
|
+
restored++;
|
|
118
|
+
messages.push(`Restored image ${prefix}:${entry.label} from Figure ${num}`);
|
|
119
|
+
return `{#${prefix}:${entry.label}}`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const cleanCaption = caption.trim();
|
|
123
|
+
return ``;
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
return { text: result, restored, messages, restoredLabels };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Restore proper markdown image syntax from Word-extracted text using image registry
|
|
131
|
+
*/
|
|
132
|
+
export function restoreImagesFromRegistry(
|
|
133
|
+
text: string,
|
|
134
|
+
projectDir: string,
|
|
135
|
+
restoredLabels: Set<string> | null = null
|
|
136
|
+
): RestoreImagesResult {
|
|
137
|
+
const messages: string[] = [];
|
|
138
|
+
let restored = 0;
|
|
139
|
+
|
|
140
|
+
const registry = readImageRegistry(projectDir);
|
|
141
|
+
if (!registry || !registry.figures || registry.figures.length === 0) {
|
|
142
|
+
return { text, restored: 0, messages: ['No image registry found'] };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!restoredLabels) {
|
|
146
|
+
restoredLabels = new Set<string>();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
let result = text;
|
|
150
|
+
|
|
151
|
+
// Pattern 1: Caption-like text
|
|
152
|
+
const captionPatterns = [
|
|
153
|
+
/@(fig|tbl):([a-zA-Z0-9_-]+):\s*([^\n]+)/gi,
|
|
154
|
+
/^(Figure|Fig\.?)\s+(\d+|S\d+)[.:]\s*([^\n]+)/gim,
|
|
155
|
+
/\|\s*@(fig|tbl):([a-zA-Z0-9_-]+):\s*([^|]+)\s*\|/gi,
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
// Fix @fig:label: caption patterns
|
|
159
|
+
result = result.replace(captionPatterns[0], (match, type, label, caption) => {
|
|
160
|
+
const key = `${type}:${label}`;
|
|
161
|
+
const entry = registry.byLabel.get(key);
|
|
162
|
+
if (entry) {
|
|
163
|
+
if (restoredLabels!.has(key)) {
|
|
164
|
+
messages.push(`Skipped duplicate ${key} (already restored)`);
|
|
165
|
+
return ``;
|
|
166
|
+
}
|
|
167
|
+
restoredLabels!.add(key);
|
|
168
|
+
restored++;
|
|
169
|
+
messages.push(`Restored ${type}:${label} from registry`);
|
|
170
|
+
return `{#${type}:${label}}`;
|
|
171
|
+
}
|
|
172
|
+
return match;
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// Fix table-wrapped captions
|
|
176
|
+
result = result.replace(captionPatterns[2], (match, type, label, caption) => {
|
|
177
|
+
const key = `${type}:${label}`;
|
|
178
|
+
const entry = registry.byLabel.get(key);
|
|
179
|
+
if (entry) {
|
|
180
|
+
if (restoredLabels!.has(key)) {
|
|
181
|
+
messages.push(`Skipped duplicate ${key} from table wrapper`);
|
|
182
|
+
return ``;
|
|
183
|
+
}
|
|
184
|
+
restoredLabels!.add(key);
|
|
185
|
+
restored++;
|
|
186
|
+
messages.push(`Restored ${type}:${label} from table wrapper`);
|
|
187
|
+
return `{#${type}:${label}}`;
|
|
188
|
+
}
|
|
189
|
+
return match;
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Clean up empty table structures
|
|
193
|
+
result = result.replace(/\|\s*\|\s*\n\|:--:\|\s*\n/g, '');
|
|
194
|
+
|
|
195
|
+
// Fix "Figure N:" standalone lines
|
|
196
|
+
result = result.replace(captionPatterns[1], (match, prefix, num, caption) => {
|
|
197
|
+
const numKey = `fig:${num}`;
|
|
198
|
+
const entry = registry.byNumber.get(numKey);
|
|
199
|
+
if (entry) {
|
|
200
|
+
const labelKey = `fig:${entry.label}`;
|
|
201
|
+
if (restoredLabels!.has(labelKey)) {
|
|
202
|
+
messages.push(`Skipped duplicate Figure ${num} (already restored)`);
|
|
203
|
+
return ``;
|
|
204
|
+
}
|
|
205
|
+
restoredLabels!.add(labelKey);
|
|
206
|
+
restored++;
|
|
207
|
+
messages.push(`Restored Figure ${num} by number lookup`);
|
|
208
|
+
return `{#fig:${entry.label}}`;
|
|
209
|
+
}
|
|
210
|
+
return match;
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Fix generic media paths by matching caption text
|
|
214
|
+
const genericImagePattern = /!\[([^\]]*)\]\(media\/[^)]+\)/g;
|
|
215
|
+
result = result.replace(genericImagePattern, (match, caption) => {
|
|
216
|
+
if (!caption || caption.trim() === '') {
|
|
217
|
+
return match;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const captionKey = caption.slice(0, 50).toLowerCase().trim();
|
|
221
|
+
const entry = registry.byCaption.get(captionKey);
|
|
222
|
+
if (entry) {
|
|
223
|
+
const labelKey = entry.label ? `${entry.type}:${entry.label}` : null;
|
|
224
|
+
if (labelKey && restoredLabels!.has(labelKey)) {
|
|
225
|
+
messages.push(`Skipped duplicate by caption match: ${captionKey.slice(0, 30)}...`);
|
|
226
|
+
return ``;
|
|
227
|
+
}
|
|
228
|
+
if (labelKey) {
|
|
229
|
+
restoredLabels!.add(labelKey);
|
|
230
|
+
}
|
|
231
|
+
restored++;
|
|
232
|
+
messages.push(`Restored image by caption match: ${captionKey.slice(0, 30)}...`);
|
|
233
|
+
const anchor = (entry.label && !restoredLabels!.has(labelKey!)) ? `{#${entry.type}:${entry.label}}` : '';
|
|
234
|
+
return `${anchor}`;
|
|
235
|
+
}
|
|
236
|
+
return match;
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
return { text: result, restored, messages };
|
|
240
|
+
}
|
package/lib/slides.ts
CHANGED
|
@@ -90,16 +90,6 @@ const BEAMER_BACKGROUNDS: Record<string, string> = {
|
|
|
90
90
|
inverse: '\\setbeamercolor{background canvas}{bg=structure.fg!90!black}\\setbeamercolor{normal text}{fg=white}\\usebeamercolor[fg]{normal text}',
|
|
91
91
|
};
|
|
92
92
|
|
|
93
|
-
/**
|
|
94
|
-
* Special slide types mapped to Beamer frame options
|
|
95
|
-
*/
|
|
96
|
-
const BEAMER_FRAME_OPTIONS: Record<string, string> = {
|
|
97
|
-
cover: 'plain,noframenumbering,c',
|
|
98
|
-
thanks: 'plain,noframenumbering,c',
|
|
99
|
-
section: 'plain,noframenumbering,c',
|
|
100
|
-
plain: 'plain',
|
|
101
|
-
};
|
|
102
|
-
|
|
103
93
|
/**
|
|
104
94
|
* Parse a bullet list into a tree structure
|
|
105
95
|
*/
|
|
@@ -473,33 +463,6 @@ export function parseSlides(markdown: string): Slide[] {
|
|
|
473
463
|
return slides;
|
|
474
464
|
}
|
|
475
465
|
|
|
476
|
-
/**
|
|
477
|
-
* Build Beamer frame options string
|
|
478
|
-
*/
|
|
479
|
-
function buildBeamerFrameOptions(style: SlideStyle | null): string {
|
|
480
|
-
if (!style) return '';
|
|
481
|
-
|
|
482
|
-
const options: string[] = [];
|
|
483
|
-
|
|
484
|
-
// Special slide type options
|
|
485
|
-
if (style.type && BEAMER_FRAME_OPTIONS[style.type]) {
|
|
486
|
-
const opts = BEAMER_FRAME_OPTIONS[style.type];
|
|
487
|
-
if (opts) options.push(...opts.split(','));
|
|
488
|
-
} else {
|
|
489
|
-
// Individual options
|
|
490
|
-
if (style.nonumber) {
|
|
491
|
-
options.push('noframenumbering');
|
|
492
|
-
}
|
|
493
|
-
if (style.center) {
|
|
494
|
-
options.push('c');
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
// Deduplicate
|
|
499
|
-
const unique = [...new Set(options)];
|
|
500
|
-
return unique.length > 0 ? `[${unique.join(',')}]` : '';
|
|
501
|
-
}
|
|
502
|
-
|
|
503
466
|
/**
|
|
504
467
|
* Generate Beamer markdown using pandoc's native slide structure
|
|
505
468
|
* Works WITH pandoc, not against it - pandoc creates frames, we add overlays
|
package/lib/trackchanges.ts
CHANGED
|
@@ -9,6 +9,7 @@ import * as path from 'path';
|
|
|
9
9
|
import { execSync } from 'child_process';
|
|
10
10
|
import AdmZip from 'adm-zip';
|
|
11
11
|
import type { TrackChangeMarker } from './types.js';
|
|
12
|
+
import { escapeXml } from './utils.js';
|
|
12
13
|
|
|
13
14
|
interface PrepareOptions {
|
|
14
15
|
author?: string;
|
|
@@ -29,18 +30,6 @@ interface ApplyResult {
|
|
|
29
30
|
};
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
/**
|
|
33
|
-
* Escape XML special characters
|
|
34
|
-
*/
|
|
35
|
-
function escapeXml(str: string): string {
|
|
36
|
-
return str
|
|
37
|
-
.replace(/&/g, '&')
|
|
38
|
-
.replace(/</g, '<')
|
|
39
|
-
.replace(/>/g, '>')
|
|
40
|
-
.replace(/"/g, '"')
|
|
41
|
-
.replace(/'/g, ''');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
33
|
/**
|
|
45
34
|
* Prepare text with CriticMarkup annotations for track changes
|
|
46
35
|
* Replaces annotations with markers that can be processed in DOCX
|