myrole-docx-editor 0.3.1 → 0.5.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.
Files changed (260) hide show
  1. package/dist/assistant-mcp.mjs +208 -15
  2. package/dist/chunks/{sdk-Bi8qAaV_.js → sdk-DdtgYtTx.js} +12181 -10853
  3. package/dist/chunks/sdk-DdtgYtTx.js.map +1 -0
  4. package/dist/chunks/{vars-blockly-BVG2ZfAW.js → vars-blockly-BSiNa0Vb.js} +4 -4
  5. package/dist/chunks/{vars-blockly-BVG2ZfAW.js.map → vars-blockly-BSiNa0Vb.js.map} +1 -1
  6. package/dist/index.js +21 -22
  7. package/dist/index.js.map +1 -1
  8. package/dist/react.js +25 -23
  9. package/dist/react.js.map +1 -1
  10. package/dist/types/packages/docx-editor/src/assistant-tools.d.ts +16 -0
  11. package/dist/types/packages/docx-editor/src/assistant.d.ts +13 -15
  12. package/dist/types/packages/docx-editor/src/chrome.d.ts +2 -0
  13. package/dist/types/packages/docx-editor/src/editor.d.ts +25 -3
  14. package/dist/types/packages/docx-editor/src/fonts.d.ts +62 -4
  15. package/dist/types/packages/docx-editor/src/index.d.ts +2 -1
  16. package/dist/types/packages/docx-editor/src/react.d.ts +1 -0
  17. package/dist/types/packages/docx-editor/src/sdk.d.ts +11 -0
  18. package/dist/types/packages/docx-editor/src/ui/icons.d.ts +6 -0
  19. package/dist/types/packages/docx-editor/src/ui/perf-hud.d.ts +13 -0
  20. package/dist/types/packages/docx-editor/src/vars-complete.d.ts +9 -3
  21. package/dist/types/packages/docx-model/src/editor.d.ts +28 -0
  22. package/dist/types/packages/docx-model/src/index.d.ts +2 -0
  23. package/dist/types/packages/docx-model/src/paste.d.ts +12 -1
  24. package/dist/types/packages/docx-render/src/canvas-page.d.ts +2 -0
  25. package/dist/types/packages/docx-render/src/render-output.d.ts +1 -1
  26. package/dist/types/packages/docx-render/src/types.d.ts +2 -0
  27. package/dist/types/packages/docx-vars/src/icons.d.ts +36 -0
  28. package/dist/types/packages/docx-vars/src/target-canvas.d.ts +1 -0
  29. package/dist/types/packages/fonts/src/aliases.d.ts +14 -0
  30. package/dist/types/packages/fonts/src/metrics.d.ts +1 -1
  31. package/package.json +3 -5
  32. package/dist/chunks/sdk-Bi8qAaV_.js.map +0 -1
  33. package/fonts/ttf/abadi-mt-condensed-extra-bold-400-normal.ttf +0 -0
  34. package/fonts/ttf/abadi-mt-condensed-light-400-normal.ttf +0 -0
  35. package/fonts/ttf/angsana-new-400-italic.ttf +0 -0
  36. package/fonts/ttf/angsana-new-400-normal.ttf +0 -0
  37. package/fonts/ttf/angsana-new-700-italic.ttf +0 -0
  38. package/fonts/ttf/angsana-new-700-normal.ttf +0 -0
  39. package/fonts/ttf/apple-color-emoji-400-normal.ttf +0 -0
  40. package/fonts/ttf/apple-symbols-400-normal.ttf +0 -0
  41. package/fonts/ttf/aptos-400-italic.ttf +0 -0
  42. package/fonts/ttf/aptos-400-normal.ttf +0 -0
  43. package/fonts/ttf/aptos-700-italic.ttf +0 -0
  44. package/fonts/ttf/aptos-700-normal.ttf +0 -0
  45. package/fonts/ttf/aptos-narrow-400-italic.ttf +0 -0
  46. package/fonts/ttf/aptos-narrow-400-normal.ttf +0 -0
  47. package/fonts/ttf/aptos-narrow-700-italic.ttf +0 -0
  48. package/fonts/ttf/aptos-narrow-700-normal.ttf +0 -0
  49. package/fonts/ttf/arial-400-italic.ttf +0 -0
  50. package/fonts/ttf/arial-400-normal.ttf +0 -0
  51. package/fonts/ttf/arial-700-italic.ttf +0 -0
  52. package/fonts/ttf/arial-700-normal.ttf +0 -0
  53. package/fonts/ttf/arial-black-700-normal.ttf +0 -0
  54. package/fonts/ttf/arial-hebrew-400-normal.ttf +0 -0
  55. package/fonts/ttf/arial-hebrew-700-normal.ttf +0 -0
  56. package/fonts/ttf/arial-narrow-400-italic.ttf +0 -0
  57. package/fonts/ttf/arial-narrow-400-normal.ttf +0 -0
  58. package/fonts/ttf/arial-narrow-700-italic.ttf +0 -0
  59. package/fonts/ttf/arial-narrow-700-normal.ttf +0 -0
  60. package/fonts/ttf/arial-rounded-mt-bold-400-normal.ttf +0 -0
  61. package/fonts/ttf/arial-unicode-ms-400-normal.ttf +0 -0
  62. package/fonts/ttf/avenir-400-italic.ttf +0 -0
  63. package/fonts/ttf/avenir-400-normal.ttf +0 -0
  64. package/fonts/ttf/avenir-700-normal.ttf +0 -0
  65. package/fonts/ttf/avenir-black-700-normal.ttf +0 -0
  66. package/fonts/ttf/avenir-book-400-normal.ttf +0 -0
  67. package/fonts/ttf/avenir-heavy-700-italic.ttf +0 -0
  68. package/fonts/ttf/avenir-heavy-700-normal.ttf +0 -0
  69. package/fonts/ttf/avenir-light-400-italic.ttf +0 -0
  70. package/fonts/ttf/avenir-light-400-normal.ttf +0 -0
  71. package/fonts/ttf/avenir-next-400-italic.ttf +0 -0
  72. package/fonts/ttf/avenir-next-400-normal.ttf +0 -0
  73. package/fonts/ttf/avenir-next-700-italic.ttf +0 -0
  74. package/fonts/ttf/avenir-next-700-normal.ttf +0 -0
  75. package/fonts/ttf/baskerville-old-face-400-normal.ttf +0 -0
  76. package/fonts/ttf/batang-400-normal.ttf +0 -0
  77. package/fonts/ttf/bauhaus-93-400-normal.ttf +0 -0
  78. package/fonts/ttf/big-caslon-400-normal.ttf +0 -0
  79. package/fonts/ttf/bookman-old-style-400-italic.ttf +0 -0
  80. package/fonts/ttf/bookman-old-style-400-normal.ttf +0 -0
  81. package/fonts/ttf/bookman-old-style-700-italic.ttf +0 -0
  82. package/fonts/ttf/bookman-old-style-700-normal.ttf +0 -0
  83. package/fonts/ttf/calibri-400-italic.ttf +0 -0
  84. package/fonts/ttf/calibri-400-normal.ttf +0 -0
  85. package/fonts/ttf/calibri-700-italic.ttf +0 -0
  86. package/fonts/ttf/calibri-700-normal.ttf +0 -0
  87. package/fonts/ttf/calibri-light-400-italic.ttf +0 -0
  88. package/fonts/ttf/calibri-light-400-normal.ttf +0 -0
  89. package/fonts/ttf/cambria-400-italic.ttf +0 -0
  90. package/fonts/ttf/cambria-400-normal.ttf +0 -0
  91. package/fonts/ttf/cambria-700-italic.ttf +0 -0
  92. package/fonts/ttf/cambria-700-normal.ttf +0 -0
  93. package/fonts/ttf/cambria-math-400-normal.ttf +0 -0
  94. package/fonts/ttf/candara-400-italic.ttf +0 -0
  95. package/fonts/ttf/candara-400-normal.ttf +0 -0
  96. package/fonts/ttf/candara-700-italic.ttf +0 -0
  97. package/fonts/ttf/candara-700-normal.ttf +0 -0
  98. package/fonts/ttf/century-400-normal.ttf +0 -0
  99. package/fonts/ttf/century-gothic-400-italic.ttf +0 -0
  100. package/fonts/ttf/century-gothic-400-normal.ttf +0 -0
  101. package/fonts/ttf/century-gothic-700-italic.ttf +0 -0
  102. package/fonts/ttf/century-gothic-700-normal.ttf +0 -0
  103. package/fonts/ttf/century-schoolbook-400-italic.ttf +0 -0
  104. package/fonts/ttf/century-schoolbook-400-normal.ttf +0 -0
  105. package/fonts/ttf/century-schoolbook-700-italic.ttf +0 -0
  106. package/fonts/ttf/century-schoolbook-700-normal.ttf +0 -0
  107. package/fonts/ttf/comic-sans-ms-400-normal.ttf +0 -0
  108. package/fonts/ttf/comic-sans-ms-700-normal.ttf +0 -0
  109. package/fonts/ttf/consolas-400-italic.ttf +0 -0
  110. package/fonts/ttf/consolas-400-normal.ttf +0 -0
  111. package/fonts/ttf/consolas-700-normal.ttf +0 -0
  112. package/fonts/ttf/corbel-400-italic.ttf +0 -0
  113. package/fonts/ttf/corbel-400-normal.ttf +0 -0
  114. package/fonts/ttf/corbel-700-italic.ttf +0 -0
  115. package/fonts/ttf/corbel-700-normal.ttf +0 -0
  116. package/fonts/ttf/cordia-new-400-italic.ttf +0 -0
  117. package/fonts/ttf/cordia-new-400-normal.ttf +0 -0
  118. package/fonts/ttf/cordia-new-700-italic.ttf +0 -0
  119. package/fonts/ttf/cordia-new-700-normal.ttf +0 -0
  120. package/fonts/ttf/courier-400-normal.ttf +0 -0
  121. package/fonts/ttf/courier-new-400-italic.ttf +0 -0
  122. package/fonts/ttf/courier-new-400-normal.ttf +0 -0
  123. package/fonts/ttf/courier-new-700-normal.ttf +0 -0
  124. package/fonts/ttf/daytona-400-italic.ttf +0 -0
  125. package/fonts/ttf/daytona-400-normal.ttf +0 -0
  126. package/fonts/ttf/daytona-700-italic.ttf +0 -0
  127. package/fonts/ttf/daytona-700-normal.ttf +0 -0
  128. package/fonts/ttf/dengxian-400-normal.ttf +0 -0
  129. package/fonts/ttf/dengxian-700-normal.ttf +0 -0
  130. package/fonts/ttf/dengxian-light-400-normal.ttf +0 -0
  131. package/fonts/ttf/didot-400-italic.ttf +0 -0
  132. package/fonts/ttf/didot-400-normal.ttf +0 -0
  133. package/fonts/ttf/didot-700-normal.ttf +0 -0
  134. package/fonts/ttf/edwardian-script-itc-400-normal.ttf +0 -0
  135. package/fonts/ttf/euphemia-ucas-400-italic.ttf +0 -0
  136. package/fonts/ttf/euphemia-ucas-400-normal.ttf +0 -0
  137. package/fonts/ttf/euphemia-ucas-700-normal.ttf +0 -0
  138. package/fonts/ttf/eurostile-400-normal.ttf +0 -0
  139. package/fonts/ttf/eurostile-700-normal.ttf +0 -0
  140. package/fonts/ttf/franklin-gothic-book-400-italic.ttf +0 -0
  141. package/fonts/ttf/franklin-gothic-book-400-normal.ttf +0 -0
  142. package/fonts/ttf/franklin-gothic-demi-400-italic.ttf +0 -0
  143. package/fonts/ttf/franklin-gothic-demi-400-normal.ttf +0 -0
  144. package/fonts/ttf/franklin-gothic-demi-cond-400-normal.ttf +0 -0
  145. package/fonts/ttf/franklin-gothic-medium-400-italic.ttf +0 -0
  146. package/fonts/ttf/franklin-gothic-medium-400-normal.ttf +0 -0
  147. package/fonts/ttf/franklin-gothic-medium-cond-400-normal.ttf +0 -0
  148. package/fonts/ttf/futura-400-italic.ttf +0 -0
  149. package/fonts/ttf/futura-400-normal.ttf +0 -0
  150. package/fonts/ttf/futura-700-normal.ttf +0 -0
  151. package/fonts/ttf/garamond-400-italic.ttf +0 -0
  152. package/fonts/ttf/garamond-400-normal.ttf +0 -0
  153. package/fonts/ttf/garamond-700-italic.ttf +0 -0
  154. package/fonts/ttf/garamond-700-normal.ttf +0 -0
  155. package/fonts/ttf/geneva-400-normal.ttf +0 -0
  156. package/fonts/ttf/georgia-400-italic.ttf +0 -0
  157. package/fonts/ttf/georgia-400-normal.ttf +0 -0
  158. package/fonts/ttf/georgia-700-normal.ttf +0 -0
  159. package/fonts/ttf/gill-sans-400-italic.ttf +0 -0
  160. package/fonts/ttf/gill-sans-400-normal.ttf +0 -0
  161. package/fonts/ttf/gill-sans-700-italic.ttf +0 -0
  162. package/fonts/ttf/gill-sans-700-normal.ttf +0 -0
  163. package/fonts/ttf/gill-sans-light-400-italic.ttf +0 -0
  164. package/fonts/ttf/gill-sans-light-400-normal.ttf +0 -0
  165. package/fonts/ttf/gill-sans-mt-400-italic.ttf +0 -0
  166. package/fonts/ttf/gill-sans-mt-400-normal.ttf +0 -0
  167. package/fonts/ttf/gill-sans-mt-700-italic.ttf +0 -0
  168. package/fonts/ttf/gill-sans-mt-700-normal.ttf +0 -0
  169. package/fonts/ttf/helvetica-400-italic.ttf +0 -0
  170. package/fonts/ttf/helvetica-400-normal.ttf +0 -0
  171. package/fonts/ttf/helvetica-700-italic.ttf +0 -0
  172. package/fonts/ttf/helvetica-700-normal.ttf +0 -0
  173. package/fonts/ttf/helvetica-neue-400-italic.ttf +0 -0
  174. package/fonts/ttf/helvetica-neue-400-normal.ttf +0 -0
  175. package/fonts/ttf/helvetica-neue-700-italic.ttf +0 -0
  176. package/fonts/ttf/helvetica-neue-700-normal.ttf +0 -0
  177. package/fonts/ttf/hind-siliguri-400-normal.ttf +0 -0
  178. package/fonts/ttf/hind-siliguri-700-normal.ttf +0 -0
  179. package/fonts/ttf/hind-siliguri-light-400-normal.ttf +0 -0
  180. package/fonts/ttf/hind-siliguri-medium-400-normal.ttf +0 -0
  181. package/fonts/ttf/hind-siliguri-semibold-700-normal.ttf +0 -0
  182. package/fonts/ttf/hoefler-text-400-italic.ttf +0 -0
  183. package/fonts/ttf/hoefler-text-400-normal.ttf +0 -0
  184. package/fonts/ttf/hoefler-text-700-italic.ttf +0 -0
  185. package/fonts/ttf/hoefler-text-700-normal.ttf +0 -0
  186. package/fonts/ttf/lucida-grande-400-normal.ttf +0 -0
  187. package/fonts/ttf/lucida-grande-700-normal.ttf +0 -0
  188. package/fonts/ttf/lucida-sans-400-italic.ttf +0 -0
  189. package/fonts/ttf/lucida-sans-400-normal.ttf +0 -0
  190. package/fonts/ttf/lucida-sans-700-italic.ttf +0 -0
  191. package/fonts/ttf/lucida-sans-700-normal.ttf +0 -0
  192. package/fonts/ttf/lucida-sans-unicode-400-normal.ttf +0 -0
  193. package/fonts/ttf/malgun-gothic-400-normal.ttf +0 -0
  194. package/fonts/ttf/malgun-gothic-700-normal.ttf +0 -0
  195. package/fonts/ttf/mangal-400-normal.ttf +0 -0
  196. package/fonts/ttf/mangal-700-normal.ttf +0 -0
  197. package/fonts/ttf/microsoft-sans-serif-400-normal.ttf +0 -0
  198. package/fonts/ttf/microsoft-yahei-400-normal.ttf +0 -0
  199. package/fonts/ttf/microsoft-yahei-700-normal.ttf +0 -0
  200. package/fonts/ttf/microsoft-yi-baiti-400-normal.ttf +0 -0
  201. package/fonts/ttf/monotype-sorts-400-normal.ttf +0 -0
  202. package/fonts/ttf/ms-gothic-400-normal.ttf +0 -0
  203. package/fonts/ttf/ms-mincho-400-normal.ttf +0 -0
  204. package/fonts/ttf/ms-ui-gothic-400-normal.ttf +0 -0
  205. package/fonts/ttf/new-york-400-italic.ttf +0 -0
  206. package/fonts/ttf/new-york-400-normal.ttf +0 -0
  207. package/fonts/ttf/news-gothic-mt-400-italic.ttf +0 -0
  208. package/fonts/ttf/news-gothic-mt-400-normal.ttf +0 -0
  209. package/fonts/ttf/news-gothic-mt-700-italic.ttf +0 -0
  210. package/fonts/ttf/news-gothic-mt-700-normal.ttf +0 -0
  211. package/fonts/ttf/nsimsun-400-normal.ttf +0 -0
  212. package/fonts/ttf/optima-400-italic.ttf +0 -0
  213. package/fonts/ttf/optima-400-normal.ttf +0 -0
  214. package/fonts/ttf/optima-700-italic.ttf +0 -0
  215. package/fonts/ttf/optima-700-normal.ttf +0 -0
  216. package/fonts/ttf/palatino-400-italic.ttf +0 -0
  217. package/fonts/ttf/palatino-400-normal.ttf +0 -0
  218. package/fonts/ttf/palatino-700-italic.ttf +0 -0
  219. package/fonts/ttf/palatino-700-normal.ttf +0 -0
  220. package/fonts/ttf/palatino-linotype-400-italic.ttf +0 -0
  221. package/fonts/ttf/palatino-linotype-400-normal.ttf +0 -0
  222. package/fonts/ttf/palatino-linotype-700-italic.ttf +0 -0
  223. package/fonts/ttf/palatino-linotype-700-normal.ttf +0 -0
  224. package/fonts/ttf/pmingliu-400-normal.ttf +0 -0
  225. package/fonts/ttf/pt-mono-400-normal.ttf +0 -0
  226. package/fonts/ttf/pt-mono-700-normal.ttf +0 -0
  227. package/fonts/ttf/segoe-ui-symbol-400-normal.ttf +0 -0
  228. package/fonts/ttf/simsun-400-normal.ttf +0 -0
  229. package/fonts/ttf/skia-400-normal.ttf +0 -0
  230. package/fonts/ttf/stencil-400-normal.ttf +0 -0
  231. package/fonts/ttf/symbol-400-normal.ttf +0 -0
  232. package/fonts/ttf/tahoma-400-normal.ttf +0 -0
  233. package/fonts/ttf/tahoma-700-normal.ttf +0 -0
  234. package/fonts/ttf/times-400-italic.ttf +0 -0
  235. package/fonts/ttf/times-400-normal.ttf +0 -0
  236. package/fonts/ttf/times-700-italic.ttf +0 -0
  237. package/fonts/ttf/times-700-normal.ttf +0 -0
  238. package/fonts/ttf/times-new-roman-400-italic.ttf +0 -0
  239. package/fonts/ttf/times-new-roman-400-normal.ttf +0 -0
  240. package/fonts/ttf/times-new-roman-700-italic.ttf +0 -0
  241. package/fonts/ttf/times-new-roman-700-normal.ttf +0 -0
  242. package/fonts/ttf/trebuchet-ms-400-italic.ttf +0 -0
  243. package/fonts/ttf/trebuchet-ms-400-normal.ttf +0 -0
  244. package/fonts/ttf/trebuchet-ms-700-italic.ttf +0 -0
  245. package/fonts/ttf/trebuchet-ms-700-normal.ttf +0 -0
  246. package/fonts/ttf/tw-cen-mt-400-normal.ttf +0 -0
  247. package/fonts/ttf/tw-cen-mt-700-normal.ttf +0 -0
  248. package/fonts/ttf/tw-cen-mt-condensed-400-normal.ttf +0 -0
  249. package/fonts/ttf/tw-cen-mt-condensed-700-normal.ttf +0 -0
  250. package/fonts/ttf/verdana-400-italic.ttf +0 -0
  251. package/fonts/ttf/verdana-400-normal.ttf +0 -0
  252. package/fonts/ttf/verdana-700-italic.ttf +0 -0
  253. package/fonts/ttf/verdana-700-normal.ttf +0 -0
  254. package/fonts/ttf/webdings-400-normal.ttf +0 -0
  255. package/fonts/ttf/wingdings-2-400-normal.ttf +0 -0
  256. package/fonts/ttf/wingdings-3-400-normal.ttf +0 -0
  257. package/fonts/ttf/wingdings-400-normal.ttf +0 -0
  258. package/fonts/ttf/yu-gothic-light-400-normal.ttf +0 -0
  259. package/fonts/ttf/yu-mincho-400-normal.ttf +0 -0
  260. package/fonts/ttf/yu-mincho-700-normal.ttf +0 -0
