@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,249 @@
1
+ import { readFile, realpath, rm, writeFile } from 'node:fs/promises';
2
+ import { readFileSync, realpathSync, renameSync } from 'node:fs';
3
+ import { dirname, relative, resolve } from 'node:path';
4
+ import { randomUUID } from 'node:crypto';
5
+ import type { DocumentState, TextEditPreview } from '../shared/types';
6
+ import type { ManualEditSummary, TextEditBatchInput, TextEditChange, TextEditInput, TextSourceValue } from '../shared/selection';
7
+ import { containedFile } from './files';
8
+ import { documentEntry, renderOnce } from './render';
9
+ import { Conflict } from './comments';
10
+ import { serializeSourceValue, textDigest, validateTextSyntax } from './text-source';
11
+ import type { SourceOverride } from './source-overrides';
12
+
13
+ type EditInput = TextEditInput | TextEditBatchInput;
14
+ interface FileChange { path: string; file: string; before: string; after: string; beforeDigest: string; afterDigest: string }
15
+ interface UndoRecord { summary: ManualEditSummary; files: FileChange[] }
16
+ interface Prepared { files: FileChange[]; overrides: SourceOverride[]; summary: Omit<ManualEditSummary, 'id' | 'at' | 'canUndo'>; entry: string }
17
+ interface PreviewRecord { id: string; directory: string; at: number; pages: number }
18
+
19
+ function current(state: DocumentState, input: Pick<TextEditInput, 'revision' | 'hash'>, id: string) {
20
+ if (state.id !== id || state.status !== 'ready' || !state.artifact || state.revision !== input.revision || state.artifact.hash !== input.hash) throw new Conflict('This document changed. Your unsaved edits are still available; refresh or discard them before saving.');
21
+ }
22
+
23
+ /** Session-local grouped Save/Undo. Authored files stay authoritative until Save. */
24
+ export class TextEditService {
25
+ private records = new Map<string, UndoRecord>();
26
+ private queues = new Map<string, Promise<unknown>>();
27
+ private previews = new Map<string, PreviewRecord>();
28
+ constructor(private root: string) {}
29
+
30
+ /** Keep folder operations from racing an in-flight Save or Undo. */
31
+ withDocument<T>(id: string, operation: () => Promise<T>) { return this.serialize(id, operation); }
32
+
33
+ private serialize<T>(id: string, operation: () => Promise<T>): Promise<T> {
34
+ const previous = this.queues.get(id) ?? Promise.resolve();
35
+ const next = previous.catch(() => undefined).then(operation);
36
+ this.queues.set(id, next);
37
+ void next.finally(() => { if (this.queues.get(id) === next) this.queues.delete(id); }).catch(() => undefined);
38
+ return next;
39
+ }
40
+
41
+ changedFiles(id: string) { return this.records.get(id)?.files.map(file => file.file) ?? []; }
42
+
43
+ async summary(id: string): Promise<ManualEditSummary | undefined> {
44
+ const record = this.records.get(id);
45
+ if (!record) return undefined;
46
+ let canUndo = record.summary.canUndo;
47
+ if (canUndo) {
48
+ try {
49
+ const entry = await documentEntry(this.root, id);
50
+ for (const item of record.files) {
51
+ const file = await containedFile(dirname(entry), resolve(this.root, item.file));
52
+ if (file !== item.path || textDigest(await readFile(file, 'utf8')) !== item.afterDigest) { canUndo = false; break; }
53
+ }
54
+ } catch { canUndo = false; }
55
+ }
56
+ return { ...record.summary, canUndo };
57
+ }
58
+
59
+ private async prepare(id: string, input: EditInput, state: DocumentState): Promise<Prepared> {
60
+ const batch = !!input && typeof input === 'object' && 'edits' in input;
61
+ const changes: TextEditChange[] = batch ? (input as TextEditBatchInput).edits : [input as TextEditInput];
62
+ if (!input || !Number.isInteger(input.revision) || typeof input.hash !== 'string' || !Array.isArray(changes) || !changes.length || changes.length > 100) throw new Error('Save between 1 and 100 text edits from the current document.');
63
+ let length = 0;
64
+ for (const change of changes) {
65
+ if (!change || typeof change.targetId !== 'string' || !Number.isInteger(change.start) || !Number.isInteger(change.end) || change.start < 0 || change.end <= change.start || typeof change.replacement !== 'string' || change.replacement.length > 8_000) throw new Error('Select one text range and enter a correction of up to 8,000 characters.');
66
+ length += change.replacement.length;
67
+ }
68
+ if (length > 128_000) throw new Error('Save a smaller group of text edits.');
69
+ current(state, input, id);
70
+ const entry = await documentEntry(this.root, id);
71
+ const workspaceRoot = await realpath(this.root);
72
+ const comments = await realpath(resolve(dirname(entry), 'comments.json')).catch(() => '');
73
+ const files = new Map<string, FileChange>();
74
+ const groups = new Map<string, { source: TextSourceValue; file: FileChange; edits: { start: number; end: number; replacement: string }[] }>();
75
+ let first: Prepared['summary'] | undefined;
76
+ for (const change of changes) {
77
+ const target = state.artifact!.textTargets?.find(target => target.id === change.targetId);
78
+ if (!target || change.end > target.text.length) throw new Conflict('This selected text is no longer available. Refresh the selection.');
79
+ const runs = target.runs.filter(run => run.start <= change.start && run.end >= change.end);
80
+ const run = runs.length === 1 ? runs[0] : undefined;
81
+ if (!run?.source || run.protected || target.text.slice(run.start, run.end) !== run.source.value) throw new Error('This selection spans separate values or generated content. Ask your agent to change it.');
82
+ const source = run.source;
83
+ const path = await containedFile(dirname(entry), resolve(this.root, source.file));
84
+ if (path === comments) throw new Error('Feedback cannot be changed through a text correction.');
85
+ if (!/\.(?:tsx?|json)$/.test(path)) throw new Error('This source does not support text corrections.');
86
+ let file = files.get(path);
87
+ if (!file) {
88
+ const before = await readFile(path, 'utf8');
89
+ file = { path, file: relative(workspaceRoot, path), before, after: before, beforeDigest: textDigest(before), afterDigest: '' };
90
+ files.set(path, file);
91
+ }
92
+ if (file.beforeDigest !== source.digest) throw new Conflict('The source changed elsewhere. Your unsaved edits have not been applied.');
93
+ if (!Number.isInteger(source.start) || !Number.isInteger(source.end) || source.start < 0 || source.end <= source.start || source.end > file.before.length) throw new Error('This source binding is invalid. Refresh the document.');
94
+ if (source.kind === 'json-string') {
95
+ const dataFile = state.artifact!.provenance?.dataFile;
96
+ if (!dataFile || await containedFile(dirname(entry), resolve(this.root, dataFile)) !== path) throw new Error('This data is not bound to the selected document.');
97
+ }
98
+ const key = JSON.stringify([path, source.start, source.end]);
99
+ let group = groups.get(key);
100
+ if (!group) { group = { source, file, edits: [] }; groups.set(key, group); }
101
+ if (group.source.value !== source.value || group.source.kind !== source.kind) throw new Conflict('Linked text has inconsistent bindings. Refresh the document.');
102
+ const local = { start: change.start - run.start, end: change.end - run.start, replacement: change.replacement };
103
+ if (group.edits.some(edit => edit.start === local.start && edit.end === local.end && edit.replacement === local.replacement)) continue;
104
+ if (group.edits.some(edit => edit.start < local.end && local.start < edit.end)) throw new Conflict('Two edits overlap the same source text. Keep one final correction for that text before saving.');
105
+ if (target.text.slice(change.start, change.end) === change.replacement) continue;
106
+ group.edits.push(local);
107
+ first ??= { blockId: target.blockId, targetId: target.id, before: target.text.slice(change.start, change.end), after: change.replacement };
108
+ }
109
+ const overrides: SourceOverride[] = [];
110
+ let count = 0;
111
+ for (const file of files.values()) {
112
+ const changes = [...groups.values()].filter(group => group.file === file && group.edits.length).sort((a, b) => a.source.start - b.source.start);
113
+ if (!changes.length) continue;
114
+ if (changes.some((group, index) => index > 0 && group.source.start < changes[index - 1].source.end)) throw new Conflict('These text bindings overlap. Refresh the document before saving.');
115
+ const replacements: SourceOverride['replacements'] = [];
116
+ for (const group of changes) {
117
+ let value = group.source.value;
118
+ for (const edit of group.edits.sort((a, b) => b.start - a.start)) value = value.slice(0, edit.start) + edit.replacement + value.slice(edit.end);
119
+ const token = serializeSourceValue(group.source, value);
120
+ replacements.push({ start: group.source.start, end: group.source.end, tokenLength: token.length, value });
121
+ }
122
+ for (let index = changes.length - 1; index >= 0; index--) {
123
+ const { source } = changes[index];
124
+ file.after = file.after.slice(0, source.start) + serializeSourceValue(source, replacements[index].value) + file.after.slice(source.end);
125
+ }
126
+ validateTextSyntax(file.path, file.after);
127
+ file.afterDigest = textDigest(file.after);
128
+ overrides.push({ file: file.path, contents: file.after, originalDigest: file.beforeDigest, replacements });
129
+ count += changes.length;
130
+ }
131
+ if (!count || !first) throw new Error('Change some text before saving.');
132
+ return { entry, files: [...files.values()].filter(file => file.afterDigest), overrides, summary: { ...first, count } };
133
+ }
134
+
135
+ /** Stage everything before replacement; rollback only bytes written by this operation. */
136
+ private async commit(files: FileChange[], check: () => void) {
137
+ const staged: { file: FileChange; temporary: string }[] = [];
138
+ const written: FileChange[] = [];
139
+ try {
140
+ for (const file of files) {
141
+ const temporary = `${file.path}.${randomUUID()}.tmp`;
142
+ staged.push({ file, temporary });
143
+ await writeFile(temporary, file.after);
144
+ }
145
+ check();
146
+ // No awaits between the final checks and renames, so our own watcher cannot
147
+ // publish an intermediate batch. Independent files have no OS-wide rename.
148
+ for (const file of files) {
149
+ if (realpathSync(resolve(this.root, file.file)) !== file.path || textDigest(readFileSync(file.path, 'utf8')) !== file.beforeDigest) throw new Conflict('The source changed during validation. Your edits have not been applied.');
150
+ }
151
+ for (const item of staged) {
152
+ if (realpathSync(resolve(this.root, item.file.file)) !== item.file.path || textDigest(readFileSync(item.file.path, 'utf8')) !== item.file.beforeDigest) throw new Conflict('The source changed during saving. Your edits have not been applied.');
153
+ renameSync(item.temporary, item.file.path); written.push(item.file);
154
+ }
155
+ } catch (error) {
156
+ let incomplete = false;
157
+ for (const file of written.reverse()) {
158
+ let temporary: string | undefined;
159
+ try {
160
+ if (realpathSync(resolve(this.root, file.file)) !== file.path || textDigest(readFileSync(file.path, 'utf8')) !== file.afterDigest) { incomplete = true; continue; }
161
+ temporary = `${file.path}.${randomUUID()}.tmp`;
162
+ await writeFile(temporary, file.before);
163
+ if (realpathSync(resolve(this.root, file.file)) !== file.path || textDigest(readFileSync(file.path, 'utf8')) !== file.afterDigest) { incomplete = true; continue; }
164
+ renameSync(temporary, file.path);
165
+ } catch { incomplete = true; }
166
+ finally { if (temporary) await rm(temporary, { force: true }).catch(() => {}); }
167
+ }
168
+ if (incomplete) throw new Conflict('The source changed while saving. Some edits could not be restored safely; review the document before continuing.');
169
+ throw error;
170
+ } finally { await Promise.all(staged.map(item => rm(item.temporary, { force: true }))); }
171
+ }
172
+
173
+ private async verifySources(prepared: Prepared, input: EditInput, state: DocumentState, id: string) {
174
+ current(state, input, id);
175
+ for (const file of prepared.files) {
176
+ if (await containedFile(dirname(prepared.entry), resolve(this.root, file.file)) !== file.path || textDigest(await readFile(file.path, 'utf8')) !== file.beforeDigest) throw new Conflict('The source changed during validation. Your unsaved edits have not been applied.');
177
+ }
178
+ current(state, input, id);
179
+ }
180
+
181
+ preview(id: string, input: TextEditBatchInput, state: DocumentState): Promise<TextEditPreview> {
182
+ return this.serialize(id, async () => {
183
+ const prepared = await this.prepare(id, input, state);
184
+ const result = await renderOnce(this.root, id, 30_000, prepared.overrides);
185
+ try {
186
+ await this.verifySources(prepared, input, state, id);
187
+ const key = randomUUID();
188
+ this.previews.set(key, { id, directory: result.directory, at: Date.now(), pages: result.artifact.pages.length });
189
+ await this.prunePreviews();
190
+ return { artifact: result.artifact, pdfUrl: `/api/documents/${id}/edits/previews/${key}/pdf` };
191
+ } catch (error) { await rm(result.directory, { recursive: true, force: true }); throw error; }
192
+ });
193
+ }
194
+
195
+ async previewPDF(id: string, key: string) {
196
+ const preview = this.previews.get(key);
197
+ if (!preview || preview.id !== id || Date.now() - preview.at > 10 * 60_000) throw new Conflict('This draft preview expired. Update an edit to render it again.');
198
+ return readFile(resolve(preview.directory, 'document.pdf'));
199
+ }
200
+
201
+ previewPageCount(id: string) {
202
+ return Math.max(1, ...[...this.previews.values()].filter(preview => preview.id === id && Date.now() - preview.at <= 10 * 60_000).map(preview => preview.pages));
203
+ }
204
+
205
+ private async prunePreviews() {
206
+ const previews = [...this.previews.entries()];
207
+ const keep = new Set(previews.slice(-24).map(([key]) => key));
208
+ const counts = new Map<string, number>();
209
+ for (const [key, preview] of previews.reverse()) {
210
+ const count = (counts.get(preview.id) ?? 0) + 1; counts.set(preview.id, count);
211
+ if (keep.has(key) && count <= 8 && Date.now() - preview.at <= 10 * 60_000) continue;
212
+ this.previews.delete(key); await rm(preview.directory, { recursive: true, force: true });
213
+ }
214
+ }
215
+
216
+ apply(id: string, input: EditInput, state: DocumentState): Promise<ManualEditSummary> {
217
+ return this.serialize(id, async () => {
218
+ const prepared = await this.prepare(id, input, state);
219
+ const result = await renderOnce(this.root, id, 30_000, prepared.overrides);
220
+ await rm(result.directory, { recursive: true, force: true });
221
+ await this.verifySources(prepared, input, state, id);
222
+ await this.commit(prepared.files, () => current(state, input, id));
223
+ const summary: ManualEditSummary = { ...prepared.summary, id: randomUUID(), at: new Date().toISOString(), canUndo: true };
224
+ this.records.set(id, { summary, files: prepared.files });
225
+ return { ...summary };
226
+ });
227
+ }
228
+
229
+ undo(id: string, editId: string): Promise<ManualEditSummary> {
230
+ return this.serialize(id, async () => {
231
+ const record = this.records.get(id);
232
+ if (!record || record.summary.id !== editId || !record.summary.canUndo) throw new Conflict('That correction is no longer the latest undoable edit.');
233
+ const entry = await documentEntry(this.root, id);
234
+ for (const file of record.files) {
235
+ const path = await containedFile(dirname(entry), resolve(this.root, file.file));
236
+ if (path !== file.path || textDigest(await readFile(path, 'utf8')) !== file.afterDigest) throw new Conflict('The source changed after these edits. Undo would overwrite newer work; ask your agent to restore the wording.');
237
+ }
238
+ await this.commit(record.files.map(file => ({ ...file, before: file.after, after: file.before, beforeDigest: file.afterDigest, afterDigest: file.beforeDigest })), () => {});
239
+ record.summary = { ...record.summary, canUndo: false };
240
+ return { ...record.summary };
241
+ });
242
+ }
243
+
244
+ async close() {
245
+ await Promise.allSettled([...this.queues.values()]);
246
+ await Promise.all([...this.previews.values()].map(preview => rm(preview.directory, { recursive: true, force: true })));
247
+ this.previews.clear();
248
+ }
249
+ }
@@ -0,0 +1,105 @@
1
+ import { access, readdir, rm, stat } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+ import type { ReviewIssue } from '../shared/types';
4
+ import type { PreviewSession } from './export-preview';
5
+ import { ExportResponseLost } from './export-errors';
6
+ import { RenderFailure } from './render-error';
7
+ import { documentEntry, renderOnce, validId } from './render';
8
+ import { publishRenderedPDF, publishFile } from './export-file';
9
+ import { readPresentationBytes } from './pptx';
10
+ import { exportInfo, type ExportFormat } from '../shared/export';
11
+ import { captureExportInputs } from './export-inputs';
12
+
13
+ export type ExportResult = {
14
+ id: string; status: 'success'; pages: number; hash: string; path: string; source: 'preview' | 'render'; warning?: string;
15
+ } | {
16
+ id: string; status: 'error'; error: string; path: string; updated: false | 'unknown'; previousOutputRetained: boolean; issues?: ReviewIssue[];
17
+ };
18
+ export interface ExportOptions { requestTimeoutMs?: number; readyTimeoutMs?: number; renderTimeoutMs?: number; format?: ExportFormat; mode?: 'preview' | 'direct' }
19
+ export const exportUsage = 'Usage: npx opendoc export <document-id> [more-ids...] [--format pdf|pptx] [--json]\n npx opendoc export --all [--format pdf|pptx] [--json]';
20
+
21
+ export function parseExportArgs(args: string[]) {
22
+ let all = false, json = false;
23
+ const ids: string[] = [];
24
+ let format: ExportFormat | undefined;
25
+ for (let index = 0; index < args.length; index++) {
26
+ const arg = args[index];
27
+ if (arg === '--format') {
28
+ const next = args[++index];
29
+ if (format || (next !== 'pdf' && next !== 'pptx')) throw new Error(`Choose one --format pdf or --format pptx.\n${exportUsage}`);
30
+ format = next; continue;
31
+ }
32
+ parseArgument(arg);
33
+ }
34
+ function parseArgument(arg: string) {
35
+ if (arg === '--') return;
36
+ if (arg === '--all') { if (all) throw new Error(`Duplicate --all option.\n${exportUsage}`); all = true; }
37
+ else if (arg === '--json') { if (json) throw new Error(`Duplicate --json option.\n${exportUsage}`); json = true; }
38
+ else if (!validId(arg)) throw new Error(`Invalid argument: ${arg}\n${exportUsage}`);
39
+ else if (!ids.includes(arg)) ids.push(arg);
40
+ }
41
+ if ((all && ids.length) || (!all && !ids.length)) throw new Error(exportUsage);
42
+ return { all, json, ids, ...(format ? { format } : {}) };
43
+ }
44
+
45
+ export async function discoverDocumentIds(root: string) {
46
+ const ids: string[] = [];
47
+ for (const dir of await readdir(resolve(root, 'documents'), { withFileTypes: true })) {
48
+ if (!dir.isDirectory() || !validId(dir.name)) continue;
49
+ try { await access(resolve(root, 'documents', dir.name, 'index.tsx')); }
50
+ catch (error) { if ((error as NodeJS.ErrnoException).code === 'ENOENT') continue; throw error; }
51
+ ids.push(dir.name);
52
+ }
53
+ return ids.sort();
54
+ }
55
+
56
+ export async function exportDocuments(root: string, requestedIds: string[], supplied: ExportOptions = {}): Promise<ExportResult[]> {
57
+ const ids = [...new Set(requestedIds)];
58
+ if (ids.some(id => !validId(id))) throw new Error('Invalid document ID.');
59
+ if (!ids.length) throw new Error('No documents were found to export.');
60
+ const options = { requestTimeoutMs: 5_000, readyTimeoutMs: 35_000, renderTimeoutMs: 30_000, ...supplied, format: supplied.format ?? 'pdf' };
61
+ let session: PreviewSession | null = null, sessionError: unknown;
62
+ // Direct production never inspects a GUI session or loads its HTTP adapter.
63
+ const preview = options.mode === 'direct' ? undefined : await import('./export-preview');
64
+ if (preview) try { session = await preview.currentSession(root, options.requestTimeoutMs); } catch (error) { sessionError = error; }
65
+ const results: ExportResult[] = new Array(ids.length);
66
+ let next = 0;
67
+ async function run() {
68
+ while (next < ids.length) {
69
+ const index = next++, id = ids[index], path = resolve(root, 'output', `${id}${exportInfo(options.format).extension}`);
70
+ try {
71
+ if (sessionError) throw sessionError;
72
+ // Validate containment for online and offline requests alike.
73
+ await documentEntry(root, id);
74
+ if (session && preview) results[index] = await preview.exportPreview(root, id, session, options);
75
+ else {
76
+ const unchanged = await captureExportInputs(root, id);
77
+ const result = await renderOnce(root, id, options.renderTimeoutMs);
78
+ let exported: Extract<ExportResult, { status: 'success' }> | undefined;
79
+ try {
80
+ if (options.format === 'pptx') {
81
+ if (result.artifact.format !== 'presentation') throw new Error('PowerPoint export is available for presentations only.');
82
+ const bytes = await readPresentationBytes(result.directory, result.artifact.hash);
83
+ await publishFile(root, id, bytes, 'pptx', unchanged);
84
+ } else await publishRenderedPDF(root, id, result.directory, unchanged);
85
+ exported = { id, status: 'success', pages: result.artifact.pages.length, hash: result.artifact.hash, path, source: 'render' };
86
+ results[index] = exported;
87
+ } finally {
88
+ try { await rm(result.directory, { recursive: true, force: true }); }
89
+ catch (error) {
90
+ if (!exported) throw error;
91
+ exported.warning = `The file was saved, but temporary render files could not be removed: ${error instanceof Error ? error.message : String(error)}`;
92
+ }
93
+ }
94
+ }
95
+ } catch (error) {
96
+ const updated = error instanceof ExportResponseLost ? 'unknown' : false;
97
+ let previousOutputRetained = false;
98
+ if (updated === false) try { previousOutputRetained = (await stat(path)).isFile(); } catch { /* No prior export. */ }
99
+ results[index] = { id, status: 'error', error: error instanceof Error ? error.message : String(error), path, updated, previousOutputRetained, ...(error instanceof RenderFailure ? { issues: error.issues } : {}) };
100
+ }
101
+ }
102
+ }
103
+ await Promise.all([run(), run()]);
104
+ return results;
105
+ }
@@ -0,0 +1,2 @@
1
+ /** The GUI may have committed an export before its response was lost. */
2
+ export class ExportResponseLost extends Error {}
@@ -0,0 +1,57 @@
1
+ import { lstat, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
2
+ import { lstatSync, renameSync } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { validId } from './render';
6
+ import { exportInfo, type ExportFormat } from '../shared/export';
7
+
8
+ export class ExportChangedError extends Error {
9
+ constructor() { super('The document changed during export. Wait for the latest preview and try again.'); }
10
+ }
11
+
12
+ /** Prepare bytes first, then publish atomically while the revision is still current. */
13
+ export async function publishFile(root: string, id: string, bytes: Uint8Array, format: ExportFormat, isCurrent: () => boolean = () => true, collection?: 'themes' | 'templates') {
14
+ if (!validId(id)) throw new Error('Invalid document ID.');
15
+ const folder = await outputFolder(root, collection ? [collection] : []);
16
+ const output = resolve(folder, `${id}${exportInfo(format).extension}`);
17
+ const previous = await lstat(output).catch(error => { if (error.code === 'ENOENT') return undefined; throw error; });
18
+ if (previous && (!previous.isFile() || previous.isSymbolicLink())) throw new Error('The export destination must be a regular local file.');
19
+ const temporary = resolve(folder, `.${id}.${randomUUID()}.tmp`);
20
+ let published = false;
21
+ try {
22
+ await writeFile(temporary, bytes, { flag: 'wx' });
23
+ for (const parent of new Set([resolve(root, 'output'), folder])) {
24
+ const info = lstatSync(parent);
25
+ if (!info.isDirectory() || info.isSymbolicLink()) throw new Error('The export output folder changed during preparation.');
26
+ }
27
+ const current = (() => { try { return lstatSync(output); } catch (error) { if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined; throw error; } })();
28
+ if (current && (!current.isFile() || current.isSymbolicLink())) throw new Error('The export destination must be a regular local file.');
29
+ if (!isCurrent()) throw new ExportChangedError();
30
+ // No event-loop turn may separate the revision check from publication.
31
+ renameSync(temporary, output);
32
+ published = true;
33
+ return output;
34
+ } finally { if (!published) await rm(temporary, { force: true }); }
35
+ }
36
+
37
+ export async function publishRenderedPDF(root: string, id: string, directory: string, isCurrent?: () => boolean) {
38
+ const bytes = await readFile(resolve(directory, 'document.pdf'));
39
+ return publishPDF(root, id, bytes, isCurrent);
40
+ }
41
+
42
+ export function publishPDF(root: string, id: string, bytes: Uint8Array, isCurrent?: () => boolean, collection?: 'themes' | 'templates') {
43
+ return publishFile(root, id, bytes, 'pdf', isCurrent, collection);
44
+ }
45
+
46
+ /** Create output parents one at a time without traversing a linked directory. */
47
+ export async function outputFolder(root: string, segments: string[] = []) {
48
+ let folder = root;
49
+ for (const segment of ['output', ...segments]) {
50
+ if (!validId(segment)) throw new Error('Invalid output folder.');
51
+ folder = resolve(folder, segment);
52
+ await mkdir(folder).catch(error => { if (error.code !== 'EEXIST') throw error; });
53
+ const info = await lstat(folder);
54
+ if (!info.isDirectory() || info.isSymbolicLink()) throw new Error('Exports need regular local output folders; symbolic links are not supported.');
55
+ }
56
+ return folder;
57
+ }
@@ -0,0 +1,66 @@
1
+ import { readdir, realpath, stat } from 'node:fs/promises';
2
+ import { readdirSync, statSync } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+ import { documentDependencies, isManagedAssetPath, isThemeAssetDefaultsPath } from './dependencies';
5
+ import { documentEntry } from './render';
6
+ import { ExportChangedError } from './export-file';
7
+
8
+ type Stamp = { size: bigint; mtimeNs: bigint; ctimeNs: bigint; ino: bigint };
9
+ const signature = (value: Stamp) => `${value.size}:${value.mtimeNs}:${value.ctimeNs}:${value.ino}`;
10
+
11
+ const sharedCompanions = ['templates', 'themes', 'assets'];
12
+
13
+ /** Capture local inputs before rendering; the final check stays synchronous with publication. */
14
+ export async function captureExportInputs(root: string, id: string): Promise<() => boolean> {
15
+ return captureEntryExportInputs(root, await documentEntry(root, id), [`documents/${id}`, ...sharedCompanions]);
16
+ }
17
+
18
+ /** Specimens include transient defaults, while authored documents include only their exact pins. */
19
+ export async function captureEntryExportInputs(root: string, entry: string, companionFolders: string[] = sharedCompanions): Promise<() => boolean> {
20
+ const entryBefore = signature(await stat(entry, { bigint: true }));
21
+ const dependencies = await documentDependencies(root, entry);
22
+ const inputs = new Map<string, { stamp: string; directory: boolean; missing?: boolean; emptyWhenMissing?: boolean }>();
23
+ const visited = new Set<string>();
24
+ const included = (parent: string, name: string) => name !== 'comments.json' && !name.startsWith('.forme-render-') && !name.endsWith('.tmp')
25
+ && (dependencies.readsFiles || (!isManagedAssetPath(root, resolve(parent, name)) && !isThemeAssetDefaultsPath(root, resolve(parent, name))));
26
+ async function collect(path: string) {
27
+ // A newly created managed logo container is equivalent to an empty catalog;
28
+ // loose legacy artwork in that container remains a conservative shared input.
29
+ const emptyWhenMissing = !dependencies.readsFiles && path === resolve(root, 'assets/logos');
30
+ let info;
31
+ try { info = await stat(path, { bigint: true }); }
32
+ catch (error) {
33
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
34
+ inputs.set(path, emptyWhenMissing ? { stamp: '[]', directory: true, emptyWhenMissing: true } : { stamp: '', directory: false, missing: true }); return;
35
+ }
36
+ if (!info.isDirectory()) { inputs.set(path, { stamp: signature(info), directory: false }); return; }
37
+ const children = (await readdir(path)).filter(name => included(path, name)).sort();
38
+ inputs.set(path, { stamp: JSON.stringify(children), directory: true, ...(emptyWhenMissing ? { emptyWhenMissing: true } : {}) });
39
+ const actual = await realpath(path);
40
+ if (visited.has(actual)) return;
41
+ visited.add(actual);
42
+ for (const child of children) await collect(resolve(path, child));
43
+ }
44
+ // Explicit dependencies bypass broad-library exclusions, including paths currently absent.
45
+ for (const path of dependencies.files) await collect(path);
46
+ for (const folder of [...new Set([...companionFolders, ...(dependencies.readsFiles ? ['documents'] : [])])]) await collect(resolve(root, folder));
47
+ if (!dependencies.readsFiles && companionFolders.some(folder => ['assets', 'assets/logos'].includes(folder))) await collect(resolve(root, 'assets/logos'));
48
+ const unchanged = () => {
49
+ try {
50
+ return [...inputs].every(([file, input]) => {
51
+ if (input.missing) {
52
+ try { statSync(file); return false; } catch (error) { return (error as NodeJS.ErrnoException).code === 'ENOENT'; }
53
+ }
54
+ if (input.emptyWhenMissing) {
55
+ try { return JSON.stringify(readdirSync(file).filter(name => included(file, name)).sort()) === input.stamp; }
56
+ catch (error) { return (error as NodeJS.ErrnoException).code === 'ENOENT' && input.stamp === '[]'; }
57
+ }
58
+ return (input.directory
59
+ ? JSON.stringify(readdirSync(file).filter(name => included(file, name)).sort())
60
+ : signature(statSync(file, { bigint: true }))) === input.stamp;
61
+ });
62
+ } catch { return false; }
63
+ };
64
+ if (signature(await stat(entry, { bigint: true })) !== entryBefore || !unchanged()) throw new ExportChangedError();
65
+ return unchanged;
66
+ }
@@ -0,0 +1,69 @@
1
+ import { resolve } from 'node:path';
2
+ import type { DocumentState } from '../shared/types';
3
+ import { exportInfo } from '../shared/export';
4
+ import { readJSON } from './files';
5
+ import type { ExportOptions, ExportResult } from './export-batch';
6
+ import { ExportResponseLost } from './export-errors';
7
+
8
+ interface Connection { origin: string; token: string }
9
+ export interface PreviewSession { connection: Connection; states: DocumentState[] }
10
+ type Session = PreviewSession;
11
+
12
+ async function responseError(response: Response, fallback: string) {
13
+ try { const data = await response.json() as { error?: unknown }; return typeof data.error === 'string' ? data.error : fallback; }
14
+ catch { return fallback; }
15
+ }
16
+
17
+ async function request(url: string, timeout: number, init?: RequestInit) {
18
+ return fetch(url, { ...init, signal: AbortSignal.timeout(timeout), redirect: 'error' });
19
+ }
20
+
21
+ async function readStates(connection: Connection, timeout: number) {
22
+ const response = await request(`${connection.origin}/api/documents`, timeout);
23
+ if (!response.ok) throw new Error(await responseError(response, `The local OpenDoc session refused the request (${response.status}).`));
24
+ const states = await response.json() as DocumentState[];
25
+ if (!Array.isArray(states)) throw new Error('The local OpenDoc session returned an invalid document list.');
26
+ return states;
27
+ }
28
+
29
+ export async function currentSession(root: string, timeout: number): Promise<Session | null> {
30
+ const connection = await readJSON<Connection | null>(resolve(root, '.opendoc/server.json'), null);
31
+ if (!connection) return null;
32
+ if (typeof connection.origin !== 'string' || !/^http:\/\/127\.0\.0\.1:\d+$/.test(connection.origin) || typeof connection.token !== 'string' || !connection.token) {
33
+ throw new Error('The local OpenDoc session file is invalid. Restart OpenDoc before exporting.');
34
+ }
35
+ try { return { connection, states: await readStates(connection, timeout) }; }
36
+ catch (error) {
37
+ // Only an unavailable server permits an offline render. A live error stays authoritative.
38
+ const code = (error as { cause?: { code?: string } }).cause?.code;
39
+ if (code === 'ECONNREFUSED' || code === 'ENOTFOUND') return null;
40
+ throw error;
41
+ }
42
+ }
43
+
44
+ export async function exportPreview(root: string, id: string, session: Session, options: Required<Pick<ExportOptions, 'requestTimeoutMs' | 'readyTimeoutMs' | 'format'>>): Promise<ExportResult> {
45
+ const deadline = Date.now() + options.readyTimeoutMs;
46
+ let state = session.states.find(item => item.id === id);
47
+ while (state?.status === 'rendering' && Date.now() < deadline) {
48
+ await new Promise(accept => setTimeout(accept, Math.min(120, Math.max(1, deadline - Date.now()))));
49
+ const remaining = deadline - Date.now();
50
+ if (remaining <= 0) break;
51
+ state = (await readStates(session.connection, Math.min(options.requestTimeoutMs, remaining))).find(item => item.id === id);
52
+ }
53
+ if (!state) throw new Error(`Document "${id}" was not found in the current OpenDoc session.`);
54
+ if (state.status !== 'ready' || !state.artifact) throw new Error(state.error ?? 'The current document is still rendering. Wait for its preview before exporting.');
55
+ let response: Response;
56
+ try {
57
+ response = await request(`${session.connection.origin}/api/documents/${id}/export`, options.requestTimeoutMs, {
58
+ method: 'POST', headers: { 'Content-Type': 'application/json', 'X-OpenDoc-Token': session.connection.token },
59
+ body: JSON.stringify({ hash: state.artifact.hash, format: options.format }),
60
+ });
61
+ } catch {
62
+ throw new ExportResponseLost('The local session stopped responding during export. The output may have been saved; its status could not be confirmed.');
63
+ }
64
+ if (!response.ok) throw new Error(await responseError(response, `Export failed (${response.status}).`));
65
+ // The endpoint saves locally before returning 200; the CLI needs no duplicate PDF download.
66
+ await response.body?.cancel().catch(() => {});
67
+ return { id, status: 'success', pages: state.artifact.pages.length, hash: state.artifact.hash, path: resolve(root, 'output', `${id}${exportInfo(options.format).extension}`), source: 'preview' };
68
+ }
69
+
@@ -0,0 +1,32 @@
1
+ import { resolve } from 'node:path';
2
+ import { pathToFileURL } from 'node:url';
3
+ import { discoverDocumentIds, exportDocuments, exportUsage, parseExportArgs, type ExportOptions } from './export-batch';
4
+
5
+ export async function runExportCli(args: string[], root = process.cwd(), settings: Pick<ExportOptions, 'mode'> = {}): Promise<void> {
6
+ if (args.includes('--help') || args.includes('-h')) {
7
+ console.log(args.includes('--json') ? JSON.stringify({ usage: exportUsage }, null, 2) : exportUsage);
8
+ return;
9
+ }
10
+ const options = parseExportArgs(args);
11
+ const ids = options.all ? await discoverDocumentIds(root) : options.ids;
12
+ const results = await exportDocuments(root, ids, { format: options.format, ...settings });
13
+ if (options.json) console.log(JSON.stringify({ results }, null, 2));
14
+ else for (const result of results) {
15
+ if (result.status === 'success') {
16
+ console.log(`Exported ${result.id} (${result.pages} ${result.pages === 1 ? 'page' : 'pages'}): ${result.path}`);
17
+ if (result.warning) console.error(result.warning);
18
+ }
19
+ else console.error(`${result.id}: ${result.error}\n${result.updated === 'unknown' ? `Check ${result.path} before retrying.` : result.previousOutputRetained ? 'Previous export retained; it was not updated.' : 'No file was written.'}`);
20
+ }
21
+ if (results.some(result => result.status === 'error')) process.exitCode = 1;
22
+ }
23
+
24
+ if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
25
+ try { await runExportCli(process.argv.slice(2)); }
26
+ catch (error) {
27
+ const message = error instanceof Error ? error.message : String(error);
28
+ if (process.argv.includes('--json')) console.log(JSON.stringify({ error: message, results: [] }, null, 2));
29
+ else console.error(message);
30
+ process.exitCode = 1;
31
+ }
32
+ }