myrole-docx-editor 0.3.0 → 0.3.1

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,5 +1,5 @@
1
1
  import * as s from "blockly";
2
- import { k as p, T as u, m, n as f, o as g, q as h } from "./sdk-CU9i-NwD.js";
2
+ import { k as p, T as u, m, n as f, o as g, q as h } from "./sdk-Bi8qAaV_.js";
3
3
  let r = !1;
4
4
  function b(o, n, i) {
5
5
  r || (p(), r = !0), o.replaceChildren();
@@ -39,4 +39,4 @@ function b(o, n, i) {
39
39
  export {
40
40
  b as mountBlockly
41
41
  };
42
- //# sourceMappingURL=vars-blockly-CBim6Ow0.js.map
42
+ //# sourceMappingURL=vars-blockly-BVG2ZfAW.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"vars-blockly-CBim6Ow0.js","sources":["../../src/vars-blockly.ts"],"sourcesContent":["import * as Blockly from 'blockly'\nimport {\n decorate, defineBlocks, fieldLibrary, setFields, THEME, TOOLBOX,\n type BlockJson,\n} from '@myrole/docx-vars'\nimport type { Tag } from '@myrole/docx-tags'\n\n/**\n * Le mode Blockly, chargé à la demande.\n *\n * Le canvas ne se replie pas — c'est ce qui a fait choisir le rendu DOM par\n * défaut — mais il sait ce que le DOM ne fait pas encore aussi bien :\n * restructurer librement une expression au glisser-déposer, avec sa poubelle,\n * son annulation et ses connexions typées.\n *\n * Il vit dans son propre module pour ne peser que si on l'ouvre : un\n * mégaoctet et demi qu'un utilisateur qui ne bascule jamais ne télécharge pas.\n */\n\nlet defined = false\n\nexport interface BlocklyView {\n load(tree: BlockJson): void\n read(): BlockJson | null\n resize(): void\n dispose(): void\n}\n\nexport function mountBlockly(\n holder: HTMLElement, onChange: () => void, tags: () => Tag[],\n): BlocklyView {\n if (!defined) { defineBlocks(); defined = true }\n holder.replaceChildren()\n const host = document.createElement('div')\n host.className = 'vp-canvas-host'\n holder.append(host)\n\n const ws = Blockly.inject(host, {\n // La boîte à outils : sans elle, on peut lire une expression et la\n // rebrancher, mais pas y AJOUTER quoi que ce soit — c'est la moitié de ce\n // qu'on vient chercher dans un canvas de blocs.\n toolbox: TOOLBOX,\n theme: THEME,\n renderer: 'geras',\n trashcan: true,\n sounds: false,\n grid: { spacing: 20, length: 1, colour: '#e8e9ed', snap: false },\n zoom: { controls: true, wheel: true, startScale: 0.95, minScale: 0.3, maxScale: 2 },\n move: { scrollbars: true, drag: true, wheel: true },\n })\n ws.addChangeListener((e) => { if (!e.isUiEvent) onChange() })\n\n return {\n load(tree) {\n // `setFields` alimente le sélecteur du bloc « champ » : sans lui, un clic\n // sur un champ n'ouvre rien.\n const groups = fieldLibrary(tags())\n setFields(groups.flatMap((g) => g.fields.map((f) => ({ path: f.path, label: f.label }))))\n Blockly.serialization.workspaces.load({ blocks: { languageVersion: 0, blocks: [tree] } }, ws)\n decorate(ws)\n Blockly.svgResize(ws)\n },\n read() {\n const state = Blockly.serialization.workspaces.save(ws) as {\n blocks?: { blocks?: BlockJson[] }\n }\n return state?.blocks?.blocks?.[0] ?? null\n },\n resize() { Blockly.svgResize(ws) },\n dispose() { ws.dispose() },\n }\n}\n"],"names":["defined","mountBlockly","holder","onChange","tags","defineBlocks","host","ws","Blockly","TOOLBOX","THEME","e","tree","groups","fieldLibrary","setFields","g","f","decorate"],"mappings":";;AAmBA,IAAIA,IAAU;AASP,SAASC,EACdC,GAAqBC,GAAsBC,GAC9B;AACb,EAAKJ,MAAWK,EAAA,GAAgBL,IAAU,KAC1CE,EAAO,gBAAA;AACP,QAAMI,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY,kBACjBJ,EAAO,OAAOI,CAAI;AAElB,QAAMC,IAAKC,EAAQ,OAAOF,GAAM;AAAA;AAAA;AAAA;AAAA,IAI9B,SAASG;AAAA,IACT,OAAOC;AAAA,IACP,UAAU;AAAA,IACV,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM,EAAE,SAAS,IAAI,QAAQ,GAAG,QAAQ,WAAW,MAAM,GAAA;AAAA,IACzD,MAAM,EAAE,UAAU,IAAM,OAAO,IAAM,YAAY,MAAM,UAAU,KAAK,UAAU,EAAA;AAAA,IAChF,MAAM,EAAE,YAAY,IAAM,MAAM,IAAM,OAAO,GAAA;AAAA,EAAK,CACnD;AACD,SAAAH,EAAG,kBAAkB,CAACI,MAAM;AAAE,IAAKA,EAAE,aAAWR,EAAA;AAAA,EAAW,CAAC,GAErD;AAAA,IACL,KAAKS,GAAM;AAGT,YAAMC,IAASC,EAAaV,GAAM;AAClC,MAAAW,EAAUF,EAAO,QAAQ,CAACG,MAAMA,EAAE,OAAO,IAAI,CAACC,OAAO,EAAE,MAAMA,EAAE,MAAM,OAAOA,EAAE,MAAA,EAAQ,CAAC,CAAC,GACxFT,EAAQ,cAAc,WAAW,KAAK,EAAE,QAAQ,EAAE,iBAAiB,GAAG,QAAQ,CAACI,CAAI,EAAA,EAAE,GAAKL,CAAE,GAC5FW,EAASX,CAAE,GACXC,EAAQ,UAAUD,CAAE;AAAA,IACtB;AAAA,IACA,OAAO;AAIL,aAHcC,EAAQ,cAAc,WAAW,KAAKD,CAAE,GAGxC,QAAQ,SAAS,CAAC,KAAK;AAAA,IACvC;AAAA,IACA,SAAS;AAAE,MAAAC,EAAQ,UAAUD,CAAE;AAAA,IAAE;AAAA,IACjC,UAAU;AAAE,MAAAA,EAAG,QAAA;AAAA,IAAU;AAAA,EAAA;AAE7B;"}
1
+ {"version":3,"file":"vars-blockly-BVG2ZfAW.js","sources":["../../src/vars-blockly.ts"],"sourcesContent":["import * as Blockly from 'blockly'\nimport {\n decorate, defineBlocks, fieldLibrary, setFields, THEME, TOOLBOX,\n type BlockJson,\n} from '@myrole/docx-vars'\nimport type { Tag } from '@myrole/docx-tags'\n\n/**\n * Le mode Blockly, chargé à la demande.\n *\n * Le canvas ne se replie pas — c'est ce qui a fait choisir le rendu DOM par\n * défaut — mais il sait ce que le DOM ne fait pas encore aussi bien :\n * restructurer librement une expression au glisser-déposer, avec sa poubelle,\n * son annulation et ses connexions typées.\n *\n * Il vit dans son propre module pour ne peser que si on l'ouvre : un\n * mégaoctet et demi qu'un utilisateur qui ne bascule jamais ne télécharge pas.\n */\n\nlet defined = false\n\nexport interface BlocklyView {\n load(tree: BlockJson): void\n read(): BlockJson | null\n resize(): void\n dispose(): void\n}\n\nexport function mountBlockly(\n holder: HTMLElement, onChange: () => void, tags: () => Tag[],\n): BlocklyView {\n if (!defined) { defineBlocks(); defined = true }\n holder.replaceChildren()\n const host = document.createElement('div')\n host.className = 'vp-canvas-host'\n holder.append(host)\n\n const ws = Blockly.inject(host, {\n // La boîte à outils : sans elle, on peut lire une expression et la\n // rebrancher, mais pas y AJOUTER quoi que ce soit — c'est la moitié de ce\n // qu'on vient chercher dans un canvas de blocs.\n toolbox: TOOLBOX,\n theme: THEME,\n renderer: 'geras',\n trashcan: true,\n sounds: false,\n grid: { spacing: 20, length: 1, colour: '#e8e9ed', snap: false },\n zoom: { controls: true, wheel: true, startScale: 0.95, minScale: 0.3, maxScale: 2 },\n move: { scrollbars: true, drag: true, wheel: true },\n })\n ws.addChangeListener((e) => { if (!e.isUiEvent) onChange() })\n\n return {\n load(tree) {\n // `setFields` alimente le sélecteur du bloc « champ » : sans lui, un clic\n // sur un champ n'ouvre rien.\n const groups = fieldLibrary(tags())\n setFields(groups.flatMap((g) => g.fields.map((f) => ({ path: f.path, label: f.label }))))\n Blockly.serialization.workspaces.load({ blocks: { languageVersion: 0, blocks: [tree] } }, ws)\n decorate(ws)\n Blockly.svgResize(ws)\n },\n read() {\n const state = Blockly.serialization.workspaces.save(ws) as {\n blocks?: { blocks?: BlockJson[] }\n }\n return state?.blocks?.blocks?.[0] ?? null\n },\n resize() { Blockly.svgResize(ws) },\n dispose() { ws.dispose() },\n }\n}\n"],"names":["defined","mountBlockly","holder","onChange","tags","defineBlocks","host","ws","Blockly","TOOLBOX","THEME","e","tree","groups","fieldLibrary","setFields","g","f","decorate"],"mappings":";;AAmBA,IAAIA,IAAU;AASP,SAASC,EACdC,GAAqBC,GAAsBC,GAC9B;AACb,EAAKJ,MAAWK,EAAA,GAAgBL,IAAU,KAC1CE,EAAO,gBAAA;AACP,QAAMI,IAAO,SAAS,cAAc,KAAK;AACzC,EAAAA,EAAK,YAAY,kBACjBJ,EAAO,OAAOI,CAAI;AAElB,QAAMC,IAAKC,EAAQ,OAAOF,GAAM;AAAA;AAAA;AAAA;AAAA,IAI9B,SAASG;AAAA,IACT,OAAOC;AAAA,IACP,UAAU;AAAA,IACV,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM,EAAE,SAAS,IAAI,QAAQ,GAAG,QAAQ,WAAW,MAAM,GAAA;AAAA,IACzD,MAAM,EAAE,UAAU,IAAM,OAAO,IAAM,YAAY,MAAM,UAAU,KAAK,UAAU,EAAA;AAAA,IAChF,MAAM,EAAE,YAAY,IAAM,MAAM,IAAM,OAAO,GAAA;AAAA,EAAK,CACnD;AACD,SAAAH,EAAG,kBAAkB,CAACI,MAAM;AAAE,IAAKA,EAAE,aAAWR,EAAA;AAAA,EAAW,CAAC,GAErD;AAAA,IACL,KAAKS,GAAM;AAGT,YAAMC,IAASC,EAAaV,GAAM;AAClC,MAAAW,EAAUF,EAAO,QAAQ,CAACG,MAAMA,EAAE,OAAO,IAAI,CAACC,OAAO,EAAE,MAAMA,EAAE,MAAM,OAAOA,EAAE,MAAA,EAAQ,CAAC,CAAC,GACxFT,EAAQ,cAAc,WAAW,KAAK,EAAE,QAAQ,EAAE,iBAAiB,GAAG,QAAQ,CAACI,CAAI,EAAA,EAAE,GAAKL,CAAE,GAC5FW,EAASX,CAAE,GACXC,EAAQ,UAAUD,CAAE;AAAA,IACtB;AAAA,IACA,OAAO;AAIL,aAHcC,EAAQ,cAAc,WAAW,KAAKD,CAAE,GAGxC,QAAQ,SAAS,CAAC,KAAK;AAAA,IACvC;AAAA,IACA,SAAS;AAAE,MAAAC,EAAQ,UAAUD,CAAE;AAAA,IAAE;AAAA,IACjC,UAAU;AAAE,MAAAA,EAAG,QAAA;AAAA,IAAU;AAAA,EAAA;AAE7B;"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { i as f, r as m, e as w, f as p, p as u, l as y, a as g, b as h, c as x } from "./chunks/sdk-CU9i-NwD.js";
2
- import { d as R, g as b, h as U, j, s as A } from "./chunks/sdk-CU9i-NwD.js";
1
+ import { i as f, r as m, e as w, f as p, p as u, l as y, a as g, b as h, c as x } from "./chunks/sdk-Bi8qAaV_.js";
2
+ import { d as R, g as b, h as U, j, s as A } from "./chunks/sdk-Bi8qAaV_.js";
3
3
  async function P(a, o, r = {}) {
4
4
  const i = performance.now(), [c] = await Promise.all([
5
5
  typeof a == "string" ? fetch(a).then((e) => e.ok ? e.arrayBuffer() : Promise.reject(new Error(`${e.status} ${a}`))) : Promise.resolve(a),
package/dist/react.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx as h } from "react/jsx-runtime";
2
2
  import { forwardRef as v, useRef as o, useEffect as a } from "react";
3
- import { d as y } from "./chunks/sdk-CU9i-NwD.js";
3
+ import { d as y } from "./chunks/sdk-Bi8qAaV_.js";
4
4
  const s = v(function({ src: u, className: b, style: S, onReady: g, ...e }, f) {
5
5
  const l = o(null), c = o(null), n = o(e);
6
6
  n.current = e;
@@ -0,0 +1,26 @@
1
+ import type { DocxEditorHandle } from './sdk';
2
+ /**
3
+ * The editor as the tool provider of a LOCAL MCP server.
4
+ *
5
+ * The tools run here, on the document open in this tab; `scripts/assistant-mcp.ts`
6
+ * only relays them between the MCP client (Claude Code) and the tab. Exactly one
7
+ * tab is connected at a time: the one where the user last pressed « Assistant ».
8
+ * The model never chooses which editor it drives, and it never sees a URL, a
9
+ * token or the package — only paragraph text, addressed by index.
10
+ *
11
+ * ponytail: body paragraphs only; headers, footers and notes when someone needs them.
12
+ */
13
+ export interface AssistantTool {
14
+ name: string;
15
+ description: string;
16
+ inputSchema: Record<string, unknown>;
17
+ readOnly: boolean;
18
+ }
19
+ export interface AssistantOptions {
20
+ /** the relay started by `scripts/assistant-mcp.ts` */
21
+ url?: string;
22
+ }
23
+ export declare const ASSISTANT_TOOLS: AssistantTool[];
24
+ export declare function runTool(handle: DocxEditorHandle, name: string, args: Record<string, unknown>): unknown;
25
+ /** The « Assistant » button of the status bar, and the connection it opens. */
26
+ export declare function mountAssistant(status: HTMLElement, handle: DocxEditorHandle, options?: AssistantOptions): () => void;
@@ -10,6 +10,7 @@
10
10
  export { createDocxEditor } from './sdk';
11
11
  export type { DocxEditorHandle, DocxEditorOptions, DocxEditorUiOptions, DocxEditorEvent, ChromeMode, Theme } from './sdk';
12
12
  export type { FeedbackReport, FeedbackContext, FeedbackOptions } from './feedback';
13
+ export type { AssistantOptions } from './assistant';
13
14
  export { renderDocx } from './embed';
14
15
  export type { Rendered } from './embed';
15
16
  export { installFonts, defaultFontsUrl } from './fonts';
@@ -21,6 +21,7 @@ import { type CommentRange } from './comments';
21
21
  import { type Panel, type DocxEditorUiOptions } from './ui/shell';
22
22
  import { type Draft } from './drafts';
23
23
  import { type FeedbackOptions } from './feedback';
24
+ import { type AssistantOptions } from './assistant';
24
25
  export type ChromeMode = 'full' | 'viewer' | 'none';
25
26
  export type Theme = 'light' | 'dark' | 'system';
26
27
  export type { DocxEditorUiOptions } from './ui/shell';
@@ -70,6 +71,8 @@ export interface DocxEditorOptions {
70
71
  comments?: boolean;
71
72
  /** Opt-in feedback button: true exports JSON; onSubmit routes the report to the host. */
72
73
  feedback?: boolean | FeedbackOptions;
74
+ /** Opt-in « Assistant » button: lends this tab's document to the local MCP relay (`scripts/assistant-mcp.ts`). */
75
+ assistant?: boolean | AssistantOptions;
73
76
  }
74
77
  export interface DocxEditorHandle {
75
78
  load(src: ArrayBuffer | Uint8Array | Blob | string, options?: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myrole-docx-editor",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Word-faithful .docx editor and renderer on canvas — the MyRole engine as an embeddable SDK, with a React component.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -46,21 +46,25 @@
46
46
  "react-dom": "^19.2.8",
47
47
  "vite": "^6.4.3",
48
48
  "@myrole/docx-model": "0.0.0",
49
- "@myrole/docx-render": "0.0.0",
50
49
  "@myrole/docx-tags": "0.0.0",
51
- "@myrole/docx-vars": "0.0.0",
52
- "@myrole/fonts": "0.1.0"
50
+ "@myrole/docx-render": "0.0.0",
51
+ "@myrole/fonts": "0.1.0",
52
+ "@myrole/docx-vars": "0.0.0"
53
53
  },
54
54
  "publishConfig": {
55
55
  "access": "public"
56
56
  },
57
57
  "scripts": {
58
58
  "fonts": "node scripts/pack-fonts.mjs",
59
- "build": "node scripts/pack-fonts.mjs && vite build && node scripts/types.mjs",
59
+ "build": "node scripts/pack-fonts.mjs && vite build && vite build --config vite.assistant.config.ts && node scripts/types.mjs",
60
60
  "watch": "vite build --watch",
61
- "check": "node scripts/pack-fonts.mjs && tsc -p tsconfig.json && tsx scripts/locking.test.ts",
61
+ "check": "node scripts/pack-fonts.mjs && tsc -p tsconfig.json && tsx scripts/locking.test.ts && tsx scripts/assistant-mcp.test.ts",
62
+ "assistant": "tsx scripts/assistant-mcp.ts",
62
63
  "types": "node scripts/types.mjs"
63
64
  },
65
+ "bin": {
66
+ "myrole-docx-assistant": "./dist/assistant-mcp.mjs"
67
+ },
64
68
  "typesVersions": {
65
69
  "*": {
66
70
  "react": [