@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.
- package/.agents/skills/opendoc-apply-comments/SKILL.md +30 -0
- package/.agents/skills/opendoc-apply-comments/agents/openai.yaml +4 -0
- package/.agents/skills/opendoc-create/SKILL.md +63 -0
- package/.agents/skills/opendoc-create/agents/openai.yaml +6 -0
- package/.agents/skills/opendoc-create-template/SKILL.md +50 -0
- package/.agents/skills/opendoc-create-template/agents/openai.yaml +4 -0
- package/.agents/skills/opendoc-create-template/references/structured-reports.md +11 -0
- package/.agents/skills/opendoc-create-theme/SKILL.md +40 -0
- package/.agents/skills/opendoc-create-theme/agents/openai.yaml +4 -0
- package/.agents/skills/opendoc-current-document/SKILL.md +32 -0
- package/.agents/skills/opendoc-current-document/agents/openai.yaml +4 -0
- package/.agents/skills/opendoc-current-document/references/context-fields.md +20 -0
- package/.agents/skills/opendoc-review-document/SKILL.md +60 -0
- package/.agents/skills/opendoc-review-document/agents/openai.yaml +4 -0
- package/AGENTS.md +69 -0
- package/CONTRIBUTING.md +38 -0
- package/LICENSE +21 -0
- package/README.md +179 -0
- package/SECURITY.md +9 -0
- package/THIRD_PARTY.md +49 -0
- package/VALIDATION.md +99 -0
- package/bin/opendoc.mjs +6 -0
- package/dist/assets/Markdown-sNZyjJi7.js +29 -0
- package/dist/assets/OpenDocSerif-Regular-D3OXs9A9.ttf +0 -0
- package/dist/assets/OpenDocSerif-Semibold-CjL9oDRo.ttf +0 -0
- package/dist/assets/geist-latin-ext-wght-italic-XgKbg5n7.woff2 +0 -0
- package/dist/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dist/assets/geist-latin-wght-italic-dTnRTFFJ.woff2 +0 -0
- package/dist/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/assets/index-DdrZ6ozO.css +1 -0
- package/dist/assets/index-DgNBz7mL.js +39 -0
- package/dist/assets/pdf-B7Emtyld.js +54 -0
- package/dist/assets/pdf.worker.min-Dswkl-cV.mjs +29 -0
- package/dist/assets/wordmark-DsqLlZpb.png +0 -0
- package/dist/index.html +17 -0
- package/docs/APPEARANCE.md +21 -0
- package/docs/ASSETS.md +176 -0
- package/docs/AUTHORING.md +178 -0
- package/docs/HEADLESS.md +120 -0
- package/docs/MEDIA.md +112 -0
- package/docs/PROJECTS.md +55 -0
- package/docs/PROSE.md +15 -0
- package/docs/SELECTION.md +59 -0
- package/docs/TEMPLATES.md +55 -0
- package/docs/THEMES.md +106 -0
- package/node_modules/@formepdf/core/LICENSE +21 -0
- package/node_modules/@formepdf/core/README.md +53 -0
- package/node_modules/@formepdf/core/dist/attachments.d.ts +55 -0
- package/node_modules/@formepdf/core/dist/attachments.js +59 -0
- package/node_modules/@formepdf/core/dist/extract.d.ts +8 -0
- package/node_modules/@formepdf/core/dist/extract.js +56 -0
- package/node_modules/@formepdf/core/dist/index.d.ts +311 -0
- package/node_modules/@formepdf/core/dist/index.js +167 -0
- package/node_modules/@formepdf/core/dist/layout.d.ts +132 -0
- package/node_modules/@formepdf/core/dist/layout.js +240 -0
- package/node_modules/@formepdf/core/dist/shared/browserHelpers.d.ts +19 -0
- package/node_modules/@formepdf/core/dist/shared/browserHelpers.js +128 -0
- package/node_modules/@formepdf/core/package.json +35 -0
- package/node_modules/@formepdf/core/pkg-node/LICENSE +21 -0
- package/node_modules/@formepdf/core/pkg-node/README.md +84 -0
- package/node_modules/@formepdf/core/pkg-node/forme.d.ts +39 -0
- package/node_modules/@formepdf/core/pkg-node/forme.js +394 -0
- package/node_modules/@formepdf/core/pkg-node/forme_bg.wasm +0 -0
- package/node_modules/@formepdf/core/pkg-node/forme_bg.wasm.d.ts +21 -0
- package/node_modules/@formepdf/core/pkg-node/package.json +25 -0
- package/node_modules/@formepdf/react/README.md +70 -0
- package/node_modules/@formepdf/react/dist/charts.d.ts +72 -0
- package/node_modules/@formepdf/react/dist/charts.js +338 -0
- package/node_modules/@formepdf/react/dist/components.d.ts +533 -0
- package/node_modules/@formepdf/react/dist/components.js +608 -0
- package/node_modules/@formepdf/react/dist/expr.d.ts +20 -0
- package/node_modules/@formepdf/react/dist/expr.js +39 -0
- package/node_modules/@formepdf/react/dist/font.d.ts +2 -0
- package/node_modules/@formepdf/react/dist/font.js +1 -0
- package/node_modules/@formepdf/react/dist/index.d.ts +11 -0
- package/node_modules/@formepdf/react/dist/index.js +15 -0
- package/node_modules/@formepdf/react/dist/render.d.ts +12 -0
- package/node_modules/@formepdf/react/dist/render.js +15 -0
- package/node_modules/@formepdf/react/dist/serialize.d.ts +12 -0
- package/node_modules/@formepdf/react/dist/serialize.js +1470 -0
- package/node_modules/@formepdf/react/dist/stylesheet.d.ts +4 -0
- package/node_modules/@formepdf/react/dist/stylesheet.js +5 -0
- package/node_modules/@formepdf/react/dist/template-proxy.d.ts +38 -0
- package/node_modules/@formepdf/react/dist/template-proxy.js +100 -0
- package/node_modules/@formepdf/react/dist/types.d.ts +287 -0
- package/node_modules/@formepdf/react/dist/types.js +1 -0
- package/node_modules/@formepdf/react/package.json +41 -0
- package/node_modules/@formepdf/shared/README.md +7 -0
- package/node_modules/@formepdf/shared/dist/canvas.d.ts +6 -0
- package/node_modules/@formepdf/shared/dist/canvas.js +43 -0
- package/node_modules/@formepdf/shared/dist/charts.d.ts +100 -0
- package/node_modules/@formepdf/shared/dist/charts.js +98 -0
- package/node_modules/@formepdf/shared/dist/encode.d.ts +27 -0
- package/node_modules/@formepdf/shared/dist/encode.js +93 -0
- package/node_modules/@formepdf/shared/dist/font.d.ts +13 -0
- package/node_modules/@formepdf/shared/dist/font.js +52 -0
- package/node_modules/@formepdf/shared/dist/index.d.ts +10 -0
- package/node_modules/@formepdf/shared/dist/index.js +15 -0
- package/node_modules/@formepdf/shared/dist/parser.d.ts +30 -0
- package/node_modules/@formepdf/shared/dist/parser.js +756 -0
- package/node_modules/@formepdf/shared/dist/semantics.d.ts +15 -0
- package/node_modules/@formepdf/shared/dist/semantics.js +44 -0
- package/node_modules/@formepdf/shared/dist/style.d.ts +7 -0
- package/node_modules/@formepdf/shared/dist/style.js +1024 -0
- package/node_modules/@formepdf/shared/dist/types.d.ts +743 -0
- package/node_modules/@formepdf/shared/dist/types.js +2 -0
- package/node_modules/@formepdf/shared/package.json +35 -0
- package/node_modules/@types/node/LICENSE +21 -0
- package/node_modules/@types/node/README.md +15 -0
- package/node_modules/@types/node/assert/strict.d.ts +111 -0
- package/node_modules/@types/node/assert.d.ts +1078 -0
- package/node_modules/@types/node/async_hooks.d.ts +603 -0
- package/node_modules/@types/node/buffer.buffer.d.ts +472 -0
- package/node_modules/@types/node/buffer.d.ts +1934 -0
- package/node_modules/@types/node/child_process.d.ts +1476 -0
- package/node_modules/@types/node/cluster.d.ts +578 -0
- package/node_modules/@types/node/compatibility/disposable.d.ts +14 -0
- package/node_modules/@types/node/compatibility/index.d.ts +9 -0
- package/node_modules/@types/node/compatibility/indexable.d.ts +20 -0
- package/node_modules/@types/node/compatibility/iterators.d.ts +20 -0
- package/node_modules/@types/node/console.d.ts +452 -0
- package/node_modules/@types/node/constants.d.ts +21 -0
- package/node_modules/@types/node/crypto.d.ts +4545 -0
- package/node_modules/@types/node/dgram.d.ts +600 -0
- package/node_modules/@types/node/diagnostics_channel.d.ts +576 -0
- package/node_modules/@types/node/dns/promises.d.ts +503 -0
- package/node_modules/@types/node/dns.d.ts +923 -0
- package/node_modules/@types/node/domain.d.ts +170 -0
- package/node_modules/@types/node/events.d.ts +976 -0
- package/node_modules/@types/node/fs/promises.d.ts +1306 -0
- package/node_modules/@types/node/fs.d.ts +4463 -0
- package/node_modules/@types/node/globals.d.ts +172 -0
- package/node_modules/@types/node/globals.typedarray.d.ts +38 -0
- package/node_modules/@types/node/http.d.ts +2097 -0
- package/node_modules/@types/node/http2.d.ts +2843 -0
- package/node_modules/@types/node/https.d.ts +579 -0
- package/node_modules/@types/node/index.d.ts +98 -0
- package/node_modules/@types/node/inspector.d.ts +253 -0
- package/node_modules/@types/node/inspector.generated.d.ts +4052 -0
- package/node_modules/@types/node/module.d.ts +891 -0
- package/node_modules/@types/node/net.d.ts +1076 -0
- package/node_modules/@types/node/os.d.ts +506 -0
- package/node_modules/@types/node/package.json +145 -0
- package/node_modules/@types/node/path.d.ts +200 -0
- package/node_modules/@types/node/perf_hooks.d.ts +968 -0
- package/node_modules/@types/node/process.d.ts +2084 -0
- package/node_modules/@types/node/punycode.d.ts +117 -0
- package/node_modules/@types/node/querystring.d.ts +152 -0
- package/node_modules/@types/node/readline/promises.d.ts +161 -0
- package/node_modules/@types/node/readline.d.ts +594 -0
- package/node_modules/@types/node/repl.d.ts +428 -0
- package/node_modules/@types/node/sea.d.ts +162 -0
- package/node_modules/@types/node/sqlite.d.ts +722 -0
- package/node_modules/@types/node/stream/consumers.d.ts +38 -0
- package/node_modules/@types/node/stream/promises.d.ts +90 -0
- package/node_modules/@types/node/stream/web.d.ts +573 -0
- package/node_modules/@types/node/stream.d.ts +1694 -0
- package/node_modules/@types/node/string_decoder.d.ts +67 -0
- package/node_modules/@types/node/test.d.ts +2265 -0
- package/node_modules/@types/node/timers/promises.d.ts +108 -0
- package/node_modules/@types/node/timers.d.ts +287 -0
- package/node_modules/@types/node/tls.d.ts +1319 -0
- package/node_modules/@types/node/trace_events.d.ts +197 -0
- package/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +468 -0
- package/node_modules/@types/node/ts5.6/globals.typedarray.d.ts +34 -0
- package/node_modules/@types/node/ts5.6/index.d.ts +98 -0
- package/node_modules/@types/node/tty.d.ts +208 -0
- package/node_modules/@types/node/url.d.ts +984 -0
- package/node_modules/@types/node/util.d.ts +2606 -0
- package/node_modules/@types/node/v8.d.ts +920 -0
- package/node_modules/@types/node/vm.d.ts +1053 -0
- package/node_modules/@types/node/wasi.d.ts +181 -0
- package/node_modules/@types/node/web-globals/abortcontroller.d.ts +34 -0
- package/node_modules/@types/node/web-globals/domexception.d.ts +68 -0
- package/node_modules/@types/node/web-globals/events.d.ts +97 -0
- package/node_modules/@types/node/web-globals/fetch.d.ts +55 -0
- package/node_modules/@types/node/web-globals/navigator.d.ts +22 -0
- package/node_modules/@types/node/web-globals/storage.d.ts +24 -0
- package/node_modules/@types/node/web-globals/streams.d.ts +22 -0
- package/node_modules/@types/node/worker_threads.d.ts +819 -0
- package/node_modules/@types/node/zlib.d.ts +747 -0
- package/node_modules/@types/react/LICENSE +21 -0
- package/node_modules/@types/react/README.md +15 -0
- package/node_modules/@types/react/canary.d.ts +129 -0
- package/node_modules/@types/react/compiler-runtime.d.ts +4 -0
- package/node_modules/@types/react/experimental.d.ts +184 -0
- package/node_modules/@types/react/global.d.ts +166 -0
- package/node_modules/@types/react/index.d.ts +4378 -0
- package/node_modules/@types/react/jsx-dev-runtime.d.ts +33 -0
- package/node_modules/@types/react/jsx-runtime.d.ts +24 -0
- package/node_modules/@types/react/package.json +210 -0
- package/node_modules/@types/react/ts5.0/canary.d.ts +129 -0
- package/node_modules/@types/react/ts5.0/experimental.d.ts +184 -0
- package/node_modules/@types/react/ts5.0/global.d.ts +166 -0
- package/node_modules/@types/react/ts5.0/index.d.ts +4365 -0
- package/node_modules/@types/react/ts5.0/jsx-dev-runtime.d.ts +33 -0
- package/node_modules/@types/react/ts5.0/jsx-runtime.d.ts +24 -0
- package/node_modules/csstype/LICENSE +19 -0
- package/node_modules/csstype/README.md +291 -0
- package/node_modules/csstype/index.d.ts +22569 -0
- package/node_modules/csstype/index.js.flow +6863 -0
- package/node_modules/csstype/package.json +70 -0
- package/node_modules/entities/LICENSE +11 -0
- package/node_modules/entities/decode.d.ts +1 -0
- package/node_modules/entities/decode.js +3 -0
- package/node_modules/entities/dist/commonjs/decode-codepoint.d.ts +19 -0
- package/node_modules/entities/dist/commonjs/decode-codepoint.d.ts.map +1 -0
- package/node_modules/entities/dist/commonjs/decode-codepoint.js +77 -0
- package/node_modules/entities/dist/commonjs/decode-codepoint.js.map +1 -0
- package/node_modules/entities/dist/commonjs/decode.d.ts +209 -0
- package/node_modules/entities/dist/commonjs/decode.d.ts.map +1 -0
- package/node_modules/entities/dist/commonjs/decode.js +511 -0
- package/node_modules/entities/dist/commonjs/decode.js.map +1 -0
- package/node_modules/entities/dist/commonjs/encode.d.ts +22 -0
- package/node_modules/entities/dist/commonjs/encode.d.ts.map +1 -0
- package/node_modules/entities/dist/commonjs/encode.js +73 -0
- package/node_modules/entities/dist/commonjs/encode.js.map +1 -0
- package/node_modules/entities/dist/commonjs/escape.d.ts +43 -0
- package/node_modules/entities/dist/commonjs/escape.d.ts.map +1 -0
- package/node_modules/entities/dist/commonjs/escape.js +121 -0
- package/node_modules/entities/dist/commonjs/escape.js.map +1 -0
- package/node_modules/entities/dist/commonjs/generated/decode-data-html.d.ts +2 -0
- package/node_modules/entities/dist/commonjs/generated/decode-data-html.d.ts.map +1 -0
- package/node_modules/entities/dist/commonjs/generated/decode-data-html.js +10 -0
- package/node_modules/entities/dist/commonjs/generated/decode-data-html.js.map +1 -0
- package/node_modules/entities/dist/commonjs/generated/decode-data-xml.d.ts +2 -0
- package/node_modules/entities/dist/commonjs/generated/decode-data-xml.d.ts.map +1 -0
- package/node_modules/entities/dist/commonjs/generated/decode-data-xml.js +10 -0
- package/node_modules/entities/dist/commonjs/generated/decode-data-xml.js.map +1 -0
- package/node_modules/entities/dist/commonjs/generated/encode-html.d.ts +8 -0
- package/node_modules/entities/dist/commonjs/generated/encode-html.d.ts.map +1 -0
- package/node_modules/entities/dist/commonjs/generated/encode-html.js +13 -0
- package/node_modules/entities/dist/commonjs/generated/encode-html.js.map +1 -0
- package/node_modules/entities/dist/commonjs/index.d.ts +96 -0
- package/node_modules/entities/dist/commonjs/index.d.ts.map +1 -0
- package/node_modules/entities/dist/commonjs/index.js +131 -0
- package/node_modules/entities/dist/commonjs/index.js.map +1 -0
- package/node_modules/entities/dist/commonjs/package.json +3 -0
- package/node_modules/entities/dist/esm/decode-codepoint.d.ts +19 -0
- package/node_modules/entities/dist/esm/decode-codepoint.d.ts.map +1 -0
- package/node_modules/entities/dist/esm/decode-codepoint.js +72 -0
- package/node_modules/entities/dist/esm/decode-codepoint.js.map +1 -0
- package/node_modules/entities/dist/esm/decode.d.ts +209 -0
- package/node_modules/entities/dist/esm/decode.d.ts.map +1 -0
- package/node_modules/entities/dist/esm/decode.js +497 -0
- package/node_modules/entities/dist/esm/decode.js.map +1 -0
- package/node_modules/entities/dist/esm/encode.d.ts +22 -0
- package/node_modules/entities/dist/esm/encode.d.ts.map +1 -0
- package/node_modules/entities/dist/esm/encode.js +69 -0
- package/node_modules/entities/dist/esm/encode.js.map +1 -0
- package/node_modules/entities/dist/esm/escape.d.ts +43 -0
- package/node_modules/entities/dist/esm/escape.d.ts.map +1 -0
- package/node_modules/entities/dist/esm/escape.js +117 -0
- package/node_modules/entities/dist/esm/escape.js.map +1 -0
- package/node_modules/entities/dist/esm/generated/decode-data-html.d.ts +2 -0
- package/node_modules/entities/dist/esm/generated/decode-data-html.d.ts.map +1 -0
- package/node_modules/entities/dist/esm/generated/decode-data-html.js +7 -0
- package/node_modules/entities/dist/esm/generated/decode-data-html.js.map +1 -0
- package/node_modules/entities/dist/esm/generated/decode-data-xml.d.ts +2 -0
- package/node_modules/entities/dist/esm/generated/decode-data-xml.d.ts.map +1 -0
- package/node_modules/entities/dist/esm/generated/decode-data-xml.js +7 -0
- package/node_modules/entities/dist/esm/generated/decode-data-xml.js.map +1 -0
- package/node_modules/entities/dist/esm/generated/encode-html.d.ts +8 -0
- package/node_modules/entities/dist/esm/generated/encode-html.d.ts.map +1 -0
- package/node_modules/entities/dist/esm/generated/encode-html.js +10 -0
- package/node_modules/entities/dist/esm/generated/encode-html.js.map +1 -0
- package/node_modules/entities/dist/esm/index.d.ts +96 -0
- package/node_modules/entities/dist/esm/index.d.ts.map +1 -0
- package/node_modules/entities/dist/esm/index.js +107 -0
- package/node_modules/entities/dist/esm/index.js.map +1 -0
- package/node_modules/entities/dist/esm/package.json +3 -0
- package/node_modules/entities/escape.d.ts +1 -0
- package/node_modules/entities/escape.js +3 -0
- package/node_modules/entities/package.json +118 -0
- package/node_modules/entities/readme.md +122 -0
- package/node_modules/entities/src/decode-codepoint.ts +81 -0
- package/node_modules/entities/src/decode.spec.ts +320 -0
- package/node_modules/entities/src/decode.ts +620 -0
- package/node_modules/entities/src/encode.spec.ts +78 -0
- package/node_modules/entities/src/encode.ts +77 -0
- package/node_modules/entities/src/escape.spec.ts +14 -0
- package/node_modules/entities/src/escape.ts +148 -0
- package/node_modules/entities/src/generated/.eslintrc.json +10 -0
- package/node_modules/entities/src/generated/decode-data-html.ts +8 -0
- package/node_modules/entities/src/generated/decode-data-xml.ts +8 -0
- package/node_modules/entities/src/generated/encode-html.ts +17 -0
- package/node_modules/entities/src/index.spec.ts +125 -0
- package/node_modules/entities/src/index.ts +188 -0
- package/node_modules/parse5/LICENSE +19 -0
- package/node_modules/parse5/README.md +38 -0
- package/node_modules/parse5/dist/cjs/common/doctype.d.ts +4 -0
- package/node_modules/parse5/dist/cjs/common/doctype.js +118 -0
- package/node_modules/parse5/dist/cjs/common/error-codes.d.ts +67 -0
- package/node_modules/parse5/dist/cjs/common/error-codes.js +66 -0
- package/node_modules/parse5/dist/cjs/common/foreign-content.d.ts +9 -0
- package/node_modules/parse5/dist/cjs/common/foreign-content.js +237 -0
- package/node_modules/parse5/dist/cjs/common/html.d.ts +289 -0
- package/node_modules/parse5/dist/cjs/common/html.js +528 -0
- package/node_modules/parse5/dist/cjs/common/token.d.ts +84 -0
- package/node_modules/parse5/dist/cjs/common/token.js +24 -0
- package/node_modules/parse5/dist/cjs/common/unicode.d.ts +42 -0
- package/node_modules/parse5/dist/cjs/common/unicode.js +70 -0
- package/node_modules/parse5/dist/cjs/index.d.ts +71 -0
- package/node_modules/parse5/dist/cjs/index.js +54 -0
- package/node_modules/parse5/dist/cjs/package.json +1 -0
- package/node_modules/parse5/dist/cjs/parser/formatting-element-list.d.ts +36 -0
- package/node_modules/parse5/dist/cjs/parser/formatting-element-list.js +114 -0
- package/node_modules/parse5/dist/cjs/parser/index.d.ts +221 -0
- package/node_modules/parse5/dist/cjs/parser/index.js +3240 -0
- package/node_modules/parse5/dist/cjs/parser/open-element-stack.d.ts +53 -0
- package/node_modules/parse5/dist/cjs/parser/open-element-stack.js +328 -0
- package/node_modules/parse5/dist/cjs/serializer/index.d.ts +60 -0
- package/node_modules/parse5/dist/cjs/serializer/index.js +172 -0
- package/node_modules/parse5/dist/cjs/tokenizer/index.d.ts +247 -0
- package/node_modules/parse5/dist/cjs/tokenizer/index.js +2714 -0
- package/node_modules/parse5/dist/cjs/tokenizer/preprocessor.d.ts +36 -0
- package/node_modules/parse5/dist/cjs/tokenizer/preprocessor.js +200 -0
- package/node_modules/parse5/dist/cjs/tree-adapters/default.d.ts +84 -0
- package/node_modules/parse5/dist/cjs/tree-adapters/default.js +176 -0
- package/node_modules/parse5/dist/cjs/tree-adapters/interface.d.ts +255 -0
- package/node_modules/parse5/dist/cjs/tree-adapters/interface.js +2 -0
- package/node_modules/parse5/dist/common/doctype.d.ts +4 -0
- package/node_modules/parse5/dist/common/doctype.js +114 -0
- package/node_modules/parse5/dist/common/error-codes.d.ts +67 -0
- package/node_modules/parse5/dist/common/error-codes.js +63 -0
- package/node_modules/parse5/dist/common/foreign-content.d.ts +9 -0
- package/node_modules/parse5/dist/common/foreign-content.js +228 -0
- package/node_modules/parse5/dist/common/html.d.ts +289 -0
- package/node_modules/parse5/dist/common/html.js +523 -0
- package/node_modules/parse5/dist/common/token.d.ts +84 -0
- package/node_modules/parse5/dist/common/token.js +20 -0
- package/node_modules/parse5/dist/common/unicode.d.ts +42 -0
- package/node_modules/parse5/dist/common/unicode.js +62 -0
- package/node_modules/parse5/dist/index.d.ts +71 -0
- package/node_modules/parse5/dist/index.js +42 -0
- package/node_modules/parse5/dist/parser/formatting-element-list.d.ts +36 -0
- package/node_modules/parse5/dist/parser/formatting-element-list.js +110 -0
- package/node_modules/parse5/dist/parser/index.d.ts +221 -0
- package/node_modules/parse5/dist/parser/index.js +3245 -0
- package/node_modules/parse5/dist/parser/open-element-stack.d.ts +53 -0
- package/node_modules/parse5/dist/parser/open-element-stack.js +324 -0
- package/node_modules/parse5/dist/serializer/index.d.ts +60 -0
- package/node_modules/parse5/dist/serializer/index.js +168 -0
- package/node_modules/parse5/dist/tokenizer/index.d.ts +247 -0
- package/node_modules/parse5/dist/tokenizer/index.js +2710 -0
- package/node_modules/parse5/dist/tokenizer/preprocessor.d.ts +36 -0
- package/node_modules/parse5/dist/tokenizer/preprocessor.js +196 -0
- package/node_modules/parse5/dist/tree-adapters/default.d.ts +84 -0
- package/node_modules/parse5/dist/tree-adapters/default.js +173 -0
- package/node_modules/parse5/dist/tree-adapters/interface.d.ts +255 -0
- package/node_modules/parse5/dist/tree-adapters/interface.js +1 -0
- package/node_modules/parse5/package.json +50 -0
- package/node_modules/undici-types/LICENSE +21 -0
- package/node_modules/undici-types/README.md +6 -0
- package/node_modules/undici-types/agent.d.ts +31 -0
- package/node_modules/undici-types/api.d.ts +43 -0
- package/node_modules/undici-types/balanced-pool.d.ts +29 -0
- package/node_modules/undici-types/cache.d.ts +36 -0
- package/node_modules/undici-types/client.d.ts +108 -0
- package/node_modules/undici-types/connector.d.ts +34 -0
- package/node_modules/undici-types/content-type.d.ts +21 -0
- package/node_modules/undici-types/cookies.d.ts +28 -0
- package/node_modules/undici-types/diagnostics-channel.d.ts +66 -0
- package/node_modules/undici-types/dispatcher.d.ts +256 -0
- package/node_modules/undici-types/env-http-proxy-agent.d.ts +21 -0
- package/node_modules/undici-types/errors.d.ts +149 -0
- package/node_modules/undici-types/eventsource.d.ts +61 -0
- package/node_modules/undici-types/fetch.d.ts +209 -0
- package/node_modules/undici-types/file.d.ts +39 -0
- package/node_modules/undici-types/filereader.d.ts +54 -0
- package/node_modules/undici-types/formdata.d.ts +108 -0
- package/node_modules/undici-types/global-dispatcher.d.ts +9 -0
- package/node_modules/undici-types/global-origin.d.ts +7 -0
- package/node_modules/undici-types/handlers.d.ts +15 -0
- package/node_modules/undici-types/header.d.ts +4 -0
- package/node_modules/undici-types/index.d.ts +71 -0
- package/node_modules/undici-types/interceptors.d.ts +17 -0
- package/node_modules/undici-types/mock-agent.d.ts +50 -0
- package/node_modules/undici-types/mock-client.d.ts +25 -0
- package/node_modules/undici-types/mock-errors.d.ts +12 -0
- package/node_modules/undici-types/mock-interceptor.d.ts +93 -0
- package/node_modules/undici-types/mock-pool.d.ts +25 -0
- package/node_modules/undici-types/package.json +55 -0
- package/node_modules/undici-types/patch.d.ts +33 -0
- package/node_modules/undici-types/pool-stats.d.ts +19 -0
- package/node_modules/undici-types/pool.d.ts +39 -0
- package/node_modules/undici-types/proxy-agent.d.ts +28 -0
- package/node_modules/undici-types/readable.d.ts +65 -0
- package/node_modules/undici-types/retry-agent.d.ts +8 -0
- package/node_modules/undici-types/retry-handler.d.ts +116 -0
- package/node_modules/undici-types/util.d.ts +18 -0
- package/node_modules/undici-types/webidl.d.ts +228 -0
- package/node_modules/undici-types/websocket.d.ts +150 -0
- package/package.json +80 -0
- package/scripts/rebuild-forme.mjs +61 -0
- package/src/app/AppearanceControl.tsx +44 -0
- package/src/app/AssetThemeDefaults.tsx +87 -0
- package/src/app/AssetsBrowser.tsx +273 -0
- package/src/app/CommentDock.tsx +108 -0
- package/src/app/CreateDocumentDialog.tsx +51 -0
- package/src/app/DocumentActions.tsx +69 -0
- package/src/app/DocumentCard.tsx +50 -0
- package/src/app/DocumentViewControl.tsx +31 -0
- package/src/app/DocumentsBrowser.tsx +70 -0
- package/src/app/ExportHistoryDialog.tsx +86 -0
- package/src/app/ExportMenu.tsx +127 -0
- package/src/app/GuideDialog.tsx +80 -0
- package/src/app/InspectionLayer.tsx +77 -0
- package/src/app/LogoUploadDialog.tsx +92 -0
- package/src/app/Markdown.tsx +34 -0
- package/src/app/MaterialsBrowser.tsx +149 -0
- package/src/app/PageNumberInput.tsx +56 -0
- package/src/app/Pdf.tsx +561 -0
- package/src/app/ProjectDialogs.tsx +100 -0
- package/src/app/Reader.tsx +769 -0
- package/src/app/SearchField.tsx +13 -0
- package/src/app/Sidebar.tsx +86 -0
- package/src/app/SkillIndex.tsx +30 -0
- package/src/app/TemplatesBrowser.tsx +149 -0
- package/src/app/ThemesBrowser.tsx +159 -0
- package/src/app/api.ts +47 -0
- package/src/app/appearance.ts +35 -0
- package/src/app/assets.css +139 -0
- package/src/app/catalogPreview.ts +20 -0
- package/src/app/colors.css +167 -0
- package/src/app/comment-dock.css +53 -0
- package/src/app/commentDrafts.ts +67 -0
- package/src/app/componentCorrection.ts +17 -0
- package/src/app/edit-workbench.css +87 -0
- package/src/app/editSession.ts +238 -0
- package/src/app/editorRecovery.ts +25 -0
- package/src/app/export-history.css +31 -0
- package/src/app/export.css +17 -0
- package/src/app/guideLinks.ts +21 -0
- package/src/app/guides.css +40 -0
- package/src/app/main.tsx +221 -0
- package/src/app/materials.css +53 -0
- package/src/app/pdfLoading.ts +12 -0
- package/src/app/pdfSelection.ts +112 -0
- package/src/app/projects.css +63 -0
- package/src/app/reader-toolbar.css +65 -0
- package/src/app/selection.css +150 -0
- package/src/app/sidebar.css +60 -0
- package/src/app/skills.css +7 -0
- package/src/app/style.css +1061 -0
- package/src/app/templates.css +49 -0
- package/src/app/themes.css +80 -0
- package/src/app/ui/Icon.tsx +92 -0
- package/src/app/ui/README.md +27 -0
- package/src/app/ui/fonts.css +36 -0
- package/src/app/ui/index.tsx +223 -0
- package/src/app/ui/ui.css +388 -0
- package/src/app/useReaderPreview.ts +19 -0
- package/src/app/useTextEditing.ts +155 -0
- package/src/assets/adapter.ts +122 -0
- package/src/assets/files.ts +378 -0
- package/src/assets/import-worker.ts +294 -0
- package/src/assets/imports.ts +124 -0
- package/src/assets/index.ts +60 -0
- package/src/assets/store.ts +798 -0
- package/src/assets/usage.ts +118 -0
- package/src/cli/check.ts +25 -0
- package/src/cli/init.ts +119 -0
- package/src/cli/lock.ts +34 -0
- package/src/cli/main.ts +118 -0
- package/src/cli/process.ts +19 -0
- package/src/cli/start.ts +96 -0
- package/src/cli/update.ts +348 -0
- package/src/cli/workspace.ts +94 -0
- package/src/document/index.tsx +641 -0
- package/src/document/page.tsx +53 -0
- package/src/document/text-targets.tsx +162 -0
- package/src/media/files.ts +124 -0
- package/src/media/render.ts +63 -0
- package/src/rendering/resolve-sources.ts +84 -0
- package/src/runtime/jsx-dev-runtime.ts +2 -0
- package/src/runtime/jsx-runtime.ts +2 -0
- package/src/runtime/paths.ts +12 -0
- package/src/server/assets-cli.ts +162 -0
- package/src/server/assets-http.ts +100 -0
- package/src/server/client.ts +50 -0
- package/src/server/clipboard.ts +22 -0
- package/src/server/comments-cli.ts +64 -0
- package/src/server/comments.ts +130 -0
- package/src/server/create-cli.ts +33 -0
- package/src/server/create.ts +228 -0
- package/src/server/dependencies.ts +91 -0
- package/src/server/documents.ts +143 -0
- package/src/server/edits.ts +249 -0
- package/src/server/export-batch.ts +105 -0
- package/src/server/export-errors.ts +2 -0
- package/src/server/export-file.ts +57 -0
- package/src/server/export-inputs.ts +66 -0
- package/src/server/export-preview.ts +69 -0
- package/src/server/export.ts +32 -0
- package/src/server/exports.ts +283 -0
- package/src/server/files.ts +21 -0
- package/src/server/guides.ts +71 -0
- package/src/server/index.ts +432 -0
- package/src/server/materials.ts +39 -0
- package/src/server/media-cli.ts +73 -0
- package/src/server/media-mutations.ts +168 -0
- package/src/server/pptx.ts +160 -0
- package/src/server/preflight.ts +129 -0
- package/src/server/projects-cli.ts +29 -0
- package/src/server/projects.ts +187 -0
- package/src/server/render-error.ts +9 -0
- package/src/server/render-source.ts +24 -0
- package/src/server/render.ts +48 -0
- package/src/server/review-cli.ts +40 -0
- package/src/server/review.ts +161 -0
- package/src/server/selection.ts +23 -0
- package/src/server/source-overrides.ts +97 -0
- package/src/server/templates-cli.ts +51 -0
- package/src/server/templates.ts +186 -0
- package/src/server/text-layout.ts +41 -0
- package/src/server/text-source.ts +307 -0
- package/src/server/themes-cli.ts +59 -0
- package/src/server/themes.ts +215 -0
- package/src/server/ttf2eot.d.ts +3 -0
- package/src/server/worker.ts +166 -0
- package/src/server/workspace.ts +242 -0
- package/src/shared/anchors.ts +69 -0
- package/src/shared/assets.ts +154 -0
- package/src/shared/export.ts +34 -0
- package/src/shared/media.ts +33 -0
- package/src/shared/projects.ts +19 -0
- package/src/shared/selection.ts +94 -0
- package/src/shared/skill-index.ts +14 -0
- package/src/shared/starters.ts +19 -0
- package/src/shared/templates.ts +18 -0
- package/src/shared/themes.ts +24 -0
- package/src/shared/types.ts +39 -0
- package/src/template/index.ts +27 -0
- package/src/themes/index.ts +3 -0
- package/src/themes/neutral.ts +20 -0
- package/src/themes/types.ts +110 -0
- package/starter/assets/brand/wordmark.png +0 -0
- package/starter/assets/fonts/InterUI-LICENSE.txt +93 -0
- package/starter/assets/fonts/InterUI-Medium.ttf +0 -0
- package/starter/assets/fonts/InterUI-Regular.ttf +0 -0
- package/starter/assets/fonts/InterUI-source.json +19 -0
- package/starter/assets/fonts/OpenDocMono-Regular.ttf +0 -0
- package/starter/assets/fonts/OpenDocSans-Italic.ttf +0 -0
- package/starter/assets/fonts/OpenDocSans-Regular.ttf +0 -0
- package/starter/assets/fonts/OpenDocSans-Semibold.ttf +0 -0
- package/starter/assets/fonts/OpenDocSans-SemiboldItalic.ttf +0 -0
- package/starter/assets/fonts/OpenDocSerif-Italic.ttf +0 -0
- package/starter/assets/fonts/OpenDocSerif-Regular.ttf +0 -0
- package/starter/assets/fonts/OpenDocSerif-Semibold.ttf +0 -0
- package/starter/assets/fonts/OpenDocSerif-SemiboldItalic.ttf +0 -0
- package/starter/assets/fonts/SourceCode-LICENSE.md +93 -0
- package/starter/assets/fonts/SourceSans-LICENSE.md +93 -0
- package/starter/assets/fonts/SourceSerif-LICENSE.md +93 -0
- package/starter/assets/fonts/geist/OFL.txt +93 -0
- package/starter/assets/fonts/geist/asset.json +7 -0
- package/starter/assets/fonts/geist/files/1a9874b3be0fc168692a3d2327bccb4d28835653d3b91537a755296a467a83e3.ttf +0 -0
- package/starter/assets/fonts/geist/files/a8eefb873ba9c9020665f8a98302697ce1f3b79ab2deef6ee508c0ca6a82e876.ttf +0 -0
- package/starter/assets/fonts/geist/files/ccce59465ae5c61930ada5453834f60500fbd95084d85db63e0e65fad0125455.ttf +0 -0
- package/starter/assets/fonts/geist/files/f5e95110d70593672515080bee9148463ada0a7f77b89ed65a3d43cb2b0ff83a.pdf +0 -0
- package/starter/assets/fonts/geist/revisions/9a2bc12fb2f23cb27bc227087e63e1407bb804ee0586480bd6b7966ec69fb474.json +60 -0
- package/starter/assets/fonts/inter/OFL.txt +93 -0
- package/starter/assets/fonts/inter/asset.json +7 -0
- package/starter/assets/fonts/inter/files/1b08e7fc267a5c7e1d614100f604b83e7e8a0be241f0f288faa2b3ac93a683ba.ttf +0 -0
- package/starter/assets/fonts/inter/files/5b6f0c6f26e5c554a64cdcc3a9b5d802b7f9aec6206f1dbcfcdcad7b5860a2a9.ttf +0 -0
- package/starter/assets/fonts/inter/files/957db8560d510a198a7d0333fae7b6b444b00c20801581126273978d778eb3c3.pdf +0 -0
- package/starter/assets/fonts/inter/files/b37284b5701b6b168dfc770aa1a4ac492106422fd3ba76bc7641e37434e8019c.ttf +0 -0
- package/starter/assets/fonts/inter/files/c1811d32ac0f6eed1bbf57529f2ecdfc6c717d48a969dd864942436315a1b198.ttf +0 -0
- package/starter/assets/fonts/inter/files/e7a1aaf7eda9f2fad4131725fa556265ec75ca7b2d756260173a040363e8d4f7.ttf +0 -0
- package/starter/assets/fonts/inter/files/ef8f755d933b9310804cc9152f1f18cb2ac460d6b05054ec913d889c9f11f79e.ttf +0 -0
- package/starter/assets/fonts/inter/revisions/600391517c413963b71e278a57c26c40366c81fa3939a6b9755f446206766d12.json +99 -0
- package/starter/assets/fonts/inter/source.json +57 -0
- package/starter/assets/fonts/lato/OFL.txt +93 -0
- package/starter/assets/fonts/lato/asset.json +7 -0
- package/starter/assets/fonts/lato/files/4a6b566dbb28adb473a8789ce5169306f42f0c8a070ac92bae93636f36348b0d.pdf +0 -0
- package/starter/assets/fonts/lato/files/5adeb6b334d8fb99ef053bc052b952773d544315e0e1d668a12c0ce8bd51375c.ttf +0 -0
- package/starter/assets/fonts/lato/files/62c1b7f0d2e74b45960154c3520efc337b553db0961bfdc950d5618334596cc8.ttf +0 -0
- package/starter/assets/fonts/lato/files/71b8b7decbe75a881ed267be539d402bd1e9420b799658aada4e0d1bd5af803c.ttf +0 -0
- package/starter/assets/fonts/lato/files/8a0aace75d33794eece4b28187bfc1df0bbd2888b5d8a56e01788c8d65d16be1.ttf +0 -0
- package/starter/assets/fonts/lato/files/d636e4683231f931eda222d588e944d082bfd3bdba02f928bee461c0f185b251.ttf +0 -0
- package/starter/assets/fonts/lato/files/e399c44efe1387100531d26c7e4800c5d12251b890d6654a3098c7c679cb1786.ttf +0 -0
- package/starter/assets/fonts/lato/revisions/49ccb93400a9d466fab7d9843b1ecf8916ec6d47a475dd79a597a22eb39616bc.json +99 -0
- package/starter/assets/fonts/lato/source.json +57 -0
- package/starter/assets/fonts/merriweather/OFL.txt +93 -0
- package/starter/assets/fonts/merriweather/asset.json +7 -0
- package/starter/assets/fonts/merriweather/files/1c54f91b910454251c4c2b7bd4e472e1abf265fba7ca3c0ef2eee2f41324099e.ttf +0 -0
- package/starter/assets/fonts/merriweather/files/8bde8da2bb7f0265e27ba0481f70bb48d0f98a976c145f2f239c648ddd6532e0.pdf +0 -0
- package/starter/assets/fonts/merriweather/files/90b7db4460fcd1a5ca49575c2668a793f3cd6447664d312a068d690e1c01e6bc.ttf +0 -0
- package/starter/assets/fonts/merriweather/files/afff81272b7653417bb6f8bef57add055b1f9fda36f27eba5f32b40752bd08da.ttf +0 -0
- package/starter/assets/fonts/merriweather/files/e029d3b71e5bae3877c73f4f2b15af28db16593d49b0aed2a328d37ff7075846.ttf +0 -0
- package/starter/assets/fonts/merriweather/files/e9864a6790bf712a04e20f3662b206a1535186ed3e877fd859dd5fb9682335df.ttf +0 -0
- package/starter/assets/fonts/merriweather/files/fa71baebdd20a7d0de2e5e445a5922530fe9e1d740efbe791f113b682d3cb093.ttf +0 -0
- package/starter/assets/fonts/merriweather/revisions/1888e390b3e4f38a3d7cd2dc1bb805aeb6ce13f986a97656f0265fd436bc91d2.json +99 -0
- package/starter/assets/fonts/merriweather/source.json +57 -0
- package/starter/assets/fonts/open-sans/OFL.txt +92 -0
- package/starter/assets/fonts/open-sans/asset.json +7 -0
- package/starter/assets/fonts/open-sans/files/1bc0594a83762b2c25d38915a34464b7fec6088298ca22d151757bf98d6700ec.ttf +0 -0
- package/starter/assets/fonts/open-sans/files/47ed1cfaa7ffca04a04ab850b2938fd52c09d1b44cfa3e2980878e166b0cbd87.ttf +0 -0
- package/starter/assets/fonts/open-sans/files/574939af301f07df8e21cfff279465c5981dd9d9cf62086f7515897df951c6f5.pdf +0 -0
- package/starter/assets/fonts/open-sans/files/6d3884d0d57c1b67e9c50c54eca7b69c535c114e76bd7a9cfda0258588185553.ttf +0 -0
- package/starter/assets/fonts/open-sans/files/733eb93b167e6d45de09aa768f6c0355647c2c26f5416dbc7407a08ed41e81c6.ttf +0 -0
- package/starter/assets/fonts/open-sans/files/75367e6da7d914eaed87883ba51b2a2b5816b5cdbb39f96ec5c81a5b032bfd5a.ttf +0 -0
- package/starter/assets/fonts/open-sans/files/ff4fdc11204e0edd14e9a0bb6c374b847a9093b0ec2c16702e03afca79ac4ef7.ttf +0 -0
- package/starter/assets/fonts/open-sans/revisions/bbbe3a4915b9bccbc883c0decb4097511c43b6bd09ae22a1516aff128c219bc5.json +99 -0
- package/starter/assets/fonts/open-sans/source.json +57 -0
- package/starter/assets/fonts/roboto/OFL.txt +93 -0
- package/starter/assets/fonts/roboto/asset.json +7 -0
- package/starter/assets/fonts/roboto/files/22d45d989248a624252b8382067ac56550212fa675dcdbaf12f03d297dd87a58.pdf +0 -0
- package/starter/assets/fonts/roboto/files/35757eaa996b3359022f47f164a67ee9eac04971af24c5b8fbd4b89e844ff190.ttf +0 -0
- package/starter/assets/fonts/roboto/files/4d3035883c531846bd1ce2dc89f36d932e72dc114f56062c7e3a9cdd74f3d3ea.ttf +0 -0
- package/starter/assets/fonts/roboto/files/be7639306a4fc4a02ce2ae2ff59eb1335e4db4a7379dd0a384ed7cc053817789.ttf +0 -0
- package/starter/assets/fonts/roboto/files/d2920cbb1b60a3fd11fbf22049286e43a6baf522d37fdf1e7c89562319bcfea5.ttf +0 -0
- package/starter/assets/fonts/roboto/files/dece7c71bbe61710787f0839c722c65e87355dd2eb4a823e6b5488121ff81e4b.ttf +0 -0
- package/starter/assets/fonts/roboto/files/f478ba88b0292e685e487901dfbb1401457d32d6ebee4030cdfd5698235bffa8.ttf +0 -0
- package/starter/assets/fonts/roboto/revisions/bda5e2d84c17313373dd2dbf3e64fe0dd450c7e1b59e6929e69557e122fe976e.json +99 -0
- package/starter/assets/fonts/roboto/source.json +57 -0
- package/starter/assets/logos/opendoc/asset.json +6 -0
- package/starter/assets/logos/opendoc/files/831d5ccd9eb6709cc8439ea257c03d81452e81a28a3d1eedbd6a3b7daff687b6.png +0 -0
- package/starter/assets/logos/opendoc/revisions/834dde8926ddb81de687254195a168bb13bfb77803307f1257de1f2228be63b2.json +33 -0
- package/starter/assets/ui-fonts/geist/OFL.txt +93 -0
- package/starter/assets/ui-fonts/geist/geist-latin-ext-wght-italic.woff2 +0 -0
- package/starter/assets/ui-fonts/geist/geist-latin-ext-wght-normal.woff2 +0 -0
- package/starter/assets/ui-fonts/geist/geist-latin-wght-italic.woff2 +0 -0
- package/starter/assets/ui-fonts/geist/geist-latin-wght-normal.woff2 +0 -0
- package/starter/assets/ui-fonts/geist/source.json +26 -0
- package/starter/documents/welcome/assets.json +7 -0
- package/starter/documents/welcome/index.tsx +160 -0
- package/starter/documents/welcome/media/.gitkeep +0 -0
- package/starter/documents/welcome/media/paper-architecture/image.png +0 -0
- package/starter/documents/welcome/media/paper-architecture/meta.json +9 -0
- package/starter/documents/welcome/media/paper-architecture/prompt.txt +1 -0
- package/starter/documents/welcome/media/studio-rhythm/chart.svg +2343 -0
- package/starter/documents/welcome/media/studio-rhythm/data.json +234 -0
- package/starter/documents/welcome/media/studio-rhythm/generation.json +9 -0
- package/starter/documents/welcome/media/studio-rhythm/image.png +0 -0
- package/starter/documents/welcome/media/studio-rhythm/meta.json +11 -0
- package/starter/documents/welcome/media/studio-rhythm/recipe.py +79 -0
- package/starter/documents/welcome/theme.tsx +5 -0
- package/starter/documents/welcome-presentation/assets.json +7 -0
- package/starter/documents/welcome-presentation/index.tsx +166 -0
- package/starter/documents/welcome-presentation/media/.gitkeep +0 -0
- package/starter/documents/welcome-presentation/media/paper-architecture/image.png +0 -0
- package/starter/documents/welcome-presentation/media/paper-architecture/meta.json +9 -0
- package/starter/documents/welcome-presentation/media/paper-architecture/prompt.txt +1 -0
- package/starter/documents/welcome-presentation/media/studio-rhythm/chart.svg +1336 -0
- package/starter/documents/welcome-presentation/media/studio-rhythm/data.json +234 -0
- package/starter/documents/welcome-presentation/media/studio-rhythm/generation.json +9 -0
- package/starter/documents/welcome-presentation/media/studio-rhythm/image.png +0 -0
- package/starter/documents/welcome-presentation/media/studio-rhythm/meta.json +13 -0
- package/starter/documents/welcome-presentation/media/studio-rhythm/recipe.py +49 -0
- package/starter/documents/welcome-presentation/theme.tsx +5 -0
- package/starter/projects.json +17 -0
- package/starter/templates/AGENTS.md +9 -0
- package/starter/templates/_shared/BusinessLogo.tsx +14 -0
- package/starter/templates/_shared/Pricing.tsx +40 -0
- package/starter/templates/_shared/commerce.ts +93 -0
- package/starter/templates/brand-guidelines/AGENTS.md +32 -0
- package/starter/templates/brand-guidelines/index.tsx +62 -0
- package/starter/templates/brand-guidelines/preview.tsx +181 -0
- package/starter/templates/brand-guidelines/starter.tsx +179 -0
- package/starter/templates/brand-guidelines/template.json +15 -0
- package/starter/templates/business-proposal/AGENTS.md +13 -0
- package/starter/templates/business-proposal/README.md +36 -0
- package/starter/templates/business-proposal/data.json +37 -0
- package/starter/templates/business-proposal/examples/long.json +142 -0
- package/starter/templates/business-proposal/examples/sparse.json +17 -0
- package/starter/templates/business-proposal/examples/typical.json +37 -0
- package/starter/templates/business-proposal/index.tsx +59 -0
- package/starter/templates/business-proposal/preview.tsx +47 -0
- package/starter/templates/business-proposal/schema.ts +14 -0
- package/starter/templates/business-proposal/starter.tsx +18 -0
- package/starter/templates/business-proposal/template.json +11 -0
- package/starter/templates/company-profile/AGENTS.md +48 -0
- package/starter/templates/company-profile/index.tsx +69 -0
- package/starter/templates/company-profile/preview.tsx +185 -0
- package/starter/templates/company-profile/starter.tsx +186 -0
- package/starter/templates/company-profile/template.json +15 -0
- package/starter/templates/consulting-report/AGENTS.md +11 -0
- package/starter/templates/consulting-report/README.md +13 -0
- package/starter/templates/consulting-report/RESEARCH.md +10 -0
- package/starter/templates/consulting-report/index.tsx +44 -0
- package/starter/templates/consulting-report/preview.tsx +39 -0
- package/starter/templates/consulting-report/starter.tsx +15 -0
- package/starter/templates/consulting-report/template.json +11 -0
- package/starter/templates/editorial-essay/AGENTS.md +11 -0
- package/starter/templates/editorial-essay/README.md +11 -0
- package/starter/templates/editorial-essay/index.tsx +30 -0
- package/starter/templates/editorial-essay/preview.tsx +26 -0
- package/starter/templates/editorial-essay/starter.tsx +15 -0
- package/starter/templates/editorial-essay/template.json +11 -0
- package/starter/templates/executive-brief/AGENTS.md +9 -0
- package/starter/templates/executive-brief/README.md +11 -0
- package/starter/templates/executive-brief/index.tsx +33 -0
- package/starter/templates/executive-brief/preview.tsx +37 -0
- package/starter/templates/executive-brief/starter.tsx +11 -0
- package/starter/templates/executive-brief/template.json +11 -0
- package/starter/templates/image-story/AGENTS.md +37 -0
- package/starter/templates/image-story/index.tsx +106 -0
- package/starter/templates/image-story/preview.tsx +33 -0
- package/starter/templates/image-story/starter.tsx +24 -0
- package/starter/templates/image-story/template.json +13 -0
- package/starter/templates/invoice/AGENTS.md +13 -0
- package/starter/templates/invoice/README.md +40 -0
- package/starter/templates/invoice/data.json +61 -0
- package/starter/templates/invoice/examples/long.json +241 -0
- package/starter/templates/invoice/examples/sparse.json +33 -0
- package/starter/templates/invoice/examples/typical.json +61 -0
- package/starter/templates/invoice/index.tsx +57 -0
- package/starter/templates/invoice/preview.tsx +12 -0
- package/starter/templates/invoice/schema.ts +45 -0
- package/starter/templates/invoice/starter.tsx +12 -0
- package/starter/templates/invoice/template.json +11 -0
- package/starter/templates/literary-text/AGENTS.md +9 -0
- package/starter/templates/literary-text/README.md +11 -0
- package/starter/templates/literary-text/index.tsx +31 -0
- package/starter/templates/literary-text/preview.tsx +20 -0
- package/starter/templates/literary-text/starter.tsx +11 -0
- package/starter/templates/literary-text/template.json +11 -0
- package/starter/templates/magazine-feature/AGENTS.md +11 -0
- package/starter/templates/magazine-feature/README.md +13 -0
- package/starter/templates/magazine-feature/index.tsx +41 -0
- package/starter/templates/magazine-feature/preview.tsx +34 -0
- package/starter/templates/magazine-feature/starter.tsx +15 -0
- package/starter/templates/magazine-feature/template.json +11 -0
- package/starter/templates/monthly-report/AGENTS.md +11 -0
- package/starter/templates/monthly-report/README.md +24 -0
- package/starter/templates/monthly-report/data.json +131 -0
- package/starter/templates/monthly-report/examples/long.json +519 -0
- package/starter/templates/monthly-report/examples/sparse.json +20 -0
- package/starter/templates/monthly-report/examples/typical.json +37 -0
- package/starter/templates/monthly-report/index.tsx +92 -0
- package/starter/templates/monthly-report/preview.tsx +14 -0
- package/starter/templates/monthly-report/schema.ts +127 -0
- package/starter/templates/monthly-report/starter.tsx +13 -0
- package/starter/templates/monthly-report/template.json +11 -0
- package/starter/templates/pitch-deck/AGENTS.md +32 -0
- package/starter/templates/pitch-deck/index.tsx +46 -0
- package/starter/templates/pitch-deck/preview.tsx +142 -0
- package/starter/templates/pitch-deck/starter.tsx +140 -0
- package/starter/templates/pitch-deck/template.json +15 -0
- package/starter/templates/proposal-deck/AGENTS.md +25 -0
- package/starter/templates/proposal-deck/index.tsx +52 -0
- package/starter/templates/proposal-deck/preview.tsx +172 -0
- package/starter/templates/proposal-deck/starter.tsx +168 -0
- package/starter/templates/proposal-deck/template.json +7 -0
- package/starter/templates/quotation/AGENTS.md +13 -0
- package/starter/templates/quotation/README.md +42 -0
- package/starter/templates/quotation/data.json +64 -0
- package/starter/templates/quotation/examples/long.json +272 -0
- package/starter/templates/quotation/examples/sparse.json +31 -0
- package/starter/templates/quotation/examples/typical.json +64 -0
- package/starter/templates/quotation/index.tsx +51 -0
- package/starter/templates/quotation/preview.tsx +12 -0
- package/starter/templates/quotation/schema.ts +27 -0
- package/starter/templates/quotation/starter.tsx +12 -0
- package/starter/templates/quotation/template.json +11 -0
- package/starter/templates/scientific-paper/AGENTS.md +11 -0
- package/starter/templates/scientific-paper/README.md +13 -0
- package/starter/templates/scientific-paper/index.tsx +47 -0
- package/starter/templates/scientific-paper/preview.tsx +43 -0
- package/starter/templates/scientific-paper/starter.tsx +15 -0
- package/starter/templates/scientific-paper/template.json +11 -0
- package/starter/themes/Specimen.tsx +54 -0
- package/starter/themes/civic-spectrum/components.tsx +92 -0
- package/starter/themes/civic-spectrum/design.md +70 -0
- package/starter/themes/civic-spectrum/index.ts +57 -0
- package/starter/themes/civic-spectrum/preview.tsx +66 -0
- package/starter/themes/field-manual/components.tsx +106 -0
- package/starter/themes/field-manual/design.md +72 -0
- package/starter/themes/field-manual/index.ts +57 -0
- package/starter/themes/field-manual/preview.tsx +82 -0
- package/starter/themes/index.ts +3 -0
- package/starter/themes/mckinsey-consulting/components.tsx +69 -0
- package/starter/themes/mckinsey-consulting/design.md +68 -0
- package/starter/themes/mckinsey-consulting/index.ts +60 -0
- package/starter/themes/mckinsey-consulting/preview.tsx +53 -0
- package/starter/themes/neutral/design.md +35 -0
- package/starter/themes/neutral/index.ts +21 -0
- package/starter/themes/neutral/preview.tsx +4 -0
- package/starter/themes/opendoc-neutral/components.tsx +77 -0
- package/starter/themes/opendoc-neutral/design.md +70 -0
- package/starter/themes/opendoc-neutral/index.ts +54 -0
- package/starter/themes/opendoc-neutral/preview.tsx +43 -0
- package/starter/themes/types.ts +3 -0
- package/tsconfig.workspace.json +24 -0
- package/vendor/formepdf/LICENSE +21 -0
- package/vendor/formepdf/README.md +97 -0
- package/vendor/formepdf/font-subset.patch +228 -0
- package/vendor/formepdf/text-writer.patch +507 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { constants } from 'node:fs';
|
|
2
|
+
import { lstat, mkdir, open, realpath, rmdir, unlink, link } from 'node:fs/promises';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
import { DOCUMENT_ID_MAX_LENGTH, TITLE_MAX_LENGTH, listStarters, type CreatedDocument, type StarterId, type StarterSummary } from '../shared/starters';
|
|
6
|
+
import { validId } from './render';
|
|
7
|
+
import { requireProject, selectedTheme, withProjects } from './projects';
|
|
8
|
+
import { resolveThemeAssets } from '../assets/files';
|
|
9
|
+
import { documentAssetAdapterSource } from '../assets/adapter';
|
|
10
|
+
|
|
11
|
+
export { listStarters } from '../shared/starters';
|
|
12
|
+
export type { CreateDocumentInput, CreatedDocument } from '../shared/starters';
|
|
13
|
+
|
|
14
|
+
type ErrorCode = 'INVALID_INPUT' | 'ALREADY_EXISTS' | 'UNSAFE_PATH' | 'CREATE_FAILED';
|
|
15
|
+
export class CreateDocumentError extends Error {
|
|
16
|
+
constructor(message: string, public code: ErrorCode, public status: 400 | 409 | 500) { super(message); this.name = 'CreateDocumentError'; }
|
|
17
|
+
}
|
|
18
|
+
const invalid = (message: string) => new CreateDocumentError(message, 'INVALID_INPUT', 400);
|
|
19
|
+
const unsafe = () => new CreateDocumentError('The document location changed or is not a regular workspace folder. Nothing was overwritten.', 'UNSAFE_PATH', 409);
|
|
20
|
+
const exists = (id: string, explicitId: boolean) => new CreateDocumentError(`A folder named "${id}" already exists. Choose a different ${explicitId ? 'document ID' : 'title'}.`, 'ALREADY_EXISTS', 409);
|
|
21
|
+
const isCode = (error: unknown, code: string) => error instanceof Error && 'code' in error && error.code === code;
|
|
22
|
+
|
|
23
|
+
async function inputValues(root: string, value: unknown) {
|
|
24
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) throw invalid('Provide a document title and project.');
|
|
25
|
+
const input = value as Record<string, unknown>;
|
|
26
|
+
if (Object.keys(input).some(key => !['title', 'starter', 'id', 'projectId', 'theme', 'format'].includes(key))) throw invalid('Only title, starter, project, theme, format, and an optional document ID are accepted.');
|
|
27
|
+
if (typeof input.projectId !== 'string' || !validId(input.projectId)) throw invalid('Choose a project before creating a document.');
|
|
28
|
+
let theme: string | null;
|
|
29
|
+
try { theme = await selectedTheme(root, input.theme); } catch { throw invalid('Choose an available theme.'); }
|
|
30
|
+
if (typeof input.title !== 'string' || !input.title.trim()) throw invalid('Give your document a title.');
|
|
31
|
+
const format = input.format ?? 'document';
|
|
32
|
+
if (format !== 'document' && format !== 'presentation') throw invalid('Choose document or presentation format.');
|
|
33
|
+
if (format === 'presentation' && input.starter !== undefined && input.starter !== 'blank') throw invalid('Presentations use a blank slide scaffold; document starters are not supported.');
|
|
34
|
+
const title = input.title.trim();
|
|
35
|
+
if (title.length > TITLE_MAX_LENGTH) throw invalid(`Keep the title to ${TITLE_MAX_LENGTH} characters or fewer.`);
|
|
36
|
+
if (/[\u0000-\u001f\u007f\u2028\u2029]/u.test(title)) throw invalid('The title must fit on one line and cannot contain control characters.');
|
|
37
|
+
const starter: StarterSummary | undefined = input.starter === undefined || input.starter === 'blank'
|
|
38
|
+
? { id: 'blank', name: 'Blank', description: '' }
|
|
39
|
+
: listStarters().find(item => item.id === input.starter);
|
|
40
|
+
if (!starter) throw invalid('Choose one of the available document starters.');
|
|
41
|
+
const derived = title.normalize('NFKD').replace(/\p{M}/gu, '').toLowerCase().replace(/[’']/g, '').replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, DOCUMENT_ID_MAX_LENGTH).replace(/-$/, '');
|
|
42
|
+
const id = input.id === undefined ? derived || 'untitled-document' : input.id;
|
|
43
|
+
if (typeof id !== 'string' || !validId(id) || id.length > DOCUMENT_ID_MAX_LENGTH) throw invalid(`Use a document ID of ${DOCUMENT_ID_MAX_LENGTH} characters or fewer, with lowercase letters, numbers, and single hyphens.`);
|
|
44
|
+
return { title, id, starter, format: format as 'document' | 'presentation', projectId: input.projectId, theme, explicitId: input.id !== undefined };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function sourceFor(starter: StarterSummary, title: string, themeOverride: string | null, format: 'document' | 'presentation') {
|
|
48
|
+
const theme = themeOverride ?? 'neutral';
|
|
49
|
+
if (format === 'presentation') return `import { Presentation, Slide, Heading, type DocumentMeta } from 'opendoc';
|
|
50
|
+
import { theme } from './theme';
|
|
51
|
+
|
|
52
|
+
export const meta: DocumentMeta = ${JSON.stringify({ title, description: '', theme }, null, 2)};
|
|
53
|
+
|
|
54
|
+
export default function Draft() {
|
|
55
|
+
return <Presentation title={meta.title} theme={theme}>
|
|
56
|
+
<Slide id="opening">
|
|
57
|
+
<Heading id="opening-title" level={1} style={{ fontSize: 44, lineHeight: 1.1 }}>{meta.title}</Heading>
|
|
58
|
+
</Slide>
|
|
59
|
+
</Presentation>;
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
const bodies: Record<StarterId, string> = {
|
|
63
|
+
blank: ` <TitleBlock id="opening" title={meta.title} />`,
|
|
64
|
+
article: ` <TitleBlock id="opening" eyebrow="Article · Working draft" title={meta.title} subtitle="Start with the idea you want the reader to carry away." />
|
|
65
|
+
<Paragraph id="opening-paragraph">Introduce the question, observation, or experience that makes this piece worth writing. Give the reader a concrete place to begin.</Paragraph>
|
|
66
|
+
<Section id="argument" title="Develop the idea" lead="Build the argument with specific examples and a clear thread between them.">
|
|
67
|
+
<Paragraph id="evidence">Add the evidence or experience that supports your point. Cite factual claims and distinguish your interpretation from what a source actually establishes.</Paragraph>
|
|
68
|
+
</Section>
|
|
69
|
+
<Section id="ending" title="Leave something with the reader" lead="Return to the opening idea with the understanding the piece has earned." />`,
|
|
70
|
+
report: ` <TitleBlock id="opening" eyebrow="Report · Working draft" title={meta.title} subtitle="A clear account of the question, the evidence, and what to do next." />
|
|
71
|
+
<Section id="summary" title="Executive summary" lead="State the question this report answers and the decision it supports. Write the final summary after reviewing the evidence." />
|
|
72
|
+
<Section id="findings" title="Findings" lead="Present the most relevant findings in a logical order.">
|
|
73
|
+
<Paragraph id="evidence">For each finding, identify the source, date, and any limits on what it can show. Replace this guidance with verified material.</Paragraph>
|
|
74
|
+
</Section>
|
|
75
|
+
<Section id="recommendation" title="Recommendation" lead="Explain the recommended action, who would own it, and what would count as progress.">
|
|
76
|
+
<Callout id="limitations" title="Before sharing">Make assumptions and unresolved questions explicit. This starter contains guidance only; it does not contain findings or verified claims.</Callout>
|
|
77
|
+
</Section>`,
|
|
78
|
+
proposal: ` <TitleBlock id="opening" eyebrow="Proposal · Working draft" title={meta.title} subtitle="A focused plan for a clearly defined need." />
|
|
79
|
+
<Section id="need" title="The need" lead="Describe the client's situation, the problem to solve, and the outcome that would make the work worthwhile." />
|
|
80
|
+
<Section id="approach" title="Proposed approach" lead="Explain how the work would proceed and why the approach fits this need.">
|
|
81
|
+
<List id="scope" items={[
|
|
82
|
+
{ id: 'deliverables', children: 'Deliverables — define the concrete outputs and how they will be accepted.' },
|
|
83
|
+
{ id: 'timing', children: 'Timing — name the phases, dependencies, and review points.' },
|
|
84
|
+
{ id: 'responsibilities', children: 'Responsibilities — explain what each party needs to provide.' },
|
|
85
|
+
]} />
|
|
86
|
+
</Section>
|
|
87
|
+
<Section id="commercials" title="Scope and next steps" lead="Specify the pricing basis, assumptions, exclusions, and the decision needed to proceed.">
|
|
88
|
+
<Paragraph id="terms-note">No prices, dates, commitments, or client facts have been supplied. Confirm them before presenting this as a proposal.</Paragraph>
|
|
89
|
+
</Section>`,
|
|
90
|
+
research: ` <TitleBlock id="opening" eyebrow="Research paper · Working draft" title={meta.title} subtitle="A question that can be examined, a method that can be understood." />
|
|
91
|
+
<Section id="abstract" title="Abstract" lead="Summarize the question, method, principal result, and limits only after the study is described. No results have been supplied in this starter." />
|
|
92
|
+
<Section id="introduction" title="Introduction" lead="Define the research question and explain its importance using traceable sources." />
|
|
93
|
+
<Section id="methods" title="Methods" lead="Describe the materials or data, selection criteria, procedure, and analysis in enough detail for another reader to evaluate the work." />
|
|
94
|
+
<Section id="results" title="Results" lead="Report the observations with units and uncertainty where appropriate. Separate measured results from interpretation." />
|
|
95
|
+
<Section id="discussion" title="Discussion and limitations" lead="Explain what the results support, what they do not support, and which limitations affect the conclusion.">
|
|
96
|
+
<Paragraph id="sources-note">Add verified reference records and cite them where they support the text. Do not use illustrative values as study results.</Paragraph>
|
|
97
|
+
</Section>`,
|
|
98
|
+
technical: ` <TitleBlock id="opening" eyebrow="Technical brief · Working draft" title={meta.title} subtitle="A decision that can be understood, implemented, and checked." />
|
|
99
|
+
<Section id="context" title="Context and requirements" lead="Explain the system or problem, the intended reader, and the constraints that shape the solution." />
|
|
100
|
+
<Section id="design" title="Design and decisions" lead="Describe the proposed design and the reasons for the main choices.">
|
|
101
|
+
<List id="decision-checks" items={[
|
|
102
|
+
{ id: 'interfaces', children: 'Interfaces — define inputs, outputs, and failure behavior.' },
|
|
103
|
+
{ id: 'tradeoffs', children: 'Tradeoffs — record the alternatives and why a choice was made.' },
|
|
104
|
+
{ id: 'constraints', children: 'Constraints — state performance, security, and compatibility requirements that actually apply.' },
|
|
105
|
+
]} />
|
|
106
|
+
</Section>
|
|
107
|
+
<Section id="verification" title="Verification" lead="Define the checks or measurements that will demonstrate the design works.">
|
|
108
|
+
<Paragraph id="verification-note">Record observed results separately from targets. Include relevant edge cases and unresolved risks; this starter makes no performance or reliability claims.</Paragraph>
|
|
109
|
+
</Section>`,
|
|
110
|
+
};
|
|
111
|
+
const body = bodies[starter.id];
|
|
112
|
+
const imports = ['Document', 'Pages', 'TitleBlock', ...(starter.id === 'blank' ? [] : ['Paragraph', 'Section']), ...(body.includes('<List') ? ['List'] : []), ...(body.includes('<Callout') ? ['Callout'] : [])];
|
|
113
|
+
return `import { ${imports.join(', ')}, type DocumentMeta } from 'opendoc';
|
|
114
|
+
import { theme } from './theme';
|
|
115
|
+
|
|
116
|
+
export const meta: DocumentMeta = ${JSON.stringify({ title, description: starter.description, ...(starter.id === 'blank' ? {} : { kind: starter.kind }), theme }, null, 2)};
|
|
117
|
+
|
|
118
|
+
// Ask Codex to develop this draft using your brief and sources. Keep block IDs stable as it grows.
|
|
119
|
+
export default function Draft() {
|
|
120
|
+
return <Document title={meta.title} theme={theme}>
|
|
121
|
+
<Pages title={meta.title}>
|
|
122
|
+
${body}
|
|
123
|
+
</Pages>
|
|
124
|
+
</Document>;
|
|
125
|
+
}
|
|
126
|
+
`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Reserve the folder exclusively, then expose index.tsx only after every companion file is complete. */
|
|
130
|
+
export async function createDocument(root: string, input: unknown): Promise<CreatedDocument> {
|
|
131
|
+
const values = await inputValues(root, input);
|
|
132
|
+
const workspace = await realpath(root);
|
|
133
|
+
return createInProject(workspace, values, async theme => ({ 'index.tsx': sourceFor(values.starter, values.title, theme, values.format) }));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export async function createDocumentFromFiles(root: string, input: { title: string; id?: string; projectId: string; theme?: string | null; format?: 'document' | 'presentation' }, files: Record<string, string> | ((id: string, theme: string | null) => Record<string, string> | Promise<Record<string, string>>)) {
|
|
137
|
+
const values = await inputValues(root, input);
|
|
138
|
+
return createInProject(root, values, async theme => typeof files === 'function' ? files(values.id, theme) : files);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function createInProject(root: string, values: Awaited<ReturnType<typeof inputValues>>, files: (theme: string | null) => Promise<Record<string, string>>) {
|
|
142
|
+
return withProjects(root, async (manifest, save) => {
|
|
143
|
+
const project = requireProject(manifest, values.projectId);
|
|
144
|
+
let theme: string | null;
|
|
145
|
+
try { theme = values.theme ?? await selectedTheme(root, project.defaultTheme ?? 'neutral'); }
|
|
146
|
+
catch { throw invalid('Choose an available theme.'); }
|
|
147
|
+
const contents = await files(theme);
|
|
148
|
+
if (Object.hasOwn(contents, 'assets.json') || Object.hasOwn(contents, 'theme.tsx')) throw invalid('assets.json and theme.tsx are created from the chosen theme. Bind different assets after creation.');
|
|
149
|
+
// Publish the immutable choices and adapter before the entry. Template factories
|
|
150
|
+
// import this adapter, so their captured theme receives the saved font choices.
|
|
151
|
+
const selections = resolveThemeAssets(root, theme ?? 'neutral');
|
|
152
|
+
contents['assets.json'] = `${JSON.stringify(selections, null, 2)}\n`;
|
|
153
|
+
contents['theme.tsx'] = documentAssetAdapterSource(theme ?? 'neutral');
|
|
154
|
+
const previous = Object.hasOwn(manifest.assignments, values.id) ? manifest.assignments[values.id] : undefined;
|
|
155
|
+
const previousFormat = manifest.formats && Object.hasOwn(manifest.formats, values.id) ? manifest.formats[values.id] : undefined;
|
|
156
|
+
let assigned = false;
|
|
157
|
+
return reserveDocument(root, values, contents, async () => {
|
|
158
|
+
manifest.assignments[values.id] = project.id;
|
|
159
|
+
if (values.format === 'presentation' || previousFormat !== undefined) (manifest.formats ??= {})[values.id] = values.format;
|
|
160
|
+
await save(); assigned = true;
|
|
161
|
+
}, async () => {
|
|
162
|
+
if (!assigned) return;
|
|
163
|
+
if (previous === undefined) delete manifest.assignments[values.id]; else manifest.assignments[values.id] = previous;
|
|
164
|
+
if (previousFormat === undefined) { if (manifest.formats) delete manifest.formats[values.id]; } else (manifest.formats ??= {})[values.id] = previousFormat;
|
|
165
|
+
await save();
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async function reserveDocument(root: string, { title, id, starter, projectId, explicitId }: Awaited<ReturnType<typeof inputValues>>, files: Record<string, string>, beforePublish: () => Promise<void>, rollback: () => Promise<void>): Promise<CreatedDocument> {
|
|
171
|
+
if (!files['index.tsx'] || Object.keys(files).some(name => !/^[a-zA-Z0-9_-]+\.(tsx|json)$/.test(name))) throw invalid('Document files need a TSX entry and simple local filenames.');
|
|
172
|
+
const workspace = await realpath(resolve(root));
|
|
173
|
+
const documents = resolve(workspace, 'documents');
|
|
174
|
+
try { await mkdir(documents); } catch (error) { if (!isCode(error, 'EEXIST')) throw error; }
|
|
175
|
+
const docsInfo = await lstat(documents);
|
|
176
|
+
if (!docsInfo.isDirectory() || docsInfo.isSymbolicLink() || await realpath(documents) !== documents) throw unsafe();
|
|
177
|
+
const destination = resolve(documents, id);
|
|
178
|
+
try { await mkdir(destination); } catch (error) { if (isCode(error, 'EEXIST')) throw exists(id, explicitId); throw error; }
|
|
179
|
+
const folderInfo = await lstat(destination);
|
|
180
|
+
const createdFolders: string[] = [];
|
|
181
|
+
const created = new Map<string, { dev: number; ino: number }>();
|
|
182
|
+
async function assertFolder() {
|
|
183
|
+
const [folder, parent] = await Promise.all([lstat(destination), lstat(documents)]);
|
|
184
|
+
if (!folder.isDirectory() || folder.isSymbolicLink() || folder.dev !== folderInfo.dev || folder.ino !== folderInfo.ino || parent.dev !== docsInfo.dev || parent.ino !== docsInfo.ino || await realpath(destination) !== destination) throw unsafe();
|
|
185
|
+
}
|
|
186
|
+
async function writeNew(name: string, content: string) {
|
|
187
|
+
await assertFolder();
|
|
188
|
+
const handle = await open(resolve(destination, name), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o644);
|
|
189
|
+
try {
|
|
190
|
+
const info = await handle.stat(); created.set(name, { dev: info.dev, ino: info.ino });
|
|
191
|
+
await handle.writeFile(content, 'utf8');
|
|
192
|
+
} finally { await handle.close(); }
|
|
193
|
+
}
|
|
194
|
+
async function removeOwn(name: string) {
|
|
195
|
+
const identity = created.get(name);
|
|
196
|
+
if (!identity) return;
|
|
197
|
+
await assertFolder();
|
|
198
|
+
const current = await lstat(resolve(destination, name)).catch(error => { if (isCode(error, 'ENOENT')) return null; throw error; });
|
|
199
|
+
if (current?.dev === identity.dev && current.ino === identity.ino) await unlink(resolve(destination, name));
|
|
200
|
+
}
|
|
201
|
+
const pending = `.index-${randomUUID()}.tmp`;
|
|
202
|
+
try {
|
|
203
|
+
for (const folder of ['media']) {
|
|
204
|
+
await assertFolder();
|
|
205
|
+
await mkdir(resolve(destination, folder)); createdFolders.push(folder);
|
|
206
|
+
await writeNew(`${folder}/.gitkeep`, '');
|
|
207
|
+
}
|
|
208
|
+
for (const [name, content] of Object.entries(files)) if (name !== 'index.tsx') await writeNew(name, content);
|
|
209
|
+
await writeNew(pending, files['index.tsx']);
|
|
210
|
+
await assertFolder();
|
|
211
|
+
await beforePublish();
|
|
212
|
+
await assertFolder();
|
|
213
|
+
// link is exclusive: even an unexpected index added during creation is never replaced.
|
|
214
|
+
await link(resolve(destination, pending), resolve(destination, 'index.tsx'));
|
|
215
|
+
// Publication succeeded. A cleanup problem must not remove the completed document's data.
|
|
216
|
+
await removeOwn(pending).catch(() => {});
|
|
217
|
+
return { id, title, starter: starter.id, projectId, entry: `documents/${id}/index.tsx` };
|
|
218
|
+
} catch (error) {
|
|
219
|
+
const rollbackError = await rollback().then(() => null, error => error);
|
|
220
|
+
// A user may have added files while creation was in progress. Remove only our own writes.
|
|
221
|
+
for (const name of created.keys()) await removeOwn(name).catch(() => {});
|
|
222
|
+
for (const folder of createdFolders.reverse()) await rmdir(resolve(destination, folder)).catch(() => {});
|
|
223
|
+
await assertFolder().then(() => rmdir(destination)).catch(() => {});
|
|
224
|
+
if (rollbackError) throw new CreateDocumentError(`Document creation failed and its project assignment could not be restored. Check projects.json before retrying. ${rollbackError instanceof Error ? rollbackError.message : ''}`, 'CREATE_FAILED', 500);
|
|
225
|
+
if (error instanceof CreateDocumentError) throw error;
|
|
226
|
+
throw new CreateDocumentError(`Could not create "${id}". No existing document was overwritten. ${error instanceof Error ? error.message : ''}`, 'CREATE_FAILED', 500);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { build } from 'esbuild';
|
|
2
|
+
import { dirname, relative, resolve, sep } from 'node:path';
|
|
3
|
+
import { existsSync, realpathSync } from 'node:fs';
|
|
4
|
+
import { bindingDependencies, readDocumentAssetsAt, readThemeAssetDefaults, resolveThemeAssets } from '../assets/files';
|
|
5
|
+
import { authoringResolutionPlugin } from './source-overrides';
|
|
6
|
+
import { applicationRoot, runtimeSource } from '../runtime/paths';
|
|
7
|
+
|
|
8
|
+
export interface DocumentDependencies { files: Set<string>; readsFiles: boolean }
|
|
9
|
+
|
|
10
|
+
/** Executed outside the authored import graph; stamp these for export freshness as well. */
|
|
11
|
+
export const renderRuntimeInputs = [
|
|
12
|
+
...['worker', 'preflight', 'text-layout', 'text-source', 'render', 'render-source', 'source-overrides'].map(name => runtimeSource(`server/${name}.ts`)),
|
|
13
|
+
runtimeSource('rendering/resolve-sources.ts'),
|
|
14
|
+
runtimeSource('runtime/paths.ts'), resolve(applicationRoot, 'package.json'), resolve(applicationRoot, 'tsconfig.workspace.json'),
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
/** Only the new family directories are managed; existing loose fonts remain conservative inputs. */
|
|
18
|
+
export function isManagedAssetPath(root: string, path: string) {
|
|
19
|
+
const parts = relative(root, resolve(root, path)).split(sep);
|
|
20
|
+
return parts[0] === 'assets' && ((parts[1] === 'logos' && (!parts[2] || /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(parts[2])))
|
|
21
|
+
|| (parts[1] === 'fonts' && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(parts[2] ?? '')));
|
|
22
|
+
}
|
|
23
|
+
export function isThemeAssetDefaultsPath(root: string, path: string) {
|
|
24
|
+
return /^themes\/[a-z0-9]+(?:-[a-z0-9]+)*\/assets\.json$/.test(relative(root, resolve(root, path)).split(sep).join('/'));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Include absent binding/manifests too, so repairing a failed asset is observable. */
|
|
28
|
+
async function managedInputs(root: string, entry: string) {
|
|
29
|
+
// documentEntry resolves macOS /var to /private/var; keep the binding path in root's spelling.
|
|
30
|
+
const parts = relative(realpathSync(root), realpathSync(entry)).split(sep);
|
|
31
|
+
const files = new Set<string>();
|
|
32
|
+
const previewTheme = parts[0] === 'themes' && parts[2] === 'preview.tsx' ? parts[1]
|
|
33
|
+
: parts[0] === 'templates' && parts[2] === 'preview.tsx' ? 'neutral' : undefined;
|
|
34
|
+
if (previewTheme) {
|
|
35
|
+
files.add(resolve(root, 'themes', previewTheme, 'assets.json'));
|
|
36
|
+
try {
|
|
37
|
+
const defaults = await readThemeAssetDefaults(root, previewTheme);
|
|
38
|
+
for (const [kind, id] of [['logos', defaults.logo?.id], ['fonts', defaults.bodyFont], ['fonts', defaults.headingFont]] as const)
|
|
39
|
+
if (id) files.add(resolve(root, 'assets', kind, id, 'asset.json'));
|
|
40
|
+
const bindings = await resolveThemeAssets(root, previewTheme);
|
|
41
|
+
for (const path of await bindingDependencies(root, bindings)) files.add(resolve(root, path));
|
|
42
|
+
} catch { /* The worker reports validation errors; preserve known paths for recovery. */ }
|
|
43
|
+
} else if (parts[0] === 'documents') {
|
|
44
|
+
const directory = dirname(resolve(root, ...parts));
|
|
45
|
+
files.add(resolve(directory, 'assets.json'));
|
|
46
|
+
try {
|
|
47
|
+
const bindings = await readDocumentAssetsAt(root, directory);
|
|
48
|
+
for (const path of await bindingDependencies(root, bindings)) files.add(resolve(root, path));
|
|
49
|
+
} catch { /* An invalid binding remains watched through its containing document. */ }
|
|
50
|
+
}
|
|
51
|
+
return files;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Follow imports without executing document code, then add immutable managed asset inputs. */
|
|
55
|
+
export async function documentDependencies(root: string, entry: string): Promise<DocumentDependencies> {
|
|
56
|
+
const result = await build({
|
|
57
|
+
absWorkingDir: root, entryPoints: [entry], bundle: true, write: false, metafile: true,
|
|
58
|
+
platform: 'node', format: 'esm', jsx: 'automatic', logLevel: 'silent', plugins: [authoringResolutionPlugin()],
|
|
59
|
+
outdir: resolve(root, '.opendoc/dependencies'),
|
|
60
|
+
});
|
|
61
|
+
const inputs = Object.entries(result.metafile!.inputs);
|
|
62
|
+
const managedRoots = ['media', 'assets'].map(folder => runtimeSource(folder)).filter(existsSync).map(folder => realpathSync(folder) + sep);
|
|
63
|
+
const documentRuntime = realpathSync(runtimeSource('document/index.tsx'));
|
|
64
|
+
const files = new Set(inputs.map(([file]) => resolve(root, file)));
|
|
65
|
+
for (const file of ['package.json', 'package-lock.json', 'pnpm-lock.yaml', 'tsconfig.json']) files.add(resolve(root, file));
|
|
66
|
+
for (const file of renderRuntimeInputs) files.add(file);
|
|
67
|
+
for (const file of await managedInputs(root, entry)) files.add(file);
|
|
68
|
+
return {
|
|
69
|
+
files,
|
|
70
|
+
// Managed reads have exact dependency records. Arbitrary authored filesystem reads stay conservative.
|
|
71
|
+
readsFiles: inputs.some(([file, input]) => {
|
|
72
|
+
const actual = realpathSync(resolve(root, file));
|
|
73
|
+
return actual !== documentRuntime && !managedRoots.some(folder => actual.startsWith(folder))
|
|
74
|
+
&& input.imports.some(item => /^(node:)?fs(?:\/promises)?$/.test(item.path));
|
|
75
|
+
}),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function includesDependency(dependencies: DocumentDependencies, path: string) {
|
|
80
|
+
return dependencies.files.has(path) || [...dependencies.files].some(file => file.startsWith(path + sep));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Worker inputs that are not necessarily imported by authored components. */
|
|
84
|
+
export function isRenderRuntimePath(root: string, path: string) {
|
|
85
|
+
const absolute = resolve(root, path);
|
|
86
|
+
const rel = relative(root, absolute).split(sep).join('/');
|
|
87
|
+
return (rel.startsWith('assets/') && !isManagedAssetPath(root, path))
|
|
88
|
+
|| /^(package\.json|package-lock\.json|pnpm-lock\.yaml|tsconfig\.json)$/.test(rel)
|
|
89
|
+
|| renderRuntimeInputs.includes(absolute)
|
|
90
|
+
|| absolute === resolve(applicationRoot, 'pnpm-lock.yaml');
|
|
91
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { DocumentFormat } from '../shared/types';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { lstat, mkdir, readdir, readFile, rename, rm, writeFile, copyFile, realpath } from 'node:fs/promises';
|
|
4
|
+
import { resolve, extname } from 'node:path';
|
|
5
|
+
import ts from 'typescript';
|
|
6
|
+
import { atomicWrite } from './files';
|
|
7
|
+
import { validId } from './render';
|
|
8
|
+
import { documentDisplayName, ProjectError, requireProject, withProjects } from './projects';
|
|
9
|
+
|
|
10
|
+
async function exists(path: string) {
|
|
11
|
+
return lstat(path).catch(error => { if (error.code === 'ENOENT') return null; throw error; });
|
|
12
|
+
}
|
|
13
|
+
async function localDirectory(path: string, create = false) {
|
|
14
|
+
if (create) await mkdir(path, { recursive: true });
|
|
15
|
+
const info = await exists(path);
|
|
16
|
+
if (!info?.isDirectory() || info.isSymbolicLink()) throw new ProjectError('Document folders must be regular local directories.', 409);
|
|
17
|
+
return path;
|
|
18
|
+
}
|
|
19
|
+
async function documentFolder(root: string, id: string) {
|
|
20
|
+
if (!validId(id) || id.length > 80) throw new ProjectError('Invalid document ID.');
|
|
21
|
+
const documents = await localDirectory(resolve(await realpath(root), 'documents'));
|
|
22
|
+
const folder = resolve(documents, id);
|
|
23
|
+
if (!await exists(folder)) throw new ProjectError('This document no longer exists.', 404);
|
|
24
|
+
await localDirectory(folder);
|
|
25
|
+
const entry = await exists(resolve(folder, 'index.tsx'));
|
|
26
|
+
if (!entry?.isFile() || entry.isSymbolicLink()) throw new ProjectError('The document needs a regular index.tsx file.', 409);
|
|
27
|
+
return folder;
|
|
28
|
+
}
|
|
29
|
+
async function trashFolder(root: string) {
|
|
30
|
+
const runtime = await localDirectory(resolve(await realpath(root), '.opendoc'));
|
|
31
|
+
return localDirectory(resolve(runtime, 'trash'), true);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function renameDocument(root: string, id: string, input: unknown) {
|
|
35
|
+
if (!input || typeof input !== 'object' || Array.isArray(input) || Object.keys(input).some(key => key !== 'name')) throw new ProjectError('Provide a document name.');
|
|
36
|
+
const name = documentDisplayName((input as { name?: unknown }).name);
|
|
37
|
+
return withProjects(root, async (manifest, save) => {
|
|
38
|
+
await documentFolder(root, id);
|
|
39
|
+
(manifest.names ??= {})[id] = name;
|
|
40
|
+
await save(); return { id, name };
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Rebind local source paths, without replacing words in authored prose or stable block IDs. */
|
|
45
|
+
function rebaseSource(text: string, file: string, root: string, from: string, to: string) {
|
|
46
|
+
const prefixes = [[`documents/${from}/`, `documents/${to}/`], [`${resolve(root, 'documents', from)}/`, `${resolve(root, 'documents', to)}/`]];
|
|
47
|
+
const source = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true, extname(file) === '.json' ? ts.ScriptKind.JSON : extname(file) === '.tsx' ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
|
|
48
|
+
const changes: { start: number; end: number; value: string }[] = [];
|
|
49
|
+
function visit(node: ts.Node) {
|
|
50
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
|
|
51
|
+
const match = prefixes.find(([prefix]) => node.text.startsWith(prefix));
|
|
52
|
+
if (match) changes.push({ start: node.getStart(source), end: node.end, value: JSON.stringify(match[1] + node.text.slice(match[0].length)) });
|
|
53
|
+
// Supplied layout starters bind provenance and media through this instance constant.
|
|
54
|
+
else if (node.text === from && ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name) && node.parent.name.text === 'documentId') changes.push({ start: node.getStart(source), end: node.end, value: JSON.stringify(to) });
|
|
55
|
+
}
|
|
56
|
+
ts.forEachChild(node, visit);
|
|
57
|
+
}
|
|
58
|
+
visit(source);
|
|
59
|
+
for (const change of changes.sort((a, b) => b.start - a.start)) text = text.slice(0, change.start) + change.value + text.slice(change.end);
|
|
60
|
+
return text;
|
|
61
|
+
}
|
|
62
|
+
async function copyDocumentTree(source: string, destination: string, root: string, from: string, to: string) {
|
|
63
|
+
await mkdir(destination);
|
|
64
|
+
for (const entry of await readdir(source, { withFileTypes: true })) {
|
|
65
|
+
const input = resolve(source, entry.name), output = resolve(destination, entry.name);
|
|
66
|
+
if (entry.isDirectory()) await copyDocumentTree(input, output, root, from, to);
|
|
67
|
+
else if (entry.isFile()) {
|
|
68
|
+
if (/\.(?:tsx?|jsx?|mjs|json)$/.test(entry.name)) await writeFile(output, rebaseSource(await readFile(input, 'utf8'), entry.name, root, from, to), { flag: 'wx' });
|
|
69
|
+
else await copyFile(input, output);
|
|
70
|
+
} else throw new ProjectError('This document contains a link or special file. Replace it with a local file before duplicating.', 409);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export async function duplicateDocument(root: string, id: string, title: string) {
|
|
75
|
+
return withProjects(root, async (manifest, save) => {
|
|
76
|
+
const source = await documentFolder(root, id);
|
|
77
|
+
const project = requireProject(manifest, manifest.assignments[id]);
|
|
78
|
+
const stem = `${id.slice(0, 65).replace(/-$/, '')}-copy`;
|
|
79
|
+
let copyId = stem, suffix = 2;
|
|
80
|
+
while (await exists(resolve(root, 'documents', copyId)) || Object.hasOwn(manifest.assignments, copyId) || (manifest.names && Object.hasOwn(manifest.names, copyId)) || (manifest.formats && Object.hasOwn(manifest.formats, copyId))) copyId = `${stem}-${suffix++}`;
|
|
81
|
+
const staging = resolve(root, 'documents', `.copy-${randomUUID()}`);
|
|
82
|
+
const name = documentDisplayName(`Copy of ${((manifest.names && Object.hasOwn(manifest.names, id) ? manifest.names[id] : title)).replace(/[\r\n]/g, ' ').trim()}`.slice(0, 160));
|
|
83
|
+
try {
|
|
84
|
+
await copyDocumentTree(source, staging, root, id, copyId);
|
|
85
|
+
manifest.assignments[copyId] = project.id;
|
|
86
|
+
(manifest.names ??= {})[copyId] = name;
|
|
87
|
+
if (manifest.formats && Object.hasOwn(manifest.formats, id)) manifest.formats[copyId] = manifest.formats[id];
|
|
88
|
+
await save();
|
|
89
|
+
try { await rename(staging, resolve(root, 'documents', copyId)); }
|
|
90
|
+
catch (error) { delete manifest.assignments[copyId]; delete manifest.names[copyId]; if (manifest.formats) delete manifest.formats[copyId]; await save(); throw error; }
|
|
91
|
+
return { id: copyId, projectId: project.id, name };
|
|
92
|
+
} finally { await rm(staging, { recursive: true, force: true }); }
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
interface TrashReceipt { format?: DocumentFormat; id: string; projectId: string | null; name?: string; deletedAt: string }
|
|
97
|
+
|
|
98
|
+
export async function deleteDocument(root: string, id: string) {
|
|
99
|
+
return withProjects(root, async (manifest, save) => {
|
|
100
|
+
const source = await documentFolder(root, id);
|
|
101
|
+
const restoreId = randomUUID();
|
|
102
|
+
const trash = resolve(await trashFolder(root), restoreId);
|
|
103
|
+
await mkdir(trash);
|
|
104
|
+
const receipt: TrashReceipt = { id, format: manifest.formats && Object.hasOwn(manifest.formats, id) ? manifest.formats[id] : 'document', projectId: Object.hasOwn(manifest.assignments, id) ? manifest.assignments[id] : null, name: manifest.names && Object.hasOwn(manifest.names, id) ? manifest.names[id] : undefined, deletedAt: new Date().toISOString() };
|
|
105
|
+
await atomicWrite(resolve(trash, 'receipt.json'), JSON.stringify(receipt, null, 2));
|
|
106
|
+
await rename(source, resolve(trash, 'document'));
|
|
107
|
+
delete manifest.assignments[id];
|
|
108
|
+
if (manifest.names) delete manifest.names[id];
|
|
109
|
+
if (manifest.formats) delete manifest.formats[id];
|
|
110
|
+
try { await save(); }
|
|
111
|
+
catch (error) { await rename(resolve(trash, 'document'), source); await rm(trash, { recursive: true, force: true }); throw error; }
|
|
112
|
+
return { id, restoreId };
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export async function restoreDocument(root: string, restoreId: string) {
|
|
117
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(restoreId)) throw new ProjectError('Invalid deleted document.');
|
|
118
|
+
return withProjects(root, async (manifest, save) => {
|
|
119
|
+
const trash = resolve(await trashFolder(root), restoreId);
|
|
120
|
+
if (!await exists(trash)) throw new ProjectError('This document has already been restored or is no longer in Trash.', 404);
|
|
121
|
+
await localDirectory(trash);
|
|
122
|
+
const receiptFile = resolve(trash, 'receipt.json');
|
|
123
|
+
const info = await exists(receiptFile);
|
|
124
|
+
if (!info?.isFile() || info.isSymbolicLink() || info.size > 4096) throw new ProjectError('The deleted document record is invalid.', 409);
|
|
125
|
+
const receipt = JSON.parse(await readFile(receiptFile, 'utf8')) as TrashReceipt;
|
|
126
|
+
if (!receipt || typeof receipt.id !== 'string' || !validId(receipt.id) || receipt.id.length > 80 || (receipt.projectId !== null && typeof receipt.projectId !== 'string')) throw new ProjectError('The deleted document record is invalid.', 409);
|
|
127
|
+
if (receipt.format !== undefined && receipt.format !== 'document' && receipt.format !== 'presentation') throw new ProjectError('The deleted document format is invalid.', 409);
|
|
128
|
+
if (receipt.name !== undefined) documentDisplayName(receipt.name);
|
|
129
|
+
if (receipt.projectId) requireProject(manifest, receipt.projectId);
|
|
130
|
+
const documents = await localDirectory(resolve(root, 'documents'));
|
|
131
|
+
const destination = resolve(documents, receipt.id);
|
|
132
|
+
if (await exists(destination) || Object.hasOwn(manifest.assignments, receipt.id) || (manifest.names && Object.hasOwn(manifest.names, receipt.id)) || (manifest.formats && Object.hasOwn(manifest.formats, receipt.id))) throw new ProjectError('A document already uses this ID. Move it aside before restoring this copy.', 409);
|
|
133
|
+
await localDirectory(resolve(trash, 'document'));
|
|
134
|
+
if (receipt.projectId) manifest.assignments[receipt.id] = receipt.projectId;
|
|
135
|
+
if (receipt.name !== undefined) (manifest.names ??= {})[receipt.id] = receipt.name;
|
|
136
|
+
if (receipt.format !== undefined) (manifest.formats ??= {})[receipt.id] = receipt.format;
|
|
137
|
+
await save();
|
|
138
|
+
try { await rename(resolve(trash, 'document'), destination); }
|
|
139
|
+
catch (error) { delete manifest.assignments[receipt.id]; if (manifest.names) delete manifest.names[receipt.id]; if (manifest.formats) delete manifest.formats[receipt.id]; await save(); throw error; }
|
|
140
|
+
await rm(trash, { recursive: true, force: true });
|
|
141
|
+
return { id: receipt.id, projectId: receipt.projectId, name: receipt.name };
|
|
142
|
+
});
|
|
143
|
+
}
|