@eigenpal/docx-editor-agents 0.0.28 → 0.0.30
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/bridge.js +3 -1
- package/dist/bridge.js.map +1 -1
- package/dist/bridge.mjs +8 -0
- package/dist/bridge.mjs.map +1 -0
- package/dist/chunk-5D2V7VK3.js +976 -0
- package/dist/chunk-5D2V7VK3.js.map +1 -0
- package/dist/chunk-5E3CFYZ4.mjs +249 -0
- package/dist/chunk-5E3CFYZ4.mjs.map +1 -0
- package/dist/chunk-GACRQVPW.js +11680 -0
- package/dist/chunk-GACRQVPW.js.map +1 -0
- package/dist/chunk-OFUT6WUQ.mjs +969 -0
- package/dist/chunk-OFUT6WUQ.mjs.map +1 -0
- package/dist/chunk-Q2HHIVUL.js +266 -0
- package/dist/chunk-Q2HHIVUL.js.map +1 -0
- package/dist/chunk-R4MIGZEJ.mjs +11587 -0
- package/dist/chunk-R4MIGZEJ.mjs.map +1 -0
- package/dist/executor-6ZG2VUZS.mjs +3 -0
- package/dist/executor-6ZG2VUZS.mjs.map +1 -0
- package/dist/executor-ZRVQSXRT.js +16 -0
- package/dist/executor-ZRVQSXRT.js.map +1 -0
- package/dist/headless-O2RRWYCB.js +422 -0
- package/dist/headless-O2RRWYCB.js.map +1 -0
- package/dist/headless-UKRSG32U.mjs +5 -0
- package/dist/headless-UKRSG32U.mjs.map +1 -0
- package/dist/index.d.mts +2013 -0
- package/dist/index.d.ts +1776 -1
- package/dist/index.js +26 -19
- package/dist/index.js.map +1 -1
- package/dist/{index.cjs → index.mjs} +23 -26
- package/dist/index.mjs.map +1 -0
- package/dist/processTemplate-7M6KZ6GR.mjs +3 -0
- package/dist/processTemplate-7M6KZ6GR.mjs.map +1 -0
- package/dist/processTemplate-H4X2MH5R.js +54 -0
- package/dist/processTemplate-H4X2MH5R.js.map +1 -0
- package/package.json +11 -9
- package/dist/bridge.cjs +0 -10
- package/dist/bridge.cjs.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -238
- /package/dist/{bridge.d.cts → bridge.d.mts} +0 -0
|
@@ -0,0 +1,976 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// ../core/src/core-plugins/registry.ts
|
|
4
|
+
var PluginRegistry = class {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.plugins = /* @__PURE__ */ new Map();
|
|
7
|
+
this.commandHandlers = /* @__PURE__ */ new Map();
|
|
8
|
+
this.eventListeners = /* @__PURE__ */ new Set();
|
|
9
|
+
this.initialized = /* @__PURE__ */ new Set();
|
|
10
|
+
}
|
|
11
|
+
// ==========================================================================
|
|
12
|
+
// REGISTRATION
|
|
13
|
+
// ==========================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Register a plugin
|
|
16
|
+
*
|
|
17
|
+
* @param plugin - The plugin to register
|
|
18
|
+
* @param options - Optional configuration
|
|
19
|
+
* @returns Registration result
|
|
20
|
+
*/
|
|
21
|
+
register(plugin, options) {
|
|
22
|
+
const warnings = [];
|
|
23
|
+
if (!plugin.id) {
|
|
24
|
+
return { success: false, error: "Plugin must have an id" };
|
|
25
|
+
}
|
|
26
|
+
if (this.plugins.has(plugin.id)) {
|
|
27
|
+
return { success: false, error: `Plugin '${plugin.id}' is already registered` };
|
|
28
|
+
}
|
|
29
|
+
if (plugin.dependencies) {
|
|
30
|
+
for (const depId of plugin.dependencies) {
|
|
31
|
+
if (!this.plugins.has(depId)) {
|
|
32
|
+
return {
|
|
33
|
+
success: false,
|
|
34
|
+
error: `Plugin '${plugin.id}' requires '${depId}' which is not registered`
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (plugin.commandHandlers) {
|
|
40
|
+
for (const [commandType, handler] of Object.entries(plugin.commandHandlers)) {
|
|
41
|
+
if (this.commandHandlers.has(commandType)) {
|
|
42
|
+
const existing = this.commandHandlers.get(commandType);
|
|
43
|
+
warnings.push(
|
|
44
|
+
`Command '${commandType}' from '${plugin.id}' overrides handler from '${existing.pluginId}'`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
this.commandHandlers.set(commandType, { pluginId: plugin.id, handler });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
this.plugins.set(plugin.id, plugin);
|
|
51
|
+
if (plugin.initialize && !this.initialized.has(plugin.id)) {
|
|
52
|
+
try {
|
|
53
|
+
const result = plugin.initialize();
|
|
54
|
+
if (result instanceof Promise) {
|
|
55
|
+
result.then(() => {
|
|
56
|
+
this.initialized.add(plugin.id);
|
|
57
|
+
}).catch((err) => {
|
|
58
|
+
this.emit({ type: "error", pluginId: plugin.id, error: err });
|
|
59
|
+
});
|
|
60
|
+
} else {
|
|
61
|
+
this.initialized.add(plugin.id);
|
|
62
|
+
}
|
|
63
|
+
} catch (err) {
|
|
64
|
+
this.emit({ type: "error", pluginId: plugin.id, error: err });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (options?.debug) {
|
|
68
|
+
console.log(`[PluginRegistry] Registered plugin: ${plugin.id}`);
|
|
69
|
+
}
|
|
70
|
+
this.emit({ type: "registered", plugin });
|
|
71
|
+
return {
|
|
72
|
+
success: true,
|
|
73
|
+
plugin,
|
|
74
|
+
warnings: warnings.length > 0 ? warnings : void 0
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Unregister a plugin
|
|
79
|
+
*
|
|
80
|
+
* @param pluginId - ID of the plugin to unregister
|
|
81
|
+
* @returns Whether unregistration succeeded
|
|
82
|
+
*/
|
|
83
|
+
unregister(pluginId) {
|
|
84
|
+
const plugin = this.plugins.get(pluginId);
|
|
85
|
+
if (!plugin) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
for (const [id, p] of this.plugins) {
|
|
89
|
+
if (p.dependencies?.includes(pluginId)) {
|
|
90
|
+
console.warn(`Cannot unregister '${pluginId}': '${id}' depends on it`);
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
for (const [commandType, { pluginId: pid }] of this.commandHandlers) {
|
|
95
|
+
if (pid === pluginId) {
|
|
96
|
+
this.commandHandlers.delete(commandType);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (plugin.destroy) {
|
|
100
|
+
try {
|
|
101
|
+
const result = plugin.destroy();
|
|
102
|
+
if (result instanceof Promise) {
|
|
103
|
+
result.catch((err) => {
|
|
104
|
+
this.emit({ type: "error", pluginId, error: err });
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
} catch (err) {
|
|
108
|
+
this.emit({ type: "error", pluginId, error: err });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
this.plugins.delete(pluginId);
|
|
112
|
+
this.initialized.delete(pluginId);
|
|
113
|
+
this.emit({ type: "unregistered", pluginId });
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
// ==========================================================================
|
|
117
|
+
// QUERIES
|
|
118
|
+
// ==========================================================================
|
|
119
|
+
/**
|
|
120
|
+
* Get a registered plugin by ID
|
|
121
|
+
*
|
|
122
|
+
* @param id - Plugin ID
|
|
123
|
+
* @returns The plugin or undefined
|
|
124
|
+
*/
|
|
125
|
+
get(id) {
|
|
126
|
+
return this.plugins.get(id);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get all registered plugins
|
|
130
|
+
*
|
|
131
|
+
* @returns Array of all plugins
|
|
132
|
+
*/
|
|
133
|
+
getAll() {
|
|
134
|
+
return Array.from(this.plugins.values());
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check if a plugin is registered
|
|
138
|
+
*
|
|
139
|
+
* @param id - Plugin ID
|
|
140
|
+
* @returns Whether the plugin is registered
|
|
141
|
+
*/
|
|
142
|
+
has(id) {
|
|
143
|
+
return this.plugins.has(id);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get number of registered plugins
|
|
147
|
+
*/
|
|
148
|
+
get size() {
|
|
149
|
+
return this.plugins.size;
|
|
150
|
+
}
|
|
151
|
+
// ==========================================================================
|
|
152
|
+
// COMMAND HANDLERS
|
|
153
|
+
// ==========================================================================
|
|
154
|
+
/**
|
|
155
|
+
* Get a command handler for a command type
|
|
156
|
+
*
|
|
157
|
+
* @param commandType - The command type
|
|
158
|
+
* @returns The handler or undefined
|
|
159
|
+
*/
|
|
160
|
+
getCommandHandler(commandType) {
|
|
161
|
+
const entry = this.commandHandlers.get(commandType);
|
|
162
|
+
return entry?.handler;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get all registered command types
|
|
166
|
+
*
|
|
167
|
+
* @returns Array of command type strings
|
|
168
|
+
*/
|
|
169
|
+
getCommandTypes() {
|
|
170
|
+
return Array.from(this.commandHandlers.keys());
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Check if a command type has a handler
|
|
174
|
+
*
|
|
175
|
+
* @param commandType - The command type
|
|
176
|
+
* @returns Whether a handler exists
|
|
177
|
+
*/
|
|
178
|
+
hasCommandHandler(commandType) {
|
|
179
|
+
return this.commandHandlers.has(commandType);
|
|
180
|
+
}
|
|
181
|
+
// ==========================================================================
|
|
182
|
+
// MCP TOOLS
|
|
183
|
+
// ==========================================================================
|
|
184
|
+
/**
|
|
185
|
+
* Get all MCP tools from all registered plugins
|
|
186
|
+
*
|
|
187
|
+
* @returns Array of MCP tool definitions
|
|
188
|
+
*/
|
|
189
|
+
getMcpTools() {
|
|
190
|
+
const tools = [];
|
|
191
|
+
for (const plugin of this.plugins.values()) {
|
|
192
|
+
if (plugin.mcpTools) {
|
|
193
|
+
tools.push(...plugin.mcpTools);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return tools;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Get MCP tools from a specific plugin
|
|
200
|
+
*
|
|
201
|
+
* @param pluginId - Plugin ID
|
|
202
|
+
* @returns Array of MCP tool definitions
|
|
203
|
+
*/
|
|
204
|
+
getMcpToolsForPlugin(pluginId) {
|
|
205
|
+
const plugin = this.plugins.get(pluginId);
|
|
206
|
+
return plugin?.mcpTools || [];
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Get an MCP tool by name
|
|
210
|
+
*
|
|
211
|
+
* @param toolName - Tool name
|
|
212
|
+
* @returns The tool definition or undefined
|
|
213
|
+
*/
|
|
214
|
+
getMcpTool(toolName) {
|
|
215
|
+
for (const plugin of this.plugins.values()) {
|
|
216
|
+
if (plugin.mcpTools) {
|
|
217
|
+
const tool = plugin.mcpTools.find((t) => t.name === toolName);
|
|
218
|
+
if (tool) return tool;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return void 0;
|
|
222
|
+
}
|
|
223
|
+
// ==========================================================================
|
|
224
|
+
// EVENTS
|
|
225
|
+
// ==========================================================================
|
|
226
|
+
/**
|
|
227
|
+
* Add an event listener
|
|
228
|
+
*
|
|
229
|
+
* @param listener - Event listener function
|
|
230
|
+
*/
|
|
231
|
+
addEventListener(listener) {
|
|
232
|
+
this.eventListeners.add(listener);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Remove an event listener
|
|
236
|
+
*
|
|
237
|
+
* @param listener - Event listener function
|
|
238
|
+
*/
|
|
239
|
+
removeEventListener(listener) {
|
|
240
|
+
this.eventListeners.delete(listener);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Emit an event to all listeners
|
|
244
|
+
*/
|
|
245
|
+
emit(event) {
|
|
246
|
+
for (const listener of this.eventListeners) {
|
|
247
|
+
try {
|
|
248
|
+
listener(event);
|
|
249
|
+
} catch (err) {
|
|
250
|
+
console.error("[PluginRegistry] Event listener error:", err);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// ==========================================================================
|
|
255
|
+
// UTILITIES
|
|
256
|
+
// ==========================================================================
|
|
257
|
+
/**
|
|
258
|
+
* Clear all registered plugins
|
|
259
|
+
*
|
|
260
|
+
* Useful for testing or resetting state.
|
|
261
|
+
*/
|
|
262
|
+
clear() {
|
|
263
|
+
for (const plugin of this.plugins.values()) {
|
|
264
|
+
if (plugin.destroy) {
|
|
265
|
+
try {
|
|
266
|
+
plugin.destroy();
|
|
267
|
+
} catch {
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
this.plugins.clear();
|
|
272
|
+
this.commandHandlers.clear();
|
|
273
|
+
this.initialized.clear();
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Get registry state for debugging
|
|
277
|
+
*/
|
|
278
|
+
getDebugInfo() {
|
|
279
|
+
return {
|
|
280
|
+
plugins: Array.from(this.plugins.keys()),
|
|
281
|
+
commandTypes: Array.from(this.commandHandlers.keys()),
|
|
282
|
+
mcpTools: this.getMcpTools().map((t) => t.name),
|
|
283
|
+
initialized: Array.from(this.initialized)
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
var pluginRegistry = new PluginRegistry();
|
|
288
|
+
function registerPlugins(plugins, options) {
|
|
289
|
+
return plugins.map((plugin) => pluginRegistry.register(plugin, options));
|
|
290
|
+
}
|
|
291
|
+
function createPluginRegistrar(options) {
|
|
292
|
+
return (plugin) => pluginRegistry.register(plugin, options);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// ../core/src/agent/executor.ts
|
|
296
|
+
function executeCommand(doc, command) {
|
|
297
|
+
const pluginHandler = pluginRegistry.getCommandHandler(command.type);
|
|
298
|
+
if (pluginHandler) {
|
|
299
|
+
return pluginHandler(doc, command);
|
|
300
|
+
}
|
|
301
|
+
switch (command.type) {
|
|
302
|
+
case "insertText":
|
|
303
|
+
return executeInsertText(doc, command);
|
|
304
|
+
case "replaceText":
|
|
305
|
+
return executeReplaceText(doc, command);
|
|
306
|
+
case "deleteText":
|
|
307
|
+
return executeDeleteText(doc, command);
|
|
308
|
+
case "formatText":
|
|
309
|
+
return executeFormatText(doc, command);
|
|
310
|
+
case "formatParagraph":
|
|
311
|
+
return executeFormatParagraph(doc, command);
|
|
312
|
+
case "applyStyle":
|
|
313
|
+
return executeApplyStyle(doc, command);
|
|
314
|
+
case "insertTable":
|
|
315
|
+
return executeInsertTable(doc, command);
|
|
316
|
+
case "insertImage":
|
|
317
|
+
return executeInsertImage(doc, command);
|
|
318
|
+
case "insertHyperlink":
|
|
319
|
+
return executeInsertHyperlink(doc, command);
|
|
320
|
+
case "removeHyperlink":
|
|
321
|
+
return executeRemoveHyperlink(doc, command);
|
|
322
|
+
case "insertParagraphBreak":
|
|
323
|
+
return executeInsertParagraphBreak(doc, command);
|
|
324
|
+
case "mergeParagraphs":
|
|
325
|
+
return executeMergeParagraphs(doc, command);
|
|
326
|
+
case "splitParagraph":
|
|
327
|
+
return executeSplitParagraph(doc, command);
|
|
328
|
+
case "setVariable":
|
|
329
|
+
return executeSetVariable(doc, command);
|
|
330
|
+
case "applyVariables":
|
|
331
|
+
return executeApplyVariables(doc, command);
|
|
332
|
+
default:
|
|
333
|
+
const _exhaustive = command;
|
|
334
|
+
throw new Error(`Unknown command type: ${_exhaustive.type}`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
function executeCommands(doc, commands) {
|
|
338
|
+
return commands.reduce((currentDoc, command) => executeCommand(currentDoc, command), doc);
|
|
339
|
+
}
|
|
340
|
+
function cloneDocument(doc) {
|
|
341
|
+
return JSON.parse(JSON.stringify(doc));
|
|
342
|
+
}
|
|
343
|
+
function getBlockIndexForParagraph(body, paragraphIndex) {
|
|
344
|
+
let currentParagraphIndex = 0;
|
|
345
|
+
for (let i = 0; i < body.content.length; i++) {
|
|
346
|
+
if (body.content[i].type === "paragraph") {
|
|
347
|
+
if (currentParagraphIndex === paragraphIndex) {
|
|
348
|
+
return i;
|
|
349
|
+
}
|
|
350
|
+
currentParagraphIndex++;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return -1;
|
|
354
|
+
}
|
|
355
|
+
function getParagraphText(paragraph) {
|
|
356
|
+
let text = "";
|
|
357
|
+
for (const item of paragraph.content) {
|
|
358
|
+
if (item.type === "run") {
|
|
359
|
+
for (const content of item.content) {
|
|
360
|
+
if (content.type === "text") {
|
|
361
|
+
text += content.text;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
} else if (item.type === "hyperlink") {
|
|
365
|
+
for (const child of item.children) {
|
|
366
|
+
if (child.type === "run") {
|
|
367
|
+
for (const content of child.content) {
|
|
368
|
+
if (content.type === "text") {
|
|
369
|
+
text += content.text;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return text;
|
|
377
|
+
}
|
|
378
|
+
function createTextRun(text, formatting) {
|
|
379
|
+
return {
|
|
380
|
+
type: "run",
|
|
381
|
+
formatting,
|
|
382
|
+
content: [
|
|
383
|
+
{
|
|
384
|
+
type: "text",
|
|
385
|
+
text
|
|
386
|
+
}
|
|
387
|
+
]
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
function insertTextAtOffset(paragraph, offset, text, formatting) {
|
|
391
|
+
const newContent = [];
|
|
392
|
+
let currentOffset = 0;
|
|
393
|
+
let inserted = false;
|
|
394
|
+
for (const item of paragraph.content) {
|
|
395
|
+
if (item.type === "run") {
|
|
396
|
+
const runText = item.content.filter((c) => c.type === "text").map((c) => c.text).join("");
|
|
397
|
+
const runStart = currentOffset;
|
|
398
|
+
const runEnd = currentOffset + runText.length;
|
|
399
|
+
if (!inserted && offset >= runStart && offset <= runEnd) {
|
|
400
|
+
const insertPos = offset - runStart;
|
|
401
|
+
if (insertPos > 0) {
|
|
402
|
+
newContent.push({
|
|
403
|
+
...item,
|
|
404
|
+
content: [{ type: "text", text: runText.slice(0, insertPos) }]
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
newContent.push(createTextRun(text, formatting || item.formatting));
|
|
408
|
+
if (insertPos < runText.length) {
|
|
409
|
+
newContent.push({
|
|
410
|
+
...item,
|
|
411
|
+
content: [{ type: "text", text: runText.slice(insertPos) }]
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
inserted = true;
|
|
415
|
+
} else {
|
|
416
|
+
newContent.push(item);
|
|
417
|
+
}
|
|
418
|
+
currentOffset = runEnd;
|
|
419
|
+
} else {
|
|
420
|
+
newContent.push(item);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
if (!inserted) {
|
|
424
|
+
newContent.push(createTextRun(text, formatting));
|
|
425
|
+
}
|
|
426
|
+
return newContent;
|
|
427
|
+
}
|
|
428
|
+
function deleteTextInParagraph(paragraph, startOffset, endOffset) {
|
|
429
|
+
const newContent = [];
|
|
430
|
+
let currentOffset = 0;
|
|
431
|
+
for (const item of paragraph.content) {
|
|
432
|
+
if (item.type === "run") {
|
|
433
|
+
const runText = item.content.filter((c) => c.type === "text").map((c) => c.text).join("");
|
|
434
|
+
const runStart = currentOffset;
|
|
435
|
+
const runEnd = currentOffset + runText.length;
|
|
436
|
+
if (runEnd <= startOffset || runStart >= endOffset) {
|
|
437
|
+
newContent.push(item);
|
|
438
|
+
} else {
|
|
439
|
+
let newText = "";
|
|
440
|
+
if (runStart < startOffset) {
|
|
441
|
+
newText += runText.slice(0, startOffset - runStart);
|
|
442
|
+
}
|
|
443
|
+
if (runEnd > endOffset) {
|
|
444
|
+
newText += runText.slice(endOffset - runStart);
|
|
445
|
+
}
|
|
446
|
+
if (newText.length > 0) {
|
|
447
|
+
newContent.push({
|
|
448
|
+
...item,
|
|
449
|
+
content: [{ type: "text", text: newText }]
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
currentOffset = runEnd;
|
|
454
|
+
} else {
|
|
455
|
+
newContent.push(item);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
return newContent;
|
|
459
|
+
}
|
|
460
|
+
function applyFormattingInParagraph(paragraph, startOffset, endOffset, formatting) {
|
|
461
|
+
const newContent = [];
|
|
462
|
+
let currentOffset = 0;
|
|
463
|
+
for (const item of paragraph.content) {
|
|
464
|
+
if (item.type === "run") {
|
|
465
|
+
const runText = item.content.filter((c) => c.type === "text").map((c) => c.text).join("");
|
|
466
|
+
const runStart = currentOffset;
|
|
467
|
+
const runEnd = currentOffset + runText.length;
|
|
468
|
+
if (runEnd <= startOffset || runStart >= endOffset) {
|
|
469
|
+
newContent.push(item);
|
|
470
|
+
} else if (runStart >= startOffset && runEnd <= endOffset) {
|
|
471
|
+
newContent.push({
|
|
472
|
+
...item,
|
|
473
|
+
formatting: { ...item.formatting, ...formatting }
|
|
474
|
+
});
|
|
475
|
+
} else {
|
|
476
|
+
const overlapStart = Math.max(startOffset, runStart);
|
|
477
|
+
const overlapEnd = Math.min(endOffset, runEnd);
|
|
478
|
+
if (runStart < overlapStart) {
|
|
479
|
+
newContent.push({
|
|
480
|
+
...item,
|
|
481
|
+
content: [{ type: "text", text: runText.slice(0, overlapStart - runStart) }]
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
newContent.push({
|
|
485
|
+
...item,
|
|
486
|
+
formatting: { ...item.formatting, ...formatting },
|
|
487
|
+
content: [
|
|
488
|
+
{
|
|
489
|
+
type: "text",
|
|
490
|
+
text: runText.slice(overlapStart - runStart, overlapEnd - runStart)
|
|
491
|
+
}
|
|
492
|
+
]
|
|
493
|
+
});
|
|
494
|
+
if (runEnd > overlapEnd) {
|
|
495
|
+
newContent.push({
|
|
496
|
+
...item,
|
|
497
|
+
content: [{ type: "text", text: runText.slice(overlapEnd - runStart) }]
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
currentOffset = runEnd;
|
|
502
|
+
} else {
|
|
503
|
+
newContent.push(item);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return newContent;
|
|
507
|
+
}
|
|
508
|
+
function executeInsertText(doc, command) {
|
|
509
|
+
const newDoc = cloneDocument(doc);
|
|
510
|
+
const body = newDoc.package.document;
|
|
511
|
+
const blockIndex = getBlockIndexForParagraph(body, command.position.paragraphIndex);
|
|
512
|
+
if (blockIndex === -1) {
|
|
513
|
+
throw new Error(`Paragraph index ${command.position.paragraphIndex} not found`);
|
|
514
|
+
}
|
|
515
|
+
const paragraph = body.content[blockIndex];
|
|
516
|
+
paragraph.content = insertTextAtOffset(
|
|
517
|
+
paragraph,
|
|
518
|
+
command.position.offset,
|
|
519
|
+
command.text,
|
|
520
|
+
command.formatting
|
|
521
|
+
);
|
|
522
|
+
return newDoc;
|
|
523
|
+
}
|
|
524
|
+
function executeReplaceText(doc, command) {
|
|
525
|
+
const newDoc = cloneDocument(doc);
|
|
526
|
+
const body = newDoc.package.document;
|
|
527
|
+
const { start, end } = command.range;
|
|
528
|
+
if (start.paragraphIndex === end.paragraphIndex) {
|
|
529
|
+
const blockIndex = getBlockIndexForParagraph(body, start.paragraphIndex);
|
|
530
|
+
if (blockIndex === -1) {
|
|
531
|
+
throw new Error(`Paragraph index ${start.paragraphIndex} not found`);
|
|
532
|
+
}
|
|
533
|
+
const paragraph = body.content[blockIndex];
|
|
534
|
+
paragraph.content = deleteTextInParagraph(paragraph, start.offset, end.offset);
|
|
535
|
+
paragraph.content = insertTextAtOffset(
|
|
536
|
+
paragraph,
|
|
537
|
+
start.offset,
|
|
538
|
+
command.text,
|
|
539
|
+
command.formatting
|
|
540
|
+
);
|
|
541
|
+
} else {
|
|
542
|
+
const startBlockIndex = getBlockIndexForParagraph(body, start.paragraphIndex);
|
|
543
|
+
const startParagraph = body.content[startBlockIndex];
|
|
544
|
+
const startText = getParagraphText(startParagraph);
|
|
545
|
+
startParagraph.content = deleteTextInParagraph(startParagraph, start.offset, startText.length);
|
|
546
|
+
startParagraph.content = insertTextAtOffset(
|
|
547
|
+
startParagraph,
|
|
548
|
+
start.offset,
|
|
549
|
+
command.text,
|
|
550
|
+
command.formatting
|
|
551
|
+
);
|
|
552
|
+
const paragraphsToRemove = [];
|
|
553
|
+
for (let i = start.paragraphIndex + 1; i <= end.paragraphIndex; i++) {
|
|
554
|
+
paragraphsToRemove.push(getBlockIndexForParagraph(body, i));
|
|
555
|
+
}
|
|
556
|
+
for (let i = paragraphsToRemove.length - 1; i >= 0; i--) {
|
|
557
|
+
if (paragraphsToRemove[i] !== -1) {
|
|
558
|
+
body.content.splice(paragraphsToRemove[i], 1);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return newDoc;
|
|
563
|
+
}
|
|
564
|
+
function executeDeleteText(doc, command) {
|
|
565
|
+
const newDoc = cloneDocument(doc);
|
|
566
|
+
const body = newDoc.package.document;
|
|
567
|
+
const { start, end } = command.range;
|
|
568
|
+
if (start.paragraphIndex === end.paragraphIndex) {
|
|
569
|
+
const blockIndex = getBlockIndexForParagraph(body, start.paragraphIndex);
|
|
570
|
+
if (blockIndex === -1) {
|
|
571
|
+
throw new Error(`Paragraph index ${start.paragraphIndex} not found`);
|
|
572
|
+
}
|
|
573
|
+
const paragraph = body.content[blockIndex];
|
|
574
|
+
paragraph.content = deleteTextInParagraph(paragraph, start.offset, end.offset);
|
|
575
|
+
} else {
|
|
576
|
+
const startBlockIndex = getBlockIndexForParagraph(body, start.paragraphIndex);
|
|
577
|
+
const startParagraph = body.content[startBlockIndex];
|
|
578
|
+
const startText = getParagraphText(startParagraph);
|
|
579
|
+
startParagraph.content = deleteTextInParagraph(startParagraph, start.offset, startText.length);
|
|
580
|
+
const endBlockIndex = getBlockIndexForParagraph(body, end.paragraphIndex);
|
|
581
|
+
const endParagraph = body.content[endBlockIndex];
|
|
582
|
+
endParagraph.content = deleteTextInParagraph(endParagraph, 0, end.offset);
|
|
583
|
+
startParagraph.content.push(...endParagraph.content);
|
|
584
|
+
const indicesToRemove = [];
|
|
585
|
+
for (let i = start.paragraphIndex + 1; i <= end.paragraphIndex; i++) {
|
|
586
|
+
indicesToRemove.push(getBlockIndexForParagraph(body, i));
|
|
587
|
+
}
|
|
588
|
+
for (let i = indicesToRemove.length - 1; i >= 0; i--) {
|
|
589
|
+
if (indicesToRemove[i] !== -1) {
|
|
590
|
+
body.content.splice(indicesToRemove[i], 1);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
return newDoc;
|
|
595
|
+
}
|
|
596
|
+
function executeFormatText(doc, command) {
|
|
597
|
+
const newDoc = cloneDocument(doc);
|
|
598
|
+
const body = newDoc.package.document;
|
|
599
|
+
const { start, end } = command.range;
|
|
600
|
+
if (start.paragraphIndex === end.paragraphIndex) {
|
|
601
|
+
const blockIndex = getBlockIndexForParagraph(body, start.paragraphIndex);
|
|
602
|
+
if (blockIndex === -1) {
|
|
603
|
+
throw new Error(`Paragraph index ${start.paragraphIndex} not found`);
|
|
604
|
+
}
|
|
605
|
+
const paragraph = body.content[blockIndex];
|
|
606
|
+
paragraph.content = applyFormattingInParagraph(
|
|
607
|
+
paragraph,
|
|
608
|
+
start.offset,
|
|
609
|
+
end.offset,
|
|
610
|
+
command.formatting
|
|
611
|
+
);
|
|
612
|
+
} else {
|
|
613
|
+
for (let i = start.paragraphIndex; i <= end.paragraphIndex; i++) {
|
|
614
|
+
const blockIndex = getBlockIndexForParagraph(body, i);
|
|
615
|
+
if (blockIndex === -1) continue;
|
|
616
|
+
const paragraph = body.content[blockIndex];
|
|
617
|
+
const paragraphText = getParagraphText(paragraph);
|
|
618
|
+
let startOffset = 0;
|
|
619
|
+
let endOffset = paragraphText.length;
|
|
620
|
+
if (i === start.paragraphIndex) {
|
|
621
|
+
startOffset = start.offset;
|
|
622
|
+
}
|
|
623
|
+
if (i === end.paragraphIndex) {
|
|
624
|
+
endOffset = end.offset;
|
|
625
|
+
}
|
|
626
|
+
paragraph.content = applyFormattingInParagraph(
|
|
627
|
+
paragraph,
|
|
628
|
+
startOffset,
|
|
629
|
+
endOffset,
|
|
630
|
+
command.formatting
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return newDoc;
|
|
635
|
+
}
|
|
636
|
+
function executeFormatParagraph(doc, command) {
|
|
637
|
+
const newDoc = cloneDocument(doc);
|
|
638
|
+
const body = newDoc.package.document;
|
|
639
|
+
const blockIndex = getBlockIndexForParagraph(body, command.paragraphIndex);
|
|
640
|
+
if (blockIndex === -1) {
|
|
641
|
+
throw new Error(`Paragraph index ${command.paragraphIndex} not found`);
|
|
642
|
+
}
|
|
643
|
+
const paragraph = body.content[blockIndex];
|
|
644
|
+
paragraph.formatting = { ...paragraph.formatting, ...command.formatting };
|
|
645
|
+
if ("numPr" in command.formatting) {
|
|
646
|
+
const numPr = command.formatting.numPr;
|
|
647
|
+
if (numPr && numPr.numId !== void 0 && numPr.numId !== 0) {
|
|
648
|
+
const ilvl = numPr.ilvl ?? 0;
|
|
649
|
+
const isBullet = numPr.numId === 1;
|
|
650
|
+
let marker = isBullet ? "\u2022" : `${1}.`;
|
|
651
|
+
if (newDoc.package.numbering) {
|
|
652
|
+
const num = newDoc.package.numbering.nums.find((n) => n.numId === numPr.numId);
|
|
653
|
+
if (num) {
|
|
654
|
+
const abstractNum = newDoc.package.numbering.abstractNums.find(
|
|
655
|
+
(a) => a.abstractNumId === num.abstractNumId
|
|
656
|
+
);
|
|
657
|
+
if (abstractNum) {
|
|
658
|
+
const level = abstractNum.levels.find((l) => l.ilvl === ilvl);
|
|
659
|
+
if (level) {
|
|
660
|
+
marker = level.lvlText || marker;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
paragraph.listRendering = {
|
|
666
|
+
level: ilvl,
|
|
667
|
+
numId: numPr.numId,
|
|
668
|
+
marker,
|
|
669
|
+
isBullet
|
|
670
|
+
};
|
|
671
|
+
} else {
|
|
672
|
+
delete paragraph.listRendering;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
return newDoc;
|
|
676
|
+
}
|
|
677
|
+
function executeApplyStyle(doc, command) {
|
|
678
|
+
const newDoc = cloneDocument(doc);
|
|
679
|
+
const body = newDoc.package.document;
|
|
680
|
+
const blockIndex = getBlockIndexForParagraph(body, command.paragraphIndex);
|
|
681
|
+
if (blockIndex === -1) {
|
|
682
|
+
throw new Error(`Paragraph index ${command.paragraphIndex} not found`);
|
|
683
|
+
}
|
|
684
|
+
const paragraph = body.content[blockIndex];
|
|
685
|
+
paragraph.formatting = {
|
|
686
|
+
...paragraph.formatting,
|
|
687
|
+
styleId: command.styleId
|
|
688
|
+
};
|
|
689
|
+
return newDoc;
|
|
690
|
+
}
|
|
691
|
+
function executeInsertTable(doc, command) {
|
|
692
|
+
const newDoc = cloneDocument(doc);
|
|
693
|
+
const body = newDoc.package.document;
|
|
694
|
+
const rows = [];
|
|
695
|
+
for (let r = 0; r < command.rows; r++) {
|
|
696
|
+
const cells = [];
|
|
697
|
+
for (let c = 0; c < command.columns; c++) {
|
|
698
|
+
const cellText = command.data?.[r]?.[c] || "";
|
|
699
|
+
cells.push({
|
|
700
|
+
type: "tableCell",
|
|
701
|
+
content: [
|
|
702
|
+
{
|
|
703
|
+
type: "paragraph",
|
|
704
|
+
content: cellText ? [createTextRun(cellText)] : []
|
|
705
|
+
}
|
|
706
|
+
]
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
rows.push({
|
|
710
|
+
type: "tableRow",
|
|
711
|
+
formatting: r === 0 && command.hasHeader ? { header: true } : void 0,
|
|
712
|
+
cells
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
const table = {
|
|
716
|
+
type: "table",
|
|
717
|
+
rows
|
|
718
|
+
};
|
|
719
|
+
const blockIndex = getBlockIndexForParagraph(body, command.position.paragraphIndex);
|
|
720
|
+
if (blockIndex === -1) {
|
|
721
|
+
body.content.push(table);
|
|
722
|
+
} else {
|
|
723
|
+
body.content.splice(blockIndex + 1, 0, table);
|
|
724
|
+
}
|
|
725
|
+
return newDoc;
|
|
726
|
+
}
|
|
727
|
+
function executeInsertImage(doc, command) {
|
|
728
|
+
const newDoc = cloneDocument(doc);
|
|
729
|
+
const body = newDoc.package.document;
|
|
730
|
+
const blockIndex = getBlockIndexForParagraph(body, command.position.paragraphIndex);
|
|
731
|
+
if (blockIndex === -1) {
|
|
732
|
+
throw new Error(`Paragraph index ${command.position.paragraphIndex} not found`);
|
|
733
|
+
}
|
|
734
|
+
const paragraph = body.content[blockIndex];
|
|
735
|
+
const image = {
|
|
736
|
+
type: "image",
|
|
737
|
+
rId: `rId_img_${Date.now()}`,
|
|
738
|
+
src: command.src,
|
|
739
|
+
alt: command.alt,
|
|
740
|
+
size: {
|
|
741
|
+
width: (command.width || 100) * 914400,
|
|
742
|
+
// Convert pixels to EMU
|
|
743
|
+
height: (command.height || 100) * 914400
|
|
744
|
+
},
|
|
745
|
+
wrap: { type: "inline" }
|
|
746
|
+
};
|
|
747
|
+
const imageRun = {
|
|
748
|
+
type: "run",
|
|
749
|
+
content: [
|
|
750
|
+
{
|
|
751
|
+
type: "drawing",
|
|
752
|
+
image
|
|
753
|
+
}
|
|
754
|
+
]
|
|
755
|
+
};
|
|
756
|
+
const newContent = insertTextAtOffset(paragraph, command.position.offset, "", void 0);
|
|
757
|
+
let inserted = false;
|
|
758
|
+
let currentOffset = 0;
|
|
759
|
+
for (let i = 0; i < newContent.length; i++) {
|
|
760
|
+
const item = newContent[i];
|
|
761
|
+
if (item.type === "run") {
|
|
762
|
+
const runText = item.content.filter((c) => c.type === "text").map((c) => c.text).join("");
|
|
763
|
+
currentOffset += runText.length;
|
|
764
|
+
if (!inserted && currentOffset >= command.position.offset) {
|
|
765
|
+
newContent.splice(i + 1, 0, imageRun);
|
|
766
|
+
inserted = true;
|
|
767
|
+
break;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
if (!inserted) {
|
|
772
|
+
newContent.push(imageRun);
|
|
773
|
+
}
|
|
774
|
+
paragraph.content = newContent;
|
|
775
|
+
return newDoc;
|
|
776
|
+
}
|
|
777
|
+
function executeInsertHyperlink(doc, command) {
|
|
778
|
+
const newDoc = cloneDocument(doc);
|
|
779
|
+
const body = newDoc.package.document;
|
|
780
|
+
const { start, end } = command.range;
|
|
781
|
+
if (start.paragraphIndex !== end.paragraphIndex) {
|
|
782
|
+
throw new Error("Hyperlinks cannot span multiple paragraphs");
|
|
783
|
+
}
|
|
784
|
+
const blockIndex = getBlockIndexForParagraph(body, start.paragraphIndex);
|
|
785
|
+
if (blockIndex === -1) {
|
|
786
|
+
throw new Error(`Paragraph index ${start.paragraphIndex} not found`);
|
|
787
|
+
}
|
|
788
|
+
const paragraph = body.content[blockIndex];
|
|
789
|
+
const paragraphText = getParagraphText(paragraph);
|
|
790
|
+
const linkText = command.displayText || paragraphText.slice(start.offset, end.offset);
|
|
791
|
+
paragraph.content = deleteTextInParagraph(paragraph, start.offset, end.offset);
|
|
792
|
+
const hyperlink = {
|
|
793
|
+
type: "hyperlink",
|
|
794
|
+
href: command.url,
|
|
795
|
+
tooltip: command.tooltip,
|
|
796
|
+
children: [createTextRun(linkText)]
|
|
797
|
+
};
|
|
798
|
+
let inserted = false;
|
|
799
|
+
let currentOffset = 0;
|
|
800
|
+
const newContent = [];
|
|
801
|
+
for (const item of paragraph.content) {
|
|
802
|
+
if (item.type === "run") {
|
|
803
|
+
const runText = item.content.filter((c) => c.type === "text").map((c) => c.text).join("");
|
|
804
|
+
const runEnd = currentOffset + runText.length;
|
|
805
|
+
if (!inserted && currentOffset <= start.offset && start.offset <= runEnd) {
|
|
806
|
+
const insertPos = start.offset - currentOffset;
|
|
807
|
+
if (insertPos > 0) {
|
|
808
|
+
newContent.push({
|
|
809
|
+
...item,
|
|
810
|
+
content: [{ type: "text", text: runText.slice(0, insertPos) }]
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
newContent.push(hyperlink);
|
|
814
|
+
if (insertPos < runText.length) {
|
|
815
|
+
newContent.push({
|
|
816
|
+
...item,
|
|
817
|
+
content: [{ type: "text", text: runText.slice(insertPos) }]
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
inserted = true;
|
|
821
|
+
} else {
|
|
822
|
+
newContent.push(item);
|
|
823
|
+
}
|
|
824
|
+
currentOffset = runEnd;
|
|
825
|
+
} else {
|
|
826
|
+
newContent.push(item);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
if (!inserted) {
|
|
830
|
+
newContent.push(hyperlink);
|
|
831
|
+
}
|
|
832
|
+
paragraph.content = newContent;
|
|
833
|
+
return newDoc;
|
|
834
|
+
}
|
|
835
|
+
function executeRemoveHyperlink(doc, command) {
|
|
836
|
+
const newDoc = cloneDocument(doc);
|
|
837
|
+
const body = newDoc.package.document;
|
|
838
|
+
const { start } = command.range;
|
|
839
|
+
const blockIndex = getBlockIndexForParagraph(body, start.paragraphIndex);
|
|
840
|
+
if (blockIndex === -1) {
|
|
841
|
+
throw new Error(`Paragraph index ${start.paragraphIndex} not found`);
|
|
842
|
+
}
|
|
843
|
+
const paragraph = body.content[blockIndex];
|
|
844
|
+
const newContent = [];
|
|
845
|
+
for (const item of paragraph.content) {
|
|
846
|
+
if (item.type === "hyperlink") {
|
|
847
|
+
for (const child of item.children) {
|
|
848
|
+
if (child.type === "run") {
|
|
849
|
+
newContent.push(child);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
} else {
|
|
853
|
+
newContent.push(item);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
paragraph.content = newContent;
|
|
857
|
+
return newDoc;
|
|
858
|
+
}
|
|
859
|
+
function executeInsertParagraphBreak(doc, command) {
|
|
860
|
+
const newDoc = cloneDocument(doc);
|
|
861
|
+
const body = newDoc.package.document;
|
|
862
|
+
const blockIndex = getBlockIndexForParagraph(body, command.position.paragraphIndex);
|
|
863
|
+
if (blockIndex === -1) {
|
|
864
|
+
throw new Error(`Paragraph index ${command.position.paragraphIndex} not found`);
|
|
865
|
+
}
|
|
866
|
+
const paragraph = body.content[blockIndex];
|
|
867
|
+
const paragraphText = getParagraphText(paragraph);
|
|
868
|
+
const beforeContent = deleteTextInParagraph(
|
|
869
|
+
{ ...paragraph, content: [...paragraph.content] },
|
|
870
|
+
command.position.offset,
|
|
871
|
+
paragraphText.length
|
|
872
|
+
);
|
|
873
|
+
const afterContent = deleteTextInParagraph(
|
|
874
|
+
{ ...paragraph, content: [...paragraph.content] },
|
|
875
|
+
0,
|
|
876
|
+
command.position.offset
|
|
877
|
+
);
|
|
878
|
+
paragraph.content = beforeContent;
|
|
879
|
+
const newParagraph = {
|
|
880
|
+
type: "paragraph",
|
|
881
|
+
formatting: paragraph.formatting,
|
|
882
|
+
content: afterContent
|
|
883
|
+
};
|
|
884
|
+
body.content.splice(blockIndex + 1, 0, newParagraph);
|
|
885
|
+
return newDoc;
|
|
886
|
+
}
|
|
887
|
+
function executeMergeParagraphs(doc, command) {
|
|
888
|
+
const newDoc = cloneDocument(doc);
|
|
889
|
+
const body = newDoc.package.document;
|
|
890
|
+
const startBlockIndex = getBlockIndexForParagraph(body, command.paragraphIndex);
|
|
891
|
+
if (startBlockIndex === -1) {
|
|
892
|
+
throw new Error(`Paragraph index ${command.paragraphIndex} not found`);
|
|
893
|
+
}
|
|
894
|
+
const baseParagraph = body.content[startBlockIndex];
|
|
895
|
+
const indicesToRemove = [];
|
|
896
|
+
for (let i = 1; i <= command.count; i++) {
|
|
897
|
+
const blockIndex = getBlockIndexForParagraph(body, command.paragraphIndex + i);
|
|
898
|
+
if (blockIndex !== -1) {
|
|
899
|
+
const para = body.content[blockIndex];
|
|
900
|
+
baseParagraph.content.push(...para.content);
|
|
901
|
+
indicesToRemove.push(blockIndex);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
for (let i = indicesToRemove.length - 1; i >= 0; i--) {
|
|
905
|
+
body.content.splice(indicesToRemove[i], 1);
|
|
906
|
+
}
|
|
907
|
+
return newDoc;
|
|
908
|
+
}
|
|
909
|
+
function executeSplitParagraph(doc, command) {
|
|
910
|
+
return executeInsertParagraphBreak(doc, {
|
|
911
|
+
position: command.position
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
function executeSetVariable(doc, command) {
|
|
915
|
+
const newDoc = cloneDocument(doc);
|
|
916
|
+
if (!newDoc.templateVariables) {
|
|
917
|
+
newDoc.templateVariables = [];
|
|
918
|
+
}
|
|
919
|
+
if (!newDoc.templateVariables.includes(command.name)) {
|
|
920
|
+
newDoc.templateVariables.push(command.name);
|
|
921
|
+
}
|
|
922
|
+
return newDoc;
|
|
923
|
+
}
|
|
924
|
+
function executeApplyVariables(doc, command) {
|
|
925
|
+
const newDoc = cloneDocument(doc);
|
|
926
|
+
const body = newDoc.package.document;
|
|
927
|
+
function replaceVariablesInRun(run) {
|
|
928
|
+
for (const content of run.content) {
|
|
929
|
+
if (content.type === "text") {
|
|
930
|
+
for (const [name, value] of Object.entries(command.values)) {
|
|
931
|
+
const pattern = new RegExp(`\\{${name}\\}`, "g");
|
|
932
|
+
content.text = content.text.replace(pattern, value);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
function replaceVariablesInParagraph(paragraph) {
|
|
938
|
+
for (const item of paragraph.content) {
|
|
939
|
+
if (item.type === "run") {
|
|
940
|
+
replaceVariablesInRun(item);
|
|
941
|
+
} else if (item.type === "hyperlink") {
|
|
942
|
+
for (const child of item.children) {
|
|
943
|
+
if (child.type === "run") {
|
|
944
|
+
replaceVariablesInRun(child);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
function replaceVariablesInBlock(block) {
|
|
951
|
+
if (block.type === "paragraph") {
|
|
952
|
+
replaceVariablesInParagraph(block);
|
|
953
|
+
} else if (block.type === "table") {
|
|
954
|
+
for (const row of block.rows) {
|
|
955
|
+
for (const cell of row.cells) {
|
|
956
|
+
for (const cellBlock of cell.content) {
|
|
957
|
+
replaceVariablesInBlock(cellBlock);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
for (const block of body.content) {
|
|
964
|
+
replaceVariablesInBlock(block);
|
|
965
|
+
}
|
|
966
|
+
return newDoc;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
exports.PluginRegistry = PluginRegistry;
|
|
970
|
+
exports.createPluginRegistrar = createPluginRegistrar;
|
|
971
|
+
exports.executeCommand = executeCommand;
|
|
972
|
+
exports.executeCommands = executeCommands;
|
|
973
|
+
exports.pluginRegistry = pluginRegistry;
|
|
974
|
+
exports.registerPlugins = registerPlugins;
|
|
975
|
+
//# sourceMappingURL=chunk-5D2V7VK3.js.map
|
|
976
|
+
//# sourceMappingURL=chunk-5D2V7VK3.js.map
|