superdoc-macros 0.8.0 → 0.9.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/README.md +23 -3
- package/dist/index.d.ts +1 -1
- package/dist/manager.d.ts +22 -1
- package/dist/manager.js +118 -0
- package/dist/messages.d.ts +6 -0
- package/dist/messages.js +4 -0
- package/dist/storage.d.ts +6 -0
- package/dist/storage.js +13 -0
- package/dist/types.d.ts +25 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A macro toolkit for **SuperDoc v2**-based editors. Originally built for [otzaria-word-editor](https://github.com/Y-PLONI/otzaria-word-editor), but fully generic: it has no dependency on that project — nor on the superdoc package itself (the engine is consumed structurally, through its public surfaces), and the core works against any editor that implements a small `MacroHost` interface.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The capabilities, in the spirit of Word macros:
|
|
6
6
|
|
|
7
7
|
| Capability | What it gives you |
|
|
8
8
|
| --- | --- |
|
|
@@ -10,10 +10,11 @@ Three capabilities, in the spirit of Word macros:
|
|
|
10
10
|
| **Macro recorder** | "Record → work normally → stop → replay" — records commands and typing, like Word's recorder |
|
|
11
11
|
| **Snippets (AutoText)** | Templates with variables (`{{date}}`, `{{selection}}`…), keyboard shortcuts, and auto-expansion while typing (type a trigger word + space) |
|
|
12
12
|
| **VBA import (read-only)** | Reads the macros already inside a `.docm` and shows the user their real source, so they can port it. Nothing is executed |
|
|
13
|
+
| **Built-in tools** | Host-implemented document actions registered on the kit — listed, run and shortcut-bound alongside everything else |
|
|
13
14
|
|
|
14
15
|
Plus: persistence (localStorage or custom storage), JSON import/export, keyboard shortcut binding, and localizable runtime messages (English by default, Hebrew locale included).
|
|
15
16
|
|
|
16
|
-
> **A note on VBA:** the toolkit does not *execute* VBA — there is no VBA engine in the browser, and running document-supplied code is not something it will grow into. What it does instead is two things: it lets a user **see** the macros a `.docm` already contains (section
|
|
17
|
+
> **A note on VBA:** the toolkit does not *execute* VBA — there is no VBA engine in the browser, and running document-supplied code is not something it will grow into. What it does instead is two things: it lets a user **see** the macros a `.docm` already contains (section 5), and it provides a parallel, JavaScript-based macro system to rewrite them in.
|
|
17
18
|
|
|
18
19
|
## Installation
|
|
19
20
|
|
|
@@ -119,7 +120,26 @@ await kit.expandSnippet(id); // or expand explicitly / via the shortcut
|
|
|
119
120
|
|
|
120
121
|
Built-in variables: `{{date}}`, `{{time}}`, `{{datetime}}` (formatted with the browser locale, or an explicit `locale` option), `{{selection}}`. Any other name resolves from the `variables` passed to `expandSnippet`; a variable with no value stays visible in the text.
|
|
121
122
|
|
|
122
|
-
## 4.
|
|
123
|
+
## 4. Built-in tools
|
|
124
|
+
|
|
125
|
+
A host often ships native document-processing actions of its own — implemented against its full engine access, beyond what the sandboxed script API exposes. Registering them on the kit puts them next to recordings and scripts: one management UI, one run-at-a-time guard, and one shortcut system with persistence and collision rules.
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
kit.registerTool({
|
|
129
|
+
id: 'typography.first-word',
|
|
130
|
+
name: 'Format first word',
|
|
131
|
+
description: 'Enlarges the first word of every selected paragraph',
|
|
132
|
+
run: () => applyFirstWordDesign(editor), // host code, returns { ok } / { ok: false, message }
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
kit.listTools(); // [{ id, name, description, shortcut? }]
|
|
136
|
+
await kit.runTool('typography.first-word'); // refused while recording or while another macro runs
|
|
137
|
+
kit.setToolShortcut('typography.first-word', 'Ctrl+Alt+1'); // persisted; validated like every binding
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Tools are runtime registrations — they are never persisted or exported. Only their shortcuts are, keyed by the tool id, so a shortcut survives restarts and waits for the day its tool is registered again; an unregistered tool's shortcut is never bound.
|
|
141
|
+
|
|
142
|
+
## 5. Reading the VBA in an existing `.docm`
|
|
123
143
|
|
|
124
144
|
A user who has relied on a macro-enabled document for years should not be told their macros are simply gone. This reads the macro project out of the package and hands back each module's real source text:
|
|
125
145
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { MacroHost, MacroOutcome, MacroStep, RecordedMacro, SavedScript, SelectionSnapshot, Snippet, TextInputEvent, } from './types.js';
|
|
1
|
+
export type { BuiltinTool, BuiltinToolInfo, MacroHost, MacroOutcome, MacroStep, RecordedMacro, SavedScript, SelectionSnapshot, Snippet, TextInputEvent, } from './types.js';
|
|
2
2
|
export { MacroKit, type MacroKitOptions, type ShortcutValidation } from './manager.js';
|
|
3
3
|
export { ENGLISH_MESSAGES, HEBREW_MESSAGES, setMacroMessages, type MacroMessages, } from './messages.js';
|
|
4
4
|
export { createSuperdocHost, type SuperdocHostOptions, type SuperdocLike, type SuperdocMacroHost } from './host/superdoc-host.js';
|
package/dist/manager.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { type AutoTextOptions } from './snippets/autotext.js';
|
|
|
14
14
|
import { type ExpandOptions } from './snippets/snippets.js';
|
|
15
15
|
import { type ShortcutTarget } from './shortcuts.js';
|
|
16
16
|
import { type MacroStorage } from './storage.js';
|
|
17
|
-
import type { MacroHost, RecordedMacro, SavedScript, Snippet } from './types.js';
|
|
17
|
+
import type { BuiltinTool, BuiltinToolInfo, MacroHost, MacroOutcome, RecordedMacro, SavedScript, Snippet } from './types.js';
|
|
18
18
|
export interface MacroKitOptions {
|
|
19
19
|
host: MacroHost;
|
|
20
20
|
/** Default: localStorage. */
|
|
@@ -66,6 +66,8 @@ export declare class MacroKit {
|
|
|
66
66
|
private readonly runOptions;
|
|
67
67
|
private readonly onLog?;
|
|
68
68
|
private state;
|
|
69
|
+
/** Built-in tools, by id. Runtime registrations — never persisted (see BuiltinTool). */
|
|
70
|
+
private readonly tools;
|
|
69
71
|
private readonly recorder;
|
|
70
72
|
private readonly autoText;
|
|
71
73
|
private readonly reservedSignatures;
|
|
@@ -160,6 +162,25 @@ export declare class MacroKit {
|
|
|
160
162
|
/** Enables auto-text (trigger + space). Returns a disable function. */
|
|
161
163
|
enableAutoText(): () => void;
|
|
162
164
|
disableAutoText(): void;
|
|
165
|
+
/**
|
|
166
|
+
* Registers a built-in tool (see BuiltinTool in types.ts). Throws on a
|
|
167
|
+
* duplicate id or an invalid name — a silent replace would let two host
|
|
168
|
+
* modules fight over one id without anyone noticing.
|
|
169
|
+
*/
|
|
170
|
+
registerTool(tool: BuiltinTool): void;
|
|
171
|
+
/** The registered tools, each with its persisted shortcut (if any). */
|
|
172
|
+
listTools(): readonly BuiltinToolInfo[];
|
|
173
|
+
/**
|
|
174
|
+
* Runs a registered tool under the same guard as scripts and replays: not
|
|
175
|
+
* while recording, and never two runs at once. A thrown error is reported
|
|
176
|
+
* as a failed outcome, never rethrown.
|
|
177
|
+
*/
|
|
178
|
+
runTool(id: string): Promise<MacroOutcome>;
|
|
179
|
+
/**
|
|
180
|
+
* Sets or clears (undefined/empty) the persisted shortcut of a registered
|
|
181
|
+
* tool, under the exact validation of every other saved binding.
|
|
182
|
+
*/
|
|
183
|
+
setToolShortcut(id: string, shortcut: string | undefined): void;
|
|
163
184
|
/**
|
|
164
185
|
* Binds the shortcuts of everything saved (scripts, recordings, snippets)
|
|
165
186
|
* to a target — usually the editor container or `window`. The list is
|
package/dist/manager.js
CHANGED
|
@@ -35,6 +35,8 @@ export class MacroKit {
|
|
|
35
35
|
runOptions;
|
|
36
36
|
onLog;
|
|
37
37
|
state;
|
|
38
|
+
/** Built-in tools, by id. Runtime registrations — never persisted (see BuiltinTool). */
|
|
39
|
+
tools = new Map();
|
|
38
40
|
recorder;
|
|
39
41
|
autoText;
|
|
40
42
|
reservedSignatures;
|
|
@@ -142,6 +144,22 @@ export class MacroKit {
|
|
|
142
144
|
for (const signature of signatures)
|
|
143
145
|
seen.add(signature);
|
|
144
146
|
}
|
|
147
|
+
const toolShortcuts = this.state.toolShortcuts;
|
|
148
|
+
if (!toolShortcuts)
|
|
149
|
+
return;
|
|
150
|
+
for (const [toolId, shortcut] of Object.entries(toolShortcuts)) {
|
|
151
|
+
if (this.bindingIssue(shortcut)) {
|
|
152
|
+
delete toolShortcuts[toolId];
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const signatures = shortcutSignatures(parseShortcut(shortcut));
|
|
156
|
+
if (signatures.some((signature) => seen.has(signature))) {
|
|
157
|
+
delete toolShortcuts[toolId];
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
for (const signature of signatures)
|
|
161
|
+
seen.add(signature);
|
|
162
|
+
}
|
|
145
163
|
}
|
|
146
164
|
findShortcutOwner(signatures, excludeId) {
|
|
147
165
|
const items = [
|
|
@@ -159,6 +177,19 @@ export class MacroKit {
|
|
|
159
177
|
if (existing.some((signature) => signatures.includes(signature)))
|
|
160
178
|
return item.name;
|
|
161
179
|
}
|
|
180
|
+
for (const [toolId, shortcut] of Object.entries(this.state.toolShortcuts ?? {})) {
|
|
181
|
+
if (toolId === excludeId)
|
|
182
|
+
continue;
|
|
183
|
+
const parsed = parseShortcut(shortcut);
|
|
184
|
+
if (!parsed)
|
|
185
|
+
continue;
|
|
186
|
+
const existing = shortcutSignatures(parsed);
|
|
187
|
+
if (existing.some((signature) => signatures.includes(signature))) {
|
|
188
|
+
// A stored shortcut can belong to a tool that is not registered in
|
|
189
|
+
// this session; its id is then the only name there is.
|
|
190
|
+
return this.tools.get(toolId)?.name ?? toolId;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
162
193
|
return null;
|
|
163
194
|
}
|
|
164
195
|
/** Throws a MacroError when the shortcut is unacceptable. The save paths call this. */
|
|
@@ -399,6 +430,80 @@ export class MacroKit {
|
|
|
399
430
|
disableAutoText() {
|
|
400
431
|
this.autoText.detach();
|
|
401
432
|
}
|
|
433
|
+
/* ---------- Built-in tools ---------- */
|
|
434
|
+
/**
|
|
435
|
+
* Registers a built-in tool (see BuiltinTool in types.ts). Throws on a
|
|
436
|
+
* duplicate id or an invalid name — a silent replace would let two host
|
|
437
|
+
* modules fight over one id without anyone noticing.
|
|
438
|
+
*/
|
|
439
|
+
registerTool(tool) {
|
|
440
|
+
if (!tool.id || tool.id.length > IMPORT_LIMITS.maxNameLength) {
|
|
441
|
+
throw new MacroError(macroMessages().fieldTooLong('id', IMPORT_LIMITS.maxNameLength), 'invalid-item');
|
|
442
|
+
}
|
|
443
|
+
this.requireItemLimits({ name: tool.name });
|
|
444
|
+
if (this.tools.has(tool.id)) {
|
|
445
|
+
const messages = macroMessages();
|
|
446
|
+
throw new MacroError(messages.toolAlreadyRegistered?.(tool.id) ?? messages.saveFailed, 'invalid-item');
|
|
447
|
+
}
|
|
448
|
+
this.tools.set(tool.id, tool);
|
|
449
|
+
}
|
|
450
|
+
/** The registered tools, each with its persisted shortcut (if any). */
|
|
451
|
+
listTools() {
|
|
452
|
+
return [...this.tools.values()].map((tool) => ({
|
|
453
|
+
id: tool.id,
|
|
454
|
+
name: tool.name,
|
|
455
|
+
...(tool.description ? { description: tool.description } : {}),
|
|
456
|
+
...(this.state.toolShortcuts?.[tool.id] ? { shortcut: this.state.toolShortcuts[tool.id] } : {}),
|
|
457
|
+
}));
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Runs a registered tool under the same guard as scripts and replays: not
|
|
461
|
+
* while recording, and never two runs at once. A thrown error is reported
|
|
462
|
+
* as a failed outcome, never rethrown.
|
|
463
|
+
*/
|
|
464
|
+
async runTool(id) {
|
|
465
|
+
const tool = this.tools.get(id);
|
|
466
|
+
if (!tool) {
|
|
467
|
+
const messages = macroMessages();
|
|
468
|
+
return { ok: false, message: messages.toolNotFound ?? messages.actionFailed, reason: 'tool-not-found' };
|
|
469
|
+
}
|
|
470
|
+
const guard = this.guardRun();
|
|
471
|
+
if (guard)
|
|
472
|
+
return { ok: false, message: guard.message };
|
|
473
|
+
this.running = true;
|
|
474
|
+
try {
|
|
475
|
+
return await tool.run();
|
|
476
|
+
}
|
|
477
|
+
catch (error) {
|
|
478
|
+
return { ok: false, message: error instanceof Error ? error.message : macroMessages().actionFailed, reason: 'threw' };
|
|
479
|
+
}
|
|
480
|
+
finally {
|
|
481
|
+
this.running = false;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Sets or clears (undefined/empty) the persisted shortcut of a registered
|
|
486
|
+
* tool, under the exact validation of every other saved binding.
|
|
487
|
+
*/
|
|
488
|
+
setToolShortcut(id, shortcut) {
|
|
489
|
+
if (!this.tools.has(id)) {
|
|
490
|
+
const messages = macroMessages();
|
|
491
|
+
throw new MacroError(messages.toolNotFound ?? messages.actionFailed, 'tool-not-found');
|
|
492
|
+
}
|
|
493
|
+
const trimmed = shortcut?.trim();
|
|
494
|
+
if (trimmed) {
|
|
495
|
+
this.requireValidShortcut(trimmed, id);
|
|
496
|
+
this.requireItemLimits({ name: this.tools.get(id).name, shortcut: trimmed });
|
|
497
|
+
}
|
|
498
|
+
this.commit((draft) => {
|
|
499
|
+
const map = draft.toolShortcuts ?? {};
|
|
500
|
+
if (trimmed)
|
|
501
|
+
map[id] = trimmed;
|
|
502
|
+
else
|
|
503
|
+
delete map[id];
|
|
504
|
+
draft.toolShortcuts = map;
|
|
505
|
+
});
|
|
506
|
+
}
|
|
402
507
|
/* ---------- Keyboard shortcuts ---------- */
|
|
403
508
|
/**
|
|
404
509
|
* Binds the shortcuts of everything saved (scripts, recordings, snippets)
|
|
@@ -428,6 +533,12 @@ export class MacroKit {
|
|
|
428
533
|
if (snippet.shortcut)
|
|
429
534
|
bindings.push({ shortcut: snippet.shortcut, run: () => this.expandSnippet(snippet.id) });
|
|
430
535
|
}
|
|
536
|
+
for (const [toolId, shortcut] of Object.entries(this.state.toolShortcuts ?? {})) {
|
|
537
|
+
// Only registered tools bind: a stored shortcut of a tool the host did
|
|
538
|
+
// not register this session must not swallow the key.
|
|
539
|
+
if (this.tools.has(toolId))
|
|
540
|
+
bindings.push({ shortcut, run: () => this.runTool(toolId) });
|
|
541
|
+
}
|
|
431
542
|
return bindings;
|
|
432
543
|
}
|
|
433
544
|
/* ---------- Import/export ---------- */
|
|
@@ -456,6 +567,9 @@ export class MacroKit {
|
|
|
456
567
|
scripts: [...this.state.scripts.map((item) => ({ ...item }))],
|
|
457
568
|
recordings: [...this.state.recordings.map((item) => ({ ...item }))],
|
|
458
569
|
snippets: [...this.state.snippets.map((item) => ({ ...item }))],
|
|
570
|
+
...(this.state.toolShortcuts || imported.toolShortcuts
|
|
571
|
+
? { toolShortcuts: { ...this.state.toolShortcuts, ...imported.toolShortcuts } }
|
|
572
|
+
: {}),
|
|
459
573
|
};
|
|
460
574
|
for (const script of imported.scripts)
|
|
461
575
|
this.upsert(candidate.scripts, script);
|
|
@@ -493,6 +607,10 @@ export class MacroKit {
|
|
|
493
607
|
...candidate.scripts,
|
|
494
608
|
...candidate.recordings,
|
|
495
609
|
...candidate.snippets,
|
|
610
|
+
...Object.entries(candidate.toolShortcuts ?? {}).map(([toolId, shortcut]) => ({
|
|
611
|
+
name: this.tools.get(toolId)?.name ?? toolId,
|
|
612
|
+
shortcut,
|
|
613
|
+
})),
|
|
496
614
|
];
|
|
497
615
|
for (const item of items) {
|
|
498
616
|
if (!item.shortcut)
|
package/dist/messages.d.ts
CHANGED
|
@@ -49,6 +49,12 @@ export interface MacroMessages {
|
|
|
49
49
|
* objects compiled against 0.7.0.
|
|
50
50
|
*/
|
|
51
51
|
recordingUncapturable?: (commandIds: string) => string;
|
|
52
|
+
/**
|
|
53
|
+
* Built-in tools. Optional for source compatibility with full locale
|
|
54
|
+
* objects compiled against 0.8.0 (same reasoning as recordingUncapturable).
|
|
55
|
+
*/
|
|
56
|
+
toolNotFound?: string;
|
|
57
|
+
toolAlreadyRegistered?: (id: string) => string;
|
|
52
58
|
shortcutInvalid: string;
|
|
53
59
|
shortcutNeedsModifier: string;
|
|
54
60
|
shortcutReserved: string;
|
package/dist/messages.js
CHANGED
|
@@ -44,6 +44,8 @@ export const ENGLISH_MESSAGES = {
|
|
|
44
44
|
recordingTooLarge: 'The recording is too large to save',
|
|
45
45
|
recordingIncomplete: (commandIds) => `The recording is missing actions that cannot be recorded (${commandIds})`,
|
|
46
46
|
recordingUncapturable: (commandIds) => `The recording contains only actions that cannot be recorded (${commandIds})`,
|
|
47
|
+
toolNotFound: 'Tool not found',
|
|
48
|
+
toolAlreadyRegistered: (id) => `A tool with the id "${id}" is already registered`,
|
|
47
49
|
shortcutInvalid: 'Invalid shortcut — use a form like Ctrl+Alt+M',
|
|
48
50
|
shortcutNeedsModifier: 'A shortcut must include Ctrl, Alt or Meta',
|
|
49
51
|
shortcutReserved: 'This shortcut is reserved by the editor',
|
|
@@ -85,6 +87,8 @@ export const HEBREW_MESSAGES = {
|
|
|
85
87
|
recordingTooLarge: 'ההקלטה גדולה מכדי להישמר',
|
|
86
88
|
recordingIncomplete: (commandIds) => `בהקלטה חסרות פעולות שאינן ניתנות להקלטה (${commandIds})`,
|
|
87
89
|
recordingUncapturable: (commandIds) => `ההקלטה מכילה רק פעולות שאינן ניתנות להקלטה (${commandIds})`,
|
|
90
|
+
toolNotFound: 'הכלי לא נמצא',
|
|
91
|
+
toolAlreadyRegistered: (id) => `כלי עם המזהה "${id}" כבר רשום`,
|
|
88
92
|
shortcutInvalid: 'קיצור לא תקין — הצורה הנדרשת היא למשל Ctrl+Alt+M',
|
|
89
93
|
shortcutNeedsModifier: 'קיצור חייב לכלול Ctrl, Alt או Meta',
|
|
90
94
|
shortcutReserved: 'הקיצור הזה שמור לעורך',
|
package/dist/storage.d.ts
CHANGED
|
@@ -9,6 +9,12 @@ export interface PersistedMacroState {
|
|
|
9
9
|
scripts: SavedScript[];
|
|
10
10
|
recordings: RecordedMacro[];
|
|
11
11
|
snippets: Snippet[];
|
|
12
|
+
/**
|
|
13
|
+
* Keyboard shortcuts of built-in tools, keyed by tool id. Optional for
|
|
14
|
+
* backward compatibility: stores written before tools existed lack it,
|
|
15
|
+
* and they must keep loading as-is.
|
|
16
|
+
*/
|
|
17
|
+
toolShortcuts?: Record<string, string>;
|
|
12
18
|
}
|
|
13
19
|
export interface MacroStorage {
|
|
14
20
|
/** `null` when there is no saved state or the saved state is unreadable. */
|
package/dist/storage.js
CHANGED
|
@@ -90,11 +90,24 @@ function isValidSnippet(value) {
|
|
|
90
90
|
optionalBoundedString(snippet.trigger, IMPORT_LIMITS.maxTriggerLength) &&
|
|
91
91
|
optionalBoundedString(snippet.shortcut, IMPORT_LIMITS.maxShortcutLength));
|
|
92
92
|
}
|
|
93
|
+
/** Tool-shortcut map: bounded ids to bounded shortcut strings, capped like the item lists. */
|
|
94
|
+
function isValidToolShortcuts(value) {
|
|
95
|
+
if (value === undefined)
|
|
96
|
+
return true;
|
|
97
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
98
|
+
return false;
|
|
99
|
+
const entries = Object.entries(value);
|
|
100
|
+
if (entries.length > IMPORT_LIMITS.maxItems)
|
|
101
|
+
return false;
|
|
102
|
+
return entries.every(([id, shortcut]) => boundedString(id, IMPORT_LIMITS.maxNameLength) &&
|
|
103
|
+
boundedString(shortcut, IMPORT_LIMITS.maxShortcutLength));
|
|
104
|
+
}
|
|
93
105
|
function isValidState(value) {
|
|
94
106
|
if (typeof value !== 'object' || value === null)
|
|
95
107
|
return false;
|
|
96
108
|
const state = value;
|
|
97
109
|
return (state.version === 1 &&
|
|
110
|
+
isValidToolShortcuts(state.toolShortcuts) &&
|
|
98
111
|
Array.isArray(state.scripts) &&
|
|
99
112
|
state.scripts.length <= IMPORT_LIMITS.maxItems &&
|
|
100
113
|
state.scripts.every(isValidScript) &&
|
package/dist/types.d.ts
CHANGED
|
@@ -125,6 +125,31 @@ export interface RecordedMacro {
|
|
|
125
125
|
shortcut?: string;
|
|
126
126
|
steps: MacroStep[];
|
|
127
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* A built-in tool the host registers on the kit: a native document-processing
|
|
130
|
+
* action (implemented by the host against its own engine access) that the kit
|
|
131
|
+
* exposes alongside recordings and scripts — listable in a management UI,
|
|
132
|
+
* runnable under the same one-run-at-a-time guard, and bindable to a
|
|
133
|
+
* persisted keyboard shortcut. Tools are runtime registrations, never
|
|
134
|
+
* persisted themselves; only their shortcuts are.
|
|
135
|
+
*/
|
|
136
|
+
export interface BuiltinTool {
|
|
137
|
+
/** Stable identifier, e.g. `'shulchan.first-word'`. Shortcut persistence is keyed by it. */
|
|
138
|
+
id: string;
|
|
139
|
+
/** Display name. */
|
|
140
|
+
name: string;
|
|
141
|
+
/** One-line description for management UIs. */
|
|
142
|
+
description?: string;
|
|
143
|
+
/** Runs the tool. A thrown error is reported as a failed outcome. */
|
|
144
|
+
run(): Promise<MacroOutcome> | MacroOutcome;
|
|
145
|
+
}
|
|
146
|
+
/** A registered tool as listed to UIs — the registration plus its persisted shortcut. */
|
|
147
|
+
export interface BuiltinToolInfo {
|
|
148
|
+
id: string;
|
|
149
|
+
name: string;
|
|
150
|
+
description?: string;
|
|
151
|
+
shortcut?: string;
|
|
152
|
+
}
|
|
128
153
|
/** A written macro — a JavaScript script that runs against the toolkit's API. */
|
|
129
154
|
export interface SavedScript {
|
|
130
155
|
id: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "superdoc-macros",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Macro toolkit for SuperDoc-based editors: sandboxed scripted macros, a Word-style macro recorder, snippets with auto-text expansion, and read-only VBA import from .docm files.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|