@ryanyahya/opendoc-headless 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 (716) 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/docs/APPEARANCE.md +21 -0
  24. package/docs/ASSETS.md +176 -0
  25. package/docs/AUTHORING.md +178 -0
  26. package/docs/HEADLESS.md +120 -0
  27. package/docs/MEDIA.md +112 -0
  28. package/docs/PROJECTS.md +55 -0
  29. package/docs/PROSE.md +15 -0
  30. package/docs/SELECTION.md +59 -0
  31. package/docs/TEMPLATES.md +55 -0
  32. package/docs/THEMES.md +106 -0
  33. package/node_modules/@formepdf/core/LICENSE +21 -0
  34. package/node_modules/@formepdf/core/README.md +53 -0
  35. package/node_modules/@formepdf/core/dist/attachments.d.ts +55 -0
  36. package/node_modules/@formepdf/core/dist/attachments.js +59 -0
  37. package/node_modules/@formepdf/core/dist/extract.d.ts +8 -0
  38. package/node_modules/@formepdf/core/dist/extract.js +56 -0
  39. package/node_modules/@formepdf/core/dist/index.d.ts +311 -0
  40. package/node_modules/@formepdf/core/dist/index.js +167 -0
  41. package/node_modules/@formepdf/core/dist/layout.d.ts +132 -0
  42. package/node_modules/@formepdf/core/dist/layout.js +240 -0
  43. package/node_modules/@formepdf/core/dist/shared/browserHelpers.d.ts +19 -0
  44. package/node_modules/@formepdf/core/dist/shared/browserHelpers.js +128 -0
  45. package/node_modules/@formepdf/core/package.json +35 -0
  46. package/node_modules/@formepdf/core/pkg-node/LICENSE +21 -0
  47. package/node_modules/@formepdf/core/pkg-node/README.md +84 -0
  48. package/node_modules/@formepdf/core/pkg-node/forme.d.ts +39 -0
  49. package/node_modules/@formepdf/core/pkg-node/forme.js +394 -0
  50. package/node_modules/@formepdf/core/pkg-node/forme_bg.wasm +0 -0
  51. package/node_modules/@formepdf/core/pkg-node/forme_bg.wasm.d.ts +21 -0
  52. package/node_modules/@formepdf/core/pkg-node/package.json +25 -0
  53. package/node_modules/@formepdf/react/README.md +70 -0
  54. package/node_modules/@formepdf/react/dist/charts.d.ts +72 -0
  55. package/node_modules/@formepdf/react/dist/charts.js +338 -0
  56. package/node_modules/@formepdf/react/dist/components.d.ts +533 -0
  57. package/node_modules/@formepdf/react/dist/components.js +608 -0
  58. package/node_modules/@formepdf/react/dist/expr.d.ts +20 -0
  59. package/node_modules/@formepdf/react/dist/expr.js +39 -0
  60. package/node_modules/@formepdf/react/dist/font.d.ts +2 -0
  61. package/node_modules/@formepdf/react/dist/font.js +1 -0
  62. package/node_modules/@formepdf/react/dist/index.d.ts +11 -0
  63. package/node_modules/@formepdf/react/dist/index.js +15 -0
  64. package/node_modules/@formepdf/react/dist/render.d.ts +12 -0
  65. package/node_modules/@formepdf/react/dist/render.js +15 -0
  66. package/node_modules/@formepdf/react/dist/serialize.d.ts +12 -0
  67. package/node_modules/@formepdf/react/dist/serialize.js +1470 -0
  68. package/node_modules/@formepdf/react/dist/stylesheet.d.ts +4 -0
  69. package/node_modules/@formepdf/react/dist/stylesheet.js +5 -0
  70. package/node_modules/@formepdf/react/dist/template-proxy.d.ts +38 -0
  71. package/node_modules/@formepdf/react/dist/template-proxy.js +100 -0
  72. package/node_modules/@formepdf/react/dist/types.d.ts +287 -0
  73. package/node_modules/@formepdf/react/dist/types.js +1 -0
  74. package/node_modules/@formepdf/react/package.json +41 -0
  75. package/node_modules/@formepdf/shared/README.md +7 -0
  76. package/node_modules/@formepdf/shared/dist/canvas.d.ts +6 -0
  77. package/node_modules/@formepdf/shared/dist/canvas.js +43 -0
  78. package/node_modules/@formepdf/shared/dist/charts.d.ts +100 -0
  79. package/node_modules/@formepdf/shared/dist/charts.js +98 -0
  80. package/node_modules/@formepdf/shared/dist/encode.d.ts +27 -0
  81. package/node_modules/@formepdf/shared/dist/encode.js +93 -0
  82. package/node_modules/@formepdf/shared/dist/font.d.ts +13 -0
  83. package/node_modules/@formepdf/shared/dist/font.js +52 -0
  84. package/node_modules/@formepdf/shared/dist/index.d.ts +10 -0
  85. package/node_modules/@formepdf/shared/dist/index.js +15 -0
  86. package/node_modules/@formepdf/shared/dist/parser.d.ts +30 -0
  87. package/node_modules/@formepdf/shared/dist/parser.js +756 -0
  88. package/node_modules/@formepdf/shared/dist/semantics.d.ts +15 -0
  89. package/node_modules/@formepdf/shared/dist/semantics.js +44 -0
  90. package/node_modules/@formepdf/shared/dist/style.d.ts +7 -0
  91. package/node_modules/@formepdf/shared/dist/style.js +1024 -0
  92. package/node_modules/@formepdf/shared/dist/types.d.ts +743 -0
  93. package/node_modules/@formepdf/shared/dist/types.js +2 -0
  94. package/node_modules/@formepdf/shared/package.json +35 -0
  95. package/node_modules/@types/node/LICENSE +21 -0
  96. package/node_modules/@types/node/README.md +15 -0
  97. package/node_modules/@types/node/assert/strict.d.ts +111 -0
  98. package/node_modules/@types/node/assert.d.ts +1078 -0
  99. package/node_modules/@types/node/async_hooks.d.ts +603 -0
  100. package/node_modules/@types/node/buffer.buffer.d.ts +472 -0
  101. package/node_modules/@types/node/buffer.d.ts +1934 -0
  102. package/node_modules/@types/node/child_process.d.ts +1476 -0
  103. package/node_modules/@types/node/cluster.d.ts +578 -0
  104. package/node_modules/@types/node/compatibility/disposable.d.ts +14 -0
  105. package/node_modules/@types/node/compatibility/index.d.ts +9 -0
  106. package/node_modules/@types/node/compatibility/indexable.d.ts +20 -0
  107. package/node_modules/@types/node/compatibility/iterators.d.ts +20 -0
  108. package/node_modules/@types/node/console.d.ts +452 -0
  109. package/node_modules/@types/node/constants.d.ts +21 -0
  110. package/node_modules/@types/node/crypto.d.ts +4545 -0
  111. package/node_modules/@types/node/dgram.d.ts +600 -0
  112. package/node_modules/@types/node/diagnostics_channel.d.ts +576 -0
  113. package/node_modules/@types/node/dns/promises.d.ts +503 -0
  114. package/node_modules/@types/node/dns.d.ts +923 -0
  115. package/node_modules/@types/node/domain.d.ts +170 -0
  116. package/node_modules/@types/node/events.d.ts +976 -0
  117. package/node_modules/@types/node/fs/promises.d.ts +1306 -0
  118. package/node_modules/@types/node/fs.d.ts +4463 -0
  119. package/node_modules/@types/node/globals.d.ts +172 -0
  120. package/node_modules/@types/node/globals.typedarray.d.ts +38 -0
  121. package/node_modules/@types/node/http.d.ts +2097 -0
  122. package/node_modules/@types/node/http2.d.ts +2843 -0
  123. package/node_modules/@types/node/https.d.ts +579 -0
  124. package/node_modules/@types/node/index.d.ts +98 -0
  125. package/node_modules/@types/node/inspector.d.ts +253 -0
  126. package/node_modules/@types/node/inspector.generated.d.ts +4052 -0
  127. package/node_modules/@types/node/module.d.ts +891 -0
  128. package/node_modules/@types/node/net.d.ts +1076 -0
  129. package/node_modules/@types/node/os.d.ts +506 -0
  130. package/node_modules/@types/node/package.json +145 -0
  131. package/node_modules/@types/node/path.d.ts +200 -0
  132. package/node_modules/@types/node/perf_hooks.d.ts +968 -0
  133. package/node_modules/@types/node/process.d.ts +2084 -0
  134. package/node_modules/@types/node/punycode.d.ts +117 -0
  135. package/node_modules/@types/node/querystring.d.ts +152 -0
  136. package/node_modules/@types/node/readline/promises.d.ts +161 -0
  137. package/node_modules/@types/node/readline.d.ts +594 -0
  138. package/node_modules/@types/node/repl.d.ts +428 -0
  139. package/node_modules/@types/node/sea.d.ts +162 -0
  140. package/node_modules/@types/node/sqlite.d.ts +722 -0
  141. package/node_modules/@types/node/stream/consumers.d.ts +38 -0
  142. package/node_modules/@types/node/stream/promises.d.ts +90 -0
  143. package/node_modules/@types/node/stream/web.d.ts +573 -0
  144. package/node_modules/@types/node/stream.d.ts +1694 -0
  145. package/node_modules/@types/node/string_decoder.d.ts +67 -0
  146. package/node_modules/@types/node/test.d.ts +2265 -0
  147. package/node_modules/@types/node/timers/promises.d.ts +108 -0
  148. package/node_modules/@types/node/timers.d.ts +287 -0
  149. package/node_modules/@types/node/tls.d.ts +1319 -0
  150. package/node_modules/@types/node/trace_events.d.ts +197 -0
  151. package/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +468 -0
  152. package/node_modules/@types/node/ts5.6/globals.typedarray.d.ts +34 -0
  153. package/node_modules/@types/node/ts5.6/index.d.ts +98 -0
  154. package/node_modules/@types/node/tty.d.ts +208 -0
  155. package/node_modules/@types/node/url.d.ts +984 -0
  156. package/node_modules/@types/node/util.d.ts +2606 -0
  157. package/node_modules/@types/node/v8.d.ts +920 -0
  158. package/node_modules/@types/node/vm.d.ts +1053 -0
  159. package/node_modules/@types/node/wasi.d.ts +181 -0
  160. package/node_modules/@types/node/web-globals/abortcontroller.d.ts +34 -0
  161. package/node_modules/@types/node/web-globals/domexception.d.ts +68 -0
  162. package/node_modules/@types/node/web-globals/events.d.ts +97 -0
  163. package/node_modules/@types/node/web-globals/fetch.d.ts +55 -0
  164. package/node_modules/@types/node/web-globals/navigator.d.ts +22 -0
  165. package/node_modules/@types/node/web-globals/storage.d.ts +24 -0
  166. package/node_modules/@types/node/web-globals/streams.d.ts +22 -0
  167. package/node_modules/@types/node/worker_threads.d.ts +819 -0
  168. package/node_modules/@types/node/zlib.d.ts +747 -0
  169. package/node_modules/@types/react/LICENSE +21 -0
  170. package/node_modules/@types/react/README.md +15 -0
  171. package/node_modules/@types/react/canary.d.ts +129 -0
  172. package/node_modules/@types/react/compiler-runtime.d.ts +4 -0
  173. package/node_modules/@types/react/experimental.d.ts +184 -0
  174. package/node_modules/@types/react/global.d.ts +166 -0
  175. package/node_modules/@types/react/index.d.ts +4378 -0
  176. package/node_modules/@types/react/jsx-dev-runtime.d.ts +33 -0
  177. package/node_modules/@types/react/jsx-runtime.d.ts +24 -0
  178. package/node_modules/@types/react/package.json +210 -0
  179. package/node_modules/@types/react/ts5.0/canary.d.ts +129 -0
  180. package/node_modules/@types/react/ts5.0/experimental.d.ts +184 -0
  181. package/node_modules/@types/react/ts5.0/global.d.ts +166 -0
  182. package/node_modules/@types/react/ts5.0/index.d.ts +4365 -0
  183. package/node_modules/@types/react/ts5.0/jsx-dev-runtime.d.ts +33 -0
  184. package/node_modules/@types/react/ts5.0/jsx-runtime.d.ts +24 -0
  185. package/node_modules/csstype/LICENSE +19 -0
  186. package/node_modules/csstype/README.md +291 -0
  187. package/node_modules/csstype/index.d.ts +22569 -0
  188. package/node_modules/csstype/index.js.flow +6863 -0
  189. package/node_modules/csstype/package.json +70 -0
  190. package/node_modules/entities/LICENSE +11 -0
  191. package/node_modules/entities/decode.d.ts +1 -0
  192. package/node_modules/entities/decode.js +3 -0
  193. package/node_modules/entities/dist/commonjs/decode-codepoint.d.ts +19 -0
  194. package/node_modules/entities/dist/commonjs/decode-codepoint.d.ts.map +1 -0
  195. package/node_modules/entities/dist/commonjs/decode-codepoint.js +77 -0
  196. package/node_modules/entities/dist/commonjs/decode-codepoint.js.map +1 -0
  197. package/node_modules/entities/dist/commonjs/decode.d.ts +209 -0
  198. package/node_modules/entities/dist/commonjs/decode.d.ts.map +1 -0
  199. package/node_modules/entities/dist/commonjs/decode.js +511 -0
  200. package/node_modules/entities/dist/commonjs/decode.js.map +1 -0
  201. package/node_modules/entities/dist/commonjs/encode.d.ts +22 -0
  202. package/node_modules/entities/dist/commonjs/encode.d.ts.map +1 -0
  203. package/node_modules/entities/dist/commonjs/encode.js +73 -0
  204. package/node_modules/entities/dist/commonjs/encode.js.map +1 -0
  205. package/node_modules/entities/dist/commonjs/escape.d.ts +43 -0
  206. package/node_modules/entities/dist/commonjs/escape.d.ts.map +1 -0
  207. package/node_modules/entities/dist/commonjs/escape.js +121 -0
  208. package/node_modules/entities/dist/commonjs/escape.js.map +1 -0
  209. package/node_modules/entities/dist/commonjs/generated/decode-data-html.d.ts +2 -0
  210. package/node_modules/entities/dist/commonjs/generated/decode-data-html.d.ts.map +1 -0
  211. package/node_modules/entities/dist/commonjs/generated/decode-data-html.js +10 -0
  212. package/node_modules/entities/dist/commonjs/generated/decode-data-html.js.map +1 -0
  213. package/node_modules/entities/dist/commonjs/generated/decode-data-xml.d.ts +2 -0
  214. package/node_modules/entities/dist/commonjs/generated/decode-data-xml.d.ts.map +1 -0
  215. package/node_modules/entities/dist/commonjs/generated/decode-data-xml.js +10 -0
  216. package/node_modules/entities/dist/commonjs/generated/decode-data-xml.js.map +1 -0
  217. package/node_modules/entities/dist/commonjs/generated/encode-html.d.ts +8 -0
  218. package/node_modules/entities/dist/commonjs/generated/encode-html.d.ts.map +1 -0
  219. package/node_modules/entities/dist/commonjs/generated/encode-html.js +13 -0
  220. package/node_modules/entities/dist/commonjs/generated/encode-html.js.map +1 -0
  221. package/node_modules/entities/dist/commonjs/index.d.ts +96 -0
  222. package/node_modules/entities/dist/commonjs/index.d.ts.map +1 -0
  223. package/node_modules/entities/dist/commonjs/index.js +131 -0
  224. package/node_modules/entities/dist/commonjs/index.js.map +1 -0
  225. package/node_modules/entities/dist/commonjs/package.json +3 -0
  226. package/node_modules/entities/dist/esm/decode-codepoint.d.ts +19 -0
  227. package/node_modules/entities/dist/esm/decode-codepoint.d.ts.map +1 -0
  228. package/node_modules/entities/dist/esm/decode-codepoint.js +72 -0
  229. package/node_modules/entities/dist/esm/decode-codepoint.js.map +1 -0
  230. package/node_modules/entities/dist/esm/decode.d.ts +209 -0
  231. package/node_modules/entities/dist/esm/decode.d.ts.map +1 -0
  232. package/node_modules/entities/dist/esm/decode.js +497 -0
  233. package/node_modules/entities/dist/esm/decode.js.map +1 -0
  234. package/node_modules/entities/dist/esm/encode.d.ts +22 -0
  235. package/node_modules/entities/dist/esm/encode.d.ts.map +1 -0
  236. package/node_modules/entities/dist/esm/encode.js +69 -0
  237. package/node_modules/entities/dist/esm/encode.js.map +1 -0
  238. package/node_modules/entities/dist/esm/escape.d.ts +43 -0
  239. package/node_modules/entities/dist/esm/escape.d.ts.map +1 -0
  240. package/node_modules/entities/dist/esm/escape.js +117 -0
  241. package/node_modules/entities/dist/esm/escape.js.map +1 -0
  242. package/node_modules/entities/dist/esm/generated/decode-data-html.d.ts +2 -0
  243. package/node_modules/entities/dist/esm/generated/decode-data-html.d.ts.map +1 -0
  244. package/node_modules/entities/dist/esm/generated/decode-data-html.js +7 -0
  245. package/node_modules/entities/dist/esm/generated/decode-data-html.js.map +1 -0
  246. package/node_modules/entities/dist/esm/generated/decode-data-xml.d.ts +2 -0
  247. package/node_modules/entities/dist/esm/generated/decode-data-xml.d.ts.map +1 -0
  248. package/node_modules/entities/dist/esm/generated/decode-data-xml.js +7 -0
  249. package/node_modules/entities/dist/esm/generated/decode-data-xml.js.map +1 -0
  250. package/node_modules/entities/dist/esm/generated/encode-html.d.ts +8 -0
  251. package/node_modules/entities/dist/esm/generated/encode-html.d.ts.map +1 -0
  252. package/node_modules/entities/dist/esm/generated/encode-html.js +10 -0
  253. package/node_modules/entities/dist/esm/generated/encode-html.js.map +1 -0
  254. package/node_modules/entities/dist/esm/index.d.ts +96 -0
  255. package/node_modules/entities/dist/esm/index.d.ts.map +1 -0
  256. package/node_modules/entities/dist/esm/index.js +107 -0
  257. package/node_modules/entities/dist/esm/index.js.map +1 -0
  258. package/node_modules/entities/dist/esm/package.json +3 -0
  259. package/node_modules/entities/escape.d.ts +1 -0
  260. package/node_modules/entities/escape.js +3 -0
  261. package/node_modules/entities/package.json +118 -0
  262. package/node_modules/entities/readme.md +122 -0
  263. package/node_modules/entities/src/decode-codepoint.ts +81 -0
  264. package/node_modules/entities/src/decode.spec.ts +320 -0
  265. package/node_modules/entities/src/decode.ts +620 -0
  266. package/node_modules/entities/src/encode.spec.ts +78 -0
  267. package/node_modules/entities/src/encode.ts +77 -0
  268. package/node_modules/entities/src/escape.spec.ts +14 -0
  269. package/node_modules/entities/src/escape.ts +148 -0
  270. package/node_modules/entities/src/generated/.eslintrc.json +10 -0
  271. package/node_modules/entities/src/generated/decode-data-html.ts +8 -0
  272. package/node_modules/entities/src/generated/decode-data-xml.ts +8 -0
  273. package/node_modules/entities/src/generated/encode-html.ts +17 -0
  274. package/node_modules/entities/src/index.spec.ts +125 -0
  275. package/node_modules/entities/src/index.ts +188 -0
  276. package/node_modules/parse5/LICENSE +19 -0
  277. package/node_modules/parse5/README.md +38 -0
  278. package/node_modules/parse5/dist/cjs/common/doctype.d.ts +4 -0
  279. package/node_modules/parse5/dist/cjs/common/doctype.js +118 -0
  280. package/node_modules/parse5/dist/cjs/common/error-codes.d.ts +67 -0
  281. package/node_modules/parse5/dist/cjs/common/error-codes.js +66 -0
  282. package/node_modules/parse5/dist/cjs/common/foreign-content.d.ts +9 -0
  283. package/node_modules/parse5/dist/cjs/common/foreign-content.js +237 -0
  284. package/node_modules/parse5/dist/cjs/common/html.d.ts +289 -0
  285. package/node_modules/parse5/dist/cjs/common/html.js +528 -0
  286. package/node_modules/parse5/dist/cjs/common/token.d.ts +84 -0
  287. package/node_modules/parse5/dist/cjs/common/token.js +24 -0
  288. package/node_modules/parse5/dist/cjs/common/unicode.d.ts +42 -0
  289. package/node_modules/parse5/dist/cjs/common/unicode.js +70 -0
  290. package/node_modules/parse5/dist/cjs/index.d.ts +71 -0
  291. package/node_modules/parse5/dist/cjs/index.js +54 -0
  292. package/node_modules/parse5/dist/cjs/package.json +1 -0
  293. package/node_modules/parse5/dist/cjs/parser/formatting-element-list.d.ts +36 -0
  294. package/node_modules/parse5/dist/cjs/parser/formatting-element-list.js +114 -0
  295. package/node_modules/parse5/dist/cjs/parser/index.d.ts +221 -0
  296. package/node_modules/parse5/dist/cjs/parser/index.js +3240 -0
  297. package/node_modules/parse5/dist/cjs/parser/open-element-stack.d.ts +53 -0
  298. package/node_modules/parse5/dist/cjs/parser/open-element-stack.js +328 -0
  299. package/node_modules/parse5/dist/cjs/serializer/index.d.ts +60 -0
  300. package/node_modules/parse5/dist/cjs/serializer/index.js +172 -0
  301. package/node_modules/parse5/dist/cjs/tokenizer/index.d.ts +247 -0
  302. package/node_modules/parse5/dist/cjs/tokenizer/index.js +2714 -0
  303. package/node_modules/parse5/dist/cjs/tokenizer/preprocessor.d.ts +36 -0
  304. package/node_modules/parse5/dist/cjs/tokenizer/preprocessor.js +200 -0
  305. package/node_modules/parse5/dist/cjs/tree-adapters/default.d.ts +84 -0
  306. package/node_modules/parse5/dist/cjs/tree-adapters/default.js +176 -0
  307. package/node_modules/parse5/dist/cjs/tree-adapters/interface.d.ts +255 -0
  308. package/node_modules/parse5/dist/cjs/tree-adapters/interface.js +2 -0
  309. package/node_modules/parse5/dist/common/doctype.d.ts +4 -0
  310. package/node_modules/parse5/dist/common/doctype.js +114 -0
  311. package/node_modules/parse5/dist/common/error-codes.d.ts +67 -0
  312. package/node_modules/parse5/dist/common/error-codes.js +63 -0
  313. package/node_modules/parse5/dist/common/foreign-content.d.ts +9 -0
  314. package/node_modules/parse5/dist/common/foreign-content.js +228 -0
  315. package/node_modules/parse5/dist/common/html.d.ts +289 -0
  316. package/node_modules/parse5/dist/common/html.js +523 -0
  317. package/node_modules/parse5/dist/common/token.d.ts +84 -0
  318. package/node_modules/parse5/dist/common/token.js +20 -0
  319. package/node_modules/parse5/dist/common/unicode.d.ts +42 -0
  320. package/node_modules/parse5/dist/common/unicode.js +62 -0
  321. package/node_modules/parse5/dist/index.d.ts +71 -0
  322. package/node_modules/parse5/dist/index.js +42 -0
  323. package/node_modules/parse5/dist/parser/formatting-element-list.d.ts +36 -0
  324. package/node_modules/parse5/dist/parser/formatting-element-list.js +110 -0
  325. package/node_modules/parse5/dist/parser/index.d.ts +221 -0
  326. package/node_modules/parse5/dist/parser/index.js +3245 -0
  327. package/node_modules/parse5/dist/parser/open-element-stack.d.ts +53 -0
  328. package/node_modules/parse5/dist/parser/open-element-stack.js +324 -0
  329. package/node_modules/parse5/dist/serializer/index.d.ts +60 -0
  330. package/node_modules/parse5/dist/serializer/index.js +168 -0
  331. package/node_modules/parse5/dist/tokenizer/index.d.ts +247 -0
  332. package/node_modules/parse5/dist/tokenizer/index.js +2710 -0
  333. package/node_modules/parse5/dist/tokenizer/preprocessor.d.ts +36 -0
  334. package/node_modules/parse5/dist/tokenizer/preprocessor.js +196 -0
  335. package/node_modules/parse5/dist/tree-adapters/default.d.ts +84 -0
  336. package/node_modules/parse5/dist/tree-adapters/default.js +173 -0
  337. package/node_modules/parse5/dist/tree-adapters/interface.d.ts +255 -0
  338. package/node_modules/parse5/dist/tree-adapters/interface.js +1 -0
  339. package/node_modules/parse5/package.json +50 -0
  340. package/node_modules/undici-types/LICENSE +21 -0
  341. package/node_modules/undici-types/README.md +6 -0
  342. package/node_modules/undici-types/agent.d.ts +31 -0
  343. package/node_modules/undici-types/api.d.ts +43 -0
  344. package/node_modules/undici-types/balanced-pool.d.ts +29 -0
  345. package/node_modules/undici-types/cache.d.ts +36 -0
  346. package/node_modules/undici-types/client.d.ts +108 -0
  347. package/node_modules/undici-types/connector.d.ts +34 -0
  348. package/node_modules/undici-types/content-type.d.ts +21 -0
  349. package/node_modules/undici-types/cookies.d.ts +28 -0
  350. package/node_modules/undici-types/diagnostics-channel.d.ts +66 -0
  351. package/node_modules/undici-types/dispatcher.d.ts +256 -0
  352. package/node_modules/undici-types/env-http-proxy-agent.d.ts +21 -0
  353. package/node_modules/undici-types/errors.d.ts +149 -0
  354. package/node_modules/undici-types/eventsource.d.ts +61 -0
  355. package/node_modules/undici-types/fetch.d.ts +209 -0
  356. package/node_modules/undici-types/file.d.ts +39 -0
  357. package/node_modules/undici-types/filereader.d.ts +54 -0
  358. package/node_modules/undici-types/formdata.d.ts +108 -0
  359. package/node_modules/undici-types/global-dispatcher.d.ts +9 -0
  360. package/node_modules/undici-types/global-origin.d.ts +7 -0
  361. package/node_modules/undici-types/handlers.d.ts +15 -0
  362. package/node_modules/undici-types/header.d.ts +4 -0
  363. package/node_modules/undici-types/index.d.ts +71 -0
  364. package/node_modules/undici-types/interceptors.d.ts +17 -0
  365. package/node_modules/undici-types/mock-agent.d.ts +50 -0
  366. package/node_modules/undici-types/mock-client.d.ts +25 -0
  367. package/node_modules/undici-types/mock-errors.d.ts +12 -0
  368. package/node_modules/undici-types/mock-interceptor.d.ts +93 -0
  369. package/node_modules/undici-types/mock-pool.d.ts +25 -0
  370. package/node_modules/undici-types/package.json +55 -0
  371. package/node_modules/undici-types/patch.d.ts +33 -0
  372. package/node_modules/undici-types/pool-stats.d.ts +19 -0
  373. package/node_modules/undici-types/pool.d.ts +39 -0
  374. package/node_modules/undici-types/proxy-agent.d.ts +28 -0
  375. package/node_modules/undici-types/readable.d.ts +65 -0
  376. package/node_modules/undici-types/retry-agent.d.ts +8 -0
  377. package/node_modules/undici-types/retry-handler.d.ts +116 -0
  378. package/node_modules/undici-types/util.d.ts +18 -0
  379. package/node_modules/undici-types/webidl.d.ts +228 -0
  380. package/node_modules/undici-types/websocket.d.ts +150 -0
  381. package/package.json +72 -0
  382. package/scripts/rebuild-forme.mjs +61 -0
  383. package/src/assets/adapter.ts +122 -0
  384. package/src/assets/files.ts +378 -0
  385. package/src/assets/import-worker.ts +294 -0
  386. package/src/assets/imports.ts +124 -0
  387. package/src/assets/index.ts +60 -0
  388. package/src/assets/store.ts +798 -0
  389. package/src/assets/usage.ts +118 -0
  390. package/src/cli/check.ts +25 -0
  391. package/src/cli/init.ts +119 -0
  392. package/src/cli/lock.ts +34 -0
  393. package/src/cli/main.ts +118 -0
  394. package/src/cli/process.ts +19 -0
  395. package/src/cli/start.ts +96 -0
  396. package/src/cli/update.ts +348 -0
  397. package/src/cli/workspace.ts +94 -0
  398. package/src/document/index.tsx +641 -0
  399. package/src/document/page.tsx +53 -0
  400. package/src/document/text-targets.tsx +162 -0
  401. package/src/media/files.ts +124 -0
  402. package/src/media/render.ts +63 -0
  403. package/src/rendering/resolve-sources.ts +84 -0
  404. package/src/runtime/jsx-dev-runtime.ts +2 -0
  405. package/src/runtime/jsx-runtime.ts +2 -0
  406. package/src/runtime/paths.ts +12 -0
  407. package/src/server/assets-cli.ts +162 -0
  408. package/src/server/assets-http.ts +100 -0
  409. package/src/server/client.ts +50 -0
  410. package/src/server/clipboard.ts +22 -0
  411. package/src/server/comments-cli.ts +64 -0
  412. package/src/server/comments.ts +130 -0
  413. package/src/server/create-cli.ts +33 -0
  414. package/src/server/create.ts +228 -0
  415. package/src/server/dependencies.ts +91 -0
  416. package/src/server/documents.ts +143 -0
  417. package/src/server/edits.ts +249 -0
  418. package/src/server/export-batch.ts +105 -0
  419. package/src/server/export-errors.ts +2 -0
  420. package/src/server/export-file.ts +57 -0
  421. package/src/server/export-inputs.ts +66 -0
  422. package/src/server/export-preview.ts +69 -0
  423. package/src/server/export.ts +32 -0
  424. package/src/server/exports.ts +283 -0
  425. package/src/server/files.ts +21 -0
  426. package/src/server/guides.ts +71 -0
  427. package/src/server/materials.ts +39 -0
  428. package/src/server/media-cli.ts +73 -0
  429. package/src/server/media-mutations.ts +168 -0
  430. package/src/server/pptx.ts +160 -0
  431. package/src/server/preflight.ts +129 -0
  432. package/src/server/projects-cli.ts +29 -0
  433. package/src/server/projects.ts +187 -0
  434. package/src/server/render-error.ts +9 -0
  435. package/src/server/render-source.ts +24 -0
  436. package/src/server/render.ts +48 -0
  437. package/src/server/review-cli.ts +40 -0
  438. package/src/server/review.ts +161 -0
  439. package/src/server/selection.ts +23 -0
  440. package/src/server/source-overrides.ts +97 -0
  441. package/src/server/templates-cli.ts +51 -0
  442. package/src/server/templates.ts +186 -0
  443. package/src/server/text-layout.ts +41 -0
  444. package/src/server/text-source.ts +307 -0
  445. package/src/server/themes-cli.ts +59 -0
  446. package/src/server/themes.ts +215 -0
  447. package/src/server/ttf2eot.d.ts +3 -0
  448. package/src/server/worker.ts +166 -0
  449. package/src/server/workspace.ts +242 -0
  450. package/src/shared/anchors.ts +69 -0
  451. package/src/shared/assets.ts +154 -0
  452. package/src/shared/export.ts +34 -0
  453. package/src/shared/media.ts +33 -0
  454. package/src/shared/projects.ts +19 -0
  455. package/src/shared/selection.ts +94 -0
  456. package/src/shared/skill-index.ts +14 -0
  457. package/src/shared/starters.ts +19 -0
  458. package/src/shared/templates.ts +18 -0
  459. package/src/shared/themes.ts +24 -0
  460. package/src/shared/types.ts +39 -0
  461. package/src/template/index.ts +27 -0
  462. package/src/themes/index.ts +3 -0
  463. package/src/themes/neutral.ts +20 -0
  464. package/src/themes/types.ts +110 -0
  465. package/starter/assets/brand/wordmark.png +0 -0
  466. package/starter/assets/fonts/InterUI-LICENSE.txt +93 -0
  467. package/starter/assets/fonts/InterUI-Medium.ttf +0 -0
  468. package/starter/assets/fonts/InterUI-Regular.ttf +0 -0
  469. package/starter/assets/fonts/InterUI-source.json +19 -0
  470. package/starter/assets/fonts/OpenDocMono-Regular.ttf +0 -0
  471. package/starter/assets/fonts/OpenDocSans-Italic.ttf +0 -0
  472. package/starter/assets/fonts/OpenDocSans-Regular.ttf +0 -0
  473. package/starter/assets/fonts/OpenDocSans-Semibold.ttf +0 -0
  474. package/starter/assets/fonts/OpenDocSans-SemiboldItalic.ttf +0 -0
  475. package/starter/assets/fonts/OpenDocSerif-Italic.ttf +0 -0
  476. package/starter/assets/fonts/OpenDocSerif-Regular.ttf +0 -0
  477. package/starter/assets/fonts/OpenDocSerif-Semibold.ttf +0 -0
  478. package/starter/assets/fonts/OpenDocSerif-SemiboldItalic.ttf +0 -0
  479. package/starter/assets/fonts/SourceCode-LICENSE.md +93 -0
  480. package/starter/assets/fonts/SourceSans-LICENSE.md +93 -0
  481. package/starter/assets/fonts/SourceSerif-LICENSE.md +93 -0
  482. package/starter/assets/fonts/geist/OFL.txt +93 -0
  483. package/starter/assets/fonts/geist/asset.json +7 -0
  484. package/starter/assets/fonts/geist/files/1a9874b3be0fc168692a3d2327bccb4d28835653d3b91537a755296a467a83e3.ttf +0 -0
  485. package/starter/assets/fonts/geist/files/a8eefb873ba9c9020665f8a98302697ce1f3b79ab2deef6ee508c0ca6a82e876.ttf +0 -0
  486. package/starter/assets/fonts/geist/files/ccce59465ae5c61930ada5453834f60500fbd95084d85db63e0e65fad0125455.ttf +0 -0
  487. package/starter/assets/fonts/geist/files/f5e95110d70593672515080bee9148463ada0a7f77b89ed65a3d43cb2b0ff83a.pdf +0 -0
  488. package/starter/assets/fonts/geist/revisions/9a2bc12fb2f23cb27bc227087e63e1407bb804ee0586480bd6b7966ec69fb474.json +60 -0
  489. package/starter/assets/fonts/inter/OFL.txt +93 -0
  490. package/starter/assets/fonts/inter/asset.json +7 -0
  491. package/starter/assets/fonts/inter/files/1b08e7fc267a5c7e1d614100f604b83e7e8a0be241f0f288faa2b3ac93a683ba.ttf +0 -0
  492. package/starter/assets/fonts/inter/files/5b6f0c6f26e5c554a64cdcc3a9b5d802b7f9aec6206f1dbcfcdcad7b5860a2a9.ttf +0 -0
  493. package/starter/assets/fonts/inter/files/957db8560d510a198a7d0333fae7b6b444b00c20801581126273978d778eb3c3.pdf +0 -0
  494. package/starter/assets/fonts/inter/files/b37284b5701b6b168dfc770aa1a4ac492106422fd3ba76bc7641e37434e8019c.ttf +0 -0
  495. package/starter/assets/fonts/inter/files/c1811d32ac0f6eed1bbf57529f2ecdfc6c717d48a969dd864942436315a1b198.ttf +0 -0
  496. package/starter/assets/fonts/inter/files/e7a1aaf7eda9f2fad4131725fa556265ec75ca7b2d756260173a040363e8d4f7.ttf +0 -0
  497. package/starter/assets/fonts/inter/files/ef8f755d933b9310804cc9152f1f18cb2ac460d6b05054ec913d889c9f11f79e.ttf +0 -0
  498. package/starter/assets/fonts/inter/revisions/600391517c413963b71e278a57c26c40366c81fa3939a6b9755f446206766d12.json +99 -0
  499. package/starter/assets/fonts/inter/source.json +57 -0
  500. package/starter/assets/fonts/lato/OFL.txt +93 -0
  501. package/starter/assets/fonts/lato/asset.json +7 -0
  502. package/starter/assets/fonts/lato/files/4a6b566dbb28adb473a8789ce5169306f42f0c8a070ac92bae93636f36348b0d.pdf +0 -0
  503. package/starter/assets/fonts/lato/files/5adeb6b334d8fb99ef053bc052b952773d544315e0e1d668a12c0ce8bd51375c.ttf +0 -0
  504. package/starter/assets/fonts/lato/files/62c1b7f0d2e74b45960154c3520efc337b553db0961bfdc950d5618334596cc8.ttf +0 -0
  505. package/starter/assets/fonts/lato/files/71b8b7decbe75a881ed267be539d402bd1e9420b799658aada4e0d1bd5af803c.ttf +0 -0
  506. package/starter/assets/fonts/lato/files/8a0aace75d33794eece4b28187bfc1df0bbd2888b5d8a56e01788c8d65d16be1.ttf +0 -0
  507. package/starter/assets/fonts/lato/files/d636e4683231f931eda222d588e944d082bfd3bdba02f928bee461c0f185b251.ttf +0 -0
  508. package/starter/assets/fonts/lato/files/e399c44efe1387100531d26c7e4800c5d12251b890d6654a3098c7c679cb1786.ttf +0 -0
  509. package/starter/assets/fonts/lato/revisions/49ccb93400a9d466fab7d9843b1ecf8916ec6d47a475dd79a597a22eb39616bc.json +99 -0
  510. package/starter/assets/fonts/lato/source.json +57 -0
  511. package/starter/assets/fonts/merriweather/OFL.txt +93 -0
  512. package/starter/assets/fonts/merriweather/asset.json +7 -0
  513. package/starter/assets/fonts/merriweather/files/1c54f91b910454251c4c2b7bd4e472e1abf265fba7ca3c0ef2eee2f41324099e.ttf +0 -0
  514. package/starter/assets/fonts/merriweather/files/8bde8da2bb7f0265e27ba0481f70bb48d0f98a976c145f2f239c648ddd6532e0.pdf +0 -0
  515. package/starter/assets/fonts/merriweather/files/90b7db4460fcd1a5ca49575c2668a793f3cd6447664d312a068d690e1c01e6bc.ttf +0 -0
  516. package/starter/assets/fonts/merriweather/files/afff81272b7653417bb6f8bef57add055b1f9fda36f27eba5f32b40752bd08da.ttf +0 -0
  517. package/starter/assets/fonts/merriweather/files/e029d3b71e5bae3877c73f4f2b15af28db16593d49b0aed2a328d37ff7075846.ttf +0 -0
  518. package/starter/assets/fonts/merriweather/files/e9864a6790bf712a04e20f3662b206a1535186ed3e877fd859dd5fb9682335df.ttf +0 -0
  519. package/starter/assets/fonts/merriweather/files/fa71baebdd20a7d0de2e5e445a5922530fe9e1d740efbe791f113b682d3cb093.ttf +0 -0
  520. package/starter/assets/fonts/merriweather/revisions/1888e390b3e4f38a3d7cd2dc1bb805aeb6ce13f986a97656f0265fd436bc91d2.json +99 -0
  521. package/starter/assets/fonts/merriweather/source.json +57 -0
  522. package/starter/assets/fonts/open-sans/OFL.txt +92 -0
  523. package/starter/assets/fonts/open-sans/asset.json +7 -0
  524. package/starter/assets/fonts/open-sans/files/1bc0594a83762b2c25d38915a34464b7fec6088298ca22d151757bf98d6700ec.ttf +0 -0
  525. package/starter/assets/fonts/open-sans/files/47ed1cfaa7ffca04a04ab850b2938fd52c09d1b44cfa3e2980878e166b0cbd87.ttf +0 -0
  526. package/starter/assets/fonts/open-sans/files/574939af301f07df8e21cfff279465c5981dd9d9cf62086f7515897df951c6f5.pdf +0 -0
  527. package/starter/assets/fonts/open-sans/files/6d3884d0d57c1b67e9c50c54eca7b69c535c114e76bd7a9cfda0258588185553.ttf +0 -0
  528. package/starter/assets/fonts/open-sans/files/733eb93b167e6d45de09aa768f6c0355647c2c26f5416dbc7407a08ed41e81c6.ttf +0 -0
  529. package/starter/assets/fonts/open-sans/files/75367e6da7d914eaed87883ba51b2a2b5816b5cdbb39f96ec5c81a5b032bfd5a.ttf +0 -0
  530. package/starter/assets/fonts/open-sans/files/ff4fdc11204e0edd14e9a0bb6c374b847a9093b0ec2c16702e03afca79ac4ef7.ttf +0 -0
  531. package/starter/assets/fonts/open-sans/revisions/bbbe3a4915b9bccbc883c0decb4097511c43b6bd09ae22a1516aff128c219bc5.json +99 -0
  532. package/starter/assets/fonts/open-sans/source.json +57 -0
  533. package/starter/assets/fonts/roboto/OFL.txt +93 -0
  534. package/starter/assets/fonts/roboto/asset.json +7 -0
  535. package/starter/assets/fonts/roboto/files/22d45d989248a624252b8382067ac56550212fa675dcdbaf12f03d297dd87a58.pdf +0 -0
  536. package/starter/assets/fonts/roboto/files/35757eaa996b3359022f47f164a67ee9eac04971af24c5b8fbd4b89e844ff190.ttf +0 -0
  537. package/starter/assets/fonts/roboto/files/4d3035883c531846bd1ce2dc89f36d932e72dc114f56062c7e3a9cdd74f3d3ea.ttf +0 -0
  538. package/starter/assets/fonts/roboto/files/be7639306a4fc4a02ce2ae2ff59eb1335e4db4a7379dd0a384ed7cc053817789.ttf +0 -0
  539. package/starter/assets/fonts/roboto/files/d2920cbb1b60a3fd11fbf22049286e43a6baf522d37fdf1e7c89562319bcfea5.ttf +0 -0
  540. package/starter/assets/fonts/roboto/files/dece7c71bbe61710787f0839c722c65e87355dd2eb4a823e6b5488121ff81e4b.ttf +0 -0
  541. package/starter/assets/fonts/roboto/files/f478ba88b0292e685e487901dfbb1401457d32d6ebee4030cdfd5698235bffa8.ttf +0 -0
  542. package/starter/assets/fonts/roboto/revisions/bda5e2d84c17313373dd2dbf3e64fe0dd450c7e1b59e6929e69557e122fe976e.json +99 -0
  543. package/starter/assets/fonts/roboto/source.json +57 -0
  544. package/starter/assets/logos/opendoc/asset.json +6 -0
  545. package/starter/assets/logos/opendoc/files/831d5ccd9eb6709cc8439ea257c03d81452e81a28a3d1eedbd6a3b7daff687b6.png +0 -0
  546. package/starter/assets/logos/opendoc/revisions/834dde8926ddb81de687254195a168bb13bfb77803307f1257de1f2228be63b2.json +33 -0
  547. package/starter/assets/ui-fonts/geist/OFL.txt +93 -0
  548. package/starter/assets/ui-fonts/geist/geist-latin-ext-wght-italic.woff2 +0 -0
  549. package/starter/assets/ui-fonts/geist/geist-latin-ext-wght-normal.woff2 +0 -0
  550. package/starter/assets/ui-fonts/geist/geist-latin-wght-italic.woff2 +0 -0
  551. package/starter/assets/ui-fonts/geist/geist-latin-wght-normal.woff2 +0 -0
  552. package/starter/assets/ui-fonts/geist/source.json +26 -0
  553. package/starter/documents/welcome/assets.json +7 -0
  554. package/starter/documents/welcome/index.tsx +160 -0
  555. package/starter/documents/welcome/media/.gitkeep +0 -0
  556. package/starter/documents/welcome/media/paper-architecture/image.png +0 -0
  557. package/starter/documents/welcome/media/paper-architecture/meta.json +9 -0
  558. package/starter/documents/welcome/media/paper-architecture/prompt.txt +1 -0
  559. package/starter/documents/welcome/media/studio-rhythm/chart.svg +2343 -0
  560. package/starter/documents/welcome/media/studio-rhythm/data.json +234 -0
  561. package/starter/documents/welcome/media/studio-rhythm/generation.json +9 -0
  562. package/starter/documents/welcome/media/studio-rhythm/image.png +0 -0
  563. package/starter/documents/welcome/media/studio-rhythm/meta.json +11 -0
  564. package/starter/documents/welcome/media/studio-rhythm/recipe.py +79 -0
  565. package/starter/documents/welcome/theme.tsx +5 -0
  566. package/starter/documents/welcome-presentation/assets.json +7 -0
  567. package/starter/documents/welcome-presentation/index.tsx +166 -0
  568. package/starter/documents/welcome-presentation/media/.gitkeep +0 -0
  569. package/starter/documents/welcome-presentation/media/paper-architecture/image.png +0 -0
  570. package/starter/documents/welcome-presentation/media/paper-architecture/meta.json +9 -0
  571. package/starter/documents/welcome-presentation/media/paper-architecture/prompt.txt +1 -0
  572. package/starter/documents/welcome-presentation/media/studio-rhythm/chart.svg +1336 -0
  573. package/starter/documents/welcome-presentation/media/studio-rhythm/data.json +234 -0
  574. package/starter/documents/welcome-presentation/media/studio-rhythm/generation.json +9 -0
  575. package/starter/documents/welcome-presentation/media/studio-rhythm/image.png +0 -0
  576. package/starter/documents/welcome-presentation/media/studio-rhythm/meta.json +13 -0
  577. package/starter/documents/welcome-presentation/media/studio-rhythm/recipe.py +49 -0
  578. package/starter/documents/welcome-presentation/theme.tsx +5 -0
  579. package/starter/projects.json +17 -0
  580. package/starter/templates/AGENTS.md +9 -0
  581. package/starter/templates/_shared/BusinessLogo.tsx +14 -0
  582. package/starter/templates/_shared/Pricing.tsx +40 -0
  583. package/starter/templates/_shared/commerce.ts +93 -0
  584. package/starter/templates/brand-guidelines/AGENTS.md +32 -0
  585. package/starter/templates/brand-guidelines/index.tsx +62 -0
  586. package/starter/templates/brand-guidelines/preview.tsx +181 -0
  587. package/starter/templates/brand-guidelines/starter.tsx +179 -0
  588. package/starter/templates/brand-guidelines/template.json +15 -0
  589. package/starter/templates/business-proposal/AGENTS.md +13 -0
  590. package/starter/templates/business-proposal/README.md +36 -0
  591. package/starter/templates/business-proposal/data.json +37 -0
  592. package/starter/templates/business-proposal/examples/long.json +142 -0
  593. package/starter/templates/business-proposal/examples/sparse.json +17 -0
  594. package/starter/templates/business-proposal/examples/typical.json +37 -0
  595. package/starter/templates/business-proposal/index.tsx +59 -0
  596. package/starter/templates/business-proposal/preview.tsx +47 -0
  597. package/starter/templates/business-proposal/schema.ts +14 -0
  598. package/starter/templates/business-proposal/starter.tsx +18 -0
  599. package/starter/templates/business-proposal/template.json +11 -0
  600. package/starter/templates/company-profile/AGENTS.md +48 -0
  601. package/starter/templates/company-profile/index.tsx +69 -0
  602. package/starter/templates/company-profile/preview.tsx +185 -0
  603. package/starter/templates/company-profile/starter.tsx +186 -0
  604. package/starter/templates/company-profile/template.json +15 -0
  605. package/starter/templates/consulting-report/AGENTS.md +11 -0
  606. package/starter/templates/consulting-report/README.md +13 -0
  607. package/starter/templates/consulting-report/RESEARCH.md +10 -0
  608. package/starter/templates/consulting-report/index.tsx +44 -0
  609. package/starter/templates/consulting-report/preview.tsx +39 -0
  610. package/starter/templates/consulting-report/starter.tsx +15 -0
  611. package/starter/templates/consulting-report/template.json +11 -0
  612. package/starter/templates/editorial-essay/AGENTS.md +11 -0
  613. package/starter/templates/editorial-essay/README.md +11 -0
  614. package/starter/templates/editorial-essay/index.tsx +30 -0
  615. package/starter/templates/editorial-essay/preview.tsx +26 -0
  616. package/starter/templates/editorial-essay/starter.tsx +15 -0
  617. package/starter/templates/editorial-essay/template.json +11 -0
  618. package/starter/templates/executive-brief/AGENTS.md +9 -0
  619. package/starter/templates/executive-brief/README.md +11 -0
  620. package/starter/templates/executive-brief/index.tsx +33 -0
  621. package/starter/templates/executive-brief/preview.tsx +37 -0
  622. package/starter/templates/executive-brief/starter.tsx +11 -0
  623. package/starter/templates/executive-brief/template.json +11 -0
  624. package/starter/templates/image-story/AGENTS.md +37 -0
  625. package/starter/templates/image-story/index.tsx +106 -0
  626. package/starter/templates/image-story/preview.tsx +33 -0
  627. package/starter/templates/image-story/starter.tsx +24 -0
  628. package/starter/templates/image-story/template.json +13 -0
  629. package/starter/templates/invoice/AGENTS.md +13 -0
  630. package/starter/templates/invoice/README.md +40 -0
  631. package/starter/templates/invoice/data.json +61 -0
  632. package/starter/templates/invoice/examples/long.json +241 -0
  633. package/starter/templates/invoice/examples/sparse.json +33 -0
  634. package/starter/templates/invoice/examples/typical.json +61 -0
  635. package/starter/templates/invoice/index.tsx +57 -0
  636. package/starter/templates/invoice/preview.tsx +12 -0
  637. package/starter/templates/invoice/schema.ts +45 -0
  638. package/starter/templates/invoice/starter.tsx +12 -0
  639. package/starter/templates/invoice/template.json +11 -0
  640. package/starter/templates/literary-text/AGENTS.md +9 -0
  641. package/starter/templates/literary-text/README.md +11 -0
  642. package/starter/templates/literary-text/index.tsx +31 -0
  643. package/starter/templates/literary-text/preview.tsx +20 -0
  644. package/starter/templates/literary-text/starter.tsx +11 -0
  645. package/starter/templates/literary-text/template.json +11 -0
  646. package/starter/templates/magazine-feature/AGENTS.md +11 -0
  647. package/starter/templates/magazine-feature/README.md +13 -0
  648. package/starter/templates/magazine-feature/index.tsx +41 -0
  649. package/starter/templates/magazine-feature/preview.tsx +34 -0
  650. package/starter/templates/magazine-feature/starter.tsx +15 -0
  651. package/starter/templates/magazine-feature/template.json +11 -0
  652. package/starter/templates/monthly-report/AGENTS.md +11 -0
  653. package/starter/templates/monthly-report/README.md +24 -0
  654. package/starter/templates/monthly-report/data.json +131 -0
  655. package/starter/templates/monthly-report/examples/long.json +519 -0
  656. package/starter/templates/monthly-report/examples/sparse.json +20 -0
  657. package/starter/templates/monthly-report/examples/typical.json +37 -0
  658. package/starter/templates/monthly-report/index.tsx +92 -0
  659. package/starter/templates/monthly-report/preview.tsx +14 -0
  660. package/starter/templates/monthly-report/schema.ts +127 -0
  661. package/starter/templates/monthly-report/starter.tsx +13 -0
  662. package/starter/templates/monthly-report/template.json +11 -0
  663. package/starter/templates/pitch-deck/AGENTS.md +32 -0
  664. package/starter/templates/pitch-deck/index.tsx +46 -0
  665. package/starter/templates/pitch-deck/preview.tsx +142 -0
  666. package/starter/templates/pitch-deck/starter.tsx +140 -0
  667. package/starter/templates/pitch-deck/template.json +15 -0
  668. package/starter/templates/proposal-deck/AGENTS.md +25 -0
  669. package/starter/templates/proposal-deck/index.tsx +52 -0
  670. package/starter/templates/proposal-deck/preview.tsx +172 -0
  671. package/starter/templates/proposal-deck/starter.tsx +168 -0
  672. package/starter/templates/proposal-deck/template.json +7 -0
  673. package/starter/templates/quotation/AGENTS.md +13 -0
  674. package/starter/templates/quotation/README.md +42 -0
  675. package/starter/templates/quotation/data.json +64 -0
  676. package/starter/templates/quotation/examples/long.json +272 -0
  677. package/starter/templates/quotation/examples/sparse.json +31 -0
  678. package/starter/templates/quotation/examples/typical.json +64 -0
  679. package/starter/templates/quotation/index.tsx +51 -0
  680. package/starter/templates/quotation/preview.tsx +12 -0
  681. package/starter/templates/quotation/schema.ts +27 -0
  682. package/starter/templates/quotation/starter.tsx +12 -0
  683. package/starter/templates/quotation/template.json +11 -0
  684. package/starter/templates/scientific-paper/AGENTS.md +11 -0
  685. package/starter/templates/scientific-paper/README.md +13 -0
  686. package/starter/templates/scientific-paper/index.tsx +47 -0
  687. package/starter/templates/scientific-paper/preview.tsx +43 -0
  688. package/starter/templates/scientific-paper/starter.tsx +15 -0
  689. package/starter/templates/scientific-paper/template.json +11 -0
  690. package/starter/themes/Specimen.tsx +54 -0
  691. package/starter/themes/civic-spectrum/components.tsx +92 -0
  692. package/starter/themes/civic-spectrum/design.md +70 -0
  693. package/starter/themes/civic-spectrum/index.ts +57 -0
  694. package/starter/themes/civic-spectrum/preview.tsx +66 -0
  695. package/starter/themes/field-manual/components.tsx +106 -0
  696. package/starter/themes/field-manual/design.md +72 -0
  697. package/starter/themes/field-manual/index.ts +57 -0
  698. package/starter/themes/field-manual/preview.tsx +82 -0
  699. package/starter/themes/index.ts +3 -0
  700. package/starter/themes/mckinsey-consulting/components.tsx +69 -0
  701. package/starter/themes/mckinsey-consulting/design.md +68 -0
  702. package/starter/themes/mckinsey-consulting/index.ts +60 -0
  703. package/starter/themes/mckinsey-consulting/preview.tsx +53 -0
  704. package/starter/themes/neutral/design.md +35 -0
  705. package/starter/themes/neutral/index.ts +21 -0
  706. package/starter/themes/neutral/preview.tsx +4 -0
  707. package/starter/themes/opendoc-neutral/components.tsx +77 -0
  708. package/starter/themes/opendoc-neutral/design.md +70 -0
  709. package/starter/themes/opendoc-neutral/index.ts +54 -0
  710. package/starter/themes/opendoc-neutral/preview.tsx +43 -0
  711. package/starter/themes/types.ts +3 -0
  712. package/tsconfig.workspace.json +24 -0
  713. package/vendor/formepdf/LICENSE +21 -0
  714. package/vendor/formepdf/README.md +97 -0
  715. package/vendor/formepdf/font-subset.patch +228 -0
  716. package/vendor/formepdf/text-writer.patch +507 -0