@@ -1,7 +1,7 @@
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-Bi8qAaV_.js";
2
+ import { n as p, T as u, o as m, q as f, t as g, u as h } from "./sdk-DdtgYtTx.js";
3
3
  let r = !1;
4
- function b(o, n, i) {
4
+ function k(o, n, i) {
5
5
  r || (p(), r = !0), o.replaceChildren();
6
6
  const t = document.createElement("div");
7
7
  t.className = "vp-canvas-host", o.append(t);
@@ -37,6 +37,6 @@ function b(o, n, i) {
37
37
  };
38
38
  }
39
39
  export {
40
- b as mountBlockly
40
+ k as mountBlockly
41
41
  };
42
- //# sourceMappingURL=vars-blockly-BVG2ZfAW.js.map
42
+ //# sourceMappingURL=vars-blockly-BSiNa0Vb.js.map
@@ -1 +1 @@
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;"}
1
+ {"version":3,"file":"vars-blockly-BSiNa0Vb.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,33 +1,32 @@
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
- async function P(a, o, r = {}) {
4
- const i = performance.now(), [c] = await Promise.all([
5
- typeof a == "string" ? fetch(a).then((e) => e.ok ? e.arrayBuffer() : Promise.reject(new Error(`${e.status} ${a}`))) : Promise.resolve(a),
6
- f(r.fontsUrl)
7
- ]), t = m(new Uint8Array(c));
8
- for (const e of w(t))
1
+ import { r as u, e as y, d as h, f as g, i as x, a as D, p as F, l as R, b, c as v, g as E } from "./chunks/sdk-DdtgYtTx.js";
2
+ import { D as C, h as O, j as S, k as V, m as j, s as k } from "./chunks/sdk-DdtgYtTx.js";
3
+ async function P(t, o, n = {}) {
4
+ const d = performance.now(), f = typeof t == "string" ? await fetch(t).then((e) => e.ok ? e.arrayBuffer() : Promise.reject(new Error(`${e.status} ${t}`))) : t, a = u(new Uint8Array(f)), r = y(a), m = new Set(r.map((e) => e.family)), c = [...h(a)].filter((e) => !m.has(e)), i = g(a);
5
+ await x(n.fontsUrl, c, i);
6
+ for (const e of r)
9
7
  try {
10
- const s = p(e), n = new FontFace(s.family, e.data, { weight: s.weight, style: s.style });
11
- await n.load(), document.fonts.add(n);
8
+ const s = D(e), l = new FontFace(s.family, e.data, { weight: s.weight, style: s.style });
9
+ await l.load(), document.fonts.add(l);
12
10
  } catch {
13
11
  }
14
- const [l, d] = await Promise.all([u(t), y(r.fontsUrl)]);
15
- return o.replaceChildren(), g({
16
- ...x(t),
12
+ const [w, p] = await Promise.all([F(a), R(n.fontsUrl, c, i)]);
13
+ return o.replaceChildren(), b({
14
+ ...E(a),
17
15
  container: o,
18
- images: l,
19
- lineRatios: d,
20
- footnotes: h(t),
16
+ images: w,
17
+ lineRatios: p,
18
+ footnotes: v(a),
21
19
  devicePixelRatio: window.devicePixelRatio || 1
22
- }), { pages: [...o.querySelectorAll("canvas")], ms: Math.round(performance.now() - i) };
20
+ }), { pages: [...o.querySelectorAll("canvas")], ms: Math.round(performance.now() - d) };
23
21
  }
24
22
  export {
25
- R as createDocxEditor,
26
- b as createDocxViewer,
27
- U as defaultFontsUrl,
23
+ C as DOCX_EDITOR_VERSION,
24
+ O as createDocxEditor,
25
+ S as createDocxViewer,
26
+ V as defaultFontsUrl,
28
27
  j as evaluateTags,
29
- f as installFonts,
28
+ x as installFonts,
30
29
  P as renderDocx,
31
- A as sampleValues
30
+ k as sampleValues
32
31
  };
33
32
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/embed.ts"],"sourcesContent":["/**\n * The renderer, embeddable in ANY page served by the studio.\n *\n * The review dashboard shows a document next to Word's render: with this\n * module the canvas side is the engine composing the document LIVE in the\n * page, not a PNG the bench cached — so a change in the engine shows on the\n * next reload, and the slider compares what the editor would draw.\n *\n * const { pages } = await renderDocx('/corpus/<name>.docx', hiddenDiv)\n *\n * Fed by `buildRenderInput`, like the editor and the bench: the third surface\n * that mounts the renderer starts from there, as CLAUDE.md asks. What it adds\n * is the platform: fonts loaded before any measurement, embedded fonts of the\n * document, images decoded by the browser.\n */\nimport { embeddedFonts, fontFaceDescriptor, readDocx } from '@myrole/docx-model'\nimport { buildRenderInput, footnoteContent, render, preloadImages } from '@myrole/docx-render'\nimport { installFonts, lineRatios } from './fonts'\n\nexport interface Rendered {\n pages: HTMLCanvasElement[]\n ms: number\n}\n\nexport async function renderDocx(\n url: string | ArrayBuffer | Uint8Array, container: HTMLElement, opts: { fontsUrl?: string } = {},\n): Promise<Rendered> {\n const t0 = performance.now()\n const [buf] = await Promise.all([\n typeof url === 'string'\n ? fetch(url).then((r) => (r.ok ? r.arrayBuffer() : Promise.reject(new Error(`${r.status} ${url}`))))\n : Promise.resolve(url),\n installFonts(opts.fontsUrl),\n ])\n const doc = readDocx(new Uint8Array(buf))\n for (const f of embeddedFonts(doc)) {\n try {\n const d = fontFaceDescriptor(f)\n const face = new FontFace(d.family, f.data as BufferSource, { weight: d.weight, style: d.style })\n await face.load()\n document.fonts.add(face)\n } catch { /* police corrompue ou format non supporté */ }\n }\n const [images, ratios] = await Promise.all([preloadImages(doc), lineRatios(opts.fontsUrl)])\n container.replaceChildren()\n render({\n ...buildRenderInput(doc),\n container,\n images,\n lineRatios: ratios,\n footnotes: footnoteContent(doc),\n devicePixelRatio: window.devicePixelRatio || 1,\n })\n return { pages: [...container.querySelectorAll('canvas')], ms: Math.round(performance.now() - t0) }\n}\n"],"names":["renderDocx","url","container","opts","t0","buf","r","installFonts","doc","readDocx","f","embeddedFonts","d","fontFaceDescriptor","face","images","ratios","preloadImages","lineRatios","render","buildRenderInput","footnoteContent"],"mappings":";;AAwBA,eAAsBA,EACpBC,GAAwCC,GAAwBC,IAA8B,CAAA,GAC3E;AACnB,QAAMC,IAAK,YAAY,IAAA,GACjB,CAACC,CAAG,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC9B,OAAOJ,KAAQ,WACX,MAAMA,CAAG,EAAE,KAAK,CAACK,MAAOA,EAAE,KAAKA,EAAE,YAAA,IAAgB,QAAQ,OAAO,IAAI,MAAM,GAAGA,EAAE,MAAM,IAAIL,CAAG,EAAE,CAAC,CAAE,IACjG,QAAQ,QAAQA,CAAG;AAAA,IACvBM,EAAaJ,EAAK,QAAQ;AAAA,EAAA,CAC3B,GACKK,IAAMC,EAAS,IAAI,WAAWJ,CAAG,CAAC;AACxC,aAAWK,KAAKC,EAAcH,CAAG;AAC/B,QAAI;AACF,YAAMI,IAAIC,EAAmBH,CAAC,GACxBI,IAAO,IAAI,SAASF,EAAE,QAAQF,EAAE,MAAsB,EAAE,QAAQE,EAAE,QAAQ,OAAOA,EAAE,OAAO;AAChG,YAAME,EAAK,KAAA,GACX,SAAS,MAAM,IAAIA,CAAI;AAAA,IACzB,QAAQ;AAAA,IAAgD;AAE1D,QAAM,CAACC,GAAQC,CAAM,IAAI,MAAM,QAAQ,IAAI,CAACC,EAAcT,CAAG,GAAGU,EAAWf,EAAK,QAAQ,CAAC,CAAC;AAC1F,SAAAD,EAAU,gBAAA,GACViB,EAAO;AAAA,IACL,GAAGC,EAAiBZ,CAAG;AAAA,IACvB,WAAAN;AAAA,IACA,QAAAa;AAAA,IACA,YAAYC;AAAA,IACZ,WAAWK,EAAgBb,CAAG;AAAA,IAC9B,kBAAkB,OAAO,oBAAoB;AAAA,EAAA,CAC9C,GACM,EAAE,OAAO,CAAC,GAAGN,EAAU,iBAAiB,QAAQ,CAAC,GAAG,IAAI,KAAK,MAAM,YAAY,IAAA,IAAQE,CAAE,EAAA;AAClG;"}
1
+ {"version":3,"file":"index.js","sources":["../src/embed.ts"],"sourcesContent":["/**\n * The renderer, embeddable in ANY page served by the studio.\n *\n * The review dashboard shows a document next to Word's render: with this\n * module the canvas side is the engine composing the document LIVE in the\n * page, not a PNG the bench cached — so a change in the engine shows on the\n * next reload, and the slider compares what the editor would draw.\n *\n * const { pages } = await renderDocx('/corpus/<name>.docx', hiddenDiv)\n *\n * Fed by `buildRenderInput`, like the editor and the bench: the third surface\n * that mounts the renderer starts from there, as CLAUDE.md asks. What it adds\n * is the platform: fonts loaded before any measurement, embedded fonts of the\n * document, images decoded by the browser.\n */\nimport { embeddedFonts, fontAltNames, fontFaceDescriptor, readDocx } from '@myrole/docx-model'\nimport { buildRenderInput, footnoteContent, render, preloadImages } from '@myrole/docx-render'\nimport { documentFonts, installFonts, lineRatios } from './fonts'\n\nexport interface Rendered {\n pages: HTMLCanvasElement[]\n ms: number\n}\n\nexport async function renderDocx(\n url: string | ArrayBuffer | Uint8Array, container: HTMLElement, opts: { fontsUrl?: string } = {},\n): Promise<Rendered> {\n const t0 = performance.now()\n const buf = typeof url === 'string'\n ? await fetch(url).then((r) => (r.ok ? r.arrayBuffer() : Promise.reject(new Error(`${r.status} ${url}`))))\n : url\n const doc = readDocx(new Uint8Array(buf))\n const embedded = embeddedFonts(doc)\n const own = new Set(embedded.map((f) => f.family))\n const families = [...documentFonts(doc)].filter((f) => !own.has(f))\n const alt = fontAltNames(doc)\n await installFonts(opts.fontsUrl, families, alt)\n for (const f of embedded) {\n try {\n const d = fontFaceDescriptor(f)\n const face = new FontFace(d.family, f.data as BufferSource, { weight: d.weight, style: d.style })\n await face.load()\n document.fonts.add(face)\n } catch { /* police corrompue ou format non supporté */ }\n }\n const [images, ratios] = await Promise.all([preloadImages(doc), lineRatios(opts.fontsUrl, families, alt)])\n container.replaceChildren()\n render({\n ...buildRenderInput(doc),\n container,\n images,\n lineRatios: ratios,\n footnotes: footnoteContent(doc),\n devicePixelRatio: window.devicePixelRatio || 1,\n })\n return { pages: [...container.querySelectorAll('canvas')], ms: Math.round(performance.now() - t0) }\n}\n"],"names":["renderDocx","url","container","opts","t0","buf","r","doc","readDocx","embedded","embeddedFonts","own","f","families","documentFonts","alt","fontAltNames","installFonts","d","fontFaceDescriptor","face","images","ratios","preloadImages","lineRatios","render","buildRenderInput","footnoteContent"],"mappings":";;AAwBA,eAAsBA,EACpBC,GAAwCC,GAAwBC,IAA8B,CAAA,GAC3E;AACnB,QAAMC,IAAK,YAAY,IAAA,GACjBC,IAAM,OAAOJ,KAAQ,WACvB,MAAM,MAAMA,CAAG,EAAE,KAAK,CAACK,MAAOA,EAAE,KAAKA,EAAE,YAAA,IAAgB,QAAQ,OAAO,IAAI,MAAM,GAAGA,EAAE,MAAM,IAAIL,CAAG,EAAE,CAAC,CAAE,IACvGA,GACEM,IAAMC,EAAS,IAAI,WAAWH,CAAG,CAAC,GAClCI,IAAWC,EAAcH,CAAG,GAC5BI,IAAM,IAAI,IAAIF,EAAS,IAAI,CAACG,MAAMA,EAAE,MAAM,CAAC,GAC3CC,IAAW,CAAC,GAAGC,EAAcP,CAAG,CAAC,EAAE,OAAO,CAACK,MAAM,CAACD,EAAI,IAAIC,CAAC,CAAC,GAC5DG,IAAMC,EAAaT,CAAG;AAC5B,QAAMU,EAAad,EAAK,UAAUU,GAAUE,CAAG;AAC/C,aAAWH,KAAKH;AACd,QAAI;AACF,YAAMS,IAAIC,EAAmBP,CAAC,GACxBQ,IAAO,IAAI,SAASF,EAAE,QAAQN,EAAE,MAAsB,EAAE,QAAQM,EAAE,QAAQ,OAAOA,EAAE,OAAO;AAChG,YAAME,EAAK,KAAA,GACX,SAAS,MAAM,IAAIA,CAAI;AAAA,IACzB,QAAQ;AAAA,IAAgD;AAE1D,QAAM,CAACC,GAAQC,CAAM,IAAI,MAAM,QAAQ,IAAI,CAACC,EAAchB,CAAG,GAAGiB,EAAWrB,EAAK,UAAUU,GAAUE,CAAG,CAAC,CAAC;AACzG,SAAAb,EAAU,gBAAA,GACVuB,EAAO;AAAA,IACL,GAAGC,EAAiBnB,CAAG;AAAA,IACvB,WAAAL;AAAA,IACA,QAAAmB;AAAA,IACA,YAAYC;AAAA,IACZ,WAAWK,EAAgBpB,CAAG;AAAA,IAC9B,kBAAkB,OAAO,oBAAoB;AAAA,EAAA,CAC9C,GACM,EAAE,OAAO,CAAC,GAAGL,EAAU,iBAAiB,QAAQ,CAAC,GAAG,IAAI,KAAK,MAAM,YAAY,IAAA,IAAQE,CAAE,EAAA;AAClG;"}
package/dist/react.js CHANGED
@@ -1,24 +1,25 @@
1
1
  import { jsx as h } from "react/jsx-runtime";
2
- import { forwardRef as v, useRef as o, useEffect as a } from "react";
3
- import { d as y } from "./chunks/sdk-Bi8qAaV_.js";
4
- const s = v(function({ src: u, className: b, style: S, onReady: g, ...e }, f) {
5
- const l = o(null), c = o(null), n = o(e);
6
- n.current = e;
2
+ import { forwardRef as v, useRef as f, useEffect as n } from "react";
3
+ import { h as y } from "./chunks/sdk-DdtgYtTx.js";
4
+ import { D as I } from "./chunks/sdk-DdtgYtTx.js";
5
+ const s = v(function({ src: u, className: b, style: i, onReady: g, ...e }, o) {
6
+ const l = f(null), c = f(null), a = f(e);
7
+ a.current = e;
7
8
  const m = (r) => {
8
- typeof f == "function" ? f(r) : f && (f.current = r);
9
+ typeof o == "function" ? o(r) : o && (o.current = r);
9
10
  };
10
- return a(() => {
11
+ return n(() => {
11
12
  const r = y(l.current, {
12
13
  ...e,
13
- onSave: e.onSave ? (t, d) => n.current.onSave(t, d) : void 0,
14
- onError: (t) => n.current.onError?.(t),
15
- onSaveState: (t) => n.current.onSaveState?.(t),
16
- onLockState: (t) => n.current.onLockState?.(t),
17
- onChange: () => n.current.onChange?.(),
14
+ onSave: e.onSave ? (t, d) => a.current.onSave(t, d) : void 0,
15
+ onError: (t) => a.current.onError?.(t),
16
+ onSaveState: (t) => a.current.onSaveState?.(t),
17
+ onLockState: (t) => a.current.onLockState?.(t),
18
+ onChange: () => a.current.onChange?.(),
18
19
  feedback: typeof e.feedback == "object" ? {
19
20
  ...e.feedback,
20
21
  onSubmit: e.feedback.onSubmit ? (t) => {
21
- const d = n.current.feedback;
22
+ const d = a.current.feedback;
22
23
  if (typeof d != "object" || !d.onSubmit) throw new Error("Feedback submission handler is no longer configured");
23
24
  return d.onSubmit(t);
24
25
  } : void 0
@@ -27,28 +28,29 @@ const s = v(function({ src: u, className: b, style: S, onReady: g, ...e }, f) {
27
28
  return c.current = r, m(r), g?.(r), () => {
28
29
  r.destroy(), c.current = null, m(null);
29
30
  };
30
- }, [e.draftKey, e.chrome, !!e.onSave]), a(() => {
31
- u && c.current && c.current.load(u).catch((r) => n.current.onError?.(r));
32
- }, [u, e.draftKey, e.chrome, !!e.onSave]), a(() => {
31
+ }, [e.draftKey, e.chrome, !!e.onSave]), n(() => {
32
+ u && c.current && c.current.load(u).catch((r) => a.current.onError?.(r));
33
+ }, [u, e.draftKey, e.chrome, !!e.onSave]), n(() => {
33
34
  e.theme && c.current?.setTheme(e.theme);
34
- }, [e.theme]), a(() => {
35
+ }, [e.theme]), n(() => {
35
36
  c.current?.setReadOnly(e.readOnly ?? !1);
36
- }, [e.readOnly]), a(() => {
37
+ }, [e.readOnly]), n(() => {
37
38
  e.zoom !== void 0 && c.current?.setZoom(e.zoom);
38
- }, [e.zoom]), a(() => {
39
+ }, [e.zoom]), n(() => {
39
40
  e.badges !== void 0 && c.current?.variables.setDisplay(e.badges);
40
- }, [typeof e.badges == "boolean" ? e.badges : e.badges?.variables, typeof e.badges == "boolean" ? e.badges : e.badges?.expressions]), /* @__PURE__ */ h("div", { ref: l, className: b, style: { height: "100%", minHeight: 320, minWidth: 0, ...S } });
41
+ }, [typeof e.badges == "boolean" ? e.badges : e.badges?.variables, typeof e.badges == "boolean" ? e.badges : e.badges?.expressions]), /* @__PURE__ */ h("div", { ref: l, className: b, style: { height: "100%", minHeight: 320, minWidth: 0, ...i } });
41
42
  });
42
- function D() {
43
- return o(null);
43
+ function x() {
44
+ return f(null);
44
45
  }
45
46
  const O = v(function(u, b) {
46
47
  return /* @__PURE__ */ h(s, { ...u, ref: b, chrome: "viewer", readOnly: !0 });
47
48
  }), w = 1;
48
49
  export {
50
+ I as DOCX_EDITOR_VERSION,
49
51
  w as DOCX_LOCKING_VERSION,
50
52
  s as DocxEditor,
51
53
  O as DocxViewer,
52
- D as useDocxEditor
54
+ x as useDocxEditor
53
55
  };
54
56
  //# sourceMappingURL=react.js.map
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","sources":["../src/react.tsx"],"sourcesContent":["/**\n * The React face of the SDK.\n *\n * <DocxEditor src={file} onSave={(bytes) => upload(bytes)} style={{ height: '100vh' }} />\n *\n * The component owns one `createDocxEditor` for its lifetime; `src` changes\n * reload the document in place, every other option is read at mount. React is\n * an optional peer: nothing here runs unless `myrole-docx-editor/react` is\n * imported.\n */\nimport { useEffect, useRef, forwardRef, type CSSProperties } from 'react'\nimport { createDocxEditor, type DocxEditorHandle, type DocxEditorOptions } from './sdk'\n\nexport interface DocxEditorProps extends Omit<DocxEditorOptions, 'onReady'> {\n /** the document: bytes, a Blob/File, or a URL */\n src?: ArrayBuffer | Uint8Array | Blob | string\n className?: string\n style?: CSSProperties\n /** the handle, once mounted */\n onReady?: (editor: DocxEditorHandle) => void\n}\n\nexport const DocxEditor = forwardRef<DocxEditorHandle | null, DocxEditorProps>(function DocxEditor(\n { src, className, style, onReady, ...options }, ref,\n) {\n const host = useRef<HTMLDivElement>(null)\n const handle = useRef<DocxEditorHandle | null>(null)\n // The latest callbacks, without remounting the editor when they change.\n const latest = useRef(options)\n latest.current = options\n\n // The forwarded ref is filled HERE, not by useImperativeHandle: that one\n // runs in the layout phase, before this effect has created anything, and\n // would hand the parent a null for the component's whole life.\n const give = (h: DocxEditorHandle | null) => {\n if (typeof ref === 'function') ref(h)\n else if (ref) ref.current = h\n }\n\n useEffect(() => {\n const h = createDocxEditor(host.current!, {\n ...options,\n onSave: options.onSave ? (b, context) => latest.current.onSave!(b, context) : undefined,\n onError: e => latest.current.onError?.(e),\n onSaveState: state => latest.current.onSaveState?.(state),\n onLockState: state => latest.current.onLockState?.(state),\n onChange: () => latest.current.onChange?.(),\n feedback: typeof options.feedback === 'object' ? {\n ...options.feedback,\n onSubmit: options.feedback.onSubmit ? report => {\n const feedback = latest.current.feedback\n if (typeof feedback !== 'object' || !feedback.onSubmit) throw new Error('Feedback submission handler is no longer configured')\n return feedback.onSubmit(report)\n } : undefined,\n } : options.feedback,\n })\n handle.current = h\n give(h)\n onReady?.(h)\n return () => { h.destroy(); handle.current = null; give(null) }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [options.draftKey, options.chrome, !!options.onSave])\n\n useEffect(() => {\n if (src && handle.current) void handle.current.load(src).catch(e => latest.current.onError?.(e))\n }, [src, options.draftKey, options.chrome, !!options.onSave])\n useEffect(() => { if (options.theme) handle.current?.setTheme(options.theme) }, [options.theme])\n useEffect(() => { handle.current?.setReadOnly(options.readOnly ?? false) }, [options.readOnly])\n useEffect(() => { if (options.zoom !== undefined) handle.current?.setZoom(options.zoom) }, [options.zoom])\n useEffect(() => { if (options.badges !== undefined) handle.current?.variables.setDisplay(options.badges) }, [typeof options.badges === 'boolean' ? options.badges : options.badges?.variables, typeof options.badges === 'boolean' ? options.badges : options.badges?.expressions])\n\n return <div ref={host} className={className} style={{ height: '100%', minHeight: 320, minWidth: 0, ...style }} />\n})\n\n/** A ref to hand to `<DocxEditor ref={…}>`, and the handle once it exists. */\nexport function useDocxEditor() {\n return useRef<DocxEditorHandle | null>(null)\n}\n\nexport type { DocxEditorHandle, DocxEditorOptions } from './sdk'\n\n/** Read-only companion, with the same rendering and lifecycle as the editor. */\nexport const DocxViewer = forwardRef<DocxEditorHandle | null, DocxEditorProps>(function DocxViewer(props, ref) {\n return <DocxEditor {...props} ref={ref} chrome=\"viewer\" readOnly />\n})\n\nexport const DOCX_LOCKING_VERSION = 1\n"],"names":["DocxEditor","forwardRef","src","className","style","onReady","options","ref","host","useRef","handle","latest","give","h","useEffect","createDocxEditor","b","context","e","state","report","feedback","jsx","useDocxEditor","DocxViewer","props","DOCX_LOCKING_VERSION"],"mappings":"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"}
1
+ {"version":3,"file":"react.js","sources":["../src/react.tsx"],"sourcesContent":["/**\n * The React face of the SDK.\n *\n * <DocxEditor src={file} onSave={(bytes) => upload(bytes)} style={{ height: '100vh' }} />\n *\n * The component owns one `createDocxEditor` for its lifetime; `src` changes\n * reload the document in place, every other option is read at mount. React is\n * an optional peer: nothing here runs unless `myrole-docx-editor/react` is\n * imported.\n */\nimport { useEffect, useRef, forwardRef, type CSSProperties } from 'react'\nimport { createDocxEditor, type DocxEditorHandle, type DocxEditorOptions } from './sdk'\n\nexport interface DocxEditorProps extends Omit<DocxEditorOptions, 'onReady'> {\n /** the document: bytes, a Blob/File, or a URL */\n src?: ArrayBuffer | Uint8Array | Blob | string\n className?: string\n style?: CSSProperties\n /** the handle, once mounted */\n onReady?: (editor: DocxEditorHandle) => void\n}\n\nexport const DocxEditor = forwardRef<DocxEditorHandle | null, DocxEditorProps>(function DocxEditor(\n { src, className, style, onReady, ...options }, ref,\n) {\n const host = useRef<HTMLDivElement>(null)\n const handle = useRef<DocxEditorHandle | null>(null)\n // The latest callbacks, without remounting the editor when they change.\n const latest = useRef(options)\n latest.current = options\n\n // The forwarded ref is filled HERE, not by useImperativeHandle: that one\n // runs in the layout phase, before this effect has created anything, and\n // would hand the parent a null for the component's whole life.\n const give = (h: DocxEditorHandle | null) => {\n if (typeof ref === 'function') ref(h)\n else if (ref) ref.current = h\n }\n\n useEffect(() => {\n const h = createDocxEditor(host.current!, {\n ...options,\n onSave: options.onSave ? (b, context) => latest.current.onSave!(b, context) : undefined,\n onError: e => latest.current.onError?.(e),\n onSaveState: state => latest.current.onSaveState?.(state),\n onLockState: state => latest.current.onLockState?.(state),\n onChange: () => latest.current.onChange?.(),\n feedback: typeof options.feedback === 'object' ? {\n ...options.feedback,\n onSubmit: options.feedback.onSubmit ? report => {\n const feedback = latest.current.feedback\n if (typeof feedback !== 'object' || !feedback.onSubmit) throw new Error('Feedback submission handler is no longer configured')\n return feedback.onSubmit(report)\n } : undefined,\n } : options.feedback,\n })\n handle.current = h\n give(h)\n onReady?.(h)\n return () => { h.destroy(); handle.current = null; give(null) }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [options.draftKey, options.chrome, !!options.onSave])\n\n useEffect(() => {\n if (src && handle.current) void handle.current.load(src).catch(e => latest.current.onError?.(e))\n }, [src, options.draftKey, options.chrome, !!options.onSave])\n useEffect(() => { if (options.theme) handle.current?.setTheme(options.theme) }, [options.theme])\n useEffect(() => { handle.current?.setReadOnly(options.readOnly ?? false) }, [options.readOnly])\n useEffect(() => { if (options.zoom !== undefined) handle.current?.setZoom(options.zoom) }, [options.zoom])\n useEffect(() => { if (options.badges !== undefined) handle.current?.variables.setDisplay(options.badges) }, [typeof options.badges === 'boolean' ? options.badges : options.badges?.variables, typeof options.badges === 'boolean' ? options.badges : options.badges?.expressions])\n\n return <div ref={host} className={className} style={{ height: '100%', minHeight: 320, minWidth: 0, ...style }} />\n})\n\n/** A ref to hand to `<DocxEditor ref={…}>`, and the handle once it exists. */\nexport function useDocxEditor() {\n return useRef<DocxEditorHandle | null>(null)\n}\n\nexport type { DocxEditorHandle, DocxEditorOptions } from './sdk'\nexport { DOCX_EDITOR_VERSION } from './sdk'\n\n/** Read-only companion, with the same rendering and lifecycle as the editor. */\nexport const DocxViewer = forwardRef<DocxEditorHandle | null, DocxEditorProps>(function DocxViewer(props, ref) {\n return <DocxEditor {...props} ref={ref} chrome=\"viewer\" readOnly />\n})\n\nexport const DOCX_LOCKING_VERSION = 1\n"],"names":["DocxEditor","forwardRef","src","className","style","onReady","options","ref","host","useRef","handle","latest","give","h","useEffect","createDocxEditor","b","context","e","state","report","feedback","jsx","useDocxEditor","DocxViewer","props","DOCX_LOCKING_VERSION"],"mappings":";;;;AAsBO,MAAMA,IAAaC,EAAqD,SAC7E,EAAE,KAAAC,GAAK,WAAAC,GAAW,OAAAC,GAAO,SAAAC,GAAS,GAAGC,EAAA,GAAWC,GAChD;AACA,QAAMC,IAAOC,EAAuB,IAAI,GAClCC,IAASD,EAAgC,IAAI,GAE7CE,IAASF,EAAOH,CAAO;AAC7B,EAAAK,EAAO,UAAUL;AAKjB,QAAMM,IAAO,CAACC,MAA+B;AAC3C,IAAI,OAAON,KAAQ,aAAYA,EAAIM,CAAC,IAC3BN,QAAS,UAAUM;AAAA,EAC9B;AAEA,SAAAC,EAAU,MAAM;AACd,UAAMD,IAAIE,EAAiBP,EAAK,SAAU;AAAA,MACxC,GAAGF;AAAA,MACH,QAAQA,EAAQ,SAAS,CAACU,GAAGC,MAAYN,EAAO,QAAQ,OAAQK,GAAGC,CAAO,IAAI;AAAA,MAC9E,SAAS,CAAAC,MAAKP,EAAO,QAAQ,UAAUO,CAAC;AAAA,MACxC,aAAa,CAAAC,MAASR,EAAO,QAAQ,cAAcQ,CAAK;AAAA,MACxD,aAAa,CAAAA,MAASR,EAAO,QAAQ,cAAcQ,CAAK;AAAA,MACxD,UAAU,MAAMR,EAAO,QAAQ,WAAA;AAAA,MAC/B,UAAU,OAAOL,EAAQ,YAAa,WAAW;AAAA,QAC/C,GAAGA,EAAQ;AAAA,QACX,UAAUA,EAAQ,SAAS,WAAW,CAAAc,MAAU;AAC9C,gBAAMC,IAAWV,EAAO,QAAQ;AAChC,cAAI,OAAOU,KAAa,YAAY,CAACA,EAAS,SAAU,OAAM,IAAI,MAAM,qDAAqD;AAC7H,iBAAOA,EAAS,SAASD,CAAM;AAAA,QACjC,IAAI;AAAA,MAAA,IACFd,EAAQ;AAAA,IAAA,CACb;AACD,WAAAI,EAAO,UAAUG,GACjBD,EAAKC,CAAC,GACNR,IAAUQ,CAAC,GACJ,MAAM;AAAE,MAAAA,EAAE,QAAA,GAAWH,EAAO,UAAU,MAAME,EAAK,IAAI;AAAA,IAAE;AAAA,EAEhE,GAAG,CAACN,EAAQ,UAAUA,EAAQ,QAAQ,CAAC,CAACA,EAAQ,MAAM,CAAC,GAEvDQ,EAAU,MAAM;AACd,IAAIZ,KAAOQ,EAAO,WAAcA,EAAO,QAAQ,KAAKR,CAAG,EAAE,MAAM,CAAAgB,MAAKP,EAAO,QAAQ,UAAUO,CAAC,CAAC;AAAA,EACjG,GAAG,CAAChB,GAAKI,EAAQ,UAAUA,EAAQ,QAAQ,CAAC,CAACA,EAAQ,MAAM,CAAC,GAC5DQ,EAAU,MAAM;AAAE,IAAIR,EAAQ,SAAOI,EAAO,SAAS,SAASJ,EAAQ,KAAK;AAAA,EAAE,GAAG,CAACA,EAAQ,KAAK,CAAC,GAC/FQ,EAAU,MAAM;AAAE,IAAAJ,EAAO,SAAS,YAAYJ,EAAQ,YAAY,EAAK;AAAA,EAAE,GAAG,CAACA,EAAQ,QAAQ,CAAC,GAC9FQ,EAAU,MAAM;AAAE,IAAIR,EAAQ,SAAS,YAAkB,SAAS,QAAQA,EAAQ,IAAI;AAAA,EAAE,GAAG,CAACA,EAAQ,IAAI,CAAC,GACzGQ,EAAU,MAAM;AAAE,IAAIR,EAAQ,WAAW,UAAWI,EAAO,SAAS,UAAU,WAAWJ,EAAQ,MAAM;AAAA,EAAE,GAAG,CAAC,OAAOA,EAAQ,UAAW,YAAYA,EAAQ,SAASA,EAAQ,QAAQ,WAAW,OAAOA,EAAQ,UAAW,YAAYA,EAAQ,SAASA,EAAQ,QAAQ,WAAW,CAAC,GAE3Q,gBAAAgB,EAAC,OAAA,EAAI,KAAKd,GAAM,WAAAL,GAAsB,OAAO,EAAE,QAAQ,QAAQ,WAAW,KAAK,UAAU,GAAG,GAAGC,KAAS;AACjH,CAAC;AAGM,SAASmB,IAAgB;AAC9B,SAAOd,EAAgC,IAAI;AAC7C;AAMO,MAAMe,IAAavB,EAAqD,SAAoBwB,GAAOlB,GAAK;AAC7G,SAAO,gBAAAe,EAACtB,KAAY,GAAGyB,GAAO,KAAAlB,GAAU,QAAO,UAAS,UAAQ,IAAC;AACnE,CAAC,GAEYmB,IAAuB;"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The assistant's tools as an MCP client sees them: names, descriptions, input
3
+ * schemas. Data only — `scripts/assistant-mcp.ts` bundles this file into the
4
+ * relay, and the relay must not carry the editor. `assistant.ts` runs them.
5
+ *
6
+ * Every description has to stand on its own: some MCP clients never show the
7
+ * server's `instructions`, all of them show these.
8
+ */
9
+ export interface AssistantTool {
10
+ name: string;
11
+ description: string;
12
+ inputSchema: Record<string, unknown>;
13
+ /** reads only: no undo step, no fake-cursor walk */
14
+ readOnly: boolean;
15
+ }
16
+ export declare const ASSISTANT_TOOLS: AssistantTool[];
@@ -1,26 +1,24 @@
1
- import type { DocxEditorHandle } from './sdk';
1
+ import { type DocxEditorHandle } from './sdk';
2
+ import { type LibraryExtras } from './vars-library';
2
3
  /**
3
4
  * The editor as the tool provider of a LOCAL MCP server.
4
5
  *
5
6
  * 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.
7
+ * only relays them between the MCP client and the tab, and `assistant-tools.ts`
8
+ * describes them. Exactly one tab is connected at a time: the one where the
9
+ * user last pressed « Assistant ». The model never chooses which editor it
10
+ * drives, and it never sees a URL, a token or the package — only paragraphs,
11
+ * addressed by index.
10
12
  *
11
- * ponytail: body paragraphs only; headers, footers and notes when someone needs them.
13
+ * Every writing call runs in `Editor.batch`: one Ctrl/Cmd+Z takes it back, and
14
+ * a call that fails halfway leaves nothing behind.
12
15
  */
13
- export interface AssistantTool {
14
- name: string;
15
- description: string;
16
- inputSchema: Record<string, unknown>;
17
- readOnly: boolean;
18
- }
19
16
  export interface AssistantOptions {
20
17
  /** the relay started by `scripts/assistant-mcp.ts` */
21
18
  url?: string;
22
19
  }
23
- export declare const ASSISTANT_TOOLS: AssistantTool[];
24
- export declare function runTool(handle: DocxEditorHandle, name: string, args: Record<string, unknown>): unknown;
20
+ type Args = Record<string, unknown>;
21
+ export declare function runTool(handle: DocxEditorHandle, name: string, args: Args, library?: () => LibraryExtras): unknown;
25
22
  /** The « Assistant » button of the status bar, and the connection it opens. */
26
- export declare function mountAssistant(status: HTMLElement, handle: DocxEditorHandle, options?: AssistantOptions): () => void;
23
+ export declare function mountAssistant(status: HTMLElement, handle: DocxEditorHandle, options?: AssistantOptions, library?: () => LibraryExtras): () => void;
24
+ export {};
@@ -30,6 +30,8 @@ export interface ChromeHost {
30
30
  get(): boolean;
31
31
  set(on: boolean): void;
32
32
  };
33
+ /** the font picker's names — a live array the host may refill */
34
+ fonts: string[];
33
35
  }
34
36
  export interface Chrome {
35
37
  refresh(ctx: EditContext | null, hasSel: boolean): void;
@@ -1,4 +1,4 @@
1
- import { type CellPatch, type MarginPatch, type DocViews, type DocxDocument, type DocPos, type EditContext, type PageSetup, type PageSetupPatch, type ParaPatch, type RunPatch } from '../../docx-model/src/index';
1
+ import { type CellPatch, type TableBorderPatch, type MarginPatch, type DocViews, type DocxDocument, type DocPos, type EditContext, type PageSetup, type PageSetupPatch, type ParaPatch, type RunPatch } from '../../docx-model/src/index';
2
2
  import { type ImageRect, type LineTrace, type MarkRect, type ResumeState, type SelRect, type TableRect, type CellRect } from '../../docx-render/src/index';
3
3
  export interface EditorHooks {
4
4
  /** appelé après chaque composition, avec ce qu'il faut pour la barre d'outils */
@@ -190,16 +190,34 @@ export declare function createEditor(setup: EditorSetup): {
190
190
  setList(ordered: boolean | null): void;
191
191
  clearTableBorders(): boolean;
192
192
  formatCell(patch: CellPatch): boolean;
193
+ /** Word's « Bordures » menu, on the whole table holding the caret. */
194
+ setTableBorders(patch: TableBorderPatch): boolean;
195
+ setRowHeight: (para: number, heightPt: number) => void;
196
+ /**
197
+ * Word's « Fusionner »: the selected cells become one; with no cell
198
+ * selection, the caret's cell takes in its right-hand neighbour.
199
+ */
200
+ mergeCells(): boolean;
193
201
  mergeNextCell(): boolean;
194
202
  replaceAll(query: string, replacement: string, matchCase?: boolean): number;
195
203
  /** Insère du texte au curseur, ou remplace la sélection. */
196
204
  insert: (text: string, patch?: RunPatch) => void;
205
+ /**
206
+ * Pastes HTML after the caret's paragraph, as one undo step, through the
207
+ * clipboard's own path: whatever `htmlToBlocks` cannot express is dropped.
208
+ */
209
+ pasteHtml(html: string): boolean;
210
+ /**
211
+ * Inserts raw `w:p` / `w:tbl` XML after a body paragraph, as one undo step,
212
+ * and returns how many paragraphs it added. Throws why the XML was refused.
213
+ */
214
+ insertOoxml(para: number, xml: string): number;
197
215
  deleteSelection: () => void;
198
216
  deleteObject: () => void;
199
217
  splitAtCaret: () => void;
200
218
  format: (patch: RunPatch) => void;
201
219
  formatPara: (patch: ParaPatch) => void;
202
- table: (what: "row" | "col", how: "above" | "below" | "left" | "right" | "delete") => void;
220
+ table: (what: "row" | "col", how: "above" | "below" | "left" | "right" | "delete", at?: number) => void;
203
221
  insertTable: (rows: number, cols: number) => boolean;
204
222
  resizeImage: (index: number, factor: number) => void;
205
223
  insertBreak: (kind: "page" | "column" | "line") => void;
@@ -207,12 +225,16 @@ export declare function createEditor(setup: EditorSetup): {
207
225
  setMargins: (patch: MarginPatch, section?: number) => void;
208
226
  setPageSetup: (patch: PageSetupPatch, section?: number) => void;
209
227
  insertSectionBreak: (kind: "nextPage" | "continuous") => boolean;
210
- setTableColumn: (col: number, widthPt: number) => void;
228
+ setTableColumn: (col: number, widthPt: number, at?: number) => void;
211
229
  /** Format d'une section — celle du curseur par défaut. */
212
230
  pageSetup: (section?: number) => PageSetup | null;
213
231
  currentSection: () => number;
214
232
  /** Section à laquelle appartient une page dessinée — ce que la règle suit. */
215
233
  sectionOfPage(page: number): number;
234
+ batch: <T>(fn: () => T) => {
235
+ value: T;
236
+ changed: boolean;
237
+ };
216
238
  undo: () => void;
217
239
  redo: () => void;
218
240
  canUndo: () => boolean;
@@ -1,5 +1,63 @@
1
+ /**
2
+ * The faces the engine measures with, declared at runtime.
3
+ *
4
+ * The app used to `import '../../fonts/src/faces'`; through a library build
5
+ * that stylesheet would carry 33 MB of base64. The SDK ships the files under
6
+ * `fonts/ttf/` instead and declares each face as a `FontFace` from a manifest
7
+ * generated at build time.
8
+ *
9
+ * Only the families a document names are declared and downloaded — a contract
10
+ * in Calibri fetches Calibri's four files, not the 229 of the manifest. A name
11
+ * we do not serve is declared under its own name with the faces of its nearest
12
+ * served family (`nearestFamily`: alias, the document's `w:altName`, then
13
+ * « Helvetica Bold » → Helvetica), so the canvas draws what the Node bench
14
+ * measures.
15
+ *
16
+ * `fontsUrl` is the directory that contains `ttf/`. In development it is the
17
+ * `@myrole/fonts` package itself (Vite serves it in place); in the published
18
+ * package it is `fonts/` next to `dist/`. A consumer whose bundler does not
19
+ * keep `fonts/` next to the bundle passes the URL it serves them from.
20
+ */
21
+ import { type DocxDocument } from '../../docx-model/src/index';
1
22
  export declare function defaultFontsUrl(): string;
2
- /** Declare every shipped face once, then wait for them like the app did. */
3
- export declare function installFonts(fontsUrl?: string): Promise<void>;
4
- /** Line-height ratios read in the served TTFs — `fontLineRatios` on our directory. */
5
- export declare function lineRatios(fontsUrl?: string): Promise<Partial<Record<"Times New Roman" | "New York" | "Cambria" | "Arial" | "Symbol" | "Calibri" | "Avenir Book" | "Avenir" | "Avenir Next" | "Gill Sans Light" | "Century Gothic" | "Century Schoolbook" | "Avenir Heavy" | "Bookman Old Style" | "Aptos" | "Consolas" | "Abadi MT Condensed Extra Bold" | "Abadi MT Condensed Light" | "Angsana New" | "Apple Color Emoji" | "Apple Symbols" | "Aptos Narrow" | "Arial Black" | "Arial Hebrew" | "Arial Narrow" | "Arial Rounded MT Bold" | "Arial Unicode MS" | "Avenir Black" | "Avenir Light" | "Baskerville Old Face" | "Batang" | "Bauhaus 93" | "Big Caslon" | "Calibri Light" | "Cambria Math" | "Candara" | "Century" | "Comic Sans MS" | "Corbel" | "Cordia New" | "Courier" | "Courier New" | "Daytona" | "DengXian" | "DengXian Light" | "Didot" | "Edwardian Script ITC" | "Euphemia UCAS" | "Eurostile" | "Franklin Gothic Book" | "Franklin Gothic Demi" | "Franklin Gothic Demi Cond" | "Franklin Gothic Medium" | "Franklin Gothic Medium Cond" | "Futura" | "Garamond" | "Geneva" | "Georgia" | "Gill Sans" | "Gill Sans MT" | "Helvetica" | "Helvetica Neue" | "Hind Siliguri" | "Hind Siliguri Light" | "Hind Siliguri Medium" | "Hind Siliguri SemiBold" | "Hoefler Text" | "Lucida Grande" | "Lucida Sans" | "Lucida Sans Unicode" | "MS Gothic" | "MS Mincho" | "MS UI Gothic" | "Malgun Gothic" | "Mangal" | "Microsoft Sans Serif" | "Microsoft YaHei" | "Microsoft Yi Baiti" | "Monotype Sorts" | "NSimSun" | "News Gothic MT" | "Optima" | "PMingLiU" | "PT Mono" | "Palatino" | "Palatino Linotype" | "Segoe UI Symbol" | "SimSun" | "Skia" | "Stencil" | "Tahoma" | "Times" | "Trebuchet MS" | "Tw Cen MT" | "Tw Cen MT Condensed" | "Verdana" | "Webdings" | "Wingdings" | "Wingdings 2" | "Wingdings 3" | "Yu Gothic Light" | "Yu Mincho", number>>>;
23
+ /**
24
+ * Declare the faces for `families` (all served families when omitted) and wait
25
+ * for them. Resolves to the names it newly declared, so a caller can recompose.
26
+ */
27
+ export declare function installFonts(fontsUrl?: string, families?: Iterable<string>, alt?: Map<string, string>): Promise<string[]>;
28
+ /**
29
+ * Every font name the document can ask the canvas for: run and style fonts
30
+ * (`w:rFonts`, numbering and headers included), the font table and the theme.
31
+ * A superset of what gets drawn — still a handful of families, not 102.
32
+ */
33
+ export declare function documentFonts(doc: DocxDocument): Set<string>;
34
+ /** Line-height ratios read in the served TTFs of `families` (all when omitted). */
35
+ export declare function lineRatios(fontsUrl?: string, families?: Iterable<string>, alt?: Map<string, string>): Promise<Partial<Record<"Times New Roman" | "New York" | "Cambria" | "Arial" | "Symbol" | "Calibri" | "Avenir Book" | "Avenir" | "Avenir Next" | "Gill Sans Light" | "Century Gothic" | "Century Schoolbook" | "Avenir Heavy" | "Bookman Old Style" | "Aptos" | "Consolas" | "Abadi MT Condensed Extra Bold" | "Abadi MT Condensed Light" | "Angsana New" | "Apple Color Emoji" | "Apple Symbols" | "Aptos Narrow" | "Arial Black" | "Arial Hebrew" | "Arial Narrow" | "Arial Rounded MT Bold" | "Arial Unicode MS" | "Avenir Black" | "Avenir Light" | "Baskerville Old Face" | "Batang" | "Bauhaus 93" | "Big Caslon" | "Calibri Light" | "Cambria Math" | "Candara" | "Century" | "Comic Sans MS" | "Corbel" | "Cordia New" | "Courier" | "Courier New" | "Daytona" | "DengXian" | "DengXian Light" | "Didot" | "Edwardian Script ITC" | "Euphemia UCAS" | "Eurostile" | "Franklin Gothic Book" | "Franklin Gothic Demi" | "Franklin Gothic Demi Cond" | "Franklin Gothic Medium" | "Franklin Gothic Medium Cond" | "Futura" | "Garamond" | "Geneva" | "Georgia" | "Gill Sans" | "Gill Sans MT" | "Helvetica" | "Helvetica Neue" | "Hind Siliguri" | "Hind Siliguri Light" | "Hind Siliguri Medium" | "Hind Siliguri SemiBold" | "Hoefler Text" | "Lucida Grande" | "Lucida Sans" | "Lucida Sans Unicode" | "MS Gothic" | "MS Mincho" | "MS UI Gothic" | "Malgun Gothic" | "Mangal" | "Microsoft Sans Serif" | "Microsoft YaHei" | "Microsoft Yi Baiti" | "Monotype Sorts" | "NSimSun" | "News Gothic MT" | "Optima" | "PMingLiU" | "PT Mono" | "Palatino" | "Palatino Linotype" | "Segoe UI Symbol" | "SimSun" | "Skia" | "Stencil" | "Tahoma" | "Times" | "Trebuchet MS" | "Tw Cen MT" | "Tw Cen MT Condensed" | "Verdana" | "Webdings" | "Wingdings" | "Wingdings 2" | "Wingdings 3" | "Yu Gothic Light" | "Yu Mincho", number>>>;
36
+ /** One face a host serves, as its catalog lists it. */
37
+ export interface RemoteFontFace {
38
+ id: string;
39
+ family: string;
40
+ weight: number;
41
+ style: 'normal' | 'italic';
42
+ }
43
+ /**
44
+ * Fonts served by the host instead of the package — licensed faces never ship
45
+ * on npm. The host owns route, authentication and cache: `list` feeds the font
46
+ * picker, `load` returns one face's bytes.
47
+ */
48
+ export interface FontSource {
49
+ list(): Promise<RemoteFontFace[]>;
50
+ load(face: RemoteFontFace): Promise<ArrayBuffer>;
51
+ }
52
+ /**
53
+ * `installFonts` over a FontSource: same contract — declare the faces for
54
+ * `families` under the name the document asks for, with its nearest served
55
+ * family, and resolve to the names newly declared. A face is fetched once even
56
+ * when several names draw with it.
57
+ */
58
+ export declare function remoteFonts(source: FontSource): {
59
+ install: (families: Iterable<string>, alt?: Map<string, string>) => Promise<string[]>;
60
+ ratios: Record<string, number>;
61
+ /** served family names, sorted — for the font picker */
62
+ families: () => Promise<string[]>;
63
+ };
@@ -7,13 +7,14 @@
7
7
  *
8
8
  * React: `import { DocxEditor } from 'myrole-docx-editor/react'`.
9
9
  */
10
- export { createDocxEditor } from './sdk';
10
+ export { createDocxEditor, DOCX_EDITOR_VERSION } from './sdk';
11
11
  export type { DocxEditorHandle, DocxEditorOptions, DocxEditorUiOptions, DocxEditorEvent, ChromeMode, Theme } from './sdk';
12
12
  export type { FeedbackReport, FeedbackContext, FeedbackOptions } from './feedback';
13
13
  export type { AssistantOptions } from './assistant';
14
14
  export { renderDocx } from './embed';
15
15
  export type { Rendered } from './embed';
16
16
  export { installFonts, defaultFontsUrl } from './fonts';
17
+ export type { FontSource, RemoteFontFace } from './fonts';
17
18
  export type { Editor, EditorEvent, Command, Decoration, DecorationProvider } from './editor';
18
19
  export type { Tag } from '../../docx-tags/src/index';
19
20
  export type { DocxDocument, DocPos, EditContext, RunPatch, ParaPatch, MarginPatch } from '../../docx-model/src/index';
@@ -22,6 +22,7 @@ export declare const DocxEditor: import("react").ForwardRefExoticComponent<DocxE
22
22
  /** A ref to hand to `<DocxEditor ref={…}>`, and the handle once it exists. */
23
23
  export declare function useDocxEditor(): import("react").RefObject<DocxEditorHandle | null>;
24
24
  export type { DocxEditorHandle, DocxEditorOptions } from './sdk';
25
+ export { DOCX_EDITOR_VERSION } from './sdk';
25
26
  /** Read-only companion, with the same rendering and lifecycle as the editor. */
26
27
  export declare const DocxViewer: import("react").ForwardRefExoticComponent<DocxEditorProps & import("react").RefAttributes<DocxEditorHandle | null>>;
27
28
  export declare const DOCX_LOCKING_VERSION = 1;
@@ -16,12 +16,15 @@ import { type DocxDocument } from '../../docx-model/src/index';
16
16
  import type { Tag } from '../../docx-tags/src/index';
17
17
  import { type Editor } from './editor';
18
18
  import { type BadgeDisplay } from './variables';
19
+ import { type FontSource } from './fonts';
19
20
  import { type LibraryExtras } from './vars-library';
20
21
  import { type CommentRange } from './comments';
21
22
  import { type Panel, type DocxEditorUiOptions } from './ui/shell';
22
23
  import { type Draft } from './drafts';
23
24
  import { type FeedbackOptions } from './feedback';
24
25
  import { type AssistantOptions } from './assistant';
26
+ /** The published version of this package, as the status bar shows it. */
27
+ export declare const DOCX_EDITOR_VERSION: string;
25
28
  export type ChromeMode = 'full' | 'viewer' | 'none';
26
29
  export type Theme = 'light' | 'dark' | 'system';
27
30
  export type { DocxEditorUiOptions } from './ui/shell';
@@ -30,6 +33,12 @@ export interface DocxEditorOptions {
30
33
  /** `full`: ribbon, rulers, panels. `viewer`: read-only pages under a slim header. `none`: pages only. */
31
34
  /** Development host compatibility only; npm instances expose no window globals or IDs. */
32
35
  debug?: boolean;
36
+ /**
37
+ * Show the « Performances » button (Affichage tab): FPS, composition time,
38
+ * keystroke-to-screen latency. Without it the panel is still one shortcut
39
+ * away — Ctrl+Alt+Shift+P (⌘⌥⇧P) — so it can be opened in production.
40
+ */
41
+ perf?: boolean;
33
42
  chrome?: ChromeMode;
34
43
  readOnly?: boolean;
35
44
  lock?: DocxLockAdapter;
@@ -37,6 +46,8 @@ export interface DocxEditorOptions {
37
46
  theme?: Theme;
38
47
  /** directory that holds `ttf/` — see `fonts.ts` */
39
48
  fontsUrl?: string | URL;
49
+ /** host-served fonts (licensed faces are not on npm); replaces `fontsUrl` */
50
+ fonts?: FontSource;
40
51
  /** hard cap on the page count — a guard against a runaway layout, never an alignment */
41
52
  maxPages?: number;
42
53
  /** the document after a quiet period, and on tab change — where autosave goes */
@@ -1,2 +1,8 @@
1
+ import { type IconName } from '../../../docx-vars/src/index';
1
2
  export declare function hasIcon(id: string): boolean;
3
+ /**
4
+ * A Material Symbols glyph from the shared library (`@myrole/docx-vars`): filled,
5
+ * on its own 960-unit grid. The table tab and the context menu use these.
6
+ */
7
+ export declare function materialIcon(name: IconName, size?: number): SVGElement;
2
8
  export declare function icon(id: string, size?: number): SVGElement;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Debug-only performance overlay: FPS, frame times, composition time and the
3
+ * keystroke-to-screen latency, refreshed twice a second.
4
+ *
5
+ * Every composition is also published as a `performance.measure('docx:compose')`,
6
+ * so a DevTools Performance recording shows it on the Timings track.
7
+ */
8
+ export interface PerfHud {
9
+ /** One composition finished: its duration and the page count it produced. */
10
+ compose(ms: number, pages: number): void;
11
+ destroy(): void;
12
+ }
13
+ export declare function mountPerfHud(root: HTMLElement, pagesEl: HTMLElement): PerfHud;
@@ -6,10 +6,15 @@ import type { Tag } from '../../docx-tags/src/index';
6
6
  * Elle ne se déclenche pas n'importe où — une liste qui s'ouvre pendant qu'on
7
7
  * rédige une phrase est une nuisance. Deux endroits, et deux seulement :
8
8
  *
9
- * - **dans un tag ouvert** (`{{` ou `{%` sans fermeture avant le curseur) :
10
- * champs et fonctions, c'est-à-dire ce qui a le droit d'y figurer ;
9
+ * - **après un `/` dans un tag ouvert** (`{{` ou `{%` sans fermeture avant le
10
+ * curseur) : champs et fonctions, insérés comme expression nue
11
+ * (`salarie.prenom`, sans `{{ }}`). Un `/` collé à un opérande (`a/b`) reste
12
+ * une division ;
11
13
  * - **après un `/` en début de mot** : champs, fonctions et extraits.
12
14
  *
15
+ * The `/` hands the keyboard to the list's search box: the query is typed
16
+ * there, not in the document, and only the `/` is replaced on insertion.
17
+ *
13
18
  * Le clavier passe AVANT l'éditeur : la capture est posée sur le champ de
14
19
  * frappe, et les flèches, Entrée, Tab et Échap ne redescendent pas jusqu'à lui
15
20
  * tant que la liste est ouverte. Sans ça, ↓ déplacerait le curseur dans la page
@@ -40,6 +45,8 @@ export interface Completer {
40
45
  open(): boolean;
41
46
  destroy(): void;
42
47
  }
48
+ /** Directives of the sections that contain the caret. */
49
+ export declare function enclosing(tags: Tag[], para: number, off: number): string[];
43
50
  /** Ce qu'on est en train de taper, et ce qu'on a le droit d'y proposer. */
44
51
  interface Context {
45
52
  para: number;
@@ -50,7 +57,6 @@ interface Context {
50
57
  kinds: LibEntry['kind'][];
51
58
  /** ce qu'on insère : le code entier, ou seulement l'expression */
52
59
  as: 'code' | 'expr';
53
- padded?: boolean;
54
60
  }
55
61
  /**
56
62
  * Lit le contexte de frappe autour du curseur.
@@ -293,9 +293,37 @@ export interface CellPatch {
293
293
  marginPt?: number;
294
294
  borderPt?: number;
295
295
  borderColor?: string;
296
+ borderStyle?: string;
296
297
  }
297
298
  /** Explicit nil borders suppress style inheritance; nested tables keep their own grid. */
298
299
  export declare function clearTableBorders(doc: DocxDocument, para: number): boolean;
299
300
  export declare function formatCell(doc: DocxDocument, para: number, patch: CellPatch): boolean;
301
+ /**
302
+ * Word's « Fusionner les cellules »: the selected rectangle becomes ONE cell.
303
+ *
304
+ * `paras` holds one paragraph of each selected cell. Within a row the cells
305
+ * add their grid columns (`w:gridSpan`); across rows the merged cells chain
306
+ * with `w:vMerge`, the top one holding every paragraph. A cell whose only
307
+ * content is an empty paragraph contributes nothing, as in Word. Refused —
308
+ * nothing changed — unless the selection is a full rectangle with no vertical
309
+ * merge already in it.
310
+ */
311
+ export declare function mergeCells(doc: DocxDocument, paras: number[]): boolean;
300
312
  /** Merge with the next cell without dropping its paragraphs. Vertical merges are protected. */
301
313
  export declare function mergeNextCell(doc: DocxDocument, para: number): boolean;
314
+ export type BorderSides = 'all' | 'outside' | 'inside' | 'none' | 'top' | 'bottom' | 'left' | 'right' | 'insideH' | 'insideV';
315
+ /** `style` is a `w:val` (single, double, dashed, dotted, thick…); `sizePt` 0 or `sides: 'none'` erases. */
316
+ export interface TableBorderPatch {
317
+ sides: BorderSides;
318
+ style?: string;
319
+ sizePt?: number;
320
+ color?: string;
321
+ }
322
+ /**
323
+ * Word's « Bordures » menu on the whole table: writes `w:tblBorders`, then drops
324
+ * the cell overrides (`w:tcBorders`) that would hide the change, on the cells
325
+ * whose edge actually lies on the chosen side.
326
+ */
327
+ export declare function setTableBorders(doc: DocxDocument, para: number, patch: TableBorderPatch): boolean;
328
+ /** Minimum height of the row holding `para` — the gesture of dragging its bottom rule. */
329
+ export declare function setRowHeight(doc: DocxDocument, para: number, heightPt: number): boolean;
@@ -17,6 +17,8 @@ export interface DocxDocument {
17
17
  /** ordre original des entrées du zip, pour rebuild déterministe */
18
18
  order: string[];
19
19
  }
20
+ /** Parses XML into the same ordered tree as a package part. */
21
+ export declare const parseXml: (xml: string) => XmlTree;
20
22
  export declare function readDocx(buf: Uint8Array): DocxDocument;
21
23
  export declare function writeDocx(doc: DocxDocument): Uint8Array;
22
24
  /** Nom de balise d'un noeud ordonné (les clés `:@` / `#text` sont des métadonnées). */