@ryanyahya/opendoc 0.4.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 (789) hide show
  1. package/.agents/skills/opendoc-apply-comments/SKILL.md +30 -0
  2. package/.agents/skills/opendoc-apply-comments/agents/openai.yaml +4 -0
  3. package/.agents/skills/opendoc-create/SKILL.md +63 -0
  4. package/.agents/skills/opendoc-create/agents/openai.yaml +6 -0
  5. package/.agents/skills/opendoc-create-template/SKILL.md +50 -0
  6. package/.agents/skills/opendoc-create-template/agents/openai.yaml +4 -0
  7. package/.agents/skills/opendoc-create-template/references/structured-reports.md +11 -0
  8. package/.agents/skills/opendoc-create-theme/SKILL.md +40 -0
  9. package/.agents/skills/opendoc-create-theme/agents/openai.yaml +4 -0
  10. package/.agents/skills/opendoc-current-document/SKILL.md +32 -0
  11. package/.agents/skills/opendoc-current-document/agents/openai.yaml +4 -0
  12. package/.agents/skills/opendoc-current-document/references/context-fields.md +20 -0
  13. package/.agents/skills/opendoc-review-document/SKILL.md +60 -0
  14. package/.agents/skills/opendoc-review-document/agents/openai.yaml +4 -0
  15. package/AGENTS.md +69 -0
  16. package/CONTRIBUTING.md +38 -0
  17. package/LICENSE +21 -0
  18. package/README.md +179 -0
  19. package/SECURITY.md +9 -0
  20. package/THIRD_PARTY.md +49 -0
  21. package/VALIDATION.md +99 -0
  22. package/bin/opendoc.mjs +6 -0
  23. package/dist/assets/Markdown-sNZyjJi7.js +29 -0
  24. package/dist/assets/OpenDocSerif-Regular-D3OXs9A9.ttf +0 -0
  25. package/dist/assets/OpenDocSerif-Semibold-CjL9oDRo.ttf +0 -0
  26. package/dist/assets/geist-latin-ext-wght-italic-XgKbg5n7.woff2 +0 -0
  27. package/dist/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  28. package/dist/assets/geist-latin-wght-italic-dTnRTFFJ.woff2 +0 -0
  29. package/dist/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  30. package/dist/assets/index-DdrZ6ozO.css +1 -0
  31. package/dist/assets/index-DgNBz7mL.js +39 -0
  32. package/dist/assets/pdf-B7Emtyld.js +54 -0
  33. package/dist/assets/pdf.worker.min-Dswkl-cV.mjs +29 -0
  34. package/dist/assets/wordmark-DsqLlZpb.png +0 -0
  35. package/dist/index.html +17 -0
  36. package/docs/APPEARANCE.md +21 -0
  37. package/docs/ASSETS.md +176 -0
  38. package/docs/AUTHORING.md +178 -0
  39. package/docs/HEADLESS.md +120 -0
  40. package/docs/MEDIA.md +112 -0
  41. package/docs/PROJECTS.md +55 -0
  42. package/docs/PROSE.md +15 -0
  43. package/docs/SELECTION.md +59 -0
  44. package/docs/TEMPLATES.md +55 -0
  45. package/docs/THEMES.md +106 -0
  46. package/node_modules/@formepdf/core/LICENSE +21 -0
  47. package/node_modules/@formepdf/core/README.md +53 -0
  48. package/node_modules/@formepdf/core/dist/attachments.d.ts +55 -0
  49. package/node_modules/@formepdf/core/dist/attachments.js +59 -0
  50. package/node_modules/@formepdf/core/dist/extract.d.ts +8 -0
  51. package/node_modules/@formepdf/core/dist/extract.js +56 -0
  52. package/node_modules/@formepdf/core/dist/index.d.ts +311 -0
  53. package/node_modules/@formepdf/core/dist/index.js +167 -0
  54. package/node_modules/@formepdf/core/dist/layout.d.ts +132 -0
  55. package/node_modules/@formepdf/core/dist/layout.js +240 -0
  56. package/node_modules/@formepdf/core/dist/shared/browserHelpers.d.ts +19 -0
  57. package/node_modules/@formepdf/core/dist/shared/browserHelpers.js +128 -0
  58. package/node_modules/@formepdf/core/package.json +35 -0
  59. package/node_modules/@formepdf/core/pkg-node/LICENSE +21 -0
  60. package/node_modules/@formepdf/core/pkg-node/README.md +84 -0
  61. package/node_modules/@formepdf/core/pkg-node/forme.d.ts +39 -0
  62. package/node_modules/@formepdf/core/pkg-node/forme.js +394 -0
  63. package/node_modules/@formepdf/core/pkg-node/forme_bg.wasm +0 -0
  64. package/node_modules/@formepdf/core/pkg-node/forme_bg.wasm.d.ts +21 -0
  65. package/node_modules/@formepdf/core/pkg-node/package.json +25 -0
  66. package/node_modules/@formepdf/react/README.md +70 -0
  67. package/node_modules/@formepdf/react/dist/charts.d.ts +72 -0
  68. package/node_modules/@formepdf/react/dist/charts.js +338 -0
  69. package/node_modules/@formepdf/react/dist/components.d.ts +533 -0
  70. package/node_modules/@formepdf/react/dist/components.js +608 -0
  71. package/node_modules/@formepdf/react/dist/expr.d.ts +20 -0
  72. package/node_modules/@formepdf/react/dist/expr.js +39 -0
  73. package/node_modules/@formepdf/react/dist/font.d.ts +2 -0
  74. package/node_modules/@formepdf/react/dist/font.js +1 -0
  75. package/node_modules/@formepdf/react/dist/index.d.ts +11 -0
  76. package/node_modules/@formepdf/react/dist/index.js +15 -0
  77. package/node_modules/@formepdf/react/dist/render.d.ts +12 -0
  78. package/node_modules/@formepdf/react/dist/render.js +15 -0
  79. package/node_modules/@formepdf/react/dist/serialize.d.ts +12 -0
  80. package/node_modules/@formepdf/react/dist/serialize.js +1470 -0
  81. package/node_modules/@formepdf/react/dist/stylesheet.d.ts +4 -0
  82. package/node_modules/@formepdf/react/dist/stylesheet.js +5 -0
  83. package/node_modules/@formepdf/react/dist/template-proxy.d.ts +38 -0
  84. package/node_modules/@formepdf/react/dist/template-proxy.js +100 -0
  85. package/node_modules/@formepdf/react/dist/types.d.ts +287 -0
  86. package/node_modules/@formepdf/react/dist/types.js +1 -0
  87. package/node_modules/@formepdf/react/package.json +41 -0
  88. package/node_modules/@formepdf/shared/README.md +7 -0
  89. package/node_modules/@formepdf/shared/dist/canvas.d.ts +6 -0
  90. package/node_modules/@formepdf/shared/dist/canvas.js +43 -0
  91. package/node_modules/@formepdf/shared/dist/charts.d.ts +100 -0
  92. package/node_modules/@formepdf/shared/dist/charts.js +98 -0
  93. package/node_modules/@formepdf/shared/dist/encode.d.ts +27 -0
  94. package/node_modules/@formepdf/shared/dist/encode.js +93 -0
  95. package/node_modules/@formepdf/shared/dist/font.d.ts +13 -0
  96. package/node_modules/@formepdf/shared/dist/font.js +52 -0
  97. package/node_modules/@formepdf/shared/dist/index.d.ts +10 -0
  98. package/node_modules/@formepdf/shared/dist/index.js +15 -0
  99. package/node_modules/@formepdf/shared/dist/parser.d.ts +30 -0
  100. package/node_modules/@formepdf/shared/dist/parser.js +756 -0
  101. package/node_modules/@formepdf/shared/dist/semantics.d.ts +15 -0
  102. package/node_modules/@formepdf/shared/dist/semantics.js +44 -0
  103. package/node_modules/@formepdf/shared/dist/style.d.ts +7 -0
  104. package/node_modules/@formepdf/shared/dist/style.js +1024 -0
  105. package/node_modules/@formepdf/shared/dist/types.d.ts +743 -0
  106. package/node_modules/@formepdf/shared/dist/types.js +2 -0
  107. package/node_modules/@formepdf/shared/package.json +35 -0
  108. package/node_modules/@types/node/LICENSE +21 -0
  109. package/node_modules/@types/node/README.md +15 -0
  110. package/node_modules/@types/node/assert/strict.d.ts +111 -0
  111. package/node_modules/@types/node/assert.d.ts +1078 -0
  112. package/node_modules/@types/node/async_hooks.d.ts +603 -0
  113. package/node_modules/@types/node/buffer.buffer.d.ts +472 -0
  114. package/node_modules/@types/node/buffer.d.ts +1934 -0
  115. package/node_modules/@types/node/child_process.d.ts +1476 -0
  116. package/node_modules/@types/node/cluster.d.ts +578 -0
  117. package/node_modules/@types/node/compatibility/disposable.d.ts +14 -0
  118. package/node_modules/@types/node/compatibility/index.d.ts +9 -0
  119. package/node_modules/@types/node/compatibility/indexable.d.ts +20 -0
  120. package/node_modules/@types/node/compatibility/iterators.d.ts +20 -0
  121. package/node_modules/@types/node/console.d.ts +452 -0
  122. package/node_modules/@types/node/constants.d.ts +21 -0
  123. package/node_modules/@types/node/crypto.d.ts +4545 -0
  124. package/node_modules/@types/node/dgram.d.ts +600 -0
  125. package/node_modules/@types/node/diagnostics_channel.d.ts +576 -0
  126. package/node_modules/@types/node/dns/promises.d.ts +503 -0
  127. package/node_modules/@types/node/dns.d.ts +923 -0
  128. package/node_modules/@types/node/domain.d.ts +170 -0
  129. package/node_modules/@types/node/events.d.ts +976 -0
  130. package/node_modules/@types/node/fs/promises.d.ts +1306 -0
  131. package/node_modules/@types/node/fs.d.ts +4463 -0
  132. package/node_modules/@types/node/globals.d.ts +172 -0
  133. package/node_modules/@types/node/globals.typedarray.d.ts +38 -0
  134. package/node_modules/@types/node/http.d.ts +2097 -0
  135. package/node_modules/@types/node/http2.d.ts +2843 -0
  136. package/node_modules/@types/node/https.d.ts +579 -0
  137. package/node_modules/@types/node/index.d.ts +98 -0
  138. package/node_modules/@types/node/inspector.d.ts +253 -0
  139. package/node_modules/@types/node/inspector.generated.d.ts +4052 -0
  140. package/node_modules/@types/node/module.d.ts +891 -0
  141. package/node_modules/@types/node/net.d.ts +1076 -0
  142. package/node_modules/@types/node/os.d.ts +506 -0
  143. package/node_modules/@types/node/package.json +145 -0
  144. package/node_modules/@types/node/path.d.ts +200 -0
  145. package/node_modules/@types/node/perf_hooks.d.ts +968 -0
  146. package/node_modules/@types/node/process.d.ts +2084 -0
  147. package/node_modules/@types/node/punycode.d.ts +117 -0
  148. package/node_modules/@types/node/querystring.d.ts +152 -0
  149. package/node_modules/@types/node/readline/promises.d.ts +161 -0
  150. package/node_modules/@types/node/readline.d.ts +594 -0
  151. package/node_modules/@types/node/repl.d.ts +428 -0
  152. package/node_modules/@types/node/sea.d.ts +162 -0
  153. package/node_modules/@types/node/sqlite.d.ts +722 -0
  154. package/node_modules/@types/node/stream/consumers.d.ts +38 -0
  155. package/node_modules/@types/node/stream/promises.d.ts +90 -0
  156. package/node_modules/@types/node/stream/web.d.ts +573 -0
  157. package/node_modules/@types/node/stream.d.ts +1694 -0
  158. package/node_modules/@types/node/string_decoder.d.ts +67 -0
  159. package/node_modules/@types/node/test.d.ts +2265 -0
  160. package/node_modules/@types/node/timers/promises.d.ts +108 -0
  161. package/node_modules/@types/node/timers.d.ts +287 -0
  162. package/node_modules/@types/node/tls.d.ts +1319 -0
  163. package/node_modules/@types/node/trace_events.d.ts +197 -0
  164. package/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +468 -0
  165. package/node_modules/@types/node/ts5.6/globals.typedarray.d.ts +34 -0
  166. package/node_modules/@types/node/ts5.6/index.d.ts +98 -0
  167. package/node_modules/@types/node/tty.d.ts +208 -0
  168. package/node_modules/@types/node/url.d.ts +984 -0
  169. package/node_modules/@types/node/util.d.ts +2606 -0
  170. package/node_modules/@types/node/v8.d.ts +920 -0
  171. package/node_modules/@types/node/vm.d.ts +1053 -0
  172. package/node_modules/@types/node/wasi.d.ts +181 -0
  173. package/node_modules/@types/node/web-globals/abortcontroller.d.ts +34 -0
  174. package/node_modules/@types/node/web-globals/domexception.d.ts +68 -0
  175. package/node_modules/@types/node/web-globals/events.d.ts +97 -0
  176. package/node_modules/@types/node/web-globals/fetch.d.ts +55 -0
  177. package/node_modules/@types/node/web-globals/navigator.d.ts +22 -0
  178. package/node_modules/@types/node/web-globals/storage.d.ts +24 -0
  179. package/node_modules/@types/node/web-globals/streams.d.ts +22 -0
  180. package/node_modules/@types/node/worker_threads.d.ts +819 -0
  181. package/node_modules/@types/node/zlib.d.ts +747 -0
  182. package/node_modules/@types/react/LICENSE +21 -0
  183. package/node_modules/@types/react/README.md +15 -0
  184. package/node_modules/@types/react/canary.d.ts +129 -0
  185. package/node_modules/@types/react/compiler-runtime.d.ts +4 -0
  186. package/node_modules/@types/react/experimental.d.ts +184 -0
  187. package/node_modules/@types/react/global.d.ts +166 -0
  188. package/node_modules/@types/react/index.d.ts +4378 -0
  189. package/node_modules/@types/react/jsx-dev-runtime.d.ts +33 -0
  190. package/node_modules/@types/react/jsx-runtime.d.ts +24 -0
  191. package/node_modules/@types/react/package.json +210 -0
  192. package/node_modules/@types/react/ts5.0/canary.d.ts +129 -0
  193. package/node_modules/@types/react/ts5.0/experimental.d.ts +184 -0
  194. package/node_modules/@types/react/ts5.0/global.d.ts +166 -0
  195. package/node_modules/@types/react/ts5.0/index.d.ts +4365 -0
  196. package/node_modules/@types/react/ts5.0/jsx-dev-runtime.d.ts +33 -0
  197. package/node_modules/@types/react/ts5.0/jsx-runtime.d.ts +24 -0
  198. package/node_modules/csstype/LICENSE +19 -0
  199. package/node_modules/csstype/README.md +291 -0
  200. package/node_modules/csstype/index.d.ts +22569 -0
  201. package/node_modules/csstype/index.js.flow +6863 -0
  202. package/node_modules/csstype/package.json +70 -0
  203. package/node_modules/entities/LICENSE +11 -0
  204. package/node_modules/entities/decode.d.ts +1 -0
  205. package/node_modules/entities/decode.js +3 -0
  206. package/node_modules/entities/dist/commonjs/decode-codepoint.d.ts +19 -0
  207. package/node_modules/entities/dist/commonjs/decode-codepoint.d.ts.map +1 -0
  208. package/node_modules/entities/dist/commonjs/decode-codepoint.js +77 -0
  209. package/node_modules/entities/dist/commonjs/decode-codepoint.js.map +1 -0
  210. package/node_modules/entities/dist/commonjs/decode.d.ts +209 -0
  211. package/node_modules/entities/dist/commonjs/decode.d.ts.map +1 -0
  212. package/node_modules/entities/dist/commonjs/decode.js +511 -0
  213. package/node_modules/entities/dist/commonjs/decode.js.map +1 -0
  214. package/node_modules/entities/dist/commonjs/encode.d.ts +22 -0
  215. package/node_modules/entities/dist/commonjs/encode.d.ts.map +1 -0
  216. package/node_modules/entities/dist/commonjs/encode.js +73 -0
  217. package/node_modules/entities/dist/commonjs/encode.js.map +1 -0
  218. package/node_modules/entities/dist/commonjs/escape.d.ts +43 -0
  219. package/node_modules/entities/dist/commonjs/escape.d.ts.map +1 -0
  220. package/node_modules/entities/dist/commonjs/escape.js +121 -0
  221. package/node_modules/entities/dist/commonjs/escape.js.map +1 -0
  222. package/node_modules/entities/dist/commonjs/generated/decode-data-html.d.ts +2 -0
  223. package/node_modules/entities/dist/commonjs/generated/decode-data-html.d.ts.map +1 -0
  224. package/node_modules/entities/dist/commonjs/generated/decode-data-html.js +10 -0
  225. package/node_modules/entities/dist/commonjs/generated/decode-data-html.js.map +1 -0
  226. package/node_modules/entities/dist/commonjs/generated/decode-data-xml.d.ts +2 -0
  227. package/node_modules/entities/dist/commonjs/generated/decode-data-xml.d.ts.map +1 -0
  228. package/node_modules/entities/dist/commonjs/generated/decode-data-xml.js +10 -0
  229. package/node_modules/entities/dist/commonjs/generated/decode-data-xml.js.map +1 -0
  230. package/node_modules/entities/dist/commonjs/generated/encode-html.d.ts +8 -0
  231. package/node_modules/entities/dist/commonjs/generated/encode-html.d.ts.map +1 -0
  232. package/node_modules/entities/dist/commonjs/generated/encode-html.js +13 -0
  233. package/node_modules/entities/dist/commonjs/generated/encode-html.js.map +1 -0
  234. package/node_modules/entities/dist/commonjs/index.d.ts +96 -0
  235. package/node_modules/entities/dist/commonjs/index.d.ts.map +1 -0
  236. package/node_modules/entities/dist/commonjs/index.js +131 -0
  237. package/node_modules/entities/dist/commonjs/index.js.map +1 -0
  238. package/node_modules/entities/dist/commonjs/package.json +3 -0
  239. package/node_modules/entities/dist/esm/decode-codepoint.d.ts +19 -0
  240. package/node_modules/entities/dist/esm/decode-codepoint.d.ts.map +1 -0
  241. package/node_modules/entities/dist/esm/decode-codepoint.js +72 -0
  242. package/node_modules/entities/dist/esm/decode-codepoint.js.map +1 -0
  243. package/node_modules/entities/dist/esm/decode.d.ts +209 -0
  244. package/node_modules/entities/dist/esm/decode.d.ts.map +1 -0
  245. package/node_modules/entities/dist/esm/decode.js +497 -0
  246. package/node_modules/entities/dist/esm/decode.js.map +1 -0
  247. package/node_modules/entities/dist/esm/encode.d.ts +22 -0
  248. package/node_modules/entities/dist/esm/encode.d.ts.map +1 -0
  249. package/node_modules/entities/dist/esm/encode.js +69 -0
  250. package/node_modules/entities/dist/esm/encode.js.map +1 -0
  251. package/node_modules/entities/dist/esm/escape.d.ts +43 -0
  252. package/node_modules/entities/dist/esm/escape.d.ts.map +1 -0
  253. package/node_modules/entities/dist/esm/escape.js +117 -0
  254. package/node_modules/entities/dist/esm/escape.js.map +1 -0
  255. package/node_modules/entities/dist/esm/generated/decode-data-html.d.ts +2 -0
  256. package/node_modules/entities/dist/esm/generated/decode-data-html.d.ts.map +1 -0
  257. package/node_modules/entities/dist/esm/generated/decode-data-html.js +7 -0
  258. package/node_modules/entities/dist/esm/generated/decode-data-html.js.map +1 -0
  259. package/node_modules/entities/dist/esm/generated/decode-data-xml.d.ts +2 -0
  260. package/node_modules/entities/dist/esm/generated/decode-data-xml.d.ts.map +1 -0
  261. package/node_modules/entities/dist/esm/generated/decode-data-xml.js +7 -0
  262. package/node_modules/entities/dist/esm/generated/decode-data-xml.js.map +1 -0
  263. package/node_modules/entities/dist/esm/generated/encode-html.d.ts +8 -0
  264. package/node_modules/entities/dist/esm/generated/encode-html.d.ts.map +1 -0
  265. package/node_modules/entities/dist/esm/generated/encode-html.js +10 -0
  266. package/node_modules/entities/dist/esm/generated/encode-html.js.map +1 -0
  267. package/node_modules/entities/dist/esm/index.d.ts +96 -0
  268. package/node_modules/entities/dist/esm/index.d.ts.map +1 -0
  269. package/node_modules/entities/dist/esm/index.js +107 -0
  270. package/node_modules/entities/dist/esm/index.js.map +1 -0
  271. package/node_modules/entities/dist/esm/package.json +3 -0
  272. package/node_modules/entities/escape.d.ts +1 -0
  273. package/node_modules/entities/escape.js +3 -0
  274. package/node_modules/entities/package.json +118 -0
  275. package/node_modules/entities/readme.md +122 -0
  276. package/node_modules/entities/src/decode-codepoint.ts +81 -0
  277. package/node_modules/entities/src/decode.spec.ts +320 -0
  278. package/node_modules/entities/src/decode.ts +620 -0
  279. package/node_modules/entities/src/encode.spec.ts +78 -0
  280. package/node_modules/entities/src/encode.ts +77 -0
  281. package/node_modules/entities/src/escape.spec.ts +14 -0
  282. package/node_modules/entities/src/escape.ts +148 -0
  283. package/node_modules/entities/src/generated/.eslintrc.json +10 -0
  284. package/node_modules/entities/src/generated/decode-data-html.ts +8 -0
  285. package/node_modules/entities/src/generated/decode-data-xml.ts +8 -0
  286. package/node_modules/entities/src/generated/encode-html.ts +17 -0
  287. package/node_modules/entities/src/index.spec.ts +125 -0
  288. package/node_modules/entities/src/index.ts +188 -0
  289. package/node_modules/parse5/LICENSE +19 -0
  290. package/node_modules/parse5/README.md +38 -0
  291. package/node_modules/parse5/dist/cjs/common/doctype.d.ts +4 -0
  292. package/node_modules/parse5/dist/cjs/common/doctype.js +118 -0
  293. package/node_modules/parse5/dist/cjs/common/error-codes.d.ts +67 -0
  294. package/node_modules/parse5/dist/cjs/common/error-codes.js +66 -0
  295. package/node_modules/parse5/dist/cjs/common/foreign-content.d.ts +9 -0
  296. package/node_modules/parse5/dist/cjs/common/foreign-content.js +237 -0
  297. package/node_modules/parse5/dist/cjs/common/html.d.ts +289 -0
  298. package/node_modules/parse5/dist/cjs/common/html.js +528 -0
  299. package/node_modules/parse5/dist/cjs/common/token.d.ts +84 -0
  300. package/node_modules/parse5/dist/cjs/common/token.js +24 -0
  301. package/node_modules/parse5/dist/cjs/common/unicode.d.ts +42 -0
  302. package/node_modules/parse5/dist/cjs/common/unicode.js +70 -0
  303. package/node_modules/parse5/dist/cjs/index.d.ts +71 -0
  304. package/node_modules/parse5/dist/cjs/index.js +54 -0
  305. package/node_modules/parse5/dist/cjs/package.json +1 -0
  306. package/node_modules/parse5/dist/cjs/parser/formatting-element-list.d.ts +36 -0
  307. package/node_modules/parse5/dist/cjs/parser/formatting-element-list.js +114 -0
  308. package/node_modules/parse5/dist/cjs/parser/index.d.ts +221 -0
  309. package/node_modules/parse5/dist/cjs/parser/index.js +3240 -0
  310. package/node_modules/parse5/dist/cjs/parser/open-element-stack.d.ts +53 -0
  311. package/node_modules/parse5/dist/cjs/parser/open-element-stack.js +328 -0
  312. package/node_modules/parse5/dist/cjs/serializer/index.d.ts +60 -0
  313. package/node_modules/parse5/dist/cjs/serializer/index.js +172 -0
  314. package/node_modules/parse5/dist/cjs/tokenizer/index.d.ts +247 -0
  315. package/node_modules/parse5/dist/cjs/tokenizer/index.js +2714 -0
  316. package/node_modules/parse5/dist/cjs/tokenizer/preprocessor.d.ts +36 -0
  317. package/node_modules/parse5/dist/cjs/tokenizer/preprocessor.js +200 -0
  318. package/node_modules/parse5/dist/cjs/tree-adapters/default.d.ts +84 -0
  319. package/node_modules/parse5/dist/cjs/tree-adapters/default.js +176 -0
  320. package/node_modules/parse5/dist/cjs/tree-adapters/interface.d.ts +255 -0
  321. package/node_modules/parse5/dist/cjs/tree-adapters/interface.js +2 -0
  322. package/node_modules/parse5/dist/common/doctype.d.ts +4 -0
  323. package/node_modules/parse5/dist/common/doctype.js +114 -0
  324. package/node_modules/parse5/dist/common/error-codes.d.ts +67 -0
  325. package/node_modules/parse5/dist/common/error-codes.js +63 -0
  326. package/node_modules/parse5/dist/common/foreign-content.d.ts +9 -0
  327. package/node_modules/parse5/dist/common/foreign-content.js +228 -0
  328. package/node_modules/parse5/dist/common/html.d.ts +289 -0
  329. package/node_modules/parse5/dist/common/html.js +523 -0
  330. package/node_modules/parse5/dist/common/token.d.ts +84 -0
  331. package/node_modules/parse5/dist/common/token.js +20 -0
  332. package/node_modules/parse5/dist/common/unicode.d.ts +42 -0
  333. package/node_modules/parse5/dist/common/unicode.js +62 -0
  334. package/node_modules/parse5/dist/index.d.ts +71 -0
  335. package/node_modules/parse5/dist/index.js +42 -0
  336. package/node_modules/parse5/dist/parser/formatting-element-list.d.ts +36 -0
  337. package/node_modules/parse5/dist/parser/formatting-element-list.js +110 -0
  338. package/node_modules/parse5/dist/parser/index.d.ts +221 -0
  339. package/node_modules/parse5/dist/parser/index.js +3245 -0
  340. package/node_modules/parse5/dist/parser/open-element-stack.d.ts +53 -0
  341. package/node_modules/parse5/dist/parser/open-element-stack.js +324 -0
  342. package/node_modules/parse5/dist/serializer/index.d.ts +60 -0
  343. package/node_modules/parse5/dist/serializer/index.js +168 -0
  344. package/node_modules/parse5/dist/tokenizer/index.d.ts +247 -0
  345. package/node_modules/parse5/dist/tokenizer/index.js +2710 -0
  346. package/node_modules/parse5/dist/tokenizer/preprocessor.d.ts +36 -0
  347. package/node_modules/parse5/dist/tokenizer/preprocessor.js +196 -0
  348. package/node_modules/parse5/dist/tree-adapters/default.d.ts +84 -0
  349. package/node_modules/parse5/dist/tree-adapters/default.js +173 -0
  350. package/node_modules/parse5/dist/tree-adapters/interface.d.ts +255 -0
  351. package/node_modules/parse5/dist/tree-adapters/interface.js +1 -0
  352. package/node_modules/parse5/package.json +50 -0
  353. package/node_modules/undici-types/LICENSE +21 -0
  354. package/node_modules/undici-types/README.md +6 -0
  355. package/node_modules/undici-types/agent.d.ts +31 -0
  356. package/node_modules/undici-types/api.d.ts +43 -0
  357. package/node_modules/undici-types/balanced-pool.d.ts +29 -0
  358. package/node_modules/undici-types/cache.d.ts +36 -0
  359. package/node_modules/undici-types/client.d.ts +108 -0
  360. package/node_modules/undici-types/connector.d.ts +34 -0
  361. package/node_modules/undici-types/content-type.d.ts +21 -0
  362. package/node_modules/undici-types/cookies.d.ts +28 -0
  363. package/node_modules/undici-types/diagnostics-channel.d.ts +66 -0
  364. package/node_modules/undici-types/dispatcher.d.ts +256 -0
  365. package/node_modules/undici-types/env-http-proxy-agent.d.ts +21 -0
  366. package/node_modules/undici-types/errors.d.ts +149 -0
  367. package/node_modules/undici-types/eventsource.d.ts +61 -0
  368. package/node_modules/undici-types/fetch.d.ts +209 -0
  369. package/node_modules/undici-types/file.d.ts +39 -0
  370. package/node_modules/undici-types/filereader.d.ts +54 -0
  371. package/node_modules/undici-types/formdata.d.ts +108 -0
  372. package/node_modules/undici-types/global-dispatcher.d.ts +9 -0
  373. package/node_modules/undici-types/global-origin.d.ts +7 -0
  374. package/node_modules/undici-types/handlers.d.ts +15 -0
  375. package/node_modules/undici-types/header.d.ts +4 -0
  376. package/node_modules/undici-types/index.d.ts +71 -0
  377. package/node_modules/undici-types/interceptors.d.ts +17 -0
  378. package/node_modules/undici-types/mock-agent.d.ts +50 -0
  379. package/node_modules/undici-types/mock-client.d.ts +25 -0
  380. package/node_modules/undici-types/mock-errors.d.ts +12 -0
  381. package/node_modules/undici-types/mock-interceptor.d.ts +93 -0
  382. package/node_modules/undici-types/mock-pool.d.ts +25 -0
  383. package/node_modules/undici-types/package.json +55 -0
  384. package/node_modules/undici-types/patch.d.ts +33 -0
  385. package/node_modules/undici-types/pool-stats.d.ts +19 -0
  386. package/node_modules/undici-types/pool.d.ts +39 -0
  387. package/node_modules/undici-types/proxy-agent.d.ts +28 -0
  388. package/node_modules/undici-types/readable.d.ts +65 -0
  389. package/node_modules/undici-types/retry-agent.d.ts +8 -0
  390. package/node_modules/undici-types/retry-handler.d.ts +116 -0
  391. package/node_modules/undici-types/util.d.ts +18 -0
  392. package/node_modules/undici-types/webidl.d.ts +228 -0
  393. package/node_modules/undici-types/websocket.d.ts +150 -0
  394. package/package.json +80 -0
  395. package/scripts/rebuild-forme.mjs +61 -0
  396. package/src/app/AppearanceControl.tsx +44 -0
  397. package/src/app/AssetThemeDefaults.tsx +87 -0
  398. package/src/app/AssetsBrowser.tsx +273 -0
  399. package/src/app/CommentDock.tsx +108 -0
  400. package/src/app/CreateDocumentDialog.tsx +51 -0
  401. package/src/app/DocumentActions.tsx +69 -0
  402. package/src/app/DocumentCard.tsx +50 -0
  403. package/src/app/DocumentViewControl.tsx +31 -0
  404. package/src/app/DocumentsBrowser.tsx +70 -0
  405. package/src/app/ExportHistoryDialog.tsx +86 -0
  406. package/src/app/ExportMenu.tsx +127 -0
  407. package/src/app/GuideDialog.tsx +80 -0
  408. package/src/app/InspectionLayer.tsx +77 -0
  409. package/src/app/LogoUploadDialog.tsx +92 -0
  410. package/src/app/Markdown.tsx +34 -0
  411. package/src/app/MaterialsBrowser.tsx +149 -0
  412. package/src/app/PageNumberInput.tsx +56 -0
  413. package/src/app/Pdf.tsx +561 -0
  414. package/src/app/ProjectDialogs.tsx +100 -0
  415. package/src/app/Reader.tsx +769 -0
  416. package/src/app/SearchField.tsx +13 -0
  417. package/src/app/Sidebar.tsx +86 -0
  418. package/src/app/SkillIndex.tsx +30 -0
  419. package/src/app/TemplatesBrowser.tsx +149 -0
  420. package/src/app/ThemesBrowser.tsx +159 -0
  421. package/src/app/api.ts +47 -0
  422. package/src/app/appearance.ts +35 -0
  423. package/src/app/assets.css +139 -0
  424. package/src/app/catalogPreview.ts +20 -0
  425. package/src/app/colors.css +167 -0
  426. package/src/app/comment-dock.css +53 -0
  427. package/src/app/commentDrafts.ts +67 -0
  428. package/src/app/componentCorrection.ts +17 -0
  429. package/src/app/edit-workbench.css +87 -0
  430. package/src/app/editSession.ts +238 -0
  431. package/src/app/editorRecovery.ts +25 -0
  432. package/src/app/export-history.css +31 -0
  433. package/src/app/export.css +17 -0
  434. package/src/app/guideLinks.ts +21 -0
  435. package/src/app/guides.css +40 -0
  436. package/src/app/main.tsx +221 -0
  437. package/src/app/materials.css +53 -0
  438. package/src/app/pdfLoading.ts +12 -0
  439. package/src/app/pdfSelection.ts +112 -0
  440. package/src/app/projects.css +63 -0
  441. package/src/app/reader-toolbar.css +65 -0
  442. package/src/app/selection.css +150 -0
  443. package/src/app/sidebar.css +60 -0
  444. package/src/app/skills.css +7 -0
  445. package/src/app/style.css +1061 -0
  446. package/src/app/templates.css +49 -0
  447. package/src/app/themes.css +80 -0
  448. package/src/app/ui/Icon.tsx +92 -0
  449. package/src/app/ui/README.md +27 -0
  450. package/src/app/ui/fonts.css +36 -0
  451. package/src/app/ui/index.tsx +223 -0
  452. package/src/app/ui/ui.css +388 -0
  453. package/src/app/useReaderPreview.ts +19 -0
  454. package/src/app/useTextEditing.ts +155 -0
  455. package/src/assets/adapter.ts +122 -0
  456. package/src/assets/files.ts +378 -0
  457. package/src/assets/import-worker.ts +294 -0
  458. package/src/assets/imports.ts +124 -0
  459. package/src/assets/index.ts +60 -0
  460. package/src/assets/store.ts +798 -0
  461. package/src/assets/usage.ts +118 -0
  462. package/src/cli/check.ts +25 -0
  463. package/src/cli/init.ts +119 -0
  464. package/src/cli/lock.ts +34 -0
  465. package/src/cli/main.ts +118 -0
  466. package/src/cli/process.ts +19 -0
  467. package/src/cli/start.ts +96 -0
  468. package/src/cli/update.ts +348 -0
  469. package/src/cli/workspace.ts +94 -0
  470. package/src/document/index.tsx +641 -0
  471. package/src/document/page.tsx +53 -0
  472. package/src/document/text-targets.tsx +162 -0
  473. package/src/media/files.ts +124 -0
  474. package/src/media/render.ts +63 -0
  475. package/src/rendering/resolve-sources.ts +84 -0
  476. package/src/runtime/jsx-dev-runtime.ts +2 -0
  477. package/src/runtime/jsx-runtime.ts +2 -0
  478. package/src/runtime/paths.ts +12 -0
  479. package/src/server/assets-cli.ts +162 -0
  480. package/src/server/assets-http.ts +100 -0
  481. package/src/server/client.ts +50 -0
  482. package/src/server/clipboard.ts +22 -0
  483. package/src/server/comments-cli.ts +64 -0
  484. package/src/server/comments.ts +130 -0
  485. package/src/server/create-cli.ts +33 -0
  486. package/src/server/create.ts +228 -0
  487. package/src/server/dependencies.ts +91 -0
  488. package/src/server/documents.ts +143 -0
  489. package/src/server/edits.ts +249 -0
  490. package/src/server/export-batch.ts +105 -0
  491. package/src/server/export-errors.ts +2 -0
  492. package/src/server/export-file.ts +57 -0
  493. package/src/server/export-inputs.ts +66 -0
  494. package/src/server/export-preview.ts +69 -0
  495. package/src/server/export.ts +32 -0
  496. package/src/server/exports.ts +283 -0
  497. package/src/server/files.ts +21 -0
  498. package/src/server/guides.ts +71 -0
  499. package/src/server/index.ts +432 -0
  500. package/src/server/materials.ts +39 -0
  501. package/src/server/media-cli.ts +73 -0
  502. package/src/server/media-mutations.ts +168 -0
  503. package/src/server/pptx.ts +160 -0
  504. package/src/server/preflight.ts +129 -0
  505. package/src/server/projects-cli.ts +29 -0
  506. package/src/server/projects.ts +187 -0
  507. package/src/server/render-error.ts +9 -0
  508. package/src/server/render-source.ts +24 -0
  509. package/src/server/render.ts +48 -0
  510. package/src/server/review-cli.ts +40 -0
  511. package/src/server/review.ts +161 -0
  512. package/src/server/selection.ts +23 -0
  513. package/src/server/source-overrides.ts +97 -0
  514. package/src/server/templates-cli.ts +51 -0
  515. package/src/server/templates.ts +186 -0
  516. package/src/server/text-layout.ts +41 -0
  517. package/src/server/text-source.ts +307 -0
  518. package/src/server/themes-cli.ts +59 -0
  519. package/src/server/themes.ts +215 -0
  520. package/src/server/ttf2eot.d.ts +3 -0
  521. package/src/server/worker.ts +166 -0
  522. package/src/server/workspace.ts +242 -0
  523. package/src/shared/anchors.ts +69 -0
  524. package/src/shared/assets.ts +154 -0
  525. package/src/shared/export.ts +34 -0
  526. package/src/shared/media.ts +33 -0
  527. package/src/shared/projects.ts +19 -0
  528. package/src/shared/selection.ts +94 -0
  529. package/src/shared/skill-index.ts +14 -0
  530. package/src/shared/starters.ts +19 -0
  531. package/src/shared/templates.ts +18 -0
  532. package/src/shared/themes.ts +24 -0
  533. package/src/shared/types.ts +39 -0
  534. package/src/template/index.ts +27 -0
  535. package/src/themes/index.ts +3 -0
  536. package/src/themes/neutral.ts +20 -0
  537. package/src/themes/types.ts +110 -0
  538. package/starter/assets/brand/wordmark.png +0 -0
  539. package/starter/assets/fonts/InterUI-LICENSE.txt +93 -0
  540. package/starter/assets/fonts/InterUI-Medium.ttf +0 -0
  541. package/starter/assets/fonts/InterUI-Regular.ttf +0 -0
  542. package/starter/assets/fonts/InterUI-source.json +19 -0
  543. package/starter/assets/fonts/OpenDocMono-Regular.ttf +0 -0
  544. package/starter/assets/fonts/OpenDocSans-Italic.ttf +0 -0
  545. package/starter/assets/fonts/OpenDocSans-Regular.ttf +0 -0
  546. package/starter/assets/fonts/OpenDocSans-Semibold.ttf +0 -0
  547. package/starter/assets/fonts/OpenDocSans-SemiboldItalic.ttf +0 -0
  548. package/starter/assets/fonts/OpenDocSerif-Italic.ttf +0 -0
  549. package/starter/assets/fonts/OpenDocSerif-Regular.ttf +0 -0
  550. package/starter/assets/fonts/OpenDocSerif-Semibold.ttf +0 -0
  551. package/starter/assets/fonts/OpenDocSerif-SemiboldItalic.ttf +0 -0
  552. package/starter/assets/fonts/SourceCode-LICENSE.md +93 -0
  553. package/starter/assets/fonts/SourceSans-LICENSE.md +93 -0
  554. package/starter/assets/fonts/SourceSerif-LICENSE.md +93 -0
  555. package/starter/assets/fonts/geist/OFL.txt +93 -0
  556. package/starter/assets/fonts/geist/asset.json +7 -0
  557. package/starter/assets/fonts/geist/files/1a9874b3be0fc168692a3d2327bccb4d28835653d3b91537a755296a467a83e3.ttf +0 -0
  558. package/starter/assets/fonts/geist/files/a8eefb873ba9c9020665f8a98302697ce1f3b79ab2deef6ee508c0ca6a82e876.ttf +0 -0
  559. package/starter/assets/fonts/geist/files/ccce59465ae5c61930ada5453834f60500fbd95084d85db63e0e65fad0125455.ttf +0 -0
  560. package/starter/assets/fonts/geist/files/f5e95110d70593672515080bee9148463ada0a7f77b89ed65a3d43cb2b0ff83a.pdf +0 -0
  561. package/starter/assets/fonts/geist/revisions/9a2bc12fb2f23cb27bc227087e63e1407bb804ee0586480bd6b7966ec69fb474.json +60 -0
  562. package/starter/assets/fonts/inter/OFL.txt +93 -0
  563. package/starter/assets/fonts/inter/asset.json +7 -0
  564. package/starter/assets/fonts/inter/files/1b08e7fc267a5c7e1d614100f604b83e7e8a0be241f0f288faa2b3ac93a683ba.ttf +0 -0
  565. package/starter/assets/fonts/inter/files/5b6f0c6f26e5c554a64cdcc3a9b5d802b7f9aec6206f1dbcfcdcad7b5860a2a9.ttf +0 -0
  566. package/starter/assets/fonts/inter/files/957db8560d510a198a7d0333fae7b6b444b00c20801581126273978d778eb3c3.pdf +0 -0
  567. package/starter/assets/fonts/inter/files/b37284b5701b6b168dfc770aa1a4ac492106422fd3ba76bc7641e37434e8019c.ttf +0 -0
  568. package/starter/assets/fonts/inter/files/c1811d32ac0f6eed1bbf57529f2ecdfc6c717d48a969dd864942436315a1b198.ttf +0 -0
  569. package/starter/assets/fonts/inter/files/e7a1aaf7eda9f2fad4131725fa556265ec75ca7b2d756260173a040363e8d4f7.ttf +0 -0
  570. package/starter/assets/fonts/inter/files/ef8f755d933b9310804cc9152f1f18cb2ac460d6b05054ec913d889c9f11f79e.ttf +0 -0
  571. package/starter/assets/fonts/inter/revisions/600391517c413963b71e278a57c26c40366c81fa3939a6b9755f446206766d12.json +99 -0
  572. package/starter/assets/fonts/inter/source.json +57 -0
  573. package/starter/assets/fonts/lato/OFL.txt +93 -0
  574. package/starter/assets/fonts/lato/asset.json +7 -0
  575. package/starter/assets/fonts/lato/files/4a6b566dbb28adb473a8789ce5169306f42f0c8a070ac92bae93636f36348b0d.pdf +0 -0
  576. package/starter/assets/fonts/lato/files/5adeb6b334d8fb99ef053bc052b952773d544315e0e1d668a12c0ce8bd51375c.ttf +0 -0
  577. package/starter/assets/fonts/lato/files/62c1b7f0d2e74b45960154c3520efc337b553db0961bfdc950d5618334596cc8.ttf +0 -0
  578. package/starter/assets/fonts/lato/files/71b8b7decbe75a881ed267be539d402bd1e9420b799658aada4e0d1bd5af803c.ttf +0 -0
  579. package/starter/assets/fonts/lato/files/8a0aace75d33794eece4b28187bfc1df0bbd2888b5d8a56e01788c8d65d16be1.ttf +0 -0
  580. package/starter/assets/fonts/lato/files/d636e4683231f931eda222d588e944d082bfd3bdba02f928bee461c0f185b251.ttf +0 -0
  581. package/starter/assets/fonts/lato/files/e399c44efe1387100531d26c7e4800c5d12251b890d6654a3098c7c679cb1786.ttf +0 -0
  582. package/starter/assets/fonts/lato/revisions/49ccb93400a9d466fab7d9843b1ecf8916ec6d47a475dd79a597a22eb39616bc.json +99 -0
  583. package/starter/assets/fonts/lato/source.json +57 -0
  584. package/starter/assets/fonts/merriweather/OFL.txt +93 -0
  585. package/starter/assets/fonts/merriweather/asset.json +7 -0
  586. package/starter/assets/fonts/merriweather/files/1c54f91b910454251c4c2b7bd4e472e1abf265fba7ca3c0ef2eee2f41324099e.ttf +0 -0
  587. package/starter/assets/fonts/merriweather/files/8bde8da2bb7f0265e27ba0481f70bb48d0f98a976c145f2f239c648ddd6532e0.pdf +0 -0
  588. package/starter/assets/fonts/merriweather/files/90b7db4460fcd1a5ca49575c2668a793f3cd6447664d312a068d690e1c01e6bc.ttf +0 -0
  589. package/starter/assets/fonts/merriweather/files/afff81272b7653417bb6f8bef57add055b1f9fda36f27eba5f32b40752bd08da.ttf +0 -0
  590. package/starter/assets/fonts/merriweather/files/e029d3b71e5bae3877c73f4f2b15af28db16593d49b0aed2a328d37ff7075846.ttf +0 -0
  591. package/starter/assets/fonts/merriweather/files/e9864a6790bf712a04e20f3662b206a1535186ed3e877fd859dd5fb9682335df.ttf +0 -0
  592. package/starter/assets/fonts/merriweather/files/fa71baebdd20a7d0de2e5e445a5922530fe9e1d740efbe791f113b682d3cb093.ttf +0 -0
  593. package/starter/assets/fonts/merriweather/revisions/1888e390b3e4f38a3d7cd2dc1bb805aeb6ce13f986a97656f0265fd436bc91d2.json +99 -0
  594. package/starter/assets/fonts/merriweather/source.json +57 -0
  595. package/starter/assets/fonts/open-sans/OFL.txt +92 -0
  596. package/starter/assets/fonts/open-sans/asset.json +7 -0
  597. package/starter/assets/fonts/open-sans/files/1bc0594a83762b2c25d38915a34464b7fec6088298ca22d151757bf98d6700ec.ttf +0 -0
  598. package/starter/assets/fonts/open-sans/files/47ed1cfaa7ffca04a04ab850b2938fd52c09d1b44cfa3e2980878e166b0cbd87.ttf +0 -0
  599. package/starter/assets/fonts/open-sans/files/574939af301f07df8e21cfff279465c5981dd9d9cf62086f7515897df951c6f5.pdf +0 -0
  600. package/starter/assets/fonts/open-sans/files/6d3884d0d57c1b67e9c50c54eca7b69c535c114e76bd7a9cfda0258588185553.ttf +0 -0
  601. package/starter/assets/fonts/open-sans/files/733eb93b167e6d45de09aa768f6c0355647c2c26f5416dbc7407a08ed41e81c6.ttf +0 -0
  602. package/starter/assets/fonts/open-sans/files/75367e6da7d914eaed87883ba51b2a2b5816b5cdbb39f96ec5c81a5b032bfd5a.ttf +0 -0
  603. package/starter/assets/fonts/open-sans/files/ff4fdc11204e0edd14e9a0bb6c374b847a9093b0ec2c16702e03afca79ac4ef7.ttf +0 -0
  604. package/starter/assets/fonts/open-sans/revisions/bbbe3a4915b9bccbc883c0decb4097511c43b6bd09ae22a1516aff128c219bc5.json +99 -0
  605. package/starter/assets/fonts/open-sans/source.json +57 -0
  606. package/starter/assets/fonts/roboto/OFL.txt +93 -0
  607. package/starter/assets/fonts/roboto/asset.json +7 -0
  608. package/starter/assets/fonts/roboto/files/22d45d989248a624252b8382067ac56550212fa675dcdbaf12f03d297dd87a58.pdf +0 -0
  609. package/starter/assets/fonts/roboto/files/35757eaa996b3359022f47f164a67ee9eac04971af24c5b8fbd4b89e844ff190.ttf +0 -0
  610. package/starter/assets/fonts/roboto/files/4d3035883c531846bd1ce2dc89f36d932e72dc114f56062c7e3a9cdd74f3d3ea.ttf +0 -0
  611. package/starter/assets/fonts/roboto/files/be7639306a4fc4a02ce2ae2ff59eb1335e4db4a7379dd0a384ed7cc053817789.ttf +0 -0
  612. package/starter/assets/fonts/roboto/files/d2920cbb1b60a3fd11fbf22049286e43a6baf522d37fdf1e7c89562319bcfea5.ttf +0 -0
  613. package/starter/assets/fonts/roboto/files/dece7c71bbe61710787f0839c722c65e87355dd2eb4a823e6b5488121ff81e4b.ttf +0 -0
  614. package/starter/assets/fonts/roboto/files/f478ba88b0292e685e487901dfbb1401457d32d6ebee4030cdfd5698235bffa8.ttf +0 -0
  615. package/starter/assets/fonts/roboto/revisions/bda5e2d84c17313373dd2dbf3e64fe0dd450c7e1b59e6929e69557e122fe976e.json +99 -0
  616. package/starter/assets/fonts/roboto/source.json +57 -0
  617. package/starter/assets/logos/opendoc/asset.json +6 -0
  618. package/starter/assets/logos/opendoc/files/831d5ccd9eb6709cc8439ea257c03d81452e81a28a3d1eedbd6a3b7daff687b6.png +0 -0
  619. package/starter/assets/logos/opendoc/revisions/834dde8926ddb81de687254195a168bb13bfb77803307f1257de1f2228be63b2.json +33 -0
  620. package/starter/assets/ui-fonts/geist/OFL.txt +93 -0
  621. package/starter/assets/ui-fonts/geist/geist-latin-ext-wght-italic.woff2 +0 -0
  622. package/starter/assets/ui-fonts/geist/geist-latin-ext-wght-normal.woff2 +0 -0
  623. package/starter/assets/ui-fonts/geist/geist-latin-wght-italic.woff2 +0 -0
  624. package/starter/assets/ui-fonts/geist/geist-latin-wght-normal.woff2 +0 -0
  625. package/starter/assets/ui-fonts/geist/source.json +26 -0
  626. package/starter/documents/welcome/assets.json +7 -0
  627. package/starter/documents/welcome/index.tsx +160 -0
  628. package/starter/documents/welcome/media/.gitkeep +0 -0
  629. package/starter/documents/welcome/media/paper-architecture/image.png +0 -0
  630. package/starter/documents/welcome/media/paper-architecture/meta.json +9 -0
  631. package/starter/documents/welcome/media/paper-architecture/prompt.txt +1 -0
  632. package/starter/documents/welcome/media/studio-rhythm/chart.svg +2343 -0
  633. package/starter/documents/welcome/media/studio-rhythm/data.json +234 -0
  634. package/starter/documents/welcome/media/studio-rhythm/generation.json +9 -0
  635. package/starter/documents/welcome/media/studio-rhythm/image.png +0 -0
  636. package/starter/documents/welcome/media/studio-rhythm/meta.json +11 -0
  637. package/starter/documents/welcome/media/studio-rhythm/recipe.py +79 -0
  638. package/starter/documents/welcome/theme.tsx +5 -0
  639. package/starter/documents/welcome-presentation/assets.json +7 -0
  640. package/starter/documents/welcome-presentation/index.tsx +166 -0
  641. package/starter/documents/welcome-presentation/media/.gitkeep +0 -0
  642. package/starter/documents/welcome-presentation/media/paper-architecture/image.png +0 -0
  643. package/starter/documents/welcome-presentation/media/paper-architecture/meta.json +9 -0
  644. package/starter/documents/welcome-presentation/media/paper-architecture/prompt.txt +1 -0
  645. package/starter/documents/welcome-presentation/media/studio-rhythm/chart.svg +1336 -0
  646. package/starter/documents/welcome-presentation/media/studio-rhythm/data.json +234 -0
  647. package/starter/documents/welcome-presentation/media/studio-rhythm/generation.json +9 -0
  648. package/starter/documents/welcome-presentation/media/studio-rhythm/image.png +0 -0
  649. package/starter/documents/welcome-presentation/media/studio-rhythm/meta.json +13 -0
  650. package/starter/documents/welcome-presentation/media/studio-rhythm/recipe.py +49 -0
  651. package/starter/documents/welcome-presentation/theme.tsx +5 -0
  652. package/starter/projects.json +17 -0
  653. package/starter/templates/AGENTS.md +9 -0
  654. package/starter/templates/_shared/BusinessLogo.tsx +14 -0
  655. package/starter/templates/_shared/Pricing.tsx +40 -0
  656. package/starter/templates/_shared/commerce.ts +93 -0
  657. package/starter/templates/brand-guidelines/AGENTS.md +32 -0
  658. package/starter/templates/brand-guidelines/index.tsx +62 -0
  659. package/starter/templates/brand-guidelines/preview.tsx +181 -0
  660. package/starter/templates/brand-guidelines/starter.tsx +179 -0
  661. package/starter/templates/brand-guidelines/template.json +15 -0
  662. package/starter/templates/business-proposal/AGENTS.md +13 -0
  663. package/starter/templates/business-proposal/README.md +36 -0
  664. package/starter/templates/business-proposal/data.json +37 -0
  665. package/starter/templates/business-proposal/examples/long.json +142 -0
  666. package/starter/templates/business-proposal/examples/sparse.json +17 -0
  667. package/starter/templates/business-proposal/examples/typical.json +37 -0
  668. package/starter/templates/business-proposal/index.tsx +59 -0
  669. package/starter/templates/business-proposal/preview.tsx +47 -0
  670. package/starter/templates/business-proposal/schema.ts +14 -0
  671. package/starter/templates/business-proposal/starter.tsx +18 -0
  672. package/starter/templates/business-proposal/template.json +11 -0
  673. package/starter/templates/company-profile/AGENTS.md +48 -0
  674. package/starter/templates/company-profile/index.tsx +69 -0
  675. package/starter/templates/company-profile/preview.tsx +185 -0
  676. package/starter/templates/company-profile/starter.tsx +186 -0
  677. package/starter/templates/company-profile/template.json +15 -0
  678. package/starter/templates/consulting-report/AGENTS.md +11 -0
  679. package/starter/templates/consulting-report/README.md +13 -0
  680. package/starter/templates/consulting-report/RESEARCH.md +10 -0
  681. package/starter/templates/consulting-report/index.tsx +44 -0
  682. package/starter/templates/consulting-report/preview.tsx +39 -0
  683. package/starter/templates/consulting-report/starter.tsx +15 -0
  684. package/starter/templates/consulting-report/template.json +11 -0
  685. package/starter/templates/editorial-essay/AGENTS.md +11 -0
  686. package/starter/templates/editorial-essay/README.md +11 -0
  687. package/starter/templates/editorial-essay/index.tsx +30 -0
  688. package/starter/templates/editorial-essay/preview.tsx +26 -0
  689. package/starter/templates/editorial-essay/starter.tsx +15 -0
  690. package/starter/templates/editorial-essay/template.json +11 -0
  691. package/starter/templates/executive-brief/AGENTS.md +9 -0
  692. package/starter/templates/executive-brief/README.md +11 -0
  693. package/starter/templates/executive-brief/index.tsx +33 -0
  694. package/starter/templates/executive-brief/preview.tsx +37 -0
  695. package/starter/templates/executive-brief/starter.tsx +11 -0
  696. package/starter/templates/executive-brief/template.json +11 -0
  697. package/starter/templates/image-story/AGENTS.md +37 -0
  698. package/starter/templates/image-story/index.tsx +106 -0
  699. package/starter/templates/image-story/preview.tsx +33 -0
  700. package/starter/templates/image-story/starter.tsx +24 -0
  701. package/starter/templates/image-story/template.json +13 -0
  702. package/starter/templates/invoice/AGENTS.md +13 -0
  703. package/starter/templates/invoice/README.md +40 -0
  704. package/starter/templates/invoice/data.json +61 -0
  705. package/starter/templates/invoice/examples/long.json +241 -0
  706. package/starter/templates/invoice/examples/sparse.json +33 -0
  707. package/starter/templates/invoice/examples/typical.json +61 -0
  708. package/starter/templates/invoice/index.tsx +57 -0
  709. package/starter/templates/invoice/preview.tsx +12 -0
  710. package/starter/templates/invoice/schema.ts +45 -0
  711. package/starter/templates/invoice/starter.tsx +12 -0
  712. package/starter/templates/invoice/template.json +11 -0
  713. package/starter/templates/literary-text/AGENTS.md +9 -0
  714. package/starter/templates/literary-text/README.md +11 -0
  715. package/starter/templates/literary-text/index.tsx +31 -0
  716. package/starter/templates/literary-text/preview.tsx +20 -0
  717. package/starter/templates/literary-text/starter.tsx +11 -0
  718. package/starter/templates/literary-text/template.json +11 -0
  719. package/starter/templates/magazine-feature/AGENTS.md +11 -0
  720. package/starter/templates/magazine-feature/README.md +13 -0
  721. package/starter/templates/magazine-feature/index.tsx +41 -0
  722. package/starter/templates/magazine-feature/preview.tsx +34 -0
  723. package/starter/templates/magazine-feature/starter.tsx +15 -0
  724. package/starter/templates/magazine-feature/template.json +11 -0
  725. package/starter/templates/monthly-report/AGENTS.md +11 -0
  726. package/starter/templates/monthly-report/README.md +24 -0
  727. package/starter/templates/monthly-report/data.json +131 -0
  728. package/starter/templates/monthly-report/examples/long.json +519 -0
  729. package/starter/templates/monthly-report/examples/sparse.json +20 -0
  730. package/starter/templates/monthly-report/examples/typical.json +37 -0
  731. package/starter/templates/monthly-report/index.tsx +92 -0
  732. package/starter/templates/monthly-report/preview.tsx +14 -0
  733. package/starter/templates/monthly-report/schema.ts +127 -0
  734. package/starter/templates/monthly-report/starter.tsx +13 -0
  735. package/starter/templates/monthly-report/template.json +11 -0
  736. package/starter/templates/pitch-deck/AGENTS.md +32 -0
  737. package/starter/templates/pitch-deck/index.tsx +46 -0
  738. package/starter/templates/pitch-deck/preview.tsx +142 -0
  739. package/starter/templates/pitch-deck/starter.tsx +140 -0
  740. package/starter/templates/pitch-deck/template.json +15 -0
  741. package/starter/templates/proposal-deck/AGENTS.md +25 -0
  742. package/starter/templates/proposal-deck/index.tsx +52 -0
  743. package/starter/templates/proposal-deck/preview.tsx +172 -0
  744. package/starter/templates/proposal-deck/starter.tsx +168 -0
  745. package/starter/templates/proposal-deck/template.json +7 -0
  746. package/starter/templates/quotation/AGENTS.md +13 -0
  747. package/starter/templates/quotation/README.md +42 -0
  748. package/starter/templates/quotation/data.json +64 -0
  749. package/starter/templates/quotation/examples/long.json +272 -0
  750. package/starter/templates/quotation/examples/sparse.json +31 -0
  751. package/starter/templates/quotation/examples/typical.json +64 -0
  752. package/starter/templates/quotation/index.tsx +51 -0
  753. package/starter/templates/quotation/preview.tsx +12 -0
  754. package/starter/templates/quotation/schema.ts +27 -0
  755. package/starter/templates/quotation/starter.tsx +12 -0
  756. package/starter/templates/quotation/template.json +11 -0
  757. package/starter/templates/scientific-paper/AGENTS.md +11 -0
  758. package/starter/templates/scientific-paper/README.md +13 -0
  759. package/starter/templates/scientific-paper/index.tsx +47 -0
  760. package/starter/templates/scientific-paper/preview.tsx +43 -0
  761. package/starter/templates/scientific-paper/starter.tsx +15 -0
  762. package/starter/templates/scientific-paper/template.json +11 -0
  763. package/starter/themes/Specimen.tsx +54 -0
  764. package/starter/themes/civic-spectrum/components.tsx +92 -0
  765. package/starter/themes/civic-spectrum/design.md +70 -0
  766. package/starter/themes/civic-spectrum/index.ts +57 -0
  767. package/starter/themes/civic-spectrum/preview.tsx +66 -0
  768. package/starter/themes/field-manual/components.tsx +106 -0
  769. package/starter/themes/field-manual/design.md +72 -0
  770. package/starter/themes/field-manual/index.ts +57 -0
  771. package/starter/themes/field-manual/preview.tsx +82 -0
  772. package/starter/themes/index.ts +3 -0
  773. package/starter/themes/mckinsey-consulting/components.tsx +69 -0
  774. package/starter/themes/mckinsey-consulting/design.md +68 -0
  775. package/starter/themes/mckinsey-consulting/index.ts +60 -0
  776. package/starter/themes/mckinsey-consulting/preview.tsx +53 -0
  777. package/starter/themes/neutral/design.md +35 -0
  778. package/starter/themes/neutral/index.ts +21 -0
  779. package/starter/themes/neutral/preview.tsx +4 -0
  780. package/starter/themes/opendoc-neutral/components.tsx +77 -0
  781. package/starter/themes/opendoc-neutral/design.md +70 -0
  782. package/starter/themes/opendoc-neutral/index.ts +54 -0
  783. package/starter/themes/opendoc-neutral/preview.tsx +43 -0
  784. package/starter/themes/types.ts +3 -0
  785. package/tsconfig.workspace.json +24 -0
  786. package/vendor/formepdf/LICENSE +21 -0
  787. package/vendor/formepdf/README.md +97 -0
  788. package/vendor/formepdf/font-subset.patch +228 -0
  789. package/vendor/formepdf/text-writer.patch +507 -0
