@wonderwhy-er/desktop-commander 0.2.36 → 0.2.38
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/README.md +240 -100
- package/dist/command-manager.js +6 -3
- package/dist/config-field-definitions.d.ts +41 -0
- package/dist/config-field-definitions.js +37 -0
- package/dist/config-manager.d.ts +2 -0
- package/dist/config-manager.js +22 -2
- package/dist/handlers/filesystem-handlers.js +6 -11
- package/dist/handlers/macos-control-handlers.d.ts +16 -0
- package/dist/handlers/macos-control-handlers.js +81 -0
- package/dist/lib.d.ts +10 -0
- package/dist/lib.js +10 -0
- package/dist/remote-device/remote-channel.d.ts +8 -3
- package/dist/remote-device/remote-channel.js +68 -21
- package/dist/search-manager.d.ts +13 -0
- package/dist/search-manager.js +146 -0
- package/dist/server.js +29 -1
- package/dist/test-docx.d.ts +1 -0
- package/dist/tools/config.d.ts +71 -0
- package/dist/tools/config.js +117 -2
- package/dist/tools/docx/builders/table.d.ts +2 -0
- package/dist/tools/docx/builders/table.js +60 -16
- package/dist/tools/docx/dom.d.ts +74 -1
- package/dist/tools/docx/dom.js +221 -1
- package/dist/tools/docx/index.d.ts +2 -2
- package/dist/tools/docx/ops/index.js +3 -0
- package/dist/tools/docx/ops/replace-paragraph-text-exact.d.ts +15 -3
- package/dist/tools/docx/ops/replace-paragraph-text-exact.js +25 -10
- package/dist/tools/docx/ops/replace-table-cell-text.d.ts +25 -0
- package/dist/tools/docx/ops/replace-table-cell-text.js +85 -0
- package/dist/tools/docx/ops/set-color-for-paragraph-exact.d.ts +2 -1
- package/dist/tools/docx/ops/set-color-for-paragraph-exact.js +9 -8
- package/dist/tools/docx/ops/set-color-for-style.d.ts +4 -0
- package/dist/tools/docx/ops/set-color-for-style.js +11 -7
- package/dist/tools/docx/ops/table-set-cell-text.js +8 -40
- package/dist/tools/docx/read.d.ts +2 -2
- package/dist/tools/docx/read.js +137 -17
- package/dist/tools/docx/types.d.ts +32 -3
- package/dist/tools/docx/xml-view-test.d.ts +1 -0
- package/dist/tools/docx/xml-view-test.js +63 -0
- package/dist/tools/docx/xml-view.d.ts +56 -0
- package/dist/tools/docx/xml-view.js +169 -0
- package/dist/tools/edit.js +57 -27
- package/dist/tools/macos-control/ax-adapter.d.ts +55 -0
- package/dist/tools/macos-control/ax-adapter.js +438 -0
- package/dist/tools/macos-control/cdp-adapter.d.ts +23 -0
- package/dist/tools/macos-control/cdp-adapter.js +402 -0
- package/dist/tools/macos-control/orchestrator.d.ts +77 -0
- package/dist/tools/macos-control/orchestrator.js +136 -0
- package/dist/tools/macos-control/role-aliases.d.ts +5 -0
- package/dist/tools/macos-control/role-aliases.js +34 -0
- package/dist/tools/macos-control/types.d.ts +129 -0
- package/dist/tools/macos-control/types.js +1 -0
- package/dist/tools/schemas.d.ts +3 -0
- package/dist/tools/schemas.js +2 -1
- package/dist/types.d.ts +0 -1
- package/dist/ui/config-editor/config-editor-runtime.js +14181 -0
- package/dist/ui/config-editor/index.html +13 -0
- package/dist/ui/config-editor/src/app.d.ts +43 -0
- package/dist/ui/config-editor/src/app.js +840 -0
- package/dist/ui/config-editor/src/array-modal.d.ts +19 -0
- package/dist/ui/config-editor/src/array-modal.js +185 -0
- package/dist/ui/config-editor/src/main.d.ts +1 -0
- package/dist/ui/config-editor/src/main.js +2 -0
- package/dist/ui/config-editor/styles.css +586 -0
- package/dist/ui/file-preview/preview-runtime.js +13337 -752
- package/dist/ui/file-preview/shared/preview-file-types.js +3 -1
- package/dist/ui/file-preview/src/app.d.ts +5 -1
- package/dist/ui/file-preview/src/app.js +114 -200
- package/dist/ui/file-preview/src/components/html-renderer.d.ts +1 -5
- package/dist/ui/file-preview/src/components/html-renderer.js +11 -27
- package/dist/ui/file-preview/styles.css +117 -83
- package/dist/ui/resources.d.ts +7 -0
- package/dist/ui/resources.js +16 -2
- package/dist/ui/shared/compact-row.d.ts +11 -0
- package/dist/ui/shared/compact-row.js +18 -0
- package/dist/ui/shared/host-context.d.ts +15 -0
- package/dist/ui/shared/host-context.js +51 -0
- package/dist/ui/shared/tool-bridge.d.ts +30 -0
- package/dist/ui/shared/tool-bridge.js +137 -0
- package/dist/ui/shared/tool-shell.d.ts +9 -0
- package/dist/ui/shared/tool-shell.js +46 -4
- package/dist/ui/shared/ui-event-tracker.d.ts +9 -0
- package/dist/ui/shared/ui-event-tracker.js +27 -0
- package/dist/utils/capture.js +173 -11
- package/dist/utils/files/base.d.ts +3 -1
- package/dist/utils/files/docx.d.ts +28 -15
- package/dist/utils/files/docx.js +622 -88
- package/dist/utils/files/factory.d.ts +6 -5
- package/dist/utils/files/factory.js +18 -6
- package/dist/utils/system-info.js +1 -1
- package/dist/utils/usageTracker.js +5 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -3
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function normalizeUiEventParams(params) {
|
|
2
|
+
const normalized = {};
|
|
3
|
+
if (!params) {
|
|
4
|
+
return normalized;
|
|
5
|
+
}
|
|
6
|
+
for (const [key, value] of Object.entries(params)) {
|
|
7
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || value === null) {
|
|
8
|
+
normalized[key] = value;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return normalized;
|
|
12
|
+
}
|
|
13
|
+
export function createUiEventTracker(callTool, options) {
|
|
14
|
+
const baseParams = options.baseParams ?? {};
|
|
15
|
+
return (event, params = {}) => {
|
|
16
|
+
void callTool('track_ui_event', {
|
|
17
|
+
event,
|
|
18
|
+
component: options.component,
|
|
19
|
+
params: {
|
|
20
|
+
...baseParams,
|
|
21
|
+
...normalizeUiEventParams(params),
|
|
22
|
+
},
|
|
23
|
+
}).catch(() => {
|
|
24
|
+
// UI analytics should never block UI interactions.
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
}
|
package/dist/utils/capture.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { platform } from 'os';
|
|
2
2
|
import * as https from 'https';
|
|
3
|
-
import { configManager } from '../config-manager.js';
|
|
3
|
+
import { configManager, isTelemetryDisabledValue } from '../config-manager.js';
|
|
4
4
|
import { currentClient } from '../server.js';
|
|
5
5
|
let VERSION = 'unknown';
|
|
6
6
|
try {
|
|
@@ -12,6 +12,9 @@ catch {
|
|
|
12
12
|
}
|
|
13
13
|
// Will be initialized when needed
|
|
14
14
|
let uniqueUserId = 'unknown';
|
|
15
|
+
// --- Telemetry Proxy (direct BigQuery ingestion) ---
|
|
16
|
+
const TELEMETRY_PROXY_URL = 'https://dc-telemetry-proxy-83847352264.europe-west1.run.app/mp/collect';
|
|
17
|
+
const TELEMETRY_PROXY_TOKEN = 'Od44UB_fTrVfGPGRPLr5QdVgFhuKdiGaBmvazTdxVdQ';
|
|
15
18
|
/**
|
|
16
19
|
* Sanitizes error objects to remove potentially sensitive information like file paths
|
|
17
20
|
* @param error Error object or string to sanitize
|
|
@@ -53,7 +56,7 @@ export const captureBase = async (captureURL, event, properties) => {
|
|
|
53
56
|
// Check if telemetry is enabled in config (defaults to true if not set)
|
|
54
57
|
const telemetryEnabled = await configManager.getValue('telemetryEnabled');
|
|
55
58
|
// If telemetry is explicitly disabled or GA credentials are missing, don't send
|
|
56
|
-
if (telemetryEnabled
|
|
59
|
+
if (isTelemetryDisabledValue(telemetryEnabled) || !captureURL) {
|
|
57
60
|
return;
|
|
58
61
|
}
|
|
59
62
|
// Get or create the client ID if not already initialized
|
|
@@ -225,19 +228,178 @@ export const captureBase = async (captureURL, event, properties) => {
|
|
|
225
228
|
// Silently fail - we don't want analytics issues to break functionality
|
|
226
229
|
}
|
|
227
230
|
};
|
|
231
|
+
/**
|
|
232
|
+
* Build the standard event properties used by both GA4 and the telemetry proxy.
|
|
233
|
+
* Extracted from captureBase so both paths get identical data.
|
|
234
|
+
*/
|
|
235
|
+
const buildEventProperties = async (properties) => {
|
|
236
|
+
if (uniqueUserId === 'unknown') {
|
|
237
|
+
uniqueUserId = await configManager.getOrCreateClientId();
|
|
238
|
+
}
|
|
239
|
+
let clientContext = {};
|
|
240
|
+
if (currentClient) {
|
|
241
|
+
clientContext = {
|
|
242
|
+
client_name: currentClient.name,
|
|
243
|
+
client_version: currentClient.version,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const sawOnboardingPage = await configManager.getValue('sawOnboardingPage');
|
|
247
|
+
if (sawOnboardingPage !== undefined) {
|
|
248
|
+
clientContext.saw_onboarding_page = sawOnboardingPage;
|
|
249
|
+
}
|
|
250
|
+
let sanitizedProperties;
|
|
251
|
+
try {
|
|
252
|
+
sanitizedProperties = properties ? JSON.parse(JSON.stringify(properties)) : {};
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
sanitizedProperties = {};
|
|
256
|
+
}
|
|
257
|
+
if (sanitizedProperties.error) {
|
|
258
|
+
if (typeof sanitizedProperties.error === 'object' && sanitizedProperties.error !== null) {
|
|
259
|
+
const sanitized = sanitizeError(sanitizedProperties.error);
|
|
260
|
+
sanitizedProperties.error = sanitized.message;
|
|
261
|
+
if (sanitized.code)
|
|
262
|
+
sanitizedProperties.errorCode = sanitized.code;
|
|
263
|
+
}
|
|
264
|
+
else if (typeof sanitizedProperties.error === 'string') {
|
|
265
|
+
sanitizedProperties.error = sanitizeError(sanitizedProperties.error).message;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
const sensitiveKeys = ['path', 'filePath', 'directory', 'file_path', 'sourcePath', 'destinationPath', 'fullPath', 'rootPath'];
|
|
269
|
+
for (const key of Object.keys(sanitizedProperties)) {
|
|
270
|
+
const lowerKey = key.toLowerCase();
|
|
271
|
+
if (sensitiveKeys.some(sk => lowerKey.includes(sk)) && lowerKey !== 'fileextension') {
|
|
272
|
+
delete sanitizedProperties[key];
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
let isDXT = 'false';
|
|
276
|
+
if (process.env.MCP_DXT)
|
|
277
|
+
isDXT = 'true';
|
|
278
|
+
const { getSystemInfo } = await import('./system-info.js');
|
|
279
|
+
const systemInfo = getSystemInfo();
|
|
280
|
+
const isContainer = systemInfo.docker.isContainer ? 'true' : 'false';
|
|
281
|
+
const containerType = systemInfo.docker.containerType || 'none';
|
|
282
|
+
const orchestrator = systemInfo.docker.orchestrator || 'none';
|
|
283
|
+
let containerName = 'none';
|
|
284
|
+
let containerImage = 'none';
|
|
285
|
+
if (systemInfo.docker.isContainer && systemInfo.docker.containerEnvironment) {
|
|
286
|
+
const env = systemInfo.docker.containerEnvironment;
|
|
287
|
+
if (env.containerName) {
|
|
288
|
+
containerName = env.containerName
|
|
289
|
+
.replace(/[0-9a-f]{8,}/gi, 'ID')
|
|
290
|
+
.replace(/[0-9]{8,}/g, 'ID')
|
|
291
|
+
.substring(0, 50);
|
|
292
|
+
}
|
|
293
|
+
if (env.dockerImage) {
|
|
294
|
+
containerImage = env.dockerImage
|
|
295
|
+
.replace(/^[^/]+\/[^/]+\//, '')
|
|
296
|
+
.replace(/^[^/]+\//, '')
|
|
297
|
+
.replace(/@sha256:.*$/, '')
|
|
298
|
+
.substring(0, 100);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
let runtimeSource = 'unknown';
|
|
302
|
+
try {
|
|
303
|
+
const processArgs = process.argv.join(' ');
|
|
304
|
+
if (processArgs.includes('@smithery/cli') || processArgs.includes('smithery')) {
|
|
305
|
+
runtimeSource = 'smithery-runtime';
|
|
306
|
+
}
|
|
307
|
+
else if (processArgs.includes('npx')) {
|
|
308
|
+
runtimeSource = 'npx-runtime';
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
runtimeSource = 'direct-runtime';
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
catch { }
|
|
315
|
+
return {
|
|
316
|
+
timestamp: new Date().toISOString(),
|
|
317
|
+
platform: platform(),
|
|
318
|
+
isContainer,
|
|
319
|
+
containerType,
|
|
320
|
+
orchestrator,
|
|
321
|
+
containerName,
|
|
322
|
+
containerImage,
|
|
323
|
+
runtimeSource,
|
|
324
|
+
isDXT,
|
|
325
|
+
app_version: VERSION,
|
|
326
|
+
engagement_time_msec: "100",
|
|
327
|
+
...clientContext,
|
|
328
|
+
...sanitizedProperties,
|
|
329
|
+
};
|
|
330
|
+
};
|
|
331
|
+
/**
|
|
332
|
+
* Send event to the telemetry proxy (direct BigQuery ingestion).
|
|
333
|
+
* Runs in parallel with GA4 — used for high-volume events to avoid
|
|
334
|
+
* the 1M/day GA4 BigQuery export limit.
|
|
335
|
+
*/
|
|
336
|
+
const sendToTelemetryProxy = async (event, eventProperties) => {
|
|
337
|
+
try {
|
|
338
|
+
const telemetryEnabled = await configManager.getValue('telemetryEnabled');
|
|
339
|
+
if (isTelemetryDisabledValue(telemetryEnabled))
|
|
340
|
+
return;
|
|
341
|
+
const payload = JSON.stringify({
|
|
342
|
+
client_id: uniqueUserId,
|
|
343
|
+
timestamp_micros: Date.now() * 1000,
|
|
344
|
+
events: [{
|
|
345
|
+
name: event,
|
|
346
|
+
params: eventProperties
|
|
347
|
+
}]
|
|
348
|
+
});
|
|
349
|
+
const url = new URL(TELEMETRY_PROXY_URL);
|
|
350
|
+
const options = {
|
|
351
|
+
hostname: url.hostname,
|
|
352
|
+
port: 443,
|
|
353
|
+
path: url.pathname,
|
|
354
|
+
method: 'POST',
|
|
355
|
+
headers: {
|
|
356
|
+
'Content-Type': 'application/json',
|
|
357
|
+
'Authorization': `Bearer ${TELEMETRY_PROXY_TOKEN}`,
|
|
358
|
+
'Content-Length': Buffer.byteLength(payload)
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
const req = https.request(options, (res) => {
|
|
362
|
+
res.resume(); // drain response
|
|
363
|
+
});
|
|
364
|
+
req.on('error', () => { }); // silent fail
|
|
365
|
+
req.setTimeout(3000, () => req.destroy());
|
|
366
|
+
req.write(payload);
|
|
367
|
+
req.end();
|
|
368
|
+
}
|
|
369
|
+
catch {
|
|
370
|
+
// Silent fail — telemetry should never break functionality
|
|
371
|
+
}
|
|
372
|
+
};
|
|
228
373
|
export const capture_call_tool = async (event, properties) => {
|
|
229
|
-
|
|
230
|
-
const
|
|
231
|
-
const
|
|
232
|
-
const
|
|
233
|
-
|
|
374
|
+
// Old property (G-8L163XZ1CE) — keeps lower-volume tool events
|
|
375
|
+
const GA_OLD_ID = 'G-8L163XZ1CE';
|
|
376
|
+
const GA_OLD_SECRET = 'hNxh4TK2TnSy4oLZn4RwTA';
|
|
377
|
+
const GA_OLD_URL = `https://www.google-analytics.com/mp/collect?measurement_id=${GA_OLD_ID}&api_secret=${GA_OLD_SECRET}`;
|
|
378
|
+
// New property (dc_high_volume) — receives highest-volume tool events to avoid 1M/day BQ export limit
|
|
379
|
+
const GA_NEW_ID = 'G-ZDF1M5403Z';
|
|
380
|
+
const GA_NEW_SECRET = 'cUEilpa0SpWfc2UjblDtKQ';
|
|
381
|
+
const GA_NEW_URL = `https://www.google-analytics.com/mp/collect?measurement_id=${GA_NEW_ID}&api_secret=${GA_NEW_SECRET}`;
|
|
382
|
+
// Route highest-volume tools to new property, rest to old
|
|
383
|
+
const HIGH_VOLUME_TOOLS = ['start_process', 'track_ui_event'];
|
|
384
|
+
const toolName = properties?.name;
|
|
385
|
+
const gaUrl = HIGH_VOLUME_TOOLS.includes(toolName) ? GA_NEW_URL : GA_OLD_URL;
|
|
386
|
+
// Build properties once, send to GA4 + telemetry proxy in parallel
|
|
387
|
+
const eventProperties = await buildEventProperties(properties);
|
|
388
|
+
await Promise.all([
|
|
389
|
+
captureBase(gaUrl, event, properties), // GA4 (routed by tool name)
|
|
390
|
+
sendToTelemetryProxy(event, eventProperties), // direct BigQuery (all events)
|
|
391
|
+
]);
|
|
234
392
|
};
|
|
235
393
|
export const capture = async (event, properties) => {
|
|
236
|
-
const GA_MEASUREMENT_ID = 'G-F3GK01G39Y';
|
|
237
|
-
const GA_API_SECRET = 'SqdcIAweSQS1RQErURMdEA';
|
|
394
|
+
const GA_MEASUREMENT_ID = 'G-F3GK01G39Y';
|
|
395
|
+
const GA_API_SECRET = 'SqdcIAweSQS1RQErURMdEA';
|
|
238
396
|
const GA_BASE_URL = `https://www.google-analytics.com/mp/collect?measurement_id=${GA_MEASUREMENT_ID}&api_secret=${GA_API_SECRET}`;
|
|
239
|
-
|
|
240
|
-
|
|
397
|
+
// Build properties once, send to both GA4 and telemetry proxy in parallel
|
|
398
|
+
const eventProperties = await buildEventProperties(properties);
|
|
399
|
+
await Promise.all([
|
|
400
|
+
captureBase(GA_BASE_URL, event, properties), // existing GA4
|
|
401
|
+
sendToTelemetryProxy(event, eventProperties), // new: direct BigQuery
|
|
402
|
+
]);
|
|
241
403
|
};
|
|
242
404
|
export const capture_ui_event = async (event, properties) => {
|
|
243
405
|
const GA_MEASUREMENT_ID = 'G-MPFSWEGQ0T';
|
|
@@ -102,6 +102,8 @@ export interface FileMetadata {
|
|
|
102
102
|
title?: string;
|
|
103
103
|
totalPages?: number;
|
|
104
104
|
pages?: PdfPageItem[];
|
|
105
|
+
/** For DOCX files */
|
|
106
|
+
isDocx?: boolean;
|
|
105
107
|
/** Error information if operation failed */
|
|
106
108
|
error?: boolean;
|
|
107
109
|
errorMessage?: string;
|
|
@@ -161,7 +163,7 @@ export interface FileInfo {
|
|
|
161
163
|
/** File permissions (octal string) */
|
|
162
164
|
permissions: string;
|
|
163
165
|
/** File type classification */
|
|
164
|
-
fileType: 'text' | 'excel' | 'image' | 'binary';
|
|
166
|
+
fileType: 'text' | 'excel' | 'image' | 'binary' | 'docx';
|
|
165
167
|
/** Type-specific metadata */
|
|
166
168
|
metadata?: FileMetadata;
|
|
167
169
|
}
|
|
@@ -1,34 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DOCX File Handler
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Approach: expose DOCX as filtered/raw XML through existing read_file + edit_block.
|
|
5
|
+
*
|
|
6
|
+
* READ (default): Returns a text-bearing outline — skips shapes, drawings, SVG noise.
|
|
7
|
+
* Shows paragraphs with text, tables with cell content, style info, and image refs.
|
|
8
|
+
* Each element shows its raw XML tag context so Claude can target it for editing.
|
|
9
|
+
*
|
|
10
|
+
* READ (with offset/length): Returns raw pretty-printed XML with line pagination,
|
|
11
|
+
* so Claude can drill into specific sections when the outline isn't enough.
|
|
12
|
+
*
|
|
13
|
+
* EDIT (old_string/new_string): Find/replace on the pretty-printed XML, then
|
|
14
|
+
* compact and repack into valid DOCX. Works exactly like text file editing.
|
|
15
|
+
*
|
|
16
|
+
* Round-trip: DOCX → unzip → pretty-print → [outline or raw] → edit → compact → repack
|
|
5
17
|
*/
|
|
6
18
|
import { FileHandler, FileResult, FileInfo, ReadOptions, EditResult } from './base.js';
|
|
7
|
-
/**
|
|
8
|
-
* File handler for DOCX documents
|
|
9
|
-
* Extracts text and metadata, supports paragraph-based pagination
|
|
10
|
-
*/
|
|
11
19
|
export declare class DocxFileHandler implements FileHandler {
|
|
12
20
|
private readonly extensions;
|
|
13
|
-
/**
|
|
14
|
-
* Check if this handler can handle the given file
|
|
15
|
-
*/
|
|
16
21
|
canHandle(path: string): boolean;
|
|
17
22
|
/**
|
|
18
|
-
* Read DOCX content
|
|
23
|
+
* Read DOCX content.
|
|
24
|
+
*
|
|
25
|
+
* Default (offset=0, no explicit length or default length): returns outline
|
|
26
|
+
* With offset/length: returns raw pretty-printed XML with line pagination
|
|
19
27
|
*/
|
|
20
28
|
read(path: string, options?: ReadOptions): Promise<FileResult>;
|
|
21
29
|
/**
|
|
22
|
-
* Write DOCX
|
|
23
|
-
*
|
|
30
|
+
* Write/create a DOCX file.
|
|
31
|
+
* Content is plain text — each line becomes a paragraph.
|
|
32
|
+
* Lines starting with # become headings (# = Heading1, ## = Heading2, etc.)
|
|
24
33
|
*/
|
|
25
34
|
write(path: string, content: any, mode?: 'rewrite' | 'append'): Promise<void>;
|
|
26
35
|
/**
|
|
27
|
-
* Edit DOCX
|
|
36
|
+
* Edit DOCX via find/replace on pretty-printed XML.
|
|
37
|
+
*
|
|
38
|
+
* Works on the same representation that read() returns when using offset/length,
|
|
39
|
+
* so XML fragments copied from read output work as search strings.
|
|
40
|
+
* After editing, XML is compacted and repacked into the DOCX.
|
|
28
41
|
*/
|
|
29
|
-
editRange(path: string,
|
|
42
|
+
editRange(path: string, _range: string, content: any, options?: Record<string, any>): Promise<EditResult>;
|
|
30
43
|
/**
|
|
31
|
-
* Get DOCX file
|
|
44
|
+
* Get DOCX file info
|
|
32
45
|
*/
|
|
33
46
|
getInfo(path: string): Promise<FileInfo>;
|
|
34
47
|
}
|