@@ -0,0 +1,215 @@
1
+ import { lstat, readdir, readFile, rm, stat } from 'node:fs/promises';
2
+ import { dirname, relative, resolve, sep } from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { build } from 'esbuild';
5
+ import { validateTheme, type DocTheme } from '../themes/index';
6
+ import type { ThemePreview, ThemeSummary } from '../shared/themes';
7
+ import { containedFile } from './files';
8
+ import { RenderFailure } from './render-error';
9
+ import { renderEntry, validId } from './render';
10
+ import { bindingDependencies, readAssetRevision, readThemeAssetDefaults, resolveThemeAssets } from '../assets/files';
11
+ import { documentDependencies, includesDependency, type DocumentDependencies, isRenderRuntimePath, isManagedAssetPath } from './dependencies';
12
+ import { authoringResolutionPlugin } from './source-overrides';
13
+
14
+ export async function themeFile(root: string, id: string, name: 'index.ts' | 'design.md' | 'preview.tsx' | 'components.tsx') {
15
+ if (typeof id !== 'string' || !validId(id)) throw new Error('Invalid theme ID.');
16
+ const folder = await containedFile(resolve(root, 'themes'), resolve(root, 'themes', id));
17
+ const file = await containedFile(folder, resolve(folder, name));
18
+ const info = await stat(file);
19
+ if (!info.isFile() || info.size > (name === 'design.md' ? 64_000 : 256_000)) throw new Error(`Theme ${name} must be a regular, reasonably sized local file.`);
20
+ return file;
21
+ }
22
+
23
+ /** Bundle the current definition, including local imports. No long-lived Node module cache or restart needed. */
24
+ export async function readTheme(root: string, id: string): Promise<DocTheme> {
25
+ const [entry] = await Promise.all(['index.ts', 'design.md', 'preview.tsx'].map(name => themeFile(root, id, name as 'index.ts' | 'design.md' | 'preview.tsx')));
26
+ await readThemePaths(root, id);
27
+ const result = await build({ absWorkingDir: root, entryPoints: [entry], bundle: true, write: false, format: 'esm', platform: 'node', logLevel: 'silent', plugins: [authoringResolutionPlugin()] });
28
+ await readThemeGuide(root, id);
29
+ const module = await import(`data:text/javascript;base64,${Buffer.from(result.outputFiles[0].contents).toString('base64')}`);
30
+ const theme = module.theme as DocTheme;
31
+ validateTheme(theme);
32
+ if (theme.id !== id) throw new Error(`Theme ID ${JSON.stringify(theme.id)} must match its folder ${JSON.stringify(id)}.`);
33
+ return theme;
34
+ }
35
+
36
+ export async function readThemeGuide(root: string, id: string) {
37
+ const markdown = await readFile(await themeFile(root, id, 'design.md'), 'utf8');
38
+ if (!markdown.trim()) throw new Error('This theme needs a design guide.');
39
+ return markdown;
40
+ }
41
+
42
+ export function themePaths(id: string) {
43
+ return { definition: `themes/${id}/index.ts`, guide: `themes/${id}/design.md`, preview: `themes/${id}/preview.tsx` };
44
+ }
45
+
46
+ /** Components are optional native PDF code, discovered without executing them. */
47
+ export async function readThemePaths(root: string, id: string): Promise<ReturnType<typeof themePaths> & { components?: string }> {
48
+ const definition = await themeFile(root, id, 'index.ts');
49
+ const components = resolve(dirname(definition), 'components.tsx');
50
+ const exists = await lstat(components).catch(error => { if (error.code === 'ENOENT') return undefined; throw error; });
51
+ if (!exists) return themePaths(id);
52
+ await themeFile(root, id, 'components.tsx');
53
+ return { ...themePaths(id), components: `themes/${id}/components.tsx` };
54
+ }
55
+ function summarize(theme: DocTheme): ThemeSummary {
56
+ return { id: theme.id, name: theme.name, description: theme.description, body: theme.body, heading: theme.heading, pageSize: theme.pageSize, useFor: theme.useFor ?? [], principles: theme.principles ?? [], palette: theme.palette ?? [], geometry: theme.geometry ?? [] };
57
+ }
58
+ async function summarizeWithAssets(root: string, theme: DocTheme): Promise<ThemeSummary> {
59
+ const summary = summarize(theme);
60
+ try {
61
+ summary.assetDefaults = await readThemeAssetDefaults(root, theme.id);
62
+ const bindings = await resolveThemeAssets(root, theme.id);
63
+ summary.baseBody = theme.body; summary.baseHeading = theme.heading;
64
+ if (bindings.bodyFont) summary.body = (await readAssetRevision(root, 'font', bindings.bodyFont.id, bindings.bodyFont.revision)).name;
65
+ if (bindings.headingFont) summary.heading = (await readAssetRevision(root, 'font', bindings.headingFont.id, bindings.headingFont.revision)).name;
66
+ } catch (error) { summary.assetError = error instanceof Error ? error.message : String(error); }
67
+ return summary;
68
+ }
69
+
70
+ type RenderedPreview = ThemePreview & { directory?: string };
71
+ /** Small discovery records; PDF work starts only when a specimen is requested, with at most two workers. */
72
+ export class ThemeCatalog {
73
+ private version = 0;
74
+ private globalVersion = 0;
75
+ private themeVersions = new Map<string, number>();
76
+ private session = randomUUID();
77
+ private summaries?: { version: number; result: Promise<ThemeSummary[]> };
78
+ private previews = new Map<string, { version: string; result: Promise<RenderedPreview> }>();
79
+ private dependencies = new Map<string, DocumentDependencies>();
80
+ private definitions = new Map<string, DocumentDependencies>();
81
+ private active = 0;
82
+ private waiting: (() => void)[] = [];
83
+ private closed = false;
84
+ constructor(private root: string) {}
85
+ invalidate(id?: string) {
86
+ this.version++;
87
+ if (id) { this.dependencies.delete(id); this.definitions.delete(id); }
88
+ else { this.dependencies.clear(); this.definitions.clear(); }
89
+ if (id) this.themeVersions.set(id, (this.themeVersions.get(id) ?? 0) + 1);
90
+ else this.globalVersion++;
91
+ }
92
+ private revision(id: string) { return `${this.session}:${this.globalVersion}:${this.themeVersions.get(id) ?? 0}`; }
93
+ /** Catalog publications affect only specimens whose current defaults depend on those bytes. */
94
+ async noteChange(file: string): Promise<string[]> {
95
+ const path = resolve(this.root, file);
96
+ const parts = relative(this.root, path).split(sep);
97
+ if (parts[0] === 'themes') this.version++;
98
+ if (!isManagedAssetPath(this.root, path)) {
99
+ const entries = await readdir(resolve(this.root, 'themes'), { withFileTypes: true }).catch(() => []);
100
+ const ids = new Set([...entries.filter(entry => entry.isDirectory() && validId(entry.name)).map(entry => entry.name), ...this.previews.keys()]);
101
+ const affected: string[] = [];
102
+ for (const id of ids) {
103
+ const graphs = [this.definitions.get(id), this.dependencies.get(id)].filter(Boolean) as DocumentDependencies[];
104
+ if (isRenderRuntimePath(this.root, path) || (parts[0] === 'themes' && (!parts[1] || parts[1] === id)) || !graphs.length || (this.previews.has(id) && !this.dependencies.has(id))
105
+ || graphs.some(graph => graph.readsFiles || includesDependency(graph, path))) { this.invalidate(id); affected.push(id); }
106
+ }
107
+ return affected;
108
+ }
109
+ const entries = await readdir(resolve(this.root, 'themes'), { withFileTypes: true }).catch(() => []);
110
+ const affected: string[] = [];
111
+ for (const entry of entries) {
112
+ if (!entry.isDirectory() || !validId(entry.name)) continue;
113
+ const graphs = [this.definitions.get(entry.name), this.dependencies.get(entry.name)].filter(Boolean) as DocumentDependencies[];
114
+ if (graphs.some(graph => graph.readsFiles || includesDependency(graph, path)) || (this.previews.has(entry.name) && !this.dependencies.has(entry.name))) {
115
+ affected.push(entry.name); this.invalidate(entry.name); continue;
116
+ }
117
+ try {
118
+ const defaults = await readThemeAssetDefaults(this.root, entry.name);
119
+ const references = [defaults.logo && ['logos', defaults.logo.id], defaults.bodyFont && ['fonts', defaults.bodyFont], defaults.headingFont && ['fonts', defaults.headingFont]].filter(Boolean) as string[][];
120
+ if (!references.some(([kind, id]) => parts[1] === kind && (!parts[2] || parts[2] === id))) continue;
121
+ let relevant = parts.length <= 3 || parts[3] === 'asset.json';
122
+ try {
123
+ const bindings = await resolveThemeAssets(this.root, entry.name);
124
+ const files = (await bindingDependencies(this.root, bindings)).map(file => resolve(this.root, file));
125
+ relevant ||= files.some(file => file === path || file.startsWith(path + sep));
126
+ } catch { relevant = true; }
127
+ if (relevant) { affected.push(entry.name); this.invalidate(entry.name); }
128
+ } catch { /* Invalid neighboring defaults do not prevent other catalogs refreshing. */ }
129
+ }
130
+ return affected;
131
+ }
132
+ async list(): Promise<ThemeSummary[]> {
133
+ if (!this.summaries || this.summaries.version !== this.version) {
134
+ const version = this.version;
135
+ const result = (async () => {
136
+ const entries = await readdir(resolve(this.root, 'themes'), { withFileTypes: true }).catch(error => { if (error.code === 'ENOENT') return []; throw error; });
137
+ const items: ThemeSummary[] = [];
138
+ for (const folder of entries.sort((a, b) => a.name.localeCompare(b.name))) {
139
+ if (!folder.isDirectory() || !validId(folder.name)) continue;
140
+ try {
141
+ const entry = await themeFile(this.root, folder.name, 'index.ts');
142
+ const dependencies = await documentDependencies(this.root, entry).catch(() => undefined);
143
+ items.push(await summarizeWithAssets(this.root, await readTheme(this.root, folder.name)));
144
+ if (dependencies && version === this.version) this.definitions.set(folder.name, dependencies);
145
+ }
146
+ catch (error) { items.push({ id: folder.name, name: folder.name, description: 'This theme needs attention.', body: '', heading: '', pageSize: '', useFor: [], principles: [], error: error instanceof Error ? error.message : String(error) }); }
147
+ }
148
+ return items.map(item => ({ ...item, revision: this.revision(item.id) }));
149
+ })();
150
+ this.summaries = { version, result };
151
+ }
152
+ const snapshot = this.summaries;
153
+ const items = await snapshot.result;
154
+ return snapshot.version === this.version ? items : this.list();
155
+ }
156
+ private async render(id: string, version: string): Promise<RenderedPreview> {
157
+ if (this.active >= 2) await new Promise<void>(accept => this.waiting.push(accept));
158
+ else this.active++;
159
+ let directory: string | undefined;
160
+ try {
161
+ if (this.closed) throw new Error('The theme catalog is closed.');
162
+ await readTheme(this.root, id);
163
+ await readThemeGuide(this.root, id);
164
+ const entry = await themeFile(this.root, id, 'preview.tsx');
165
+ const dependencies = await documentDependencies(this.root, entry).catch(() => undefined);
166
+ const rendered = await renderEntry(this.root, entry, `theme-${id}`);
167
+ directory = rendered.directory;
168
+ if (rendered.artifact.meta.theme !== id) throw new Error('The specimen must use its own theme ID.');
169
+ if (dependencies && version === this.revision(id)) {
170
+ for (const file of rendered.artifact.assetDependencies ?? []) dependencies.files.add(resolve(this.root, file));
171
+ this.dependencies.set(id, dependencies);
172
+ }
173
+ return rendered;
174
+ } catch (error) {
175
+ if (directory) await rm(directory, { recursive: true, force: true });
176
+ return { error: error instanceof Error ? error.message : String(error), ...(error instanceof RenderFailure ? { issues: error.issues } : {}) };
177
+ } finally { const next = this.waiting.shift(); if (next) next(); else this.active--; }
178
+ }
179
+ private async current(id: string): Promise<RenderedPreview> {
180
+ if (typeof id !== 'string' || !validId(id)) throw new Error('Invalid theme ID.');
181
+ if (this.closed) throw new Error('The theme catalog is closed.');
182
+ let snapshot = this.previews.get(id);
183
+ if (!snapshot || snapshot.version !== this.revision(id)) {
184
+ const previous = snapshot;
185
+ const version = this.revision(id);
186
+ const result = (async () => {
187
+ const old = await previous?.result;
188
+ const next = await this.render(id, version);
189
+ if (old?.directory) await rm(old.directory, { recursive: true, force: true });
190
+ return next;
191
+ })();
192
+ snapshot = { version, result }; this.previews.set(id, snapshot);
193
+ }
194
+ const result = await snapshot.result;
195
+ if (snapshot.version !== this.revision(id)) return this.current(id);
196
+ // A failed preview is retryable even before a file watcher observes a repair.
197
+ if (result.error && this.previews.get(id) === snapshot) this.previews.delete(id);
198
+ return result;
199
+ }
200
+ async preview(id: string): Promise<ThemePreview> {
201
+ const { directory: _directory, ...preview } = await this.current(id);
202
+ return preview;
203
+ }
204
+ async pdf(id: string, hash: string) {
205
+ const item = await this.current(id);
206
+ if (!item.directory || item.artifact?.hash !== hash) throw new Error('This theme preview changed. Reload the theme.');
207
+ return readFile(resolve(item.directory, 'document.pdf'));
208
+ }
209
+ async close() {
210
+ this.closed = true;
211
+ const entries = await Promise.all([...this.previews.values()].map(item => item.result));
212
+ await Promise.all(entries.map(item => item.directory && rm(item.directory, { recursive: true, force: true })));
213
+ this.previews.clear();
214
+ }
215
+ }
@@ -0,0 +1,3 @@
1
+ declare module 'ttf2eot' {
2
+ export default function ttf2eot(font: Uint8Array): Uint8Array;
3
+ }
@@ -0,0 +1,166 @@
1
+ import { mkdir, writeFile } from 'node:fs/promises';
2
+ import { resolve, dirname, relative, sep } from 'node:path';
3
+ import { readFileSync, realpathSync } from 'node:fs';
4
+ import { createTextSourceResolver, createJsonTextSourceResolver, type TextSourceResolver } from './text-source';
5
+ import { attachTextLines } from './text-layout';
6
+ import type { TextGlobals } from '../document/text-targets';
7
+ import type { TextTarget } from '../shared/selection';
8
+ import { createHash } from 'node:crypto';
9
+ import { renderDocumentSource } from './render-source';
10
+ import type { MediaUse } from '../shared/media';
11
+ import type { AssetUse, DocumentAssets } from '../shared/assets';
12
+ import { readDocumentAssetsAt, resolveThemeAssets } from '../assets/files';
13
+ import type { LayoutInfo, ElementInfo } from '@formepdf/core';
14
+ import type { BlockInfo, DocumentMeta, DocumentProvenance, RenderArtifact, Fragment, DocumentFormat, SlideInfo } from '../shared/types';
15
+ import { RenderFailure } from './render-error';
16
+ import { inspectLayout, assertLayoutSafe, assertSlideLayout } from './preflight';
17
+ import { containedFile } from './files';
18
+ import { readProjects } from './projects';
19
+ import { originalBinding, type SourceOverride } from './source-overrides';
20
+ import { runtimeSource } from '../runtime/paths';
21
+
22
+ const [inputEntry, destination, overrideFlag] = process.argv.slice(2);
23
+ const entry = realpathSync(inputEntry);
24
+ const root = process.cwd();
25
+ const sourceOverrides = overrideFlag ? await new Promise<SourceOverride[]>(accept => process.once('message', (message: { sourceOverrides: SourceOverride[] }) => accept(message.sourceOverrides))) : [];
26
+ const overrides = new Map(sourceOverrides.map(override => [override.file, override]));
27
+ const globalState = globalThis as TextGlobals & { __opendocTemplateValidated?: boolean; __opendocDataFile?: string; __opendocRoot?: string; __opendocDocumentDirectory?: string; __opendocDocumentAssets?: DocumentAssets; __opendocCapture?: { format: DocumentFormat; slides: SlideInfo[]; themeId: string; meta: DocumentMeta; blocks: Record<string, BlockInfo>; provenance?: Partial<DocumentProvenance>; media?: MediaUse[]; assets?: AssetUse[]; assetBindings?: DocumentAssets; assetDependencies?: string[]; textTargets?: TextTarget[] } };
28
+ globalState.__opendocRoot = root;
29
+ globalState.__opendocDocumentDirectory = dirname(entry);
30
+ const documentDirectory = realpathSync(dirname(entry));
31
+ const resolvers = new Map<string, TextSourceResolver>();
32
+ const fieldResolvers = new Map<string, ReturnType<typeof createJsonTextSourceResolver>>();
33
+ function documentFile(file: string) {
34
+ try {
35
+ const absolute = realpathSync(resolve(root, file));
36
+ return absolute.startsWith(documentDirectory + sep) ? absolute : undefined;
37
+ } catch { return undefined; }
38
+ }
39
+ globalState.__opendocResolveTextSource = (location, slot, childIndex) => {
40
+ const absolute = documentFile(location.file);
41
+ if (!absolute || !/\.[cm]?[jt]sx?$/.test(absolute)) return undefined;
42
+ let resolver = resolvers.get(absolute);
43
+ if (!resolver) { resolver = createTextSourceResolver(relative(root, absolute), overrides.get(absolute)?.contents ?? readFileSync(absolute, 'utf8')); resolvers.set(absolute, resolver); }
44
+ return originalBinding(resolver.resolveAt(location.line, location.column, slot, childIndex), overrides.get(absolute));
45
+ };
46
+ globalState.__opendocResolveTextField = field => {
47
+ const absolute = globalState.__opendocDataFile && documentFile(globalState.__opendocDataFile);
48
+ if (!absolute || !absolute.endsWith('.json')) return undefined;
49
+ let resolver = fieldResolvers.get(absolute);
50
+ if (!resolver) { resolver = createJsonTextSourceResolver(relative(root, absolute), overrides.get(absolute)?.contents ?? readFileSync(absolute, 'utf8')); fieldResolvers.set(absolute, resolver); }
51
+ return originalBinding(resolver(field), overrides.get(absolute));
52
+ };
53
+
54
+ function pagesFromLayout(layout: LayoutInfo, blocks: Record<string, BlockInfo>) {
55
+ return layout.pages.map(page => {
56
+ const groups = new Map<string, Fragment>();
57
+ function visit(node: ElementInfo, inherited?: string) {
58
+ const file = node.sourceLocation?.file;
59
+ const id = file?.startsWith('opendoc:block:') ? file.slice('opendoc:block:'.length) : inherited;
60
+ if (id && blocks[id]) {
61
+ if (node.textContent) blocks[id].text += `${node.textContent} `;
62
+ if (node.width > 0 && node.height > 0) {
63
+ const prev = groups.get(id);
64
+ const x = node.x, y = node.y;
65
+ const right = node.x + node.width, bottom = node.y + node.height;
66
+ if (prev) {
67
+ const newRight = Math.max(prev.x + prev.width, right), newBottom = Math.max(prev.y + prev.height, bottom);
68
+ prev.x = Math.min(prev.x, x); prev.y = Math.min(prev.y, y);
69
+ prev.width = newRight - prev.x; prev.height = newBottom - prev.y;
70
+ } else groups.set(id, { id, x, y, width: right - x, height: bottom - y });
71
+ }
72
+ }
73
+ for (const child of node.children) visit(child, id);
74
+ }
75
+ for (const node of page.elements) visit(node);
76
+ return { width: page.width, height: page.height, fragments: [...groups.values()] };
77
+ });
78
+ }
79
+
80
+ try {
81
+ const entryPath = relative(root, entry).split(sep).join('/');
82
+ const themePreview = /^themes\/([a-z0-9-]+)\/preview\.tsx$/.exec(entryPath)?.[1];
83
+ const templatePreview = /^templates\/[a-z0-9-]+\/preview\.tsx$/.test(entryPath);
84
+ if (themePreview || templatePreview) {
85
+ const themeId = themePreview ?? 'neutral';
86
+ const bindings = resolveThemeAssets(root, themeId);
87
+ globalState.__opendocDocumentAssets = bindings;
88
+ // Adapt the module in this isolated worker before a specimen's template
89
+ // factory executes. Shared exported aliases keep the same object identity.
90
+ const themeEntry = realpathSync(resolve(root, 'themes', themeId, 'index.ts'));
91
+ const original = readFileSync(themeEntry, 'utf8');
92
+ overrides.set(themeEntry, { file: themeEntry, originalDigest: createHash('sha256').update(original).digest('hex'), replacements: [],
93
+ contents: `${original}\nimport { withDocumentAssets as __opendocWithAssets } from ${JSON.stringify(runtimeSource('assets/index.ts'))};\nObject.assign(theme, __opendocWithAssets(theme, ${JSON.stringify(bindings)}));\n` });
94
+ } else {
95
+ globalState.__opendocDocumentAssets = readDocumentAssetsAt(root, dirname(entry));
96
+ }
97
+ const source = `
98
+ import Entry, * as definition from ${JSON.stringify(entry)};
99
+ import { prepareDocument } from ${JSON.stringify(runtimeSource('document/index.tsx'))};
100
+ export default function OpenDocRender() {
101
+ globalThis.__opendocDataFile = definition.provenance?.dataFile;
102
+ const input = typeof Entry === 'function' ? Entry() : Entry;
103
+ const prepared = prepareDocument(input);
104
+ globalThis.__opendocCapture = { format: prepared.format, slides: prepared.slides, themeId: prepared.themeId, meta: definition.meta, blocks: prepared.blocks, provenance: definition.provenance, media: prepared.media, assets: prepared.assets, assetBindings: prepared.assetBindings, assetDependencies: prepared.assetDependencies, textTargets: prepared.textTargets };
105
+ return prepared.element;
106
+ }
107
+ `;
108
+ const result = await renderDocumentSource(source, entry, overrides);
109
+ if (sourceOverrides.some(override => override.file.endsWith('.json')) && !globalState.__opendocTemplateValidated) throw new Error('The document does not declare a data parser for these corrections. Ask your agent to change it.');
110
+ const capture = globalState.__opendocCapture;
111
+ if (!capture?.meta || typeof capture.meta.title !== 'string' || !capture.meta.title.trim()) throw new Error('Export meta with a nonempty title.');
112
+ if (capture.meta.kind !== undefined && (typeof capture.meta.kind !== 'string' || !capture.meta.kind.trim())) throw new Error('meta.kind must be a nonempty descriptive label when supplied.');
113
+ if (typeof capture.meta.description !== 'string') throw new Error('meta.description must be a string.');
114
+ if (typeof capture.meta.theme !== 'string' || !capture.meta.theme.trim()) throw new Error('meta.theme must identify a theme.');
115
+ if (capture.meta.theme !== capture.themeId) throw new Error('meta.theme must match the theme used by Document.');
116
+ if (capture.meta.author !== undefined && typeof capture.meta.author !== 'string') throw new Error('meta.author must be a string.');
117
+ const provenance: DocumentProvenance = { entry: relative(root, entry) };
118
+ if (capture.provenance !== undefined) {
119
+ if (!capture.provenance || typeof capture.provenance !== 'object' || Array.isArray(capture.provenance)) throw new Error('provenance must identify local template and data files.');
120
+ for (const key of ['template', 'dataFile'] as const) {
121
+ const value = capture.provenance[key];
122
+ if (value === undefined) continue;
123
+ if (typeof value !== 'string' || !value || value.startsWith('/') || value.split(/[\\/]/).includes('..')) throw new Error(`provenance.${key} must be a workspace-relative file path.`);
124
+ await containedFile(root, resolve(root, value));
125
+ provenance[key] = value;
126
+ }
127
+ }
128
+ const ownerId = /^documents\/([^/]+)\/index\.tsx$/.exec(entryPath)?.[1];
129
+ if (ownerId) {
130
+ const manifest = await readProjects(root);
131
+ const format = manifest.formats && Object.hasOwn(manifest.formats, ownerId) ? manifest.formats[ownerId] : 'document';
132
+ if (capture.format !== format) throw new Error(`This ${format} must use the ${format === 'presentation' ? 'Presentation' : 'Document'} root. Create presentations with --format presentation.`);
133
+ }
134
+ const textTargets = capture.textTargets ?? [];
135
+ attachTextLines(result.layout, textTargets);
136
+ const pages = pagesFromLayout(result.layout, capture.blocks);
137
+ if (!pages.length) throw new Error('The document rendered no pages.');
138
+ for (const block of Object.values(capture.blocks)) {
139
+ block.text = block.text.trim();
140
+ if (block.source) block.source.file = relative(root, block.source.file);
141
+ }
142
+ if (capture.format === 'presentation') assertSlideLayout(result.layout, capture.slides, capture.blocks);
143
+ const { issues, outline } = inspectLayout(result.layout, capture.blocks);
144
+ if (capture.format === 'presentation') {
145
+ // Standalone titles and low captions are intentional slide compositions.
146
+ for (let index = issues.length - 1; index >= 0; index--) if (issues[index].code === 'stranded-heading') issues.splice(index, 1);
147
+ for (const issue of issues) {
148
+ const slide = capture.slides[(issue.page ?? 1) - 1];
149
+ issue.message = `Slide ${slide?.id ?? issue.page}: ${issue.message.replace(/page (\d+)/g, 'slide $1').replace('or allow the content to flow onto another page', 'or split it into explicit slides')}`;
150
+ }
151
+ }
152
+ for (const message of result.warnings) issues.push({ code: 'renderer-warning', severity: 'warning', message });
153
+ assertLayoutSafe(issues);
154
+ const artifact: RenderArtifact = { meta: capture.meta, format: capture.format, ...(capture.format === 'presentation' ? { slides: capture.slides } : {}), media: capture.media ?? [], assets: capture.assets ?? [], assetBindings: capture.assetBindings, assetDependencies: capture.assetDependencies ?? [], textTargets, blocks: capture.blocks, pages, provenance, issues, outline, hash: createHash('sha256').update(result.pdf).digest('hex'), renderedAt: new Date().toISOString() };
155
+ await mkdir(destination, { recursive: true });
156
+ await writeFile(resolve(destination, 'document.pdf'), result.pdf);
157
+ await writeFile(resolve(destination, 'artifact.json'), JSON.stringify(artifact, null, 2));
158
+ await writeFile(resolve(destination, 'layout.json'), JSON.stringify(result.layout));
159
+ if (capture.format === 'presentation') await writeFile(resolve(destination, 'presentation.json'), JSON.stringify({ version: 1, hash: artifact.hash, meta: capture.meta, slides: capture.slides, doc: result.doc, layout: result.layout }));
160
+ process.send?.({ ok: true });
161
+ } catch (error) {
162
+ const message = error instanceof Error ? error.message : String(error);
163
+ process.send?.({ ok: false, error: message, ...(error instanceof RenderFailure ? { issues: error.issues } : {}) });
164
+ if (!process.send) console.error(message);
165
+ process.exitCode = 1;
166
+ }
@@ -0,0 +1,242 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { access, readdir, rm } from 'node:fs/promises';
3
+ import { relative, resolve, sep } from 'node:path';
4
+ import { renderOnce, validId, documentEntry } from './render';
5
+ import { atomicWrite } from './files';
6
+ import { themePaths, readThemePaths } from './themes';
7
+ import { readProjects } from './projects';
8
+ import { readComments } from './comments';
9
+ import { documentDependencies, includesDependency, type DocumentDependencies, isRenderRuntimePath, isThemeAssetDefaultsPath } from './dependencies';
10
+ import { readMedia, mediaFreshness } from '../media/files';
11
+ import { readAssetHead, readAssetRevision, readDocumentAssets, readThemeAssetDefaults } from '../assets/files';
12
+ import { documentName, getBlock, type DocumentState, type WorkspaceContext, type RenderArtifact } from '../shared/types';
13
+ import { getEditableSelection, getTextTarget, resolveCommentAnchor } from '../shared/anchors';
14
+ import type { ManualEditSummary } from '../shared/selection';
15
+
16
+ export class Workspace extends EventEmitter {
17
+ states = new Map<string, DocumentState>();
18
+ outputs = new Map<string, { directory: string; artifact: RenderArtifact }[]>();
19
+ context: WorkspaceContext = { documentId: null, blockId: null, page: 1 };
20
+ manualEditSummary?: (id: string) => Promise<ManualEditSummary | undefined>;
21
+ private running = new Set<string>();
22
+ private pending = new Set<string>();
23
+ private scheduled = new Set<string>();
24
+ private dependencies = new Map<string, DocumentDependencies>();
25
+ private debounce?: ReturnType<typeof setTimeout>;
26
+ private contextWrites = Promise.resolve();
27
+ private closed = false;
28
+ constructor(public root: string, public timeoutMs = 30_000) { super(); }
29
+ list() { return [...this.states.values()].sort((a, b) => documentName(a).localeCompare(documentName(b))); }
30
+ async discover() {
31
+ const manifest = await readProjects(this.root);
32
+ const entries = await readdir(resolve(this.root, 'documents'), { withFileTypes: true }).catch(error => { if (error.code === 'ENOENT') return []; throw error; });
33
+ const found = new Set<string>();
34
+ for (const dir of entries) {
35
+ if (!dir.isDirectory() || !validId(dir.name)) continue;
36
+ try { await access(resolve(this.root, 'documents', dir.name, 'index.tsx')); await documentEntry(this.root, dir.name); } catch { continue; }
37
+ found.add(dir.name);
38
+ if (!this.states.has(dir.name)) this.states.set(dir.name, { id: dir.name, status: 'rendering', revision: 0 });
39
+ const state = this.states.get(dir.name)!;
40
+ const format = manifest.formats && Object.hasOwn(manifest.formats, dir.name) ? manifest.formats[dir.name] : 'document';
41
+ const formatChanged = state.format !== undefined && state.format !== format;
42
+ state.format = format;
43
+ if (formatChanged) this.invalidate(dir.name);
44
+ this.states.get(dir.name)!.projectId = Object.hasOwn(manifest.assignments, dir.name) ? manifest.assignments[dir.name] : null;
45
+ this.states.get(dir.name)!.name = manifest.names && Object.hasOwn(manifest.names, dir.name) ? manifest.names[dir.name] : undefined;
46
+ }
47
+ for (const id of this.states.keys()) if (!found.has(id)) {
48
+ this.states.delete(id); this.pending.delete(id); this.scheduled.delete(id); this.dependencies.delete(id);
49
+ for (const out of this.outputs.get(id) ?? []) await rm(out.directory, { recursive: true, force: true });
50
+ this.outputs.delete(id);
51
+ if (this.context.documentId === id) this.context = { documentId: null, blockId: null, page: 1 };
52
+ }
53
+ return found;
54
+ }
55
+ async refresh() {
56
+ if (this.closed) return;
57
+ clearTimeout(this.debounce); this.scheduled.clear();
58
+ for (const id of await this.discover()) this.invalidate(id);
59
+ this.changed();
60
+ }
61
+ async refreshProjects() { await this.discover(); this.changed(); }
62
+ private stale(id: string) {
63
+ const state = this.states.get(id);
64
+ if (!state) return;
65
+ state.revision++; state.status = 'rendering'; delete state.error;
66
+ // The edited entry may now import files absent from its previous graph.
67
+ this.dependencies.delete(id);
68
+ }
69
+ invalidate(id: string) {
70
+ if (!this.states.has(id)) return;
71
+ this.stale(id); this.pending.add(id); this.pump();
72
+ }
73
+ /** Disable affected exports immediately; queue costly discovery and rendering after a short quiet period. */
74
+ noteChange(file: string) {
75
+ if (this.closed) return [];
76
+ const path = resolve(this.root, file);
77
+ const parts = relative(this.root, path).split(sep);
78
+ const owner = parts[0] === 'documents' && validId(parts[1] ?? '') ? parts[1] : undefined;
79
+ const sharedRuntime = isRenderRuntimePath(this.root, path) || (parts[0] === 'documents' && parts.length === 1);
80
+ const affected: string[] = [];
81
+ const dependencyUsers = [...this.dependencies].filter(([, dependencies]) => includesDependency(dependencies, path)).map(([id]) => id);
82
+ for (const id of this.states.keys()) {
83
+ const dependencies = this.dependencies.get(id);
84
+ const themeInput = parts[0] === 'themes' && parts[1] === this.states.get(id)?.artifact?.meta.theme && !isThemeAssetDefaultsPath(this.root, path);
85
+ const match = owner
86
+ ? id === owner || !dependencies || dependencies.readsFiles || dependencyUsers.includes(id)
87
+ : sharedRuntime || themeInput || !dependencies || dependencies.readsFiles || dependencyUsers.includes(id);
88
+ if (match) {
89
+ this.stale(id); this.pending.delete(id); this.scheduled.add(id); affected.push(id);
90
+ }
91
+ }
92
+ // A new document has no state yet; discovery picks it up when changes settle.
93
+ if (owner) this.scheduled.add(owner);
94
+ if (!affected.length && !owner) return affected;
95
+ clearTimeout(this.debounce);
96
+ this.debounce = setTimeout(() => { void this.flushChanges().catch(error => this.emit('workspace-error', error)); }, 180);
97
+ this.changed();
98
+ return affected;
99
+ }
100
+ async flushChanges() {
101
+ if (this.closed) return;
102
+ clearTimeout(this.debounce); this.debounce = undefined;
103
+ const scheduled = new Set(this.scheduled); this.scheduled.clear();
104
+ const known = new Set(this.states.keys());
105
+ const found = await this.discover();
106
+ for (const id of found) if ((scheduled.has(id) || !known.has(id)) && !this.scheduled.has(id)) this.pending.add(id);
107
+ this.changed(); this.pump();
108
+ }
109
+ private pump() {
110
+ if (this.closed) return;
111
+ for (const id of this.pending) {
112
+ if (this.running.size >= 2) break;
113
+ if (this.running.has(id)) continue;
114
+ this.pending.delete(id); this.running.add(id);
115
+ void this.run(id);
116
+ }
117
+ }
118
+ private async run(id: string) {
119
+ const state = this.states.get(id)!;
120
+ const revision = state.revision;
121
+ const dependencyResult = documentEntry(this.root, id).then(entry => documentDependencies(this.root, entry)).catch(() => null);
122
+ try {
123
+ const result = await renderOnce(this.root, id, this.timeoutMs);
124
+ const dependencies = await dependencyResult;
125
+ if (this.closed || this.states.get(id) !== state || revision !== state.revision) {
126
+ await rm(result.directory, { recursive: true, force: true });
127
+ } else {
128
+ const previous = this.outputs.get(id) ?? [];
129
+ this.outputs.set(id, [result, ...previous].slice(0, 2));
130
+ if (dependencies) {
131
+ for (const file of result.artifact.assetDependencies ?? []) dependencies.files.add(resolve(this.root, file));
132
+ this.dependencies.set(id, dependencies);
133
+ } else this.dependencies.delete(id);
134
+ state.artifact = result.artifact; state.status = 'ready'; delete state.error;
135
+ // Publish state before asynchronous cleanup; a newer invalidation must stay authoritative.
136
+ for (const old of previous.slice(1)) await rm(old.directory, { recursive: true, force: true }).catch(error => this.emit('workspace-error', error));
137
+ }
138
+ } catch (error) {
139
+ const dependencies = await dependencyResult;
140
+ if (this.states.get(id) === state && revision === state.revision) {
141
+ // Retain a completed current graph even after a missing/corrupt pinned asset fails rendering.
142
+ // An unresolved import has no trustworthy graph and remains conservatively invalidatable.
143
+ if (dependencies) this.dependencies.set(id, dependencies); else this.dependencies.delete(id);
144
+ state.status = 'error'; state.error = error instanceof Error ? error.message : String(error);
145
+ }
146
+ } finally { this.running.delete(id); this.changed(); this.pump(); }
147
+ }
148
+ output(id: string, hash: string) { return this.outputs.get(id)?.find(out => out.artifact.hash === hash); }
149
+ changed() { this.emit('change'); void this.writeContext().catch(error => this.emit('workspace-error', error)); }
150
+ async setContext(context: WorkspaceContext) { this.context = context; await this.writeContext(); }
151
+ writeContext() {
152
+ this.contextWrites = this.contextWrites.catch(() => {}).then(async () => {
153
+ const state = this.context.documentId ? this.states.get(this.context.documentId) : undefined;
154
+ if (state && this.manualEditSummary) state.manualEdit = await this.manualEditSummary(state.id);
155
+ const manifest = await readProjects(this.root);
156
+ const projectId = state ? state.projectId : this.context.documentId ? null : this.context.projectId;
157
+ const project = manifest.projects.find(project => project.id === projectId) ?? null;
158
+ let comments: unknown[] = [], commentsError: string | undefined;
159
+ if (state) try { comments = (await readComments(this.root, state.id)).filter(c => c.status === 'open').map(c => {
160
+ const resolved = resolveCommentAnchor(state.artifact, c);
161
+ return { ...c, targetAvailable: resolved.status !== 'missing', anchorStatus: resolved.status, selection: resolved.selection };
162
+ }); }
163
+ catch (e) { commentsError = String(e); }
164
+ let selectedMedia: unknown = null;
165
+ if (state && this.context.mediaId) {
166
+ const folder = `documents/${state.id}/media/${this.context.mediaId}`;
167
+ try { const asset = readMedia(resolve(this.root, 'documents', state.id), this.context.mediaId); selectedMedia = { folder, meta: asset.meta, ...mediaFreshness(asset) }; }
168
+ catch (error) { selectedMedia = { folder, error: (error as Error).message }; }
169
+ }
170
+ let selectedAsset: unknown = null;
171
+ if (this.context.selectedAsset) {
172
+ const selection = this.context.selectedAsset;
173
+ const folder = `assets/${selection.kind === 'logo' ? 'logos' : 'fonts'}/${selection.id}`;
174
+ try {
175
+ const head = await readAssetHead(this.root, selection.kind, selection.id);
176
+ const asset = await readAssetRevision(this.root, selection.kind, selection.id, selection.revision ?? head.revision);
177
+ selectedAsset = { ...selection, folder, asset, head,
178
+ variation: asset.kind === 'logo' && selection.variation ? asset.variations.find(item => item.id === selection.variation) ?? null : undefined,
179
+ face: asset.kind === 'font' && selection.face ? asset.faces.find(item => item.id === selection.face) ?? null : undefined,
180
+ };
181
+ } catch (error) { selectedAsset = { ...selection, folder, error: (error as Error).message }; }
182
+ }
183
+ let documentAssets: unknown = null;
184
+ if (state) {
185
+ const file = `documents/${state.id}/assets.json`;
186
+ try { documentAssets = { file, bindings: await readDocumentAssets(this.root, state.id), saved: await access(resolve(this.root, file)).then(() => true, () => false) }; }
187
+ catch (error) { documentAssets = { file, error: (error as Error).message }; }
188
+ }
189
+ const selectedBlock = getBlock(state?.artifact, this.context.blockId);
190
+ const selection = this.context.selection;
191
+ const selectedTarget = getTextTarget(state?.artifact, selection?.targetId);
192
+ const selectionCurrent = !!state && !!selection && (!selection?.renderHash || selection.renderHash === state.artifact?.hash)
193
+ && (selection?.revision === undefined || selection.revision === state.revision) && state.status === 'ready';
194
+ const editable = selectionCurrent ? getEditableSelection(state?.artifact, selection) : undefined;
195
+ const themeId = state?.artifact?.meta.theme ?? this.context.themeId ?? project?.defaultTheme ?? null;
196
+ const theme = themeId ? await readThemePaths(this.root, themeId).then(
197
+ paths => ({ id: themeId, ...paths, available: true }),
198
+ () => ({ id: themeId, ...themePaths(themeId), available: false }),
199
+ ) : null;
200
+ const assetDefaults = themeId ? await Promise.resolve().then(() => readThemeAssetDefaults(this.root, themeId)).then(
201
+ choices => ({ file: `themes/${themeId}/assets.json`, choices, appliesTo: 'new-documents' }),
202
+ error => ({ file: `themes/${themeId}/assets.json`, error: (error as Error).message, appliesTo: 'new-documents' }),
203
+ ) : undefined;
204
+ await atomicWrite(resolve(this.root, '.opendoc/current.json'), JSON.stringify({
205
+ ...this.context, updatedAt: new Date().toISOString(),
206
+ projectId: project?.id ?? null, project,
207
+ themeId, theme: theme ? { ...theme, assetDefaults } : null,
208
+ status: state?.status ?? 'idle', error: state?.error, revision: state?.revision,
209
+ format: state?.format,
210
+ slides: state?.artifact?.slides,
211
+ title: state?.artifact?.meta.title,
212
+ name: state ? documentName(state) : undefined,
213
+ provenance: state ? state.artifact?.provenance ?? { entry: `documents/${state.id}/index.tsx` } : null,
214
+ renderHash: state?.artifact?.hash, source: selectedBlock?.source ?? null,
215
+ selectedBlock: selectedBlock ?? null,
216
+ selection: selection ?? null,
217
+ selectionCurrent,
218
+ selectedText: selectedTarget ? {
219
+ targetId: selectedTarget.id, blockId: selectedTarget.blockId, slot: selectedTarget.slot,
220
+ text: selectedTarget.text.slice(0, 1200),
221
+ editable: !!editable,
222
+ source: editable ? { file: editable.source.file, digest: editable.source.digest, start: editable.source.start, end: editable.source.end, linkedOccurrences: editable.source.linkedOccurrences } : null,
223
+ } : null,
224
+ manualEdit: { editing: this.context.editing ?? false, pendingEdits: this.context.pendingEdits ?? 0, draftPreview: this.context.draftPreview ?? false, lastCorrection: state?.manualEdit ?? null, renderStatus: state?.status ?? 'idle' },
225
+ selectedMedia,
226
+ selectedAsset,
227
+ documentAssets,
228
+ renderedAssets: state?.artifact ? { uses: state.artifact.assets ?? [], bindings: state.artifact.assetBindings ?? null, current: state.status === 'ready', renderHash: state.artifact.hash } : null,
229
+ materials: state ? { media: `documents/${state.id}/media`, usedMedia: state.artifact?.media ?? [] } : null,
230
+ pendingComments: comments, commentsError,
231
+ }, null, 2) + '\n');
232
+ });
233
+ return this.contextWrites;
234
+ }
235
+ async close() {
236
+ this.closed = true; clearTimeout(this.debounce); this.pending.clear(); this.scheduled.clear();
237
+ while (this.running.size) await new Promise(r => setTimeout(r, 30));
238
+ await this.contextWrites;
239
+ await Promise.all([...this.outputs.values()].flat().map(output => rm(output.directory, { recursive: true, force: true })));
240
+ this.outputs.clear();
241
+ }
242
+ }