@@ -0,0 +1,168 @@
1
+ import { constants, lstatSync, mkdirSync, openSync, closeSync, fstatSync, readFileSync, renameSync, realpathSync, readdirSync, rmSync, unlinkSync, writeFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { prepareMediaImage, type UploadFile } from '../assets/imports';
5
+ import { hashBytes, mediaId, parseMediaMeta } from '../media/files';
6
+ import type { MediaKind, MediaMeta } from '../shared/media';
7
+ import { Conflict, withCommentLock } from './comments';
8
+ import { documentEntry } from './render';
9
+
10
+ export interface MediaImportMetadata {
11
+ id?: string;
12
+ title: string;
13
+ description: string;
14
+ kind: MediaKind;
15
+ alt?: string;
16
+ attribution?: string;
17
+ sources?: string[];
18
+ }
19
+ export interface MediaMutationResult { documentId: string; id: string; metadataRevision: string }
20
+ const editable = ['title', 'description', 'kind', 'alt', 'attribution', 'sources'] as const;
21
+ const known = [...editable, 'file', 'data', 'recipe'];
22
+ const metadataHash = (meta: unknown) => hashBytes(Buffer.from(JSON.stringify(meta)));
23
+
24
+ /** Check each component before creating the next one; never follow a linked folder. */
25
+ function ordinaryDirectory(root: string, parts: string[], create = false) {
26
+ let path = root;
27
+ for (const part of parts) {
28
+ path = resolve(path, part);
29
+ let info;
30
+ try { info = lstatSync(path); }
31
+ catch (error) {
32
+ if (!create || (error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
33
+ try { mkdirSync(path); } catch (failure) { if ((failure as NodeJS.ErrnoException).code !== 'EEXIST') throw failure; }
34
+ info = lstatSync(path);
35
+ }
36
+ if (!info.isDirectory() || info.isSymbolicLink()) throw new Error('Document media must stay in ordinary local folders, without symbolic links.');
37
+ }
38
+ return path;
39
+ }
40
+
41
+ async function ownerDirectory(root: string, documentId: string) {
42
+ const entry = await documentEntry(root, documentId);
43
+ const directory = ordinaryDirectory(root, ['documents', documentId]);
44
+ const info = lstatSync(resolve(directory, 'index.tsx'));
45
+ if (!info.isFile() || info.isSymbolicLink() || entry !== resolve(directory, 'index.tsx')) throw new Error('Choose an ordinary document in this workspace as the media owner.');
46
+ return directory;
47
+ }
48
+
49
+ function readMetadata(folder: string) {
50
+ const file = resolve(folder, 'meta.json');
51
+ const fd = openSync(file, constants.O_RDONLY | constants.O_NOFOLLOW);
52
+ try {
53
+ const info = fstatSync(fd);
54
+ if (!info.isFile() || info.size > 32_000) throw new Error('Keep media metadata in a regular local file below 32 KB.');
55
+ const value = JSON.parse(readFileSync(fd, 'utf8')) as unknown;
56
+ if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('meta.json must contain a media record.');
57
+ const raw = value as Record<string, unknown>;
58
+ // Preserve future or source-specific fields without giving this editor authority to change them.
59
+ parseMediaMeta(Object.fromEntries(Object.entries(raw).filter(([key]) => known.includes(key as (typeof known)[number]))));
60
+ return raw;
61
+ } finally { closeSync(fd); }
62
+ }
63
+
64
+ function metadataText(meta: unknown) {
65
+ const text = JSON.stringify(meta, null, 2) + '\n';
66
+ if (Buffer.byteLength(text) > 32_000) throw new Error('Keep media metadata below 32 KB.');
67
+ return text;
68
+ }
69
+
70
+ function stagingRoot(root: string) {
71
+ const directory = ordinaryDirectory(root, ['.opendoc', 'media-imports'], true);
72
+ // A killed import can leave its private stage behind. Only remove dead-process stages
73
+ // with the exact files this service owns; leave any unexpected user material alone.
74
+ for (const name of readdirSync(directory)) {
75
+ const match = /^(\d+)-[0-9a-f-]{36}$/.exec(name);
76
+ if (!match) continue;
77
+ try {
78
+ const path = resolve(directory, name);
79
+ const info = lstatSync(path);
80
+ if (!info.isDirectory() || info.isSymbolicLink()) continue;
81
+ try { process.kill(Number(match[1]), 0); continue; }
82
+ catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ESRCH') continue; }
83
+ const entries = readdirSync(path, { withFileTypes: true });
84
+ if (entries.every(entry => entry.isFile() && ['image.png', 'image.jpg', 'meta.json'].includes(entry.name))) rmSync(path, { recursive: true, force: true });
85
+ } catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; }
86
+ }
87
+ return directory;
88
+ }
89
+
90
+ function prepareDocumentLock(root: string, documentId: string) {
91
+ const directory = ordinaryDirectory(root, ['.opendoc', 'locks'], true);
92
+ try {
93
+ const info = lstatSync(resolve(directory, `${documentId}.lock`));
94
+ if (!info.isDirectory() || info.isSymbolicLink()) throw new Error('The document lock must be an ordinary local folder, without symbolic links.');
95
+ } catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; }
96
+ }
97
+
98
+ export async function importMedia(root: string, documentId: string, metadata: MediaImportMetadata, file: UploadFile): Promise<MediaMutationResult> {
99
+ const workspace = realpathSync(root);
100
+ await ownerDirectory(workspace, documentId);
101
+ if (!metadata || typeof metadata !== 'object' || Array.isArray(metadata)) throw new Error('Give the image a title, description, and kind.');
102
+ for (const key of Object.keys(metadata)) if (key !== 'id' && !editable.includes(key as (typeof editable)[number])) throw new Error(`This image import cannot set ${key}. Add preparation files separately.`);
103
+ if (metadata.id !== undefined && (!mediaId.test(metadata.id) || metadata.id.length > 100)) throw new Error('Use a lowercase media ID with single hyphens, up to 100 characters.');
104
+ const { id: requestedId, ...fields } = metadata;
105
+ // Validate text before starting the bounded image parser.
106
+ parseMediaMeta({ ...fields, file: 'image.png' });
107
+ const image = await prepareMediaImage(file);
108
+ const name = image.mime === 'image/png' ? 'image.png' : 'image.jpg';
109
+ const meta = parseMediaMeta({ ...fields, file: name });
110
+ const text = metadataText(meta);
111
+ const stageRoot = stagingRoot(workspace);
112
+ prepareDocumentLock(workspace, documentId);
113
+ const stage = resolve(stageRoot, `${process.pid}-${randomUUID()}`);
114
+ mkdirSync(stage);
115
+ try {
116
+ writeFileSync(resolve(stage, name), image.contents, { flag: 'wx' });
117
+ writeFileSync(resolve(stage, 'meta.json'), text, { flag: 'wx' });
118
+ return await withCommentLock(workspace, documentId, async () => {
119
+ await ownerDirectory(workspace, documentId);
120
+ const parent = ordinaryDirectory(workspace, ['documents', documentId, 'media'], true);
121
+ let id = requestedId ?? (metadata.title.normalize('NFKD').replace(/[\u0300-\u036f]/g, '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 80).replace(/-$/, '') || 'media');
122
+ let target = resolve(parent, id);
123
+ try {
124
+ lstatSync(target);
125
+ if (requestedId) throw new Conflict('That media ID already exists. Choose another ID; the existing visual was preserved.');
126
+ id = `${id}-${randomUUID().slice(0, 8)}`; target = resolve(parent, id);
127
+ try { lstatSync(target); throw new Conflict('That media ID already exists. Try adding the image again.'); }
128
+ catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; }
129
+ } catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; }
130
+ // No asynchronous gap between the final existence check and directory publication.
131
+ renameSync(stage, target);
132
+ return { documentId, id, metadataRevision: metadataHash(meta) };
133
+ });
134
+ } finally { rmSync(stage, { recursive: true, force: true }); }
135
+ }
136
+
137
+ export async function editMedia(root: string, documentId: string, id: string, input: { expectedRevision: string; meta: MediaMeta }): Promise<MediaMutationResult> {
138
+ const workspace = realpathSync(root);
139
+ await ownerDirectory(workspace, documentId);
140
+ if (!mediaId.test(id)) throw new Error('Choose a valid media item.');
141
+ if (!input || typeof input.expectedRevision !== 'string' || !/^[a-f0-9]{64}$/.test(input.expectedRevision)) throw new Conflict('Reload this image before saving its metadata.');
142
+ if (!input.meta || typeof input.meta !== 'object' || Array.isArray(input.meta)) throw new Error('Provide the image metadata to edit.');
143
+ prepareDocumentLock(workspace, documentId);
144
+ return withCommentLock(workspace, documentId, async () => {
145
+ await ownerDirectory(workspace, documentId);
146
+ const folder = ordinaryDirectory(workspace, ['documents', documentId, 'media', id]);
147
+ const current = readMetadata(folder);
148
+ if (metadataHash(current) !== input.expectedRevision) throw new Conflict('This image metadata changed. Reload it before saving; your changes have not overwritten it.');
149
+ for (const [key, value] of Object.entries(input.meta)) {
150
+ if (!editable.includes(key as (typeof editable)[number]) && JSON.stringify(value) !== JSON.stringify(current[key])) throw new Error(`The metadata editor cannot change ${key}. Ask your agent to update preparation files separately.`);
151
+ }
152
+ const next = { ...current };
153
+ for (const key of editable) {
154
+ if (input.meta[key] === undefined) delete next[key];
155
+ else next[key] = input.meta[key];
156
+ }
157
+ parseMediaMeta(Object.fromEntries(Object.entries(next).filter(([key]) => known.includes(key as (typeof known)[number]))));
158
+ const text = metadataText(next);
159
+ const temporary = resolve(folder, `.meta-${randomUUID()}.tmp`);
160
+ try {
161
+ writeFileSync(temporary, text, { flag: 'wx' });
162
+ ordinaryDirectory(workspace, ['documents', documentId, 'media', id]);
163
+ if (metadataHash(readMetadata(folder)) !== input.expectedRevision) throw new Conflict('This image metadata changed while saving. Reload it and try again.');
164
+ renameSync(temporary, resolve(folder, 'meta.json'));
165
+ } finally { try { unlinkSync(temporary); } catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; } }
166
+ return { documentId, id, metadataRevision: metadataHash(next) };
167
+ });
168
+ }
@@ -0,0 +1,160 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+ import { createHash } from 'node:crypto';
4
+ import * as fontkit from 'fontkit';
5
+ import ttf2eot from 'ttf2eot';
6
+ import TsPptx, { type TextPropsOptions } from '@shbernal/ts-pptx';
7
+ import type { ElementInfo, ElementStyleInfo, LayoutInfo, Color } from '@formepdf/core';
8
+ import type { FormeDocument, FormeNode, FormeStyle } from '@formepdf/react';
9
+ import type { DocumentMeta, SlideInfo, SourceLocation } from '../shared/types';
10
+
11
+ export interface PresentationCapture {
12
+ version: 1; hash: string; meta: DocumentMeta; slides: SlideInfo[]; doc: FormeDocument; layout: LayoutInfo;
13
+ }
14
+ type TextKind = Extract<FormeNode['kind'], { type: 'Text' | 'Heading' }>;
15
+ type Run = { text: string; style: FormeStyle; href?: string };
16
+ type FontFace = { bytes: Buffer; family: string; weight: number; italic: boolean; restrictions: { noEmbedding?: boolean; bitmapOnly?: boolean; viewOnly?: boolean } };
17
+ type PaintStyle = ElementStyleInfo & { borderStyle?: Partial<Record<'top' | 'right' | 'bottom' | 'left', string>>; transform?: unknown };
18
+ const PT = 72;
19
+ const key = (location: SourceLocation | undefined, type: string) => `${location?.file ?? ''}:${location?.line ?? 0}:${location?.column ?? 0}:${type}`;
20
+ const hex = (color: Color) => [color.r, color.g, color.b].map(v => Math.round(v * 255).toString(16).padStart(2, '0')).join('').toUpperCase();
21
+ const fill = (color: Color) => ({ color: hex(color), transparency: (1 - (color.a ?? 1)) * 100 });
22
+ const box = (node: ElementInfo) => ({ x: node.x / PT, y: node.y / PT, w: node.width / PT, h: node.height / PT });
23
+
24
+ /** Preserve authored runs inside one editable textbox, using the reviewed line breaks. */
25
+ export function presentationTextRuns(source: TextKind, lines: Pick<ElementInfo, 'textContent'>[]): Run[] | null {
26
+ const input = source.runs ?? [{ content: source.content, href: source.href }];
27
+ if (input.map(r => r.content).join('').replace(/\s/g, '') !== lines.map(l => l.textContent ?? '').join('').replace(/\s/g, '')) return null;
28
+ const chars = input.flatMap(run => Array.from(run.content, c => ({ c, style: run.style ?? {}, href: run.href ?? source.href })));
29
+ let position = 0;
30
+ const output: Run[] = [];
31
+ for (const [index, line] of lines.entries()) {
32
+ if (index) output.push({ text: '\n', style: {} });
33
+ for (const c of line.textContent ?? '') {
34
+ while (position < chars.length && /\s/.test(chars[position].c) && chars[position].c !== c) position++;
35
+ if (position >= chars.length || chars[position].c !== c) return null;
36
+ const run = chars[position++], last = output.at(-1);
37
+ if (last && last.text !== '\n' && JSON.stringify(last.style) === JSON.stringify(run.style) && last.href === run.href) last.text += c;
38
+ else output.push({ text: c, style: run.style, href: run.href });
39
+ }
40
+ while (position < chars.length && /\s/.test(chars[position].c)) position++;
41
+ }
42
+ return output;
43
+ }
44
+
45
+ function fontCatalog(doc: FormeDocument) {
46
+ const fonts = new Map<string, FontFace>();
47
+ for (const item of doc.fonts ?? []) {
48
+ const bytes = typeof item.src === 'string' ? Buffer.from(item.src, 'base64') : Buffer.from(item.src);
49
+ const font = fontkit.create(bytes);
50
+ if (!('familyName' in font)) throw new Error('PowerPoint export requires individual font faces, not a font collection.');
51
+ const restrictions = (font as unknown as { 'OS/2'?: { fsType?: FontFace['restrictions'] } })['OS/2']?.fsType ?? {};
52
+ fonts.set(`${item.family}:${item.weight ?? 400}:${!!item.italic}`, { bytes, family: font.familyName, weight: item.weight ?? 400, italic: !!item.italic, restrictions });
53
+ }
54
+ return fonts;
55
+ }
56
+
57
+ export async function presentationBytes(capture: PresentationCapture): Promise<Uint8Array> {
58
+ if (capture.version !== 1 || capture.slides.length !== capture.layout.pages.length || capture.doc.children.length !== capture.slides.length) throw new Error('The presentation preview is incomplete. Render it again before exporting.');
59
+ const fonts = fontCatalog(capture.doc), used = new Map<string, FontFace>();
60
+ const pptx = new TsPptx();
61
+ pptx.defineLayout({ name: 'OPENDOC', width: 960 / PT, height: 540 / PT });
62
+ pptx.layout = 'OPENDOC'; pptx.title = capture.meta.title; pptx.author = capture.meta.author ?? 'OpenDoc';
63
+ function textStyle(style: ElementStyleInfo): TextPropsOptions {
64
+ // Match Forme 0.20.1 FontRegistry::resolve: exact, snapped, then opposite weight.
65
+ // Choosing the numerically closest face would disagree with the reviewed PDF.
66
+ const weight = style.fontWeight ?? 400, snapped = weight >= 600 ? 700 : 400;
67
+ let font: FontFace | undefined;
68
+ for (const family of style.fontFamily.split(',').map(name => name.trim().replace(/^["']|["']$/g, ''))) {
69
+ for (const candidate of [weight, snapped, snapped === 700 ? 400 : 700]) {
70
+ font = fonts.get(`${family}:${candidate}:${style.fontStyle === 'Italic'}`);
71
+ if (font) break;
72
+ }
73
+ if (font) break;
74
+ }
75
+ if (!font) throw new Error(`PowerPoint export needs the exact font face: ${style.fontFamily}, weight ${style.fontWeight}.`);
76
+ const slot = `${font.family}:${font.weight >= 600}:${font.italic}`, previous = used.get(slot);
77
+ if (previous && !previous.bytes.equals(font.bytes)) throw new Error(`PowerPoint cannot preserve these different weights of ${font.family} in the same font style. Use regular and semibold/bold faces.`);
78
+ used.set(slot, font);
79
+ return { fontFace: font.family, fontSize: style.fontSize, bold: font.weight >= 600, italic: font.italic,
80
+ color: hex(style.color), transparency: (1 - (style.color.a ?? 1)) * 100, charSpacing: style.letterSpacing ?? 0,
81
+ ...(style.textDecoration === 'Underline' ? { underline: { style: 'sng' as const } } : {}), ...(style.textDecoration === 'LineThrough' ? { strike: true } : {}) };
82
+ }
83
+ for (const [index, page] of capture.layout.pages.entries()) {
84
+ const sourcePage = capture.doc.children[index], label = capture.slides[index].id;
85
+ if (page.width !== 960 || page.height !== 540 || sourcePage.kind.type !== 'Page') throw new Error('PowerPoint export requires 960 × 540 presentation slides.');
86
+ const sources = new Map<string, FormeNode[]>();
87
+ function indexSource(node: FormeNode) {
88
+ const styles = [node.style, ...('runs' in node.kind ? node.kind.runs?.map(run => run.style) ?? [] : [])];
89
+ for (const style of styles) {
90
+ if (!style) continue;
91
+ const unsupported = style.transform?.length ? 'transforms' : style.boxShadow ? 'shadows' : style.background && style.background.type !== 'color' ? 'gradients' : style.wordSpacing ? 'custom word spacing' : style.textAlign === 'Justify' ? 'justified text' : undefined;
92
+ if (unsupported) throw new Error(`Slide ${label}: PowerPoint export does not yet support ${unsupported}.`);
93
+ }
94
+ if (['Text', 'Heading', 'Image'].includes(node.kind.type)) {
95
+ const id = key(node.sourceLocation, node.kind.type), list = sources.get(id) ?? [];
96
+ list.push(node); sources.set(id, list);
97
+ }
98
+ node.children.forEach(indexSource);
99
+ }
100
+ indexSource(sourcePage);
101
+ const slide = pptx.addSlide(), config = sourcePage.kind.config;
102
+ if (config.backgroundImage) slide.addImage({ data: config.backgroundImage, x: 0, y: 0, w: 960 / PT, h: 540 / PT, transparency: (1 - (config.backgroundOpacity ?? 1)) * 100 });
103
+ function visit(node: ElementInfo) {
104
+ const style = node.style as PaintStyle;
105
+ if (style.opacity === 0) return;
106
+ if (style.opacity !== undefined && style.opacity !== 1) throw new Error(`Slide ${label}: PowerPoint export does not yet support group opacity.`);
107
+ if (style.transform) throw new Error(`Slide ${label}: PowerPoint export does not yet support transforms.`);
108
+ if (node.kind === 'Rect') {
109
+ if (Object.values(style.borderRadius ?? {}).some(radius => radius !== 0)) throw new Error(`Slide ${label}: PowerPoint export does not yet support rounded corners.`);
110
+ if (style.backgroundColor) slide.addShape('rect', { ...box(node), line: { transparency: 100 }, fill: fill(style.backgroundColor) });
111
+ for (const side of ['top', 'right', 'bottom', 'left'] as const) if (style.borderWidth?.[side] > 0) {
112
+ if (style.borderStyle?.[side] !== 'solid') throw new Error(`Slide ${label}: PowerPoint export does not yet support this border style.`);
113
+ const horizontal = side === 'top' || side === 'bottom';
114
+ slide.addShape('line', { x: (node.x + (side === 'right' ? node.width : 0)) / PT, y: (node.y + (side === 'bottom' ? node.height : 0)) / PT,
115
+ w: horizontal ? node.width / PT : 0, h: horizontal ? 0 : node.height / PT,
116
+ line: { ...fill(style.borderColor[side]), width: style.borderWidth[side], beginArrowType: 'none', endArrowType: 'none' } });
117
+ }
118
+ }
119
+ const type = /^H[1-6]$/.test(node.nodeType) ? 'Heading' : node.nodeType;
120
+ if (['Text', 'Heading'].includes(type) && node.children.some(child => child.nodeType === 'TextLine')) {
121
+ const source = sources.get(key(node.sourceLocation, type))?.shift();
122
+ if (!source || (source.kind.type !== 'Text' && source.kind.type !== 'Heading')) throw new Error(`Slide ${label}: an editable text source could not be matched.`);
123
+ const lines = node.children.filter(child => child.nodeType === 'TextLine');
124
+ const pageNumbers = (text: string) => text.replaceAll('{{pageNumber}}', String(index + 1)).replaceAll('{{totalPages}}', String(capture.slides.length)).replaceAll('\u0002', String(index + 1)).replaceAll('\u0003', String(capture.slides.length));
125
+ const runs = presentationTextRuns({ ...source.kind, content: pageNumbers(source.kind.content), runs: source.kind.runs?.map(run => ({ ...run, content: pageNumbers(run.content) })) }, lines.map(line => ({ textContent: pageNumbers(line.textContent ?? '') })));
126
+ if (!runs) throw new Error(`Slide ${label}: PowerPoint export cannot preserve this text transformation.`);
127
+ const rich = runs.map(run => ({ text: run.text, options: { ...textStyle({ ...style, ...run.style } as ElementStyleInfo), ...(run.href ? { hyperlink: { url: run.href } } : {}) } }));
128
+ slide.addText(rich, { ...box(node), y: lines[0].y / PT, ...textStyle(style), margin: 0, breakLine: false, paraSpaceAfter: 0, paraSpaceBefore: 0,
129
+ lineSpacing: style.fontSize * style.lineHeight, align: style.textAlign.toLowerCase() as TextPropsOptions['align'], valign: 'top', wrap: false, fit: 'none',
130
+ objectName: node.sourceLocation?.file?.replace('opendoc:block:', '') ?? 'text' });
131
+ return;
132
+ }
133
+ if (node.kind === 'Image') {
134
+ const source = sources.get(key(node.sourceLocation, 'Image'))?.shift();
135
+ if (source?.kind.type !== 'Image' || !source.kind.src) throw new Error(`Slide ${label}: an image source could not be matched.`);
136
+ slide.addImage({ data: source.kind.src, ...box(node), altText: source.alt ?? '' }); return;
137
+ }
138
+ if (!['Rect', 'None', 'Text'].includes(node.kind)) throw new Error(`Slide ${label}: PowerPoint export does not yet support ${node.nodeType}.`);
139
+ if (node.nodeType === 'TextLine') throw new Error(`Slide ${label}: an editable text line could not be matched.`);
140
+ node.children.forEach(visit);
141
+ }
142
+ page.elements.forEach(visit);
143
+ }
144
+ for (const font of used.values()) {
145
+ if (font.restrictions.noEmbedding || font.restrictions.bitmapOnly || font.restrictions.viewOnly) throw new Error(`${font.family} does not permit editable font embedding. Choose a font that does before exporting PowerPoint.`);
146
+ if (font.bytes.readUInt32BE(0) !== 0x00010000) throw new Error(`PowerPoint export currently requires TrueType outlines: ${font.family}.`);
147
+ // PowerPoint consumes EOT containers in .fntdata, not the raw TTF accepted by ts-pptx.
148
+ await pptx.embedFont({ data: ttf2eot(font.bytes), typeface: font.family, style: font.italic ? (font.weight >= 600 ? 'boldItalic' : 'italic') : (font.weight >= 600 ? 'bold' : 'regular') });
149
+ }
150
+ const bytes = await pptx.write({ outputType: 'uint8array' });
151
+ if (!(bytes instanceof Uint8Array)) throw new Error('PowerPoint export returned an unexpected file format.');
152
+ return bytes;
153
+ }
154
+
155
+ export async function readPresentationBytes(directory: string, hash: string) {
156
+ const capture = JSON.parse(await readFile(resolve(directory, 'presentation.json'), 'utf8')) as PresentationCapture;
157
+ const pdf = await readFile(resolve(directory, 'document.pdf'));
158
+ if (capture.hash !== hash || createHash('sha256').update(pdf).digest('hex') !== hash) throw new Error('The presentation preview changed. Wait for the latest preview and try again.');
159
+ return presentationBytes(capture);
160
+ }
@@ -0,0 +1,129 @@
1
+ import { RenderFailure } from './render-error';
2
+ import type { ElementInfo, LayoutInfo } from '@formepdf/core';
3
+ import type { BlockInfo, OutlineEntry, ReviewIssue, SlideInfo } from '../shared/types';
4
+
5
+ /** Verify slide identity as well as page count; a shifted or duplicated page must fail. */
6
+ export function assertSlideLayout(layout: LayoutInfo, slides: SlideInfo[], blocks: Record<string, BlockInfo>) {
7
+ if (layout.pages.length !== slides.length) {
8
+ const message = `Presentation layout failed: ${slides.length} slides produced ${layout.pages.length} pages. Content must fit on its own slide; shorten it or split it into explicit slides.`;
9
+ throw new RenderFailure(message, [{ code: 'slide-page-count', severity: 'error', message }]);
10
+ }
11
+ const ids = new Set(slides.map(slide => slide.id));
12
+ for (const [index, page] of layout.pages.entries()) {
13
+ const expected = slides[index].id;
14
+ const found = new Set<string>();
15
+ const paper = { x: 0, y: 0, width: page.width, height: page.height };
16
+ const visit = (node: ElementInfo, inherited?: string, clips: ElementInfo[] = []) => {
17
+ const id = blockIdOf(node, inherited);
18
+ if (id && ids.has(id)) found.add(id);
19
+ const owner = id && blocks[id]?.slideId;
20
+ if (owner && owner !== expected) {
21
+ const message = `Slide ${owner}: component ${id} moved onto slide ${expected}. Content must fit on its own slide.`;
22
+ throw new RenderFailure(message, [{ code: 'slide-content-moved', severity: 'error', message, page: index + 1, blockId: id }]);
23
+ }
24
+ // Native View backgrounds/borders are drawable rectangles too. Document
25
+ // preflight permits decorative bleed; a slide's bounded composition does not.
26
+ if (node.kind === 'Rect' && node.style.opacity !== 0 && (outside(node, paper) || clips.some(box => outside(node, box)))) {
27
+ const message = `Slide ${expected}: ${id ?? 'a visual'} extends outside the slide or is clipped. Resize or reposition it.`;
28
+ throw new RenderFailure(message, [{ code: 'slide-overflow', severity: 'error', message, page: index + 1, blockId: id }]);
29
+ }
30
+ const nextClips = node.style?.overflow === 'Hidden' ? [...clips, node] : clips;
31
+ node.children.forEach(child => visit(child, id, nextClips));
32
+ };
33
+ page.elements.forEach(node => visit(node));
34
+ if (page.width !== 960 || page.height !== 540 || found.size !== 1 || !found.has(expected)) {
35
+ const message = `Slide ${expected}: content moved to another page or the slide dimensions changed. Each slide must stay on its own 960 × 540 page.`;
36
+ throw new RenderFailure(message, [{ code: 'slide-identity', severity: 'error', message, page: index + 1, blockId: expected }]);
37
+ }
38
+ }
39
+ }
40
+
41
+ const tolerance = 0.75;
42
+ const visualKinds = new Set(['Image', 'Svg', 'QrCode', 'Barcode', 'Canvas', 'BarChart', 'LineChart', 'PieChart', 'AreaChart', 'DotPlot']);
43
+ type Mark = { node: ElementInfo; blockId?: string; heading?: ElementInfo; fixed: boolean };
44
+ function blockIdOf(node: ElementInfo, inherited?: string) {
45
+ const source = node.sourceLocation?.file;
46
+ return source?.startsWith('opendoc:block:') ? source.slice(14) : inherited;
47
+ }
48
+ function overlaps(a: ElementInfo, b: ElementInfo) {
49
+ return a.x < b.x + b.width - tolerance && b.x < a.x + a.width - tolerance &&
50
+ a.y < b.y + b.height - tolerance && b.y < a.y + a.height - tolerance;
51
+ }
52
+ function outside(node: ElementInfo, box: { x: number; y: number; width: number; height: number }) {
53
+ return node.x < box.x - tolerance || node.y < box.y - tolerance ||
54
+ node.x + node.width > box.x + box.width + tolerance || node.y + node.height > box.y + box.height + tolerance;
55
+ }
56
+
57
+ /** Check concrete geometry, not aesthetic taste. Decorative page backgrounds may bleed. */
58
+ export function inspectLayout(layout: LayoutInfo, blocks: Record<string, BlockInfo>) {
59
+ const issues: ReviewIssue[] = [];
60
+ const outline: OutlineEntry[] = [];
61
+ const seen = new Set<string>();
62
+ const outlined = new Set<string>();
63
+ const add = (issue: ReviewIssue) => {
64
+ const key = `${issue.code}:${issue.page}:${issue.blockId ?? ''}`;
65
+ if (!seen.has(key)) { seen.add(key); issues.push(issue); }
66
+ };
67
+ for (const [index, page] of layout.pages.entries()) {
68
+ const number = index + 1;
69
+ const leaves: Mark[] = [], headings: Mark[] = [];
70
+ const paper = { x: 0, y: 0, width: page.width, height: page.height };
71
+ const visit = (node: ElementInfo, inherited?: string, fixed = false, heading?: ElementInfo, clips: ElementInfo[] = []) => {
72
+ const blockId = blockIdOf(node, inherited);
73
+ fixed ||= node.nodeType === 'FixedHeader' || node.nodeType === 'FixedFooter';
74
+ if (/^H[1-6]$/.test(node.nodeType)) {
75
+ heading = node;
76
+ headings.push({ node, blockId, fixed });
77
+ }
78
+ const visible = node.nodeType === 'TextLine' ? !!node.textContent?.trim() : visualKinds.has(node.nodeType);
79
+ if (visible && node.style.opacity !== 0) {
80
+ leaves.push({ node, blockId, heading, fixed });
81
+ if (![node.x, node.y, node.width, node.height].every(Number.isFinite) || outside(node, paper)) {
82
+ add({ code: 'page-overflow', severity: 'error', page: number, blockId,
83
+ message: `Content extends beyond page ${number}. Reduce the fixed width or height, or allow the content to flow onto another page.` });
84
+ }
85
+ if (clips.some(box => outside(node, box))) {
86
+ add({ code: 'clipped-content', severity: 'error', page: number, blockId,
87
+ message: `Content is clipped by a fixed container on page ${number}. Remove the clipping or give it enough space.` });
88
+ }
89
+ }
90
+ const nextClips = node.style.overflow === 'Hidden' ? [...clips, node] : clips;
91
+ for (const child of node.children) visit(child, blockId, fixed, heading, nextClips);
92
+ };
93
+ for (const node of page.elements) visit(node);
94
+ const furniture = leaves.filter(mark => mark.fixed);
95
+ for (const mark of leaves) {
96
+ if (!mark.fixed && furniture.some(other => overlaps(mark.node, other.node))) {
97
+ add({ code: 'page-furniture-overlap', severity: 'error', page: number, blockId: mark.blockId,
98
+ message: `Content overlaps the running header or footer on page ${number}. Reduce the unbreakable content or adjust the page margins.` });
99
+ }
100
+ }
101
+ for (const mark of headings) {
102
+ if (mark.fixed) continue;
103
+ const heading = mark.node;
104
+ const title = leaves.filter(leaf => leaf.heading === heading).map(leaf => leaf.node.textContent ?? '').join(' ').trim();
105
+ if (mark.blockId && title && !outlined.has(mark.blockId)) {
106
+ outline.push({ id: mark.blockId, title, level: Number(heading.nodeType.slice(1)), page: number });
107
+ outlined.add(mark.blockId);
108
+ }
109
+ const lowerPage = heading.y + heading.height > page.contentY + page.contentHeight * 0.72;
110
+ const bodyFollows = leaves.some(leaf => !leaf.fixed && !leaf.heading && leaf.node.y >= heading.y + heading.height - tolerance &&
111
+ leaf.node.x < heading.x + heading.width && leaf.node.x + leaf.node.width > heading.x);
112
+ if (lowerPage && !bodyFollows) {
113
+ add({ code: 'stranded-heading', severity: 'warning', page: number, blockId: mark.blockId,
114
+ message: `“${title || blocks[mark.blockId ?? '']?.text || 'Heading'}” has no following body content on page ${number}. Use Section with a short lead to keep them together.` });
115
+ }
116
+ }
117
+ if (!leaves.some(mark => !mark.fixed)) {
118
+ add({ code: 'empty-page', severity: 'warning', page: number,
119
+ message: `Page ${number} has no body content. Check whether a page break or oversized block created an unwanted blank page.` });
120
+ }
121
+ }
122
+ return { issues, outline };
123
+ }
124
+
125
+ export function assertLayoutSafe(issues: ReviewIssue[]) {
126
+ const errors = issues.filter(issue => issue.severity === 'error');
127
+ if (!errors.length) return;
128
+ throw new RenderFailure(`Layout check failed:\n${errors.slice(0, 8).map(issue => `- ${issue.blockId ? `${issue.blockId}: ` : ''}${issue.message}`).join('\n')}${errors.length > 8 ? `\n- ${errors.length - 8} more layout errors.` : ''}`, issues);
129
+ }
@@ -0,0 +1,29 @@
1
+ import { parseArgs } from 'node:util';
2
+ import { resolve } from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+ import { assignProject, createProject, deleteProject, readProjects, updateProject } from './projects';
5
+
6
+ const usage = 'Usage: npx opendoc projects list [--json]\n npx opendoc projects create <id> --name "Project name" [--theme <theme-id>]\n npx opendoc projects update <id> [--name "Project name"] [--theme <theme-id|none>]\n npx opendoc projects assign <document-id> <project-id>\n npx opendoc projects delete <empty-project-id>';
7
+
8
+ export async function runProjectsCli(args: string[], root = process.cwd()): Promise<void> {
9
+ const { values, positionals } = parseArgs({ args: args[0] === '--' ? args.slice(1) : args, allowPositionals: true, options: {
10
+ name: { type: 'string' }, theme: { type: 'string' }, json: { type: 'boolean' }, help: { type: 'boolean', short: 'h' },
11
+ } });
12
+ const [action = 'list', id, projectId] = positionals;
13
+ let result: unknown;
14
+ if (values.help) {
15
+ console.log(values.json ? JSON.stringify({ usage }, null, 2) : usage);
16
+ } else {
17
+ if (action === 'list' && positionals.length <= 1) result = await readProjects(root);
18
+ else if (action === 'create' && id && positionals.length === 2) result = await createProject(root, { id, name: values.name, defaultTheme: values.theme === 'none' ? null : values.theme });
19
+ else if (action === 'update' && id && positionals.length === 2) result = await updateProject(root, id, { ...(values.name === undefined ? {} : { name: values.name }), ...(values.theme === undefined ? {} : { defaultTheme: values.theme === 'none' ? null : values.theme }) });
20
+ else if (action === 'assign' && id && projectId && positionals.length === 3) result = await assignProject(root, id, projectId);
21
+ else if (action === 'delete' && id && positionals.length === 2) { await deleteProject(root, id); result = { deleted: id }; }
22
+ else throw new Error('Unknown project command or missing arguments. Use npx opendoc projects --help.');
23
+ console.log(JSON.stringify(result, null, 2));
24
+ }
25
+ }
26
+
27
+ if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
28
+ runProjectsCli(process.argv.slice(2)).catch(error => { console.error(error instanceof Error ? error.message : String(error)); process.exitCode = 1; });
29
+ }