@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,118 @@
1
+ import { lstat, readdir, readFile, realpath } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+ import ts from 'typescript';
4
+ import type { AssetKind, AssetRef, AssetUsage, DocumentAssets } from '../shared/assets';
5
+ import type { DocumentState, RenderArtifact } from '../shared/types';
6
+ import { assertAssetId, assertKind, readDocumentAssetsAt, readThemeAssetDefaults, safeAssetPath, validAssetId, validRevision } from './files';
7
+
8
+ async function directories(root: string, folder: string) {
9
+ try {
10
+ const path = safeAssetPath(root, folder, true);
11
+ return (await readdir(path, { withFileTypes: true })).filter(item => item.isDirectory()).map(item => item.name).sort();
12
+ } catch { return []; }
13
+ }
14
+ async function localText(root: string, file: string, maximum = 512_000) {
15
+ try { const path = safeAssetPath(root, file); if ((await lstat(path)).size > maximum) return undefined; return await readFile(path, 'utf8'); }
16
+ catch { return undefined; }
17
+ }
18
+ async function localJson(root: string, file: string, maximum?: number): Promise<any> {
19
+ const text = await localText(root, file, maximum);
20
+ if (text === undefined) return undefined;
21
+ try { return JSON.parse(text); } catch { return undefined; }
22
+ }
23
+ function literalName(contents: string | undefined, property: 'name' | 'title', themeId?: string) {
24
+ if (!contents) return undefined;
25
+ const source = ts.createSourceFile('index.tsx', contents, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
26
+ let found: string | undefined;
27
+ function value(node: ts.ObjectLiteralExpression, key: string) {
28
+ for (const field of node.properties) if (ts.isPropertyAssignment(field) && (ts.isIdentifier(field.name) || ts.isStringLiteral(field.name)) && field.name.text === key && (ts.isStringLiteral(field.initializer) || ts.isNoSubstitutionTemplateLiteral(field.initializer))) return field.initializer.text;
29
+ }
30
+ function visit(node: ts.Node) {
31
+ if (found) return;
32
+ if (ts.isObjectLiteralExpression(node) && (themeId ? value(node, 'id') === themeId : ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name) && node.parent.name.text === 'meta')) found = value(node, property)?.trim() || undefined;
33
+ ts.forEachChild(node, visit);
34
+ }
35
+ visit(source);
36
+ return found;
37
+ }
38
+ function bindingRoles(bindings: DocumentAssets, kind: AssetKind) {
39
+ const entries: [string, AssetRef | undefined][] = kind === 'logo'
40
+ ? [['logo', bindings.logo], ...Object.entries(bindings.logos ?? {}).map(([name, ref]) => [`logo:${name}`, ref] as [string, AssetRef])]
41
+ : [['body', bindings.bodyFont], ['headings', bindings.headingFont]];
42
+ return entries.filter((entry): entry is [string, AssetRef] => !!entry[1]);
43
+ }
44
+ const choices = (bindings: DocumentAssets, kind: AssetKind, id: string) => bindingRoles(bindings, kind).filter(([, reference]) => reference.id === id);
45
+ function actualRevisions(artifact: RenderArtifact | undefined, kind: AssetKind, id: string) {
46
+ return new Set((Array.isArray(artifact?.assets) ? artifact.assets : []).filter(use => use && use.kind === kind && use.id === id && validRevision(use.revision)).map(use => use.revision));
47
+ }
48
+
49
+ /** Read relationships without rendering a theme, evaluating document source, or guessing PDF usage. */
50
+ export async function assetUsage(workspace: string, kind: AssetKind, id: string, states?: DocumentState[]): Promise<AssetUsage> {
51
+ assertKind(kind); assertAssetId(id);
52
+ const root = await realpath(workspace);
53
+ const usage: AssetUsage = { themes: [], documents: [] };
54
+ for (const themeId of await directories(root, resolve(root, 'themes'))) {
55
+ if (!validAssetId(themeId)) continue;
56
+ try {
57
+ const defaults = readThemeAssetDefaults(root, themeId);
58
+ const roles = kind === 'logo' ? defaults.logo?.id === id ? ['logo'] : [] : [defaults.bodyFont === id ? 'body' : '', defaults.headingFont === id ? 'headings' : ''].filter(Boolean);
59
+ if (roles.length) usage.themes.push({ id: themeId, name: literalName(await localText(root, resolve(root, 'themes', themeId, 'index.ts')), 'name', themeId) ?? themeId, roles });
60
+ } catch { /* An invalid neighboring theme is reported by its own inspector. */ }
61
+ }
62
+ const projectManifest = await localJson(root, resolve(root, 'projects.json'), 1_000_000);
63
+ const names = projectManifest?.names && typeof projectManifest.names === 'object' ? projectManifest.names as Record<string, unknown> : {};
64
+ const live = new Map((states ?? []).map(state => [state.id, state]));
65
+ const documents: { id: string; folder: string; name?: string; trashed?: boolean; deletedAt?: number }[] = [];
66
+ for (const documentId of await directories(root, resolve(root, 'documents'))) {
67
+ if (!validAssetId(documentId)) continue;
68
+ const folder = resolve(root, 'documents', documentId);
69
+ if (await localText(root, resolve(folder, 'index.tsx')) === undefined) continue;
70
+ documents.push({ id: documentId, folder });
71
+ }
72
+ for (const restoreId of await directories(root, resolve(root, '.opendoc/trash'))) {
73
+ const receipt = await localJson(root, resolve(root, '.opendoc/trash', restoreId, 'receipt.json'), 4096);
74
+ if (!validAssetId(receipt?.id)) continue;
75
+ const folder = resolve(root, '.opendoc/trash', restoreId, 'document');
76
+ if (await localText(root, resolve(folder, 'index.tsx')) === undefined) continue;
77
+ documents.push({ id: receipt.id, folder, trashed: true, ...(Number.isFinite(Date.parse(receipt.deletedAt)) ? { deletedAt: Date.parse(receipt.deletedAt) } : {}), ...(typeof receipt.name === 'string' && receipt.name.trim() ? { name: receipt.name } : {}) });
78
+ }
79
+ // Live states carry the authoritative last successful PDF. CLI readers may use
80
+ // persisted render artifacts as historical evidence, never as current readiness.
81
+ const persisted = new Map<string, RenderArtifact>();
82
+ const needed = documents.filter(doc => doc.trashed || !live.get(doc.id)?.artifact);
83
+ const neededIds = new Set(needed.map(doc => doc.id));
84
+ if (needed.length) for (const folder of await directories(root, resolve(root, '.opendoc/renders'))) {
85
+ const documentId = folder.replace(/-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/, '');
86
+ if (!neededIds.has(documentId)) continue;
87
+ const artifact = await localJson(root, resolve(root, '.opendoc/renders', folder, 'artifact.json'), 16_000_000) as RenderArtifact | undefined;
88
+ if (artifact?.provenance?.entry !== `documents/${documentId}/index.tsx` || !Number.isFinite(Date.parse(artifact.renderedAt))) continue;
89
+ for (const document of needed.filter(doc => doc.id === documentId)) {
90
+ // IDs can be reused after deleting a document. A newer PDF must never be
91
+ // attributed to the old copy in Trash merely because its path once matched.
92
+ if (document.trashed && (document.deletedAt === undefined || Date.parse(artifact.renderedAt) > document.deletedAt)) continue;
93
+ const previous = persisted.get(document.folder);
94
+ if (!previous || Date.parse(previous.renderedAt) < Date.parse(artifact.renderedAt)) persisted.set(document.folder, artifact);
95
+ }
96
+ }
97
+ for (const document of documents) {
98
+ const state = document.trashed ? undefined : live.get(document.id);
99
+ const artifact = state?.artifact ?? persisted.get(document.folder);
100
+ let bindings: DocumentAssets = { version: 1 };
101
+ try { bindings = readDocumentAssetsAt(root, document.folder); } catch { /* Retain actual PDF evidence even when the saved choices need repair. */ }
102
+ const bound = choices(bindings, kind, id), rendered = actualRevisions(artifact, kind, id);
103
+ const revisions = new Set([...bound.map(([, reference]) => reference.revision), ...rendered]);
104
+ if (!revisions.size) continue;
105
+ const savedName = !document.trashed && typeof names[document.id] === 'string' ? names[document.id] as string : undefined;
106
+ const name = document.name ?? state?.name ?? savedName ?? (typeof artifact?.meta?.title === 'string' ? artifact.meta.title : undefined) ?? literalName(await localText(root, resolve(document.folder, 'index.tsx')), 'title') ?? document.id;
107
+ for (const revision of revisions) {
108
+ const renderedBindings = artifact?.assetBindings;
109
+ const roles = new Set(bound.filter(([, reference]) => reference.revision === revision).map(([role]) => role));
110
+ if (rendered.has(revision) && renderedBindings) for (const [role, reference] of choices(renderedBindings, kind, id)) if (reference.revision === revision) roles.add(role);
111
+ const rebound = [...roles].some(role => !bindingRoles(bindings, kind).some(([currentRole, reference]) => currentRole === role && reference.id === id && reference.revision === revision));
112
+ usage.documents.push({ id: document.id, name, revision, roles: [...roles], rendered: rendered.has(revision), current: !!state && state.status === 'ready' && rendered.has(revision) && !rebound, ...(document.trashed ? { trashed: true } : {}) });
113
+ }
114
+ }
115
+ usage.themes.sort((a, b) => a.name.localeCompare(b.name));
116
+ usage.documents.sort((a, b) => a.name.localeCompare(b.name) || Number(!!a.trashed) - Number(!!b.trashed) || a.revision.localeCompare(b.revision));
117
+ return usage;
118
+ }
@@ -0,0 +1,25 @@
1
+ import { dirname, resolve } from 'node:path';
2
+ import { access, readFile } from 'node:fs/promises';
3
+ import { runtimeResolve, applicationRoot } from '../runtime/paths';
4
+ import { runProcess } from './process';
5
+ import { packageIdentity, packageMetadata } from './workspace';
6
+
7
+ export async function validateInstallation() {
8
+ const { edition } = packageIdentity(await packageMetadata());
9
+ await Promise.all([...(edition === 'normal' ? ['dist/index.html'] : []), 'src/server/worker.ts', 'src/assets/import-worker.ts', 'tsconfig.workspace.json'].map(path => access(resolve(applicationRoot, path))));
10
+ const core = runtimeResolve('@formepdf/core');
11
+ const manifest = JSON.parse(await readFile(resolve(dirname(core), '../package.json'), 'utf8'));
12
+ if (manifest.version !== '0.20.1-opendoc.3') throw new Error('The repaired OpenDoc rendering engine is missing. Reinstall this OpenDoc release.');
13
+ const { transform } = await import('esbuild');
14
+ await transform('const ok: boolean = true', { loader: 'ts' });
15
+ }
16
+
17
+ export async function checkWorkspace(root: string, json = false, quiet = false) {
18
+ const compiler = runtimeResolve('typescript/lib/tsc.js');
19
+ const result = await runProcess(process.execPath, [compiler, '--project', resolve(root, 'tsconfig.json'), '--noEmit'], root, { capture: true });
20
+ if (result.code) {
21
+ if (result.stdout.trim()) process.stderr.write(result.stdout);
22
+ throw new Error('Workspace typecheck failed. Correct the authoring errors above and run npx opendoc check again.');
23
+ }
24
+ if (!quiet) console.log(json ? JSON.stringify({ ok: true, workspace: root }) : 'Workspace authoring files typecheck successfully.');
25
+ }
@@ -0,0 +1,119 @@
1
+ import { cp, lstat, mkdir, mkdtemp, readdir, readFile, rm, writeFile } from 'node:fs/promises';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ import { createInterface } from 'node:readline/promises';
5
+ import { parseArgs } from 'node:util';
6
+ import { applicationRoot } from '../runtime/paths';
7
+ import { dependencyPin, installedApplication, packageIdentity, packageMetadata, packageNames, workspaceFormat, type Edition, type PackageIdentity } from './workspace';
8
+ import { runProcess } from './process';
9
+
10
+ const usageFor = (edition: Edition) => edition === 'headless'
11
+ ? `Usage: npx --yes ${packageNames.headless} init <folder> [--json]\nCreates a headless workspace without starting a server. The folder must be new or empty.`
12
+ : `Usage: npx --yes ${packageNames.normal} init [folder] [--no-start] [--no-open] [--json]\nCreates a new workspace. The folder must be new or empty.`;
13
+ const quote = (value: string) => `'${value.replaceAll("'", "'\\''")}'`;
14
+ const skills = ['opendoc-create', 'opendoc-current-document', 'opendoc-apply-comments', 'opendoc-create-theme', 'opendoc-create-template', 'opendoc-review-document'];
15
+ const instructions = `# OpenDoc workspace\n\nThis folder contains your documents, presentations, projects, themes, templates, and assets.\n\nRead [the OpenDoc agent guide](node_modules/opendoc/AGENTS.md) before authoring or editing. Use the matching OpenDoc skill below; its substantive instructions live with the installed runtime. Resolve document and catalog paths from this workspace, not from the installed package.\n\nUse \`npx opendoc\` commands from this folder or a subfolder. Start the app with \`npx opendoc start\`; check authoring with \`npx opendoc check\`. Keep stable content identities and saved corrections. Finish authorized work through reviewed exports.\n\nDo not edit \`node_modules/opendoc\` to change a document or theme. The workspace-owned \`themes/\` and \`templates/\` are editable. Runtime updates use \`npx opendoc update\` after stopping OpenDoc with Ctrl+C.\n`;
16
+ const headlessInstructions = `# OpenDoc Headless workspace\n\nThis folder contains your documents, presentations, projects, themes, templates, and assets. OpenDoc runs in the agent's environment; recipients receive finished PDF and PowerPoint files and need no OpenDoc installation.\n\nRead [the OpenDoc Headless agent guide](node_modules/opendoc/AGENTS.md) before authoring or editing. Use the matching OpenDoc skill; its substantive instructions live with the installed runtime. Resolve document and catalog paths from this workspace, not from the installed package.\n\nUse \`npx opendoc\` commands from this folder or a subfolder. Author from the user's brief, run \`npx opendoc check\`, then \`npx opendoc review <id> --json\`. Inspect every generated page image and the extracted text, correct issues, and export the final PDF with \`npx opendoc export <id>\`. For presentations also export editable PowerPoint with \`npx opendoc export <id> --format pptx\`. Deliver the requested files through your existing channel. Keep stable content identities and saved corrections. The workflow does not require a browser or persistent server.\n\nDo not edit \`node_modules/opendoc\` to change a document or theme. The workspace-owned \`themes/\` and \`templates/\` are editable. Keep this workspace when future revisions or reusable themes and templates are needed. Runtime updates use \`npx opendoc update\` and preserve the Headless edition and workspace content.\n`;
17
+
18
+ export async function requireEmptyDestination(root: string) {
19
+ try {
20
+ const info = await lstat(root);
21
+ if (!info.isDirectory() || info.isSymbolicLink() || (await readdir(root)).length) throw new Error(`Refusing to overwrite ${root}. Choose a new or empty directory.`);
22
+ } catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; }
23
+ }
24
+
25
+ export type InitDependencies = {
26
+ install?: (stage: string, version: string, identity: PackageIdentity) => Promise<void>;
27
+ validate?: (stage: string) => Promise<void>;
28
+ };
29
+
30
+ async function copyContents(source: string, destination: string) {
31
+ for (const entry of await readdir(source)) {
32
+ await cp(resolve(source, entry), resolve(destination, entry), { recursive: true, force: false, errorOnExist: true, verbatimSymlinks: true });
33
+ }
34
+ }
35
+
36
+ /** Prepare privately, then copy without ever overwriting a destination file. */
37
+ export async function initializeWorkspace(destination: string, options: { sourceRoot?: string; tarball?: string } = {}, dependencies: InitDependencies = {}) {
38
+ if (!['darwin', 'linux'].includes(process.platform)) throw new Error('OpenDoc 0.4 supports macOS and Linux.');
39
+ const root = resolve(destination === '~' ? homedir() : destination.startsWith('~/') ? resolve(homedir(), destination.slice(2)) : destination);
40
+ await requireEmptyDestination(root);
41
+ const sourceRoot = options.sourceRoot ?? applicationRoot;
42
+ const identity = packageIdentity(await packageMetadata(sourceRoot));
43
+ const { version, edition } = identity;
44
+ const pin = dependencyPin(identity);
45
+ await mkdir(dirname(root), { recursive: true });
46
+ const stage = await mkdtemp(resolve(dirname(root), '.opendoc-init-'));
47
+ try {
48
+ await copyContents(resolve(sourceRoot, 'starter'), stage);
49
+ const manifest = { name: 'opendoc-workspace', private: true, type: 'module', dependencies: { opendoc: pin } };
50
+ await writeFile(resolve(stage, 'package.json'), JSON.stringify(manifest, null, 2) + '\n', { flag: 'wx' });
51
+ await writeFile(resolve(stage, 'tsconfig.json'), JSON.stringify({ extends: 'opendoc/tsconfig.workspace.json', include: ['documents', 'templates', 'themes'] }, null, 2) + '\n', { flag: 'wx' });
52
+ await mkdir(resolve(stage, '.opendoc'), { recursive: true });
53
+ await writeFile(resolve(stage, '.opendoc/workspace.json'), JSON.stringify({ formatVersion: workspaceFormat, createdWith: version, edition }, null, 2) + '\n', { flag: 'wx' });
54
+ await writeFile(resolve(stage, 'AGENTS.md'), edition === 'headless' ? headlessInstructions : instructions, { flag: 'wx' });
55
+ await writeFile(resolve(stage, 'CLAUDE.md'), '# OpenDoc\n\nRead and follow [AGENTS.md](AGENTS.md), including its installed OpenDoc guide and skills.\n', { flag: 'wx' });
56
+ await writeFile(resolve(stage, '.gitignore'), 'node_modules/\n.opendoc/*\n!.opendoc/workspace.json\noutput/\n.DS_Store\n', { flag: 'wx' });
57
+ for (const skill of skills) {
58
+ const source = await readFile(resolve(sourceRoot, '.agents/skills', skill, 'SKILL.md'), 'utf8');
59
+ const frontmatter = source.match(/^---\r?\n[\s\S]*?\r?\n---/)?.[0] ?? `---\nname: ${skill}\ndescription: OpenDoc authoring workflow.\n---`;
60
+ const directory = resolve(stage, '.agents/skills', skill);
61
+ await mkdir(directory, { recursive: true });
62
+ await writeFile(resolve(directory, 'SKILL.md'), `${frontmatter}\n\nRead and follow [the installed ${skill} skill](../../../node_modules/opendoc/.agents/skills/${skill}/SKILL.md). Resolve document and catalog paths from this workspace; the installed file contains version-matched instructions.\n`, { flag: 'wx' });
63
+ }
64
+ console.error(`Installing OpenDoc${edition === 'headless' ? ' Headless' : ''} ${version}…`);
65
+ if (dependencies.install) await dependencies.install(stage, version, identity);
66
+ else {
67
+ const tarball = options.tarball ?? process.env.OPENDOC_PACKAGE_TARBALL;
68
+ const args = ['install', '--ignore-scripts', '--no-audit', '--no-fund', ...(tarball ? ['--save-exact', `opendoc@file:${resolve(tarball)}`] : [])];
69
+ const result = await runProcess('npm', args, stage, { diagnostics: true });
70
+ if (result.code) throw new Error(`npm install failed (exit ${result.code}).`);
71
+ // Local release acceptance uses a tarball; keep the public workspace contract exactly pinned.
72
+ if (tarball) {
73
+ await writeFile(resolve(stage, 'package.json'), JSON.stringify(manifest, null, 2) + '\n');
74
+ const lockPath = resolve(stage, 'package-lock.json');
75
+ const lock = JSON.parse(await readFile(lockPath, 'utf8'));
76
+ lock.packages[''].dependencies.opendoc = pin;
77
+ await writeFile(lockPath, JSON.stringify(lock, null, 2) + '\n');
78
+ }
79
+ }
80
+ await installedApplication(stage);
81
+ if (dependencies.validate) await dependencies.validate(stage);
82
+ else {
83
+ const result = await runProcess(process.execPath, [resolve(stage, 'node_modules/opendoc/bin/opendoc.mjs'), 'check', '--json'], stage, { capture: true });
84
+ if (result.code) throw new Error('The installed workspace did not pass its authoring check.');
85
+ }
86
+ await requireEmptyDestination(root);
87
+ await mkdir(root, { recursive: true });
88
+ await copyContents(stage, root);
89
+ await rm(stage, { recursive: true, force: true });
90
+ return { workspace: root, version, edition };
91
+ } catch (error) {
92
+ throw new Error(`${(error as Error).message}\nThe destination was not overwritten. Prepared files remain at ${stage}.\nTo recover, inspect that folder, run npm install there, then npx opendoc check${edition === 'normal' ? ' and npx opendoc start' : ''}. Or retry initialization in a new empty folder.`, { cause: error });
93
+ }
94
+ }
95
+
96
+ export async function runInit(args: string[]) {
97
+ const { edition } = packageIdentity(await packageMetadata());
98
+ const usage = usageFor(edition);
99
+ const { values, positionals } = parseArgs({ args, allowPositionals: true, options: { 'no-start': { type: 'boolean' }, 'no-open': { type: 'boolean' }, json: { type: 'boolean' }, help: { type: 'boolean', short: 'h' } } });
100
+ if (values.help) { console.log(values.json ? JSON.stringify({ usage }) : usage); return; }
101
+ if (positionals.length > 1) throw new Error(usage);
102
+ let destination = positionals[0];
103
+ if (!destination) {
104
+ if (edition === 'headless') throw new Error(`OpenDoc Headless requires an explicit workspace folder: npx --yes ${packageNames.headless} init <folder>`);
105
+ if (!process.stdin.isTTY) throw new Error(`Provide a workspace folder when input is not interactive: npx --yes ${packageNames.normal} init <folder> --no-start`);
106
+ const prompt = createInterface({ input: process.stdin, output: process.stderr });
107
+ try { destination = (await prompt.question('Workspace folder [~/Documents/My OpenDoc]: ')).trim() || resolve(homedir(), 'Documents/My OpenDoc'); }
108
+ finally { prompt.close(); }
109
+ }
110
+ const result = await initializeWorkspace(destination);
111
+ if (edition === 'headless') console.log(values.json ? JSON.stringify(result) : `Created ${result.workspace}\nRead its AGENTS.md, then author, review, and deliver finished PDF or PowerPoint files with npx opendoc.`);
112
+ else if (values['no-start']) console.log(values.json ? JSON.stringify(result) : `Created ${result.workspace}\nOpen this folder in your coding agent.\nStart OpenDoc: npx opendoc start ${quote(result.workspace)}`);
113
+ else {
114
+ console.error(`Created ${result.workspace}. Open this folder in your coding agent.`);
115
+ // Launch the installed runtime, including when init came from npm's temporary cache.
116
+ const child = await runProcess(process.execPath, [resolve(result.workspace, 'node_modules/opendoc/bin/opendoc.mjs'), 'start', ...(values['no-open'] ? ['--no-open'] : []), ...(values.json ? ['--json'] : [])], result.workspace);
117
+ if (child.code) process.exitCode = child.code;
118
+ }
119
+ }
@@ -0,0 +1,34 @@
1
+ import { mkdir, open, readFile, unlink } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+
5
+ /** Startup, update activation, and Headless commands share the workspace runtime lock. */
6
+ export async function withWorkspaceLock<T>(root: string, action: () => Promise<T>): Promise<T> {
7
+ const file = resolve(root, '.opendoc/update.lock');
8
+ await mkdir(resolve(root, '.opendoc'), { recursive: true });
9
+ const contents = JSON.stringify({ pid: process.pid, id: randomUUID() });
10
+ try {
11
+ const handle = await open(file, 'wx', 0o600);
12
+ try { await handle.writeFile(contents); } finally { await handle.close(); }
13
+ } catch (error) {
14
+ if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
15
+ const recovery = `Confirm no OpenDoc command is running, then remove ${file} and retry.`;
16
+ let owner: { pid?: number };
17
+ try { owner = JSON.parse(await readFile(file, 'utf8')); } catch { throw new Error(`OpenDoc has an incomplete workspace runtime lock. ${recovery}`); }
18
+ if (!owner || !Number.isSafeInteger(owner.pid) || owner.pid! <= 0 || owner.pid! > 2 ** 31 - 1) throw new Error(`Invalid OpenDoc workspace runtime lock. ${recovery}`);
19
+ try { process.kill(owner.pid!, 0); }
20
+ catch (ownerError) {
21
+ if ((ownerError as NodeJS.ErrnoException).code !== 'ESRCH') throw ownerError;
22
+ // Stat-then-unlink recovery could delete a new contender's lock. Leave stale locks intact.
23
+ throw new Error(`The previous OpenDoc command stopped before releasing its lock. ${recovery}`);
24
+ }
25
+ throw new Error('Another OpenDoc command is in progress. Wait for it to finish, then retry.');
26
+ }
27
+ try { return await action(); }
28
+ finally {
29
+ try { if (await readFile(file, 'utf8') === contents) await unlink(file); }
30
+ catch (error) {
31
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') console.error(`OpenDoc could not remove its workspace runtime lock after the operation: ${error instanceof Error ? error.message : String(error)}. Confirm no OpenDoc command is running, then remove ${file} and retry.`);
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,118 @@
1
+ import { resolve } from 'node:path';
2
+ import { realpath } from 'node:fs/promises';
3
+ import { applicationRoot } from '../runtime/paths';
4
+ import { discoverWorkspace, explicitWorkspace, installedApplication, packageIdentity, packageMetadata, packageNames, type Edition } from './workspace';
5
+ import { runProcess } from './process';
6
+ import { withWorkspaceLock } from './lock';
7
+ import { RenderFailure } from '../server/render-error';
8
+
9
+ const usageFor = (edition: Edition) => `OpenDoc${edition === 'headless' ? ' Headless — remote document production for agents' : ' — local documents and editable presentations'}
10
+
11
+ ${edition === 'headless'
12
+ ? ` npx --yes ${packageNames.headless} init <folder>\n Create a workspace without a server`
13
+ : ` npx --yes ${packageNames.normal} init [folder]\n Create a workspace and open OpenDoc\n npx opendoc start [folder] Start its installed runtime`}
14
+ npx opendoc create <id> Create a document or presentation
15
+ npx opendoc projects Manage projects and membership
16
+ npx opendoc templates Inspect, check, and preview templates
17
+ npx opendoc themes Inspect, check, and preview themes
18
+ npx opendoc assets Manage fonts, logos, and bindings
19
+ npx opendoc media Manage document-owned media
20
+ npx opendoc comments Read and resolve feedback
21
+ npx opendoc export <id...> Export PDF or editable PowerPoint
22
+ npx opendoc review <id> Generate page images, text, and review issues
23
+ npx opendoc check Typecheck workspace authoring
24
+ npx opendoc update [--check] Explicitly update the runtime
25
+
26
+ Commands discover the workspace from this folder or an ancestor.
27
+ Use --workspace <folder> to select one and --json for structured results.
28
+ Use <command> --help for options, or --version for the active version.`;
29
+
30
+ export function parseGlobalArgs(args: string[]) {
31
+ const rest: string[] = [];
32
+ let workspace: string | undefined;
33
+ let json = false;
34
+ for (let index = 0; index < args.length; index++) {
35
+ const arg = args[index];
36
+ if (arg === '--') { rest.push(...args.slice(index)); break; }
37
+ if (arg === '--workspace' || arg.startsWith('--workspace=')) {
38
+ if (workspace !== undefined) throw new Error('Provide --workspace only once.');
39
+ workspace = arg === '--workspace' ? args[++index] : arg.slice('--workspace='.length);
40
+ if (!workspace || workspace.startsWith('--')) throw new Error('Provide a folder after --workspace.');
41
+ } else if (arg === '--json') json = true;
42
+ else rest.push(arg);
43
+ }
44
+ return { args: rest, workspace, json };
45
+ }
46
+
47
+ export async function main(rawArgs = process.argv.slice(2)) {
48
+ let json = rawArgs.includes('--json');
49
+ try {
50
+ if (Number(process.versions.node.split('.')[0]) < 24) throw new Error('OpenDoc requires Node.js 24 or newer. Install Node.js 24, then retry.');
51
+ const parsed = parseGlobalArgs(rawArgs);
52
+ json = parsed.json;
53
+ const identity = packageIdentity(await packageMetadata());
54
+ const usage = usageFor(identity.edition);
55
+ const [command, ...args] = parsed.args;
56
+ if (!command || ['--help', '-h', 'help'].includes(command)) {
57
+ console.log(json ? JSON.stringify({ usage }) : usage); return;
58
+ }
59
+ if (command === 'init') {
60
+ if (parsed.workspace) throw new Error('Use init <folder> to choose the new workspace.');
61
+ const { runInit } = await import('./init');
62
+ await runInit([...(json ? ['--json'] : []), ...args]); return;
63
+ }
64
+ let startFolder: string | undefined;
65
+ if (command === 'start') {
66
+ const index = args.findIndex(arg => !arg.startsWith('-'));
67
+ if (index >= 0) startFolder = args.splice(index, 1)[0];
68
+ if (startFolder && parsed.workspace) throw new Error('Choose start <folder> or --workspace <folder>, not both.');
69
+ }
70
+ const root = parsed.workspace || startFolder
71
+ ? await explicitWorkspace(parsed.workspace ?? startFolder!)
72
+ : await discoverWorkspace();
73
+ if (root) {
74
+ const active = await installedApplication(root);
75
+ if (active !== await realpath(applicationRoot)) {
76
+ const result = await runProcess(process.execPath, [resolve(active, 'bin/opendoc.mjs'), ...rawArgs], process.cwd());
77
+ if (result.code) process.exitCode = result.code;
78
+ return;
79
+ }
80
+ }
81
+ if (command === '--version' || command === '-v') {
82
+ if (args.length) throw new Error('Use --version without other arguments.');
83
+ const { version } = await packageMetadata();
84
+ console.log(json ? JSON.stringify({ version }) : version); return;
85
+ }
86
+ if (!root) throw new Error(`No OpenDoc workspace found. Run npx --yes ${identity.name} init <folder>, or use --workspace <folder> for an existing workspace.`);
87
+ const flags = [...(json ? ['--json'] : []), ...args];
88
+ const dispatch = async () => {
89
+ switch (command) {
90
+ case 'start': await (await import('./start')).runStart(flags, root); break;
91
+ case 'create': await (await import('../server/create-cli')).runCreateCli(flags, root); break;
92
+ case 'projects': await (await import('../server/projects-cli')).runProjectsCli(flags, root); break;
93
+ case 'templates': await (await import('../server/templates-cli')).runTemplatesCli(flags, root); break;
94
+ case 'themes': await (await import('../server/themes-cli')).runThemesCli(flags, root); break;
95
+ case 'assets': await (await import('../server/assets-cli')).runAssetsCli(flags, root); break;
96
+ case 'media': await (await import('../server/media-cli')).runMediaCli(flags, root); break;
97
+ case 'comments': await (await import('../server/comments-cli')).runCommentsCli(flags, root, { mode: identity.edition === 'headless' ? 'direct' : 'auto' }); break;
98
+ case 'export': await (await import('../server/export')).runExportCli(flags, root, { mode: identity.edition === 'headless' ? 'direct' : 'preview' }); break;
99
+ case 'review': await (await import('../server/review-cli')).runReviewCli(flags, root); break;
100
+ case 'update': await (await import('./update')).runUpdate(flags, root); break;
101
+ case 'check': {
102
+ if (args.includes('--help') || args.includes('-h')) { const help = 'Usage: npx opendoc check [--json]\nTypechecks workspace documents, themes, and templates.'; console.log(json ? JSON.stringify({ usage: help }) : help); break; }
103
+ if (args.length) throw new Error('Usage: npx opendoc check [--json]');
104
+ const { checkWorkspace, validateInstallation } = await import('./check');
105
+ await validateInstallation(); await checkWorkspace(root, json); break;
106
+ }
107
+ default: throw new Error(`Unknown command: ${command}. Use npx opendoc --help.`);
108
+ }
109
+ };
110
+ if (identity.edition === 'headless' && !['update', 'start'].includes(command)) await withWorkspaceLock(root, dispatch);
111
+ else await dispatch();
112
+ } catch (error) {
113
+ const message = error instanceof Error ? error.message : String(error);
114
+ console.error(message);
115
+ if (json) console.log(JSON.stringify({ error: message, ...(error instanceof RenderFailure ? { issues: error.issues } : {}) }));
116
+ if (!process.exitCode) process.exitCode = 1;
117
+ }
118
+ }
@@ -0,0 +1,19 @@
1
+ import { spawn } from 'node:child_process';
2
+
3
+ export async function runProcess(command: string, args: string[], cwd: string, options: { capture?: boolean; diagnostics?: boolean } = {}) {
4
+ return await new Promise<{ stdout: string; code: number }>((accept, reject) => {
5
+ const child = spawn(command, args, { cwd, stdio: ['inherit', options.capture || options.diagnostics ? 'pipe' : 'inherit', 'inherit'] });
6
+ let stdout = '';
7
+ let canceled = false;
8
+ child.stdout?.on('data', chunk => { if (options.capture) stdout += String(chunk); else process.stderr.write(chunk); });
9
+ const cancel = () => { canceled = true; child.kill('SIGINT'); };
10
+ process.on('SIGINT', cancel);
11
+ child.once('error', error => { process.off('SIGINT', cancel); reject(error); });
12
+ child.once('exit', (code, signal) => {
13
+ process.off('SIGINT', cancel);
14
+ if (canceled || signal === 'SIGINT') { process.exitCode = 130; reject(new Error('Operation canceled.')); }
15
+ else if (signal) reject(new Error(`${command} stopped (${signal}).`));
16
+ else accept({ stdout, code: code ?? 1 });
17
+ });
18
+ });
19
+ }
@@ -0,0 +1,96 @@
1
+ import { spawn, type ChildProcess } from 'node:child_process';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { resolve } from 'node:path';
4
+ import { setTimeout } from 'node:timers/promises';
5
+ import { parseArgs } from 'node:util';
6
+ import { runtimeResolve, runtimeSource } from '../runtime/paths';
7
+ import { packageIdentity, packageMetadata } from './workspace';
8
+ import { withWorkspaceLock } from './lock';
9
+ import { validateInstallation } from './check';
10
+
11
+ export async function runningSession(root: string): Promise<{ origin: string; pid: number } | null> {
12
+ let session: { origin: string; token: string; pid: number };
13
+ try { session = JSON.parse(await readFile(resolve(root, '.opendoc/server.json'), 'utf8')); }
14
+ catch (error) { if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null; throw new Error('Cannot read the OpenDoc session. Check .opendoc/server.json before starting another server.'); }
15
+ if (!/^http:\/\/127\.0\.0\.1:\d+$/.test(session?.origin ?? '') || typeof session.token !== 'string' || !session.token) throw new Error('The OpenDoc session record is invalid. Check .opendoc/server.json before starting another server.');
16
+ let response;
17
+ try { response = await fetch(`${session.origin}/api/session`, { signal: AbortSignal.timeout(1500), redirect: 'error' }); }
18
+ catch (error) {
19
+ if ((error as { cause?: { code?: string } }).cause?.code === 'ECONNREFUSED') {
20
+ if (Number.isSafeInteger(session.pid) && session.pid > 0 && session.pid <= 2 ** 31 - 1) {
21
+ try { process.kill(session.pid, 0); }
22
+ catch (ownerError) { if ((ownerError as NodeJS.ErrnoException).code === 'ESRCH') return null; throw ownerError; }
23
+ throw new Error('OpenDoc is still finishing its previous session. Wait for its terminal to stop, then retry.');
24
+ }
25
+ return null;
26
+ }
27
+ throw new Error('Cannot verify whether OpenDoc is running. Check its terminal before starting another server.');
28
+ }
29
+ const live = await response.json().catch(() => null);
30
+ if (response.ok && live?.token === session.token) return { origin: session.origin, pid: session.pid };
31
+ throw new Error('The recorded OpenDoc session no longer matches the server at its address. Stop the previous server and remove the stale .opendoc/server.json before retrying.');
32
+ }
33
+
34
+ async function openBrowser(origin: string) {
35
+ const command = process.platform === 'darwin' ? 'open' : 'xdg-open';
36
+ await new Promise<void>(accept => {
37
+ const child = spawn(command, [origin], { stdio: 'ignore' });
38
+ child.once('error', () => { console.error(`Open ${origin} in your browser.`); accept(); });
39
+ child.once('exit', code => { if (code) console.error(`Open ${origin} in your browser.`); accept(); });
40
+ });
41
+ }
42
+
43
+ export async function runStart(args: string[], root: string) {
44
+ if (packageIdentity(await packageMetadata()).edition === 'headless') throw new Error('OpenDoc Headless has no browser service. Use npx opendoc create, review, and export to produce files, then deliver the PDF or PowerPoint directly.');
45
+ const { values, positionals } = parseArgs({ args, allowPositionals: true, options: { 'no-open': { type: 'boolean' }, json: { type: 'boolean' }, help: { type: 'boolean', short: 'h' } } });
46
+ const usage = 'Usage: npx opendoc start [folder] [--no-open] [--json]\nRuns the installed workspace version. Ctrl+C stops the server.';
47
+ if (values.help) { console.log(values.json ? JSON.stringify({ usage }) : usage); return; }
48
+ if (positionals.length) throw new Error(usage);
49
+ let child: ChildProcess | undefined;
50
+ let exited: Promise<{ code: number | null; signal: NodeJS.Signals | null }> | undefined;
51
+ let stopped: { code: number | null; signal: NodeJS.Signals | null } | undefined;
52
+ let startupFailure: Error | undefined;
53
+ const forwardInterrupt = () => child?.kill('SIGINT');
54
+ const forwardTerminate = () => child?.kill('SIGTERM');
55
+ process.on('SIGINT', forwardInterrupt);
56
+ process.on('SIGTERM', forwardTerminate);
57
+ try {
58
+ const ready = await withWorkspaceLock(root, async () => {
59
+ const existing = await runningSession(root);
60
+ if (existing) return { ...existing, reused: true };
61
+ await validateInstallation();
62
+ child = spawn(process.execPath, ['--import', runtimeResolve('tsx'), runtimeSource('server/index.ts'), '--production'], { cwd: root, stdio: ['inherit', values.json ? 'pipe' : 'inherit', 'inherit'] });
63
+ if (values.json) child.stdout?.on('data', data => process.stderr.write(data));
64
+ exited = new Promise((accept, reject) => {
65
+ child!.once('error', error => { startupFailure = error; reject(error); });
66
+ child!.once('exit', (code, signal) => { stopped = { code, signal }; accept(stopped); });
67
+ });
68
+ // Attach a handler immediately so a spawn error cannot become an unhandled rejection.
69
+ void exited.catch(() => {});
70
+ const deadline = Date.now() + 30_000;
71
+ while (Date.now() < deadline) {
72
+ if (startupFailure) throw startupFailure;
73
+ if (stopped) throw new Error(`OpenDoc stopped during startup (${stopped.signal ?? stopped.code}).`);
74
+ const session = await runningSession(root);
75
+ if (session && child.pid && session.pid === child.pid) return { ...session, reused: false };
76
+ await setTimeout(100);
77
+ }
78
+ throw new Error('OpenDoc did not become ready within 30 seconds. See its terminal output.');
79
+ });
80
+ const { version } = await packageMetadata();
81
+ if (values.json) console.log(JSON.stringify({ workspace: root, version, origin: ready.origin, reused: ready.reused }));
82
+ else if (ready.reused) console.log(`OpenDoc is already running at ${ready.origin}`);
83
+ if (!values['no-open']) await openBrowser(ready.origin);
84
+ if (exited) {
85
+ const result = await exited;
86
+ if (result.code) process.exitCode = result.code;
87
+ else if (result.signal && !['SIGINT', 'SIGTERM'].includes(result.signal)) process.exitCode = 1;
88
+ }
89
+ } catch (error) {
90
+ child?.kill('SIGTERM');
91
+ throw error;
92
+ } finally {
93
+ process.off('SIGINT', forwardInterrupt);
94
+ process.off('SIGTERM', forwardTerminate);
95
+ }
96
+ }