superdoc-macros 0.2.0 → 0.3.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.
@@ -1,34 +1,23 @@
1
- /**
2
- * ה-API שסקריפט מאקרו מקבל.
3
- *
4
- * שני צרכנים לאותו מימוש: מריץ ה-eval מקבל את האובייקט `api` ישירות, ומריץ
5
- * ה-iframe מדבר איתו דרך `call(method, args)` — RPC על postMessage. לכן כל
6
- * מתודה רשומה במילון אחד, וה-proxy בתוך ה-iframe פונה לאותם שמות בדיוק.
7
- *
8
- * כללי כשל: פעולות כתיבה זורקות `MacroError` כשהן נכשלות, כדי שסקריפט ייעצר
9
- * במקום להמשיך על מסמך במצב לא צפוי. `command()` הגולמית מחזירה את התוצאה
10
- * ואינה זורקת — למי שרוצה לבדוק בעצמו.
11
- */
12
1
  import type { MacroHost, MacroOutcome } from '../types.js';
13
- /** כשל של פעולת מאקרו. השם מאפשר לסקריפט להבחין בינו ובין TypeError שלו. */
2
+ /** A macro operation failure. Named so a script can tell it apart from its own TypeError. */
14
3
  export declare class MacroError extends Error {
15
4
  readonly reason?: string;
16
5
  constructor(message: string, reason?: string);
17
6
  }
18
- /** תצלום בחירה בטוח למסירה ל-iframe (בלי היעד האטום של המנוע). */
7
+ /** Selection snapshot that is safe to hand to the iframe (without the engine's opaque target). */
19
8
  export interface ScriptSelection {
20
9
  text: string;
21
10
  hasRange: boolean;
22
11
  blockId: string | null;
23
12
  empty: boolean;
24
13
  }
25
- /** מה שסקריפט מקבל בתור `api`. כל המתודות א-סינכרוניות. */
14
+ /** What a script receives as `api`. Every method is async. */
26
15
  export interface MacroApi {
27
- /** מריצה פקודה מקטלוג המנוע. מחזירה תוצאה ואינה זורקת. */
16
+ /** Runs a command from the engine catalog. Returns the outcome, never throws. */
28
17
  command(id: string, payload?: unknown): Promise<MacroOutcome>;
29
- /** האם המנוע מכיר את הפקודה. */
18
+ /** Whether the engine recognizes the command. */
30
19
  hasCommand(id: string): Promise<boolean>;
31
- /** מזהי הפקודות המוכרות. */
20
+ /** The known command ids. */
32
21
  commandIds(): Promise<readonly string[]>;
33
22
  insertText(text: string): Promise<void>;
34
23
  insertParagraph(): Promise<void>;
@@ -36,7 +25,7 @@ export interface MacroApi {
36
25
  getSelection(): Promise<ScriptSelection>;
37
26
  getSelectionText(): Promise<string>;
38
27
  getDocumentText(): Promise<string>;
39
- /** מחליפה את כל המופעים. מחזירה כמה הוחלפו. */
28
+ /** Replaces every occurrence. Returns how many were replaced. */
40
29
  replaceAll(query: string, replacement: string): Promise<number>;
41
30
  bold(): Promise<void>;
42
31
  italic(): Promise<void>;
@@ -51,19 +40,19 @@ export interface MacroApi {
51
40
  directionLtr(): Promise<void>;
52
41
  undo(): Promise<void>;
53
42
  redo(): Promise<void>;
54
- /** כותבת שורה ליומן הריצה (מוצג למשתמש, לא ל-console). */
43
+ /** Writes a line to the run log (shown to the user, not to the console). */
55
44
  log(...parts: unknown[]): Promise<void>;
56
45
  }
57
46
  export interface MacroApiOptions {
58
- /** מקבלת כל שורת `api.log`. ברירת המחדל: console.info. */
47
+ /** Receives every `api.log` line. Default: console.info. */
59
48
  onLog?: (line: string) => void;
60
49
  }
61
50
  export interface MacroBridge {
62
51
  api: MacroApi;
63
- /** מסלול ה-RPC: מפעילה מתודה לפי שם. זורקת על מתודה שאינה קיימת. */
52
+ /** The RPC path: invokes a method by name. Throws on an unknown method. */
64
53
  call(method: string, args: readonly unknown[]): Promise<unknown>;
65
- /** מספר הקריאות שבוצעו עד כה. משמש לתקרת קריאות במריצים. */
54
+ /** Number of calls made so far. Used by the runners' call limit. */
66
55
  callCount(): number;
67
56
  }
68
- /** בונה את ה-API מעל מארח. */
57
+ /** Builds the API on top of a host. */
69
58
  export declare function createMacroApi(host: MacroHost, options?: MacroApiOptions): MacroBridge;
@@ -1,4 +1,19 @@
1
- /** כשל של פעולת מאקרו. השם מאפשר לסקריפט להבחין בינו ובין TypeError שלו. */
1
+ /**
2
+ * The API a macro script receives.
3
+ *
4
+ * Two consumers share one implementation: the eval runner hands the `api`
5
+ * object to the script directly, and the iframe runner talks to it through
6
+ * `call(method, args)` — RPC over postMessage. Every method therefore lives
7
+ * in a single dictionary, and the proxy inside the iframe addresses exactly
8
+ * the same names.
9
+ *
10
+ * Failure rules: write operations throw a `MacroError` when they fail, so a
11
+ * script stops instead of continuing against a document in an unexpected
12
+ * state. The raw `command()` returns the outcome and does not throw — for
13
+ * scripts that want to check it themselves.
14
+ */
15
+ import { macroMessages } from '../messages.js';
16
+ /** A macro operation failure. Named so a script can tell it apart from its own TypeError. */
2
17
  export class MacroError extends Error {
3
18
  reason;
4
19
  constructor(message, reason) {
@@ -14,7 +29,7 @@ function requireOk(outcome, action) {
14
29
  }
15
30
  function asText(value, name) {
16
31
  if (typeof value !== 'string')
17
- throw new MacroError(`${name} חייב להיות מחרוזת`);
32
+ throw new MacroError(macroMessages().mustBeString(name));
18
33
  return value;
19
34
  }
20
35
  function formatLogPart(part) {
@@ -27,27 +42,27 @@ function formatLogPart(part) {
27
42
  return String(part);
28
43
  }
29
44
  }
30
- /** בונה את ה-API מעל מארח. */
45
+ /** Builds the API on top of a host. */
31
46
  export function createMacroApi(host, options = {}) {
32
47
  const onLog = options.onLog ?? ((line) => console.info('[superdoc-macros]', line));
33
48
  const commandSugar = async (id) => {
34
- requireOk(await host.commands.execute(id), `הפקודה ${id} נכשלה`);
49
+ requireOk(await host.commands.execute(id), macroMessages().commandFailed(id));
35
50
  };
36
51
  const api = {
37
52
  command: (id, payload) => host.commands.execute(asText(id, 'id'), payload),
38
53
  hasCommand: async (id) => host.commands.has(asText(id, 'id')),
39
54
  commandIds: async () => host.commands.ids(),
40
55
  async insertText(text) {
41
- requireOk(await host.insertText(asText(text, 'text')), 'הכנסת הטקסט נכשלה');
56
+ requireOk(await host.insertText(asText(text, 'text')), macroMessages().insertTextFailed);
42
57
  },
43
58
  async insertParagraph() {
44
- requireOk(await host.insertText('\n'), 'הכנסת הפסקה נכשלה');
59
+ requireOk(await host.insertText('\n'), macroMessages().insertParagraphFailed);
45
60
  },
46
61
  async deleteBackward(count = 1) {
47
62
  const n = Math.max(0, Math.trunc(Number(count)));
48
63
  if (n === 0)
49
64
  return;
50
- requireOk(await host.deleteBackward(n), 'המחיקה נכשלה');
65
+ requireOk(await host.deleteBackward(n), macroMessages().deleteFailed);
51
66
  },
52
67
  async getSelection() {
53
68
  const snapshot = await host.getSelection({ includeText: true });
@@ -65,7 +80,7 @@ export function createMacroApi(host, options = {}) {
65
80
  async replaceAll(query, replacement) {
66
81
  const result = await host.replaceAll(asText(query, 'query'), asText(replacement, 'replacement'));
67
82
  if (!result.ok)
68
- throw new MacroError(result.message ?? 'ההחלפה נכשלה');
83
+ throw new MacroError(result.message ?? macroMessages().replaceFailed);
69
84
  return result.replaced;
70
85
  },
71
86
  bold: () => commandSugar('bold'),
@@ -92,7 +107,7 @@ export function createMacroApi(host, options = {}) {
92
107
  async call(method, args) {
93
108
  const fn = methods[method];
94
109
  if (typeof fn !== 'function' || !Object.prototype.hasOwnProperty.call(api, method)) {
95
- throw new MacroError(`מתודה לא מוכרת: ${String(method)}`);
110
+ throw new MacroError(macroMessages().unknownMethod(String(method)));
96
111
  }
97
112
  calls += 1;
98
113
  return fn.apply(api, args);
@@ -1,4 +1,4 @@
1
- /** חוזה משותף לשני המריצים (eval ו-iframe). */
1
+ /** Contract shared by the two runners (eval and iframe). */
2
2
  import type { MacroBridge } from './macro-api.js';
3
3
  export type MacroRunResult = {
4
4
  ok: true;
@@ -9,9 +9,9 @@ export type MacroRunResult = {
9
9
  reason?: 'timeout' | 'error' | 'call-limit';
10
10
  };
11
11
  export interface MacroRunOptions {
12
- /** תקרת זמן לריצה כולה. ברירת מחדל: 30 שניות. */
12
+ /** Time cap for the whole run. Default: 30 seconds. */
13
13
  timeoutMs?: number;
14
- /** תקרת קריאות API, נגד לולאה בורחת. ברירת מחדל: 10,000. */
14
+ /** API call cap, against runaway loops. Default: 10,000. */
15
15
  maxApiCalls?: number;
16
16
  }
17
17
  export declare const DEFAULT_TIMEOUT_MS = 30000;
@@ -1,7 +1,8 @@
1
1
  /**
2
- * קיצורי מקלדת למאקרו ולקטעים: ניתוח מחרוזת `Ctrl+Alt+M` והתאמה לאירוע.
2
+ * Keyboard shortcuts for macros and snippets: parsing a `Ctrl+Alt+M` string
3
+ * and matching it against an event.
3
4
  *
4
- * ההתאמה לפי `event.key` באותיות קטנות. `Mod` פירושו Ctrl (אובמק).
5
+ * Matching is by lowercased `event.key`. `Mod` means Ctrl (oron macOS).
5
6
  */
6
7
  export interface ParsedShortcut {
7
8
  key: string;
@@ -9,10 +10,10 @@ export interface ParsedShortcut {
9
10
  alt: boolean;
10
11
  shift: boolean;
11
12
  meta: boolean;
12
- /** Ctrl או Meta — לקיצורים שנכתבו עם `Mod`. */
13
+ /** Ctrl or Meta — for shortcuts written with `Mod`. */
13
14
  mod: boolean;
14
15
  }
15
- /** תת-הצורה של KeyboardEvent שההתאמה צריכה. מאפשר בדיקות בלי DOM. */
16
+ /** The subset of KeyboardEvent that matching needs. Enables DOM-free tests. */
16
17
  export interface KeyEventLike {
17
18
  key: string;
18
19
  ctrlKey: boolean;
@@ -33,7 +34,8 @@ export interface ShortcutTarget {
33
34
  removeEventListener(type: 'keydown', listener: (event: KeyboardEvent) => void, options?: boolean): void;
34
35
  }
35
36
  /**
36
- * קושרת קיצורים ליעד. `getBindings` נקראת בכל הקשה כך רשימת המאקרו יכולה
37
- * להשתנות בלי לקשור מחדש. מחזירה פונקציית ניתוק.
37
+ * Binds shortcuts to a target. `getBindings` is called on every keystroke
38
+ * so the macro list can change without rebinding. Returns a dispose
39
+ * function.
38
40
  */
39
41
  export declare function bindShortcuts(target: ShortcutTarget, getBindings: () => readonly ShortcutBinding[]): () => void;
package/dist/shortcuts.js CHANGED
@@ -29,7 +29,7 @@ export function parseShortcut(shortcut) {
29
29
  break;
30
30
  default: {
31
31
  if (parsed.key)
32
- return null; // שני מקשים שאינם modifiers קיצור פסול.
32
+ return null; // two non-modifier keysan invalid shortcut.
33
33
  parsed.key = normalizeKey(part);
34
34
  }
35
35
  }
@@ -50,7 +50,7 @@ export function eventMatches(parsed, event) {
50
50
  if (parsed.mod) {
51
51
  if (!event.ctrlKey && !event.metaKey)
52
52
  return false;
53
- // עם Mod לא בודקים ctrl/meta בנפרדאבל alt/shift חייבים להתאים בדיוק.
53
+ // With Mod, ctrl/meta are not checked individually but alt/shift must match exactly.
54
54
  return event.altKey === parsed.alt && event.shiftKey === parsed.shift;
55
55
  }
56
56
  return (event.ctrlKey === parsed.ctrl &&
@@ -59,8 +59,9 @@ export function eventMatches(parsed, event) {
59
59
  event.metaKey === parsed.meta);
60
60
  }
61
61
  /**
62
- * קושרת קיצורים ליעד. `getBindings` נקראת בכל הקשה כך רשימת המאקרו יכולה
63
- * להשתנות בלי לקשור מחדש. מחזירה פונקציית ניתוק.
62
+ * Binds shortcuts to a target. `getBindings` is called on every keystroke
63
+ * so the macro list can change without rebinding. Returns a dispose
64
+ * function.
64
65
  */
65
66
  export function bindShortcuts(target, getBindings) {
66
67
  const listener = (event) => {
@@ -1,25 +1,28 @@
1
1
  /**
2
- * השלמה אוטומטית (AutoText): הקלדת מילת ההפעלה של קטע ואחריה רווח מחליפה את
3
- * המילה בתוכן הקטע.
2
+ * Auto-text: typing a snippet's trigger word followed by a space replaces
3
+ * the word with the snippet's content.
4
4
  *
5
- * איך זה עובד: נשמר חוצץ קטן של התווים שהוקלדו ברצף הנוכחי (מתוך אירועי
6
- * `TextInputEvent` של המארח). כשמוקלד תו הרחבה (רווח כברירת מחדל) והמילה
7
- * שלפניו היא trigger של קטע המילה ותו ההרחבה נמחקים לאחור, והתוכן המורחב
8
- * מוכנס במקומם עם תו ההרחבה בסופו.
5
+ * How it works: a small buffer keeps the characters typed in the current run
6
+ * (from the host's `TextInputEvent`s). When an expansion character (space by
7
+ * default) is typed and the word before it is some snippet's trigger, the
8
+ * word and the expansion character are deleted backwards and the rendered
9
+ * content is inserted in their place, with the expansion character restored
10
+ * at the end.
9
11
  *
10
- * החוצץ מתאפס על פסקה חדשה, על מחיקה קדימה ועל פקודה שרצה באמצע כל דבר
11
- * שמנתק את הרצף בין מה שהוקלד ובין מה שנמצא בפועל לפני הסמן. עדיף פספוס
12
- * הרחבה על הרחבה שמוחקת טקסט לא נכון.
12
+ * The buffer resets on a new paragraph, on forward deletion and on a command
13
+ * running mid-typing anything that breaks the correspondence between what
14
+ * was typed and what actually sits before the caret. A missed expansion is
15
+ * better than an expansion that deletes the wrong text.
13
16
  */
14
17
  import type { MacroHost, Snippet } from '../types.js';
15
18
  export interface AutoTextOptions {
16
- /** תווי ההרחבה. ברירת מחדל: רווח בלבד. */
19
+ /** The expansion characters. Default: space only. */
17
20
  expandOn?: readonly string[];
18
- /** גודל החוצץ. מילת הפעלה ארוכה מזה לא תזוהה. */
21
+ /** Buffer size. A trigger word longer than this will not be recognized. */
19
22
  bufferSize?: number;
20
- /** נקראת אחרי הרחבה מוצלחת. */
23
+ /** Called after a successful expansion. */
21
24
  onExpand?: (snippet: Snippet) => void;
22
- /** נקראת כשהרחבה נכשלה (למשל מסמך לקריאה בלבד). */
25
+ /** Called when an expansion failed (e.g. a read-only document). */
23
26
  onError?: (message: string) => void;
24
27
  }
25
28
  export declare class AutoText {
@@ -27,7 +27,7 @@ export class AutoText {
27
27
  return () => this.detach();
28
28
  this.buffer = '';
29
29
  this.disposeInput = this.host.onTextInput((event) => void this.handleInput(event));
30
- // פקודה באמצע הקלדה (עיצוב, הדבקה) מנתקת את הקשר בין החוצץ למסמך.
30
+ // A command mid-typing (formatting, paste) breaks the buffer's link to the document.
31
31
  this.disposeCommand = this.host.onCommand(() => {
32
32
  if (!this.busy)
33
33
  this.buffer = '';
@@ -42,7 +42,7 @@ export class AutoText {
42
42
  this.buffer = '';
43
43
  }
44
44
  async handleInput(event) {
45
- // קלט שנוצר בזמן שההרחבה עצמה כותבתלא חלק מההקלדה של המשתמש.
45
+ // Input generated while the expansion itself is writing not the user's typing.
46
46
  if (this.busy)
47
47
  return;
48
48
  switch (event.kind) {
@@ -74,14 +74,16 @@ export class AutoText {
74
74
  async expand(snippet, trigger, expandChar) {
75
75
  this.busy = true;
76
76
  try {
77
- // אירוע הקלט (beforeinput) נורה לפני שהתו נכתב למסמך. הדחייה לתור
78
- // המשימות מבטיחה שתו ההרחבה כבר בפנים לפני שמוחקים אותו יחד עם ה-trigger.
77
+ // The input event (beforeinput) fires before the character is written
78
+ // to the document. Deferring to the task queue guarantees the expansion
79
+ // character is already in before it is deleted along with the trigger.
79
80
  await new Promise((resolve) => setTimeout(resolve, 0));
80
81
  const selectionText = usesSelection(snippet.text)
81
82
  ? (await this.host.getSelection({ includeText: true })).text
82
83
  : undefined;
83
84
  const rendered = renderSnippet(snippet.text, { selectionText });
84
- // תו ההרחבה כבר נכתב למסמך כשמגיעים לכאן, ולכן הוא נכלל במחיקה ומוחזר בסוף.
85
+ // The expansion character is already in the document by now, so it is
86
+ // included in the deletion and restored at the end.
85
87
  const deleted = await this.host.deleteBackward(trigger.length + 1);
86
88
  if (!deleted.ok) {
87
89
  this.onError?.(deleted.message);
@@ -99,7 +101,7 @@ export class AutoText {
99
101
  }
100
102
  }
101
103
  }
102
- /** המילה שבסוף החוצץרצף שאינו רווח לבן. */
104
+ /** The word at the end of the buffer a run of non-whitespace. */
103
105
  function trailingWord(buffer) {
104
106
  const match = /(\S+)$/u.exec(buffer);
105
107
  return match?.[1] ?? null;
@@ -1,26 +1,30 @@
1
1
  /**
2
- * קטעי טקסט (Snippets): תבניות שמוכנסות במיקום הסמן, עם משתני `{{...}}`.
2
+ * Text snippets: templates inserted at the caret, with `{{...}}` variables.
3
3
  *
4
- * משתנים מובנים: `{{date}}`, `{{time}}`, `{{datetime}}` (בעברית, לפי שעון
5
- * המערכת), `{{selection}}` (הטקסט המסומן ברגע ההרחבה). כל שם אחר נפתר מתוך
6
- * `variables` שנמסרו בקריאה; משתנה שאין לו ערך נשאר כמו שהוא בטקסט — כדי
7
- * שטעות כתיב תיראה במסמך ולא תיעלם בשקט.
4
+ * Built-in variables: `{{date}}`, `{{time}}`, `{{datetime}}` (system clock,
5
+ * formatted with the configured locale) and `{{selection}}` (the selected
6
+ * text at expansion time). Any other name resolves from the `variables`
7
+ * passed to the call; a variable with no value stays visible in the text —
8
+ * so a typo shows up in the document instead of vanishing silently.
8
9
  */
9
10
  import type { MacroHost, MacroOutcome, Snippet } from '../types.js';
10
11
  export interface RenderContext {
11
- /** ערכים למשתנים מותאמים. */
12
+ /** Values for custom variables. */
12
13
  variables?: Readonly<Record<string, string>>;
13
- /** הטקסט שיוצב ב-`{{selection}}`. */
14
+ /** The text substituted for `{{selection}}`. */
14
15
  selectionText?: string;
15
- /** הזמן ל-`{{date}}`/`{{time}}`. ברירת מחדל: עכשיו. קיים בשביל בדיקות. */
16
+ /** The time for `{{date}}`/`{{time}}`. Default: now. Exists for tests. */
16
17
  now?: Date;
18
+ /** BCP-47 locale for date/time formatting. Default: the browser's. */
19
+ locale?: string;
17
20
  }
18
21
  export declare function renderSnippet(text: string, context?: RenderContext): string;
19
- /** האם הקטע משתמש ב-`{{selection}}` — ואז ההרחבה צריכה לקרוא את הבחירה. */
22
+ /** Whether the snippet uses `{{selection}}` — in which case expansion must read the selection. */
20
23
  export declare function usesSelection(text: string): boolean;
21
24
  export interface ExpandOptions {
22
25
  variables?: Readonly<Record<string, string>>;
23
26
  now?: Date;
27
+ locale?: string;
24
28
  }
25
- /** מרחיבה קטע במיקום הסמן. */
29
+ /** Expands a snippet at the caret. */
26
30
  export declare function expandSnippet(host: MacroHost, snippet: Pick<Snippet, 'text'>, options?: ExpandOptions): Promise<MacroOutcome>;
@@ -1,15 +1,16 @@
1
1
  const VARIABLE_PATTERN = /\{\{\s*([\p{L}\p{N}_-]+)\s*\}\}/gu;
2
2
  export function renderSnippet(text, context = {}) {
3
3
  const now = context.now ?? new Date();
4
+ const locale = context.locale;
4
5
  return text.replace(VARIABLE_PATTERN, (whole, rawName) => {
5
6
  const name = rawName.toLowerCase();
6
7
  switch (name) {
7
8
  case 'date':
8
- return now.toLocaleDateString('he-IL');
9
+ return now.toLocaleDateString(locale);
9
10
  case 'time':
10
- return now.toLocaleTimeString('he-IL', { hour: '2-digit', minute: '2-digit' });
11
+ return now.toLocaleTimeString(locale, { hour: '2-digit', minute: '2-digit' });
11
12
  case 'datetime':
12
- return `${now.toLocaleDateString('he-IL')} ${now.toLocaleTimeString('he-IL', { hour: '2-digit', minute: '2-digit' })}`;
13
+ return `${now.toLocaleDateString(locale)} ${now.toLocaleTimeString(locale, { hour: '2-digit', minute: '2-digit' })}`;
13
14
  case 'selection':
14
15
  return context.selectionText ?? '';
15
16
  default: {
@@ -19,13 +20,13 @@ export function renderSnippet(text, context = {}) {
19
20
  }
20
21
  });
21
22
  }
22
- /** האם הקטע משתמש ב-`{{selection}}` — ואז ההרחבה צריכה לקרוא את הבחירה. */
23
+ /** Whether the snippet uses `{{selection}}` — in which case expansion must read the selection. */
23
24
  export function usesSelection(text) {
24
25
  return /\{\{\s*selection\s*\}\}/iu.test(text);
25
26
  }
26
- /** מרחיבה קטע במיקום הסמן. */
27
+ /** Expands a snippet at the caret. */
27
28
  export async function expandSnippet(host, snippet, options = {}) {
28
- // הבחירה נקראת רק כשנחוצה: חילוץ טקסט הבחירה עולה בביצועים במנוע.
29
+ // The selection is read only when needed: extracting its text has an engine cost.
29
30
  const selectionText = usesSelection(snippet.text)
30
31
  ? (await host.getSelection({ includeText: true })).text
31
32
  : undefined;
@@ -33,6 +34,7 @@ export async function expandSnippet(host, snippet, options = {}) {
33
34
  variables: options.variables,
34
35
  selectionText,
35
36
  now: options.now,
37
+ locale: options.locale,
36
38
  });
37
39
  return host.insertText(rendered);
38
40
  }
package/dist/storage.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
- * שמירת המאקרו, ההקלטות והקטעים. ברירת המחדל: localStorage; הממשק ניתן
3
- * להחלפה כדי שמארח יוכל לשמור בקובץ (למשל ב-workspace של תוסף אוצריא).
2
+ * Persistence for macros, recordings and snippets. Default: localStorage;
3
+ * the interface is swappable so a host can persist to a file (e.g. a
4
+ * plugin workspace).
4
5
  */
5
6
  import type { RecordedMacro, SavedScript, Snippet } from './types.js';
6
7
  export interface PersistedMacroState {
@@ -10,15 +11,15 @@ export interface PersistedMacroState {
10
11
  snippets: Snippet[];
11
12
  }
12
13
  export interface MacroStorage {
13
- /** `null` כשאין מצב שמור או כשהשמור אינו קריא. */
14
+ /** `null` when there is no saved state or the saved state is unreadable. */
14
15
  load(): PersistedMacroState | null;
15
16
  save(state: PersistedMacroState): void;
16
17
  }
17
18
  export declare function emptyState(): PersistedMacroState;
18
- /** מפענחת מצב שמור. `null` על כל צורה לא צפויה לא זורקת. */
19
+ /** Parses saved state. `null` on any unexpected shapenever throws. */
19
20
  export declare function parsePersistedState(json: string): PersistedMacroState | null;
20
21
  export declare const DEFAULT_STORAGE_KEY = "superdoc-macros:v1";
21
- /** localStorage עם הגנות: גישה חסומה או מלאה אינה מפילה את הערכה. */
22
+ /** localStorage with guards: blocked or full storage must not take the toolkit down. */
22
23
  export declare function createLocalStorage(key?: string, storage?: Pick<Storage, 'getItem' | 'setItem'>): MacroStorage;
23
- /** אחסון בזיכרוןלבדיקות ולמצבים שבהם אין persistence. */
24
+ /** In-memory storagefor tests and for setups with no persistence. */
24
25
  export declare function createMemoryStorage(): MacroStorage;
package/dist/storage.js CHANGED
@@ -10,7 +10,7 @@ function isValidState(value) {
10
10
  Array.isArray(state.recordings) &&
11
11
  Array.isArray(state.snippets));
12
12
  }
13
- /** מפענחת מצב שמור. `null` על כל צורה לא צפויה לא זורקת. */
13
+ /** Parses saved state. `null` on any unexpected shapenever throws. */
14
14
  export function parsePersistedState(json) {
15
15
  try {
16
16
  const parsed = JSON.parse(json);
@@ -21,7 +21,7 @@ export function parsePersistedState(json) {
21
21
  }
22
22
  }
23
23
  export const DEFAULT_STORAGE_KEY = 'superdoc-macros:v1';
24
- /** localStorage עם הגנות: גישה חסומה או מלאה אינה מפילה את הערכה. */
24
+ /** localStorage with guards: blocked or full storage must not take the toolkit down. */
25
25
  export function createLocalStorage(key = DEFAULT_STORAGE_KEY, storage) {
26
26
  const backing = () => {
27
27
  if (storage)
@@ -48,12 +48,12 @@ export function createLocalStorage(key = DEFAULT_STORAGE_KEY, storage) {
48
48
  backing()?.setItem(key, JSON.stringify(state));
49
49
  }
50
50
  catch (error) {
51
- console.warn('[superdoc-macros] שמירת המאקרו נכשלה', error);
51
+ console.warn('[superdoc-macros] saving macros failed', error);
52
52
  }
53
53
  },
54
54
  };
55
55
  }
56
- /** אחסון בזיכרוןלבדיקות ולמצבים שבהם אין persistence. */
56
+ /** In-memory storagefor tests and for setups with no persistence. */
57
57
  export function createMemoryStorage() {
58
58
  let saved = null;
59
59
  return {