@ecsplico/editor 2.1.1 → 3.0.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/CHANGELOG.md +74 -1
- package/README.md +39 -156
- package/dist/adapters/comments/drizzle.d.ts +1 -1
- package/dist/adapters/comments/{client.js → rest-model.js} +3 -3
- package/dist/adapters/comments/rest-model.js.map +1 -0
- package/dist/adapters/comments/types.d.ts +2 -2
- package/dist/adapters/document-state.d.ts +23 -0
- package/dist/adapters/document-state.js +66 -0
- package/dist/adapters/document-state.js.map +1 -0
- package/dist/adapters/documents.js +14 -11
- package/dist/adapters/documents.js.map +1 -1
- package/dist/adapters/drizzle.d.ts +2 -2
- package/dist/adapters/drizzle.js +97 -88
- package/dist/adapters/drizzle.js.map +1 -1
- package/dist/adapters/forge.d.ts +12 -7
- package/dist/adapters/forge.js +38 -45
- package/dist/adapters/forge.js.map +1 -1
- package/dist/adapters/http.d.ts +20 -0
- package/dist/adapters/http.js +68 -0
- package/dist/adapters/http.js.map +1 -0
- package/dist/adapters/index.d.ts +5 -5
- package/dist/adapters/json.d.ts +3 -3
- package/dist/adapters/json.js +58 -49
- package/dist/adapters/json.js.map +1 -1
- package/dist/adapters/memory.d.ts +21 -0
- package/dist/adapters/memory.js +53 -0
- package/dist/adapters/memory.js.map +1 -0
- package/dist/adapters/nitro.d.ts +23 -20
- package/dist/adapters/nitro.js +58 -163
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/react.d.ts +55 -0
- package/dist/adapters/react.js +209 -0
- package/dist/adapters/react.js.map +1 -0
- package/dist/adapters/shared.d.ts +15 -21
- package/dist/adapters/shared.js +10 -8
- package/dist/adapters/shared.js.map +1 -1
- package/dist/adapters/vue.d.ts +15 -30
- package/dist/adapters/vue.js +36 -87
- package/dist/adapters/vue.js.map +1 -1
- package/dist/code/CodeSurface.vue.d.ts +3 -3
- package/dist/config/index.d.ts +105 -0
- package/dist/config/index.js +95 -0
- package/dist/config/index.js.map +1 -0
- package/dist/core/abilities.js +1 -0
- package/dist/core/abilities.js.map +1 -1
- package/dist/{adapters/routes.js → core/api-routes.js} +5 -3
- package/dist/core/api-routes.js.map +1 -0
- package/dist/core/backend-capability.d.ts +7 -0
- package/dist/core/backend-capability.js +17 -0
- package/dist/core/backend-capability.js.map +1 -0
- package/dist/core/backend-types.d.ts +245 -0
- package/dist/core/backend-types.js +17 -0
- package/dist/core/backend-types.js.map +1 -0
- package/dist/core/backend.d.ts +108 -0
- package/dist/core/backend.js +14 -0
- package/dist/core/backend.js.map +1 -0
- package/dist/core/block-convert.d.ts +7 -5
- package/dist/core/block-convert.js +28 -5
- package/dist/core/block-convert.js.map +1 -1
- package/dist/core/command-types.d.ts +89 -0
- package/dist/core/commands.d.ts +40 -0
- package/dist/core/commands.js +151 -0
- package/dist/core/commands.js.map +1 -0
- package/dist/core/context.d.ts +17 -20
- package/dist/core/context.js +24 -21
- package/dist/core/context.js.map +1 -1
- package/dist/core/core-feature.d.ts +22 -7
- package/dist/core/core-feature.js +51 -18
- package/dist/core/core-feature.js.map +1 -1
- package/dist/core/define-editor.d.ts +4 -3
- package/dist/core/define-editor.js +14 -7
- package/dist/core/define-editor.js.map +1 -1
- package/dist/core/document-markdown.js +12 -3
- package/dist/core/document-markdown.js.map +1 -1
- package/dist/core/editor-ui.d.ts +8 -1
- package/dist/core/editor-ui.js +9 -8
- package/dist/core/editor-ui.js.map +1 -1
- package/dist/core/extension-points.d.ts +3 -15
- package/dist/core/feature-context.d.ts +8 -7
- package/dist/core/feature-context.js +12 -11
- package/dist/core/feature-context.js.map +1 -1
- package/dist/core/feature.d.ts +35 -19
- package/dist/core/feature.js.map +1 -1
- package/dist/core/fences.d.ts +2 -1
- package/dist/core/fences.js +3 -2
- package/dist/core/fences.js.map +1 -1
- package/dist/core/fetch-error.d.ts +1 -1
- package/dist/core/fetch-error.js +3 -1
- package/dist/core/fetch-error.js.map +1 -1
- package/dist/core/hash.d.ts +5 -0
- package/dist/core/hash.js +11 -0
- package/dist/core/hash.js.map +1 -0
- package/dist/core/http-backend.d.ts +11 -0
- package/dist/core/http-backend.js +195 -0
- package/dist/core/http-backend.js.map +1 -0
- package/dist/core/index.d.ts +14 -9
- package/dist/core/index.js +12 -9
- package/dist/core/palette.d.ts +48 -0
- package/dist/core/palette.js +95 -0
- package/dist/core/palette.js.map +1 -0
- package/dist/core/schema/abilities.d.ts +2 -1
- package/dist/core/schema/abilities.js +5 -1
- package/dist/core/schema/abilities.js.map +1 -1
- package/dist/core/schema/index.d.ts +11 -5
- package/dist/core/schema/index.js +13 -8
- package/dist/core/schema/index.js.map +1 -1
- package/dist/core/schema/mark-flags.d.ts +8 -1
- package/dist/core/schema/of-features.d.ts +13 -0
- package/dist/core/schema/of-features.js +14 -0
- package/dist/core/schema/of-features.js.map +1 -0
- package/dist/core/slash.d.ts +8 -6
- package/dist/core/slash.js +24 -16
- package/dist/core/slash.js.map +1 -1
- package/dist/core/surface-session.js +13 -5
- package/dist/core/surface-session.js.map +1 -1
- package/dist/core/toolbar-items.d.ts +10 -4
- package/dist/core/toolbar-items.js +269 -195
- package/dist/core/toolbar-items.js.map +1 -1
- package/dist/core/util.js +11 -0
- package/dist/core/util.js.map +1 -0
- package/dist/document/DocumentSurface.d.ts +1 -1
- package/dist/document/DocumentSurface.vue.d.ts +3 -3
- package/dist/features/ai/agent-op-review.d.ts +1 -1
- package/dist/features/ai/agent-op-review.js +1 -1
- package/dist/features/ai/agent-ops.js +1 -1
- package/dist/features/ai/ai-apply.d.ts +2 -2
- package/dist/features/ai/ai-apply.js +1 -1
- package/dist/features/ai/ai-review.js +1 -1
- package/dist/features/ai/ai-sse.d.ts +6 -6
- package/dist/features/ai/ai-sse.js +20 -63
- package/dist/features/ai/ai-sse.js.map +1 -1
- package/dist/features/ai/assistant.d.ts +8 -7
- package/dist/features/ai/assistant.js +3 -3
- package/dist/features/ai/assistant.js.map +1 -1
- package/dist/features/ai/block-actions.d.ts +3 -2
- package/dist/features/ai/block-actions.js +3 -2
- package/dist/features/ai/block-actions.js.map +1 -1
- package/dist/features/ai/components/AiSelectionMenu.js +1 -1
- package/dist/features/ai/components/DocumentChatAnswer.js +1 -1
- package/dist/features/ai/components/DocumentChatOps.vue.d.ts +1 -1
- package/dist/features/ai/components/SettingsModelProfiles.js +8 -8
- package/dist/features/ai/components/SettingsModelProfiles.js.map +1 -1
- package/dist/features/ai/document-chat-model.d.ts +8 -7
- package/dist/features/ai/document-chat-model.js +5 -5
- package/dist/features/ai/document-chat-model.js.map +1 -1
- package/dist/features/ai/document-chat.js +1 -1
- package/dist/features/ai/feature.js +27 -14
- package/dist/features/ai/feature.js.map +1 -1
- package/dist/features/ai/ghost-autocomplete.d.ts +7 -6
- package/dist/features/ai/ghost-autocomplete.js +6 -9
- package/dist/features/ai/ghost-autocomplete.js.map +1 -1
- package/dist/features/ai/index.d.ts +4 -3
- package/dist/features/ai/index.js +10 -10
- package/dist/features/ai/model-profiles.d.ts +5 -4
- package/dist/features/ai/model-profiles.js +2 -2
- package/dist/features/ai/model-profiles.js.map +1 -1
- package/dist/features/ai/protocol/block-lines.js +1 -1
- package/dist/features/ai/protocol/block-lines.js.map +1 -1
- package/dist/features/ai/protocol/chat.js +4 -1
- package/dist/features/ai/protocol/chat.js.map +1 -1
- package/dist/features/ai/protocol/index.d.ts +3 -2
- package/dist/features/ai/protocol/models.d.ts +2 -16
- package/dist/features/ai/protocol/models.js.map +1 -1
- package/dist/features/ai/rate-limit.d.ts +1 -1
- package/dist/features/ai/rate-limit.js +3 -1
- package/dist/features/ai/rate-limit.js.map +1 -1
- package/dist/features/ai/react/AiSelectionMenu.js +2 -2
- package/dist/features/ai/react/AiSidebar.js +4 -4
- package/dist/features/ai/react/DocumentChatAnswer.js +1 -1
- package/dist/features/ai/react/DocumentChatOps.d.ts +1 -1
- package/dist/features/ai/react/DocumentChatOps.js +1 -1
- package/dist/features/ai/react/SettingsModelProfiles.js +8 -10
- package/dist/features/ai/react/SettingsModelProfiles.js.map +1 -1
- package/dist/features/ai/react/use-ai-assistant.d.ts +1 -1
- package/dist/features/ai/react/use-ai-assistant.js +3 -3
- package/dist/features/ai/react/use-ai-assistant.js.map +1 -1
- package/dist/features/ai/react/use-document-chat.js +2 -2
- package/dist/features/ai/react/use-document-chat.js.map +1 -1
- package/dist/features/ai/react/use-model-profiles.d.ts +2 -1
- package/dist/features/ai/selection-flow.d.ts +1 -1
- package/dist/features/ai/selection-flow.js +1 -1
- package/dist/features/ai/sidebar-flow.d.ts +1 -1
- package/dist/features/ai/sidebar-flow.js +1 -1
- package/dist/features/ai/use-ai-assistant.d.ts +1 -1
- package/dist/features/ai/use-ai-assistant.js +3 -3
- package/dist/features/ai/use-ai-assistant.js.map +1 -1
- package/dist/features/ai/use-document-chat.js +2 -2
- package/dist/features/ai/use-document-chat.js.map +1 -1
- package/dist/features/ai/use-model-profiles.d.ts +2 -1
- package/dist/features/authors/attribution.d.ts +1 -1
- package/dist/features/authors/feature.js +12 -11
- package/dist/features/authors/feature.js.map +1 -1
- package/dist/features/block-ui/block-actions.d.ts +22 -1
- package/dist/features/block-ui/block-actions.js +26 -2
- package/dist/features/block-ui/block-actions.js.map +1 -1
- package/dist/features/block-ui/components/BlockActionsOverlay.js +33 -4
- package/dist/features/block-ui/components/BlockActionsOverlay.js.map +1 -1
- package/dist/features/block-ui/components/BlockActionsOverlay.vue.d.ts +4 -0
- package/dist/features/block-ui/components/BlockUi.js +1 -1
- package/dist/features/block-ui/feature.js +1 -0
- package/dist/features/block-ui/feature.js.map +1 -1
- package/dist/features/block-ui/index.d.ts +2 -2
- package/dist/features/block-ui/index.js +2 -2
- package/dist/features/block-ui/react/BlockActionsOverlay.d.ts +4 -0
- package/dist/features/block-ui/react/BlockActionsOverlay.js +38 -12
- package/dist/features/block-ui/react/BlockActionsOverlay.js.map +1 -1
- package/dist/features/block-ui/react/BlockUi.js +1 -1
- package/dist/features/collab/anchor-resolver.js +1 -1
- package/dist/features/collab/feature.js +2 -0
- package/dist/features/collab/feature.js.map +1 -1
- package/dist/features/comments/components/CommentThreadView.vue.d.ts +2 -1
- package/dist/features/comments/feature.js +12 -11
- package/dist/features/comments/feature.js.map +1 -1
- package/dist/features/comments/index.d.ts +3 -2
- package/dist/features/comments/index.js +1 -1
- package/dist/features/comments/margin-layout.d.ts +3 -2
- package/dist/features/comments/model.d.ts +3 -67
- package/dist/features/comments/model.js +2 -2
- package/dist/features/comments/model.js.map +1 -1
- package/dist/features/comments/react/CommentThreadView.d.ts +3 -2
- package/dist/features/comments/react/use-comments.d.ts +2 -1
- package/dist/features/comments/react.d.ts +1 -1
- package/dist/features/comments/schema.d.ts +2 -52
- package/dist/features/comments/schema.js.map +1 -1
- package/dist/features/comments/snapshot-equality.js.map +1 -1
- package/dist/features/comments/use-comments.d.ts +3 -2
- package/dist/features/comments/vue.d.ts +1 -1
- package/dist/features/composites/accepted-children.d.ts +1 -0
- package/dist/features/composites/accepted-children.js +16 -1
- package/dist/features/composites/accepted-children.js.map +1 -1
- package/dist/features/composites/ai-brief.js +31 -0
- package/dist/features/composites/ai-brief.js.map +1 -1
- package/dist/features/composites/bibliography-command.d.ts +11 -0
- package/dist/features/composites/bibliography-form.js +90 -0
- package/dist/features/composites/bibliography-form.js.map +1 -0
- package/dist/features/composites/bibliography.d.ts +33 -0
- package/dist/features/composites/bibliography.js +120 -0
- package/dist/features/composites/bibliography.js.map +1 -0
- package/dist/features/composites/components/BibliographyEditor.js +261 -0
- package/dist/features/composites/components/BibliographyEditor.js.map +1 -0
- package/dist/features/composites/components/CompositeChrome.js +75 -26
- package/dist/features/composites/components/CompositeChrome.js.map +1 -1
- package/dist/features/composites/components/CompositeDetails.js +46 -11
- package/dist/features/composites/components/CompositeDetails.js.map +1 -1
- package/dist/features/composites/components/CompositeDetails.vue.d.ts +2 -1
- package/dist/features/composites/components/CompositeFieldEditor.js +37 -4
- package/dist/features/composites/components/CompositeFieldEditor.js.map +1 -1
- package/dist/features/composites/components/CompositeInspector.js +17 -5
- package/dist/features/composites/components/CompositeInspector.js.map +1 -1
- package/dist/features/composites/components/CompositeTable.js +13 -4
- package/dist/features/composites/components/CompositeTable.js.map +1 -1
- package/dist/features/composites/components/CompositeTagsEditor.js +1 -1
- package/dist/features/composites/components/CompositeView.js +11 -1
- package/dist/features/composites/components/CompositeView.js.map +1 -1
- package/dist/features/composites/components/DerivationBadge.js +103 -0
- package/dist/features/composites/components/DerivationBadge.js.map +1 -0
- package/dist/features/composites/components/ReferenceFieldSelect.js +60 -0
- package/dist/features/composites/components/ReferenceFieldSelect.js.map +1 -0
- package/dist/features/composites/components/ReferenceView.js +122 -0
- package/dist/features/composites/components/ReferenceView.js.map +1 -0
- package/dist/features/composites/components/ReferenceView.vue.d.ts +96 -0
- package/dist/features/composites/components/SettingsEditingTab.js +1 -1
- package/dist/features/composites/convert.js +2 -2
- package/dist/features/composites/convert.js.map +1 -1
- package/dist/features/composites/derivation.d.ts +61 -0
- package/dist/features/composites/derivation.js +98 -0
- package/dist/features/composites/derivation.js.map +1 -0
- package/dist/features/composites/derived-chrome.js +69 -0
- package/dist/features/composites/derived-chrome.js.map +1 -0
- package/dist/features/composites/feature.js +159 -109
- package/dist/features/composites/feature.js.map +1 -1
- package/dist/features/composites/fences.d.ts +4 -3
- package/dist/features/composites/fences.js +51 -7
- package/dist/features/composites/fences.js.map +1 -1
- package/dist/features/composites/index.d.ts +12 -3
- package/dist/features/composites/index.js +15 -6
- package/dist/features/composites/inspector-model.d.ts +4 -1
- package/dist/features/composites/inspector-model.js +8 -4
- package/dist/features/composites/inspector-model.js.map +1 -1
- package/dist/features/composites/kinds.d.ts +8 -1
- package/dist/features/composites/kinds.js +145 -6
- package/dist/features/composites/kinds.js.map +1 -1
- package/dist/features/composites/legacy.d.ts +4 -1
- package/dist/features/composites/legacy.js +56 -1
- package/dist/features/composites/legacy.js.map +1 -1
- package/dist/features/composites/meta-display.js +40 -1
- package/dist/features/composites/meta-display.js.map +1 -1
- package/dist/features/composites/meta-keys.d.ts +7 -0
- package/dist/features/composites/meta-keys.js +21 -0
- package/dist/features/composites/meta-keys.js.map +1 -0
- package/dist/features/composites/node-views.d.ts +6 -3
- package/dist/features/composites/node-views.js +7 -3
- package/dist/features/composites/node-views.js.map +1 -1
- package/dist/features/composites/nodes.d.ts +6 -1
- package/dist/features/composites/nodes.js +33 -7
- package/dist/features/composites/nodes.js.map +1 -1
- package/dist/features/composites/react/BibliographyEditor.js +229 -0
- package/dist/features/composites/react/BibliographyEditor.js.map +1 -0
- package/dist/features/composites/react/CompositeChrome.js +65 -17
- package/dist/features/composites/react/CompositeChrome.js.map +1 -1
- package/dist/features/composites/react/CompositeDetails.d.ts +2 -1
- package/dist/features/composites/react/CompositeDetails.js +45 -6
- package/dist/features/composites/react/CompositeDetails.js.map +1 -1
- package/dist/features/composites/react/CompositeFieldEditor.d.ts +1 -1
- package/dist/features/composites/react/CompositeFieldEditor.js +24 -1
- package/dist/features/composites/react/CompositeFieldEditor.js.map +1 -1
- package/dist/features/composites/react/CompositeInspector.js +11 -5
- package/dist/features/composites/react/CompositeInspector.js.map +1 -1
- package/dist/features/composites/react/CompositeStatusMenu.js +1 -1
- package/dist/features/composites/react/CompositeSummaryEditor.js +1 -1
- package/dist/features/composites/react/CompositeTable.js +16 -2
- package/dist/features/composites/react/CompositeTable.js.map +1 -1
- package/dist/features/composites/react/CompositeTagsEditor.js +2 -2
- package/dist/features/composites/react/CompositeView.js +6 -1
- package/dist/features/composites/react/CompositeView.js.map +1 -1
- package/dist/features/composites/react/DerivationBadge.js +116 -0
- package/dist/features/composites/react/DerivationBadge.js.map +1 -0
- package/dist/features/composites/react/ReferenceFieldSelect.js +52 -0
- package/dist/features/composites/react/ReferenceFieldSelect.js.map +1 -0
- package/dist/features/composites/react/ReferenceView.d.ts +11 -0
- package/dist/features/composites/react/ReferenceView.js +115 -0
- package/dist/features/composites/react/ReferenceView.js.map +1 -0
- package/dist/features/composites/react/SettingsEditingTab.js +2 -2
- package/dist/features/composites/react.d.ts +2 -1
- package/dist/features/composites/react.js +7 -3
- package/dist/features/composites/react.js.map +1 -1
- package/dist/features/composites/reference-ai.js +16 -0
- package/dist/features/composites/reference-ai.js.map +1 -0
- package/dist/features/composites/reference-label.d.ts +19 -0
- package/dist/features/composites/reference-label.js +58 -0
- package/dist/features/composites/reference-label.js.map +1 -0
- package/dist/features/composites/reference-suggestion.d.ts +10 -0
- package/dist/features/composites/reference-suggestion.js +41 -0
- package/dist/features/composites/reference-suggestion.js.map +1 -0
- package/dist/features/composites/reference-text.d.ts +18 -0
- package/dist/features/composites/reference-text.js +89 -0
- package/dist/features/composites/reference-text.js.map +1 -0
- package/dist/features/composites/reference.d.ts +44 -0
- package/dist/features/composites/reference.js +148 -0
- package/dist/features/composites/reference.js.map +1 -0
- package/dist/features/composites/reveal-source.d.ts +32 -0
- package/dist/features/composites/reveal-source.js +89 -0
- package/dist/features/composites/reveal-source.js.map +1 -0
- package/dist/features/composites/rows.d.ts +21 -2
- package/dist/features/composites/rows.js +63 -9
- package/dist/features/composites/rows.js.map +1 -1
- package/dist/features/composites/schema.d.ts +9 -3
- package/dist/features/composites/schema.js +11 -4
- package/dist/features/composites/schema.js.map +1 -1
- package/dist/features/composites/table-model.js +12 -21
- package/dist/features/composites/table-model.js.map +1 -1
- package/dist/features/composites/vue.d.ts +3 -2
- package/dist/features/composites/vue.js +8 -4
- package/dist/features/composites/vue.js.map +1 -1
- package/dist/features/media/assets.d.ts +2 -0
- package/dist/features/media/assets.js +3 -2
- package/dist/features/media/assets.js.map +1 -1
- package/dist/features/media/components/FileView.js +13 -4
- package/dist/features/media/components/FileView.js.map +1 -1
- package/dist/features/media/feature.d.ts +3 -3
- package/dist/features/media/feature.js +21 -28
- package/dist/features/media/feature.js.map +1 -1
- package/dist/features/media/file-import.js +2 -2
- package/dist/features/media/file-import.js.map +1 -1
- package/dist/features/media/index.d.ts +2 -2
- package/dist/features/media/index.js +2 -2
- package/dist/features/media/react/FileView.js +19 -2
- package/dist/features/media/react/FileView.js.map +1 -1
- package/dist/features/media/schema.d.ts +8 -0
- package/dist/features/media/schema.js +126 -11
- package/dist/features/media/schema.js.map +1 -1
- package/dist/features/media/upload.d.ts +16 -14
- package/dist/features/media/upload.js +13 -19
- package/dist/features/media/upload.js.map +1 -1
- package/dist/features/mentions/index.d.ts +4 -3
- package/dist/features/mentions/index.js +4 -1
- package/dist/features/mentions/index.js.map +1 -1
- package/dist/features/mentions/mention-text.d.ts +1 -1
- package/dist/features/mentions/mention-text.js.map +1 -1
- package/dist/features/mentions/mention.d.ts +0 -6
- package/dist/features/mentions/mention.js.map +1 -1
- package/dist/features/mentions/metadata-defaults.d.ts +2 -2
- package/dist/features/mentions/metadata-defaults.js +3 -9
- package/dist/features/mentions/metadata-defaults.js.map +1 -1
- package/dist/features/mentions/schema.d.ts +2 -1
- package/dist/features/mentions/schema.js.map +1 -1
- package/dist/features/tables/feature.d.ts +2 -1
- package/dist/features/tables/feature.js +90 -70
- package/dist/features/tables/feature.js.map +1 -1
- package/dist/features/themes/components/SettingsAppearanceTab.js +6 -9
- package/dist/features/themes/components/SettingsAppearanceTab.js.map +1 -1
- package/dist/features/themes/feature.js +2 -0
- package/dist/features/themes/feature.js.map +1 -1
- package/dist/features/themes/index.d.ts +2 -1
- package/dist/features/themes/react/SettingsAppearanceTab.js +7 -10
- package/dist/features/themes/react/SettingsAppearanceTab.js.map +1 -1
- package/dist/features/themes/schema.d.ts +2 -6
- package/dist/features/themes/schema.js.map +1 -1
- package/dist/features/themes/theme-runtime.d.ts +1 -1
- package/dist/features/themes/theme-runtime.js +4 -2
- package/dist/features/themes/theme-runtime.js.map +1 -1
- package/dist/features/transcript/TranscriptSegmentView.js +48 -28
- package/dist/features/transcript/TranscriptSegmentView.js.map +1 -1
- package/dist/features/transcript/feature.js +21 -19
- package/dist/features/transcript/feature.js.map +1 -1
- package/dist/features/transcript/react/TranscriptSegmentView.js +55 -36
- package/dist/features/transcript/react/TranscriptSegmentView.js.map +1 -1
- package/dist/features/transcript/segment-node.d.ts +2 -0
- package/dist/features/transcript/segment-node.js +35 -7
- package/dist/features/transcript/segment-node.js.map +1 -1
- package/dist/i18n/de/composites.js +91 -1
- package/dist/i18n/de/composites.js.map +1 -1
- package/dist/i18n/de/integrations.js +49 -8
- package/dist/i18n/de/integrations.js.map +1 -1
- package/dist/i18n/de/media.js +0 -1
- package/dist/i18n/de/media.js.map +1 -1
- package/dist/i18n/de/palette.js +22 -0
- package/dist/i18n/de/palette.js.map +1 -0
- package/dist/i18n/de/tables.js +0 -1
- package/dist/i18n/de/tables.js.map +1 -1
- package/dist/i18n/de/transcript.js +2 -1
- package/dist/i18n/de/transcript.js.map +1 -1
- package/dist/i18n/de/tree.js +3 -0
- package/dist/i18n/de/tree.js.map +1 -1
- package/dist/i18n/de.d.ts +157 -11
- package/dist/i18n/de.js +3 -1
- package/dist/i18n/de.js.map +1 -1
- package/dist/i18n/en/composites.js +89 -1
- package/dist/i18n/en/composites.js.map +1 -1
- package/dist/i18n/en/integrations.js +49 -8
- package/dist/i18n/en/integrations.js.map +1 -1
- package/dist/i18n/en/media.js +0 -1
- package/dist/i18n/en/media.js.map +1 -1
- package/dist/i18n/en/palette.js +22 -0
- package/dist/i18n/en/palette.js.map +1 -0
- package/dist/i18n/en/tables.js +0 -1
- package/dist/i18n/en/tables.js.map +1 -1
- package/dist/i18n/en/transcript.js +2 -1
- package/dist/i18n/en/transcript.js.map +1 -1
- package/dist/i18n/en/tree.js +3 -0
- package/dist/i18n/en/tree.js.map +1 -1
- package/dist/i18n/en.js +3 -1
- package/dist/i18n/en.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/integrations/composite-ai/bibliography-fetch.d.ts +31 -0
- package/dist/integrations/composite-ai/bibliography-fetch.js +159 -0
- package/dist/integrations/composite-ai/bibliography-fetch.js.map +1 -0
- package/dist/integrations/composite-ai/composite-fill.d.ts +30 -8
- package/dist/integrations/composite-ai/composite-fill.js +97 -56
- package/dist/integrations/composite-ai/composite-fill.js.map +1 -1
- package/dist/integrations/composite-ai/composite-summary.d.ts +4 -12
- package/dist/integrations/composite-ai/composite-summary.js +7 -26
- package/dist/integrations/composite-ai/composite-summary.js.map +1 -1
- package/dist/integrations/composite-ai/derive.d.ts +29 -0
- package/dist/integrations/composite-ai/derive.js +173 -0
- package/dist/integrations/composite-ai/derive.js.map +1 -0
- package/dist/integrations/composite-ai/index.d.ts +11 -7
- package/dist/integrations/composite-ai/index.js +72 -14
- package/dist/integrations/composite-ai/index.js.map +1 -1
- package/dist/integrations/composite-ai/rendition.d.ts +45 -0
- package/dist/integrations/composite-ai/rendition.js +314 -0
- package/dist/integrations/composite-ai/rendition.js.map +1 -0
- package/dist/integrations/composite-media/index.d.ts +7 -5
- package/dist/integrations/composite-media/index.js +86 -13
- package/dist/integrations/composite-media/index.js.map +1 -1
- package/dist/integrations/transcript-ai/index.d.ts +1 -1
- package/dist/integrations/transcript-ai/index.js +5 -2
- package/dist/integrations/transcript-ai/index.js.map +1 -1
- package/dist/integrations/transcript-ai/protocol.d.ts +2 -12
- package/dist/integrations/transcript-ai/protocol.js +0 -2
- package/dist/integrations/transcript-ai/protocol.js.map +1 -1
- package/dist/integrations/transcript-ai/transcript-cleanup.d.ts +5 -5
- package/dist/integrations/transcript-ai/transcript-cleanup.js +7 -10
- package/dist/integrations/transcript-ai/transcript-cleanup.js.map +1 -1
- package/dist/markdown/MarkdownSurface.vue.d.ts +10 -9
- package/dist/markdown/MarkdownSurface2.js +3 -6
- package/dist/markdown/MarkdownSurface2.js.map +1 -1
- package/dist/markdown/document.js +1 -1
- package/dist/markdown/source-mode.d.ts +1 -1
- package/dist/nuxt/module.d.ts +1402 -54
- package/dist/nuxt/module.js +6 -49
- package/dist/nuxt/module.js.map +1 -1
- package/dist/nuxt/runtime/install-context.d.ts +7 -3
- package/dist/nuxt/runtime/install-context.js +14 -8
- package/dist/nuxt/runtime/install-context.js.map +1 -1
- package/dist/nuxt/runtime/plugins/editor-context-nuxt-ui.client.ts +2 -2
- package/dist/nuxt/runtime/server/plugins/editor-server.js +20 -12
- package/dist/nuxt/runtime/server/plugins/editor-server.js.map +1 -1
- package/dist/presets/compose.d.ts +94 -0
- package/dist/presets/compose.js +164 -0
- package/dist/presets/compose.js.map +1 -0
- package/dist/react/AdvancedEditor.d.ts +15 -15
- package/dist/react/AdvancedEditor.js +15 -13
- package/dist/react/AdvancedEditor.js.map +1 -1
- package/dist/react/EditorCommandPalette.d.ts +13 -0
- package/dist/react/EditorCommandPalette.js +118 -0
- package/dist/react/EditorCommandPalette.js.map +1 -0
- package/dist/react/EditorSettingsModal.d.ts +5 -5
- package/dist/react/EditorSettingsModal.js +7 -4
- package/dist/react/EditorSettingsModal.js.map +1 -1
- package/dist/react/EditorSettingsPanel.d.ts +7 -7
- package/dist/react/EditorSettingsPanel.js +8 -5
- package/dist/react/EditorSettingsPanel.js.map +1 -1
- package/dist/react/EditorSurface.d.ts +7 -7
- package/dist/react/EditorSurface.js +10 -6
- package/dist/react/EditorSurface.js.map +1 -1
- package/dist/react/EditorToolbar.d.ts +4 -6
- package/dist/react/EditorToolbar.js +29 -37
- package/dist/react/EditorToolbar.js.map +1 -1
- package/dist/react/SimpleEditor.d.ts +22 -23
- package/dist/react/SimpleEditor.js +21 -7
- package/dist/react/SimpleEditor.js.map +1 -1
- package/dist/react/advanced.d.ts +4 -3
- package/dist/react/advanced.js +2 -2
- package/dist/react/compose.d.ts +20 -0
- package/dist/react/compose.js +49 -0
- package/dist/react/compose.js.map +1 -0
- package/dist/react/composed-surface.d.ts +39 -0
- package/dist/react/composed-surface.js +71 -0
- package/dist/react/composed-surface.js.map +1 -0
- package/dist/react/context.js +6 -2
- package/dist/react/context.js.map +1 -1
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +2 -1
- package/dist/react/key-labels.js +15 -0
- package/dist/react/key-labels.js.map +1 -0
- package/dist/react/settings.d.ts +1 -1
- package/dist/react/simple.d.ts +2 -2
- package/dist/react/ui/command.js +36 -1
- package/dist/react/ui/command.js.map +1 -1
- package/dist/schema/advanced.d.ts +6 -6
- package/dist/schema/advanced.js +26 -29
- package/dist/schema/advanced.js.map +1 -1
- package/dist/server/ai.d.ts +5 -16
- package/dist/server/ai.js.map +1 -1
- package/dist/server/auth.d.ts +9 -0
- package/dist/server/collab-state.d.ts +1 -1
- package/dist/server/collab-state.js.map +1 -1
- package/dist/server/collab.d.ts +13 -13
- package/dist/server/collab.js +34 -18
- package/dist/server/collab.js.map +1 -1
- package/dist/server/crossref.js +78 -0
- package/dist/server/crossref.js.map +1 -0
- package/dist/server/errors.d.ts +1 -1
- package/dist/server/errors.js +1 -1
- package/dist/server/errors.js.map +1 -1
- package/dist/server/extract.js +308 -0
- package/dist/server/extract.js.map +1 -0
- package/dist/{nuxt/runtime/server/utils/editor-route.js → server/h3.js} +8 -16
- package/dist/server/h3.js.map +1 -0
- package/dist/server/handlers/ai.d.ts +30 -9
- package/dist/server/handlers/ai.js +170 -36
- package/dist/server/handlers/ai.js.map +1 -1
- package/dist/server/handlers/context.d.ts +12 -5
- package/dist/server/handlers/context.js +10 -4
- package/dist/server/handlers/context.js.map +1 -1
- package/dist/server/handlers/editor.d.ts +19 -13
- package/dist/server/handlers/editor.js +49 -38
- package/dist/server/handlers/editor.js.map +1 -1
- package/dist/server/handlers/index.d.ts +4 -4
- package/dist/server/handlers/index.js +4 -4
- package/dist/server/host.d.ts +16 -25
- package/dist/server/host.js +58 -41
- package/dist/server/host.js.map +1 -1
- package/dist/server/index.d.ts +6 -4
- package/dist/server/index.js +3 -2
- package/dist/server/pdf.js +97 -0
- package/dist/server/pdf.js.map +1 -0
- package/dist/server/{adapter.d.ts → ports.d.ts} +81 -30
- package/dist/server/ports.js +29 -0
- package/dist/server/ports.js.map +1 -0
- package/dist/server/routes.js +144 -0
- package/dist/server/routes.js.map +1 -0
- package/dist/settings/index.d.ts +1 -1
- package/dist/settings/index.js.map +1 -1
- package/dist/styles/composites.css +25 -0
- package/dist/tree/DocumentTree.js +56 -29
- package/dist/tree/DocumentTree.js.map +1 -1
- package/dist/tree/react/DocumentTree.js +23 -0
- package/dist/tree/react/DocumentTree.js.map +1 -1
- package/dist/tree/tree-host.js +1 -1
- package/dist/vue/AdvancedEditor.js +30 -9
- package/dist/vue/AdvancedEditor.js.map +1 -1
- package/dist/vue/AdvancedEditor.vue.d.ts +32 -12
- package/dist/vue/SimpleEditor.js +62 -16
- package/dist/vue/SimpleEditor.js.map +1 -1
- package/dist/vue/SimpleEditor.vue.d.ts +37 -7
- package/dist/vue/advanced.d.ts +3 -2
- package/dist/vue/advanced.js +2 -2
- package/dist/vue/components/EditorCommandPalette.js +91 -0
- package/dist/vue/components/EditorCommandPalette.js.map +1 -0
- package/dist/vue/components/EditorCommandPalette.vue.d.ts +15 -0
- package/dist/vue/components/EditorSettingsModal.js +10 -6
- package/dist/vue/components/EditorSettingsModal.js.map +1 -1
- package/dist/vue/components/EditorSettingsModal.vue.d.ts +4 -4
- package/dist/vue/components/EditorSettingsPanel.js +10 -6
- package/dist/vue/components/EditorSettingsPanel.js.map +1 -1
- package/dist/vue/components/EditorSettingsPanel.vue.d.ts +6 -6
- package/dist/vue/components/EditorSurface.js +11 -6
- package/dist/vue/components/EditorSurface.js.map +1 -1
- package/dist/vue/components/EditorSurface.vue.d.ts +11 -11
- package/dist/vue/components/EditorToolbar.js +41 -49
- package/dist/vue/components/EditorToolbar.js.map +1 -1
- package/dist/vue/components/EditorToolbar.vue.d.ts +2 -4
- package/dist/vue/compose.d.ts +17 -0
- package/dist/vue/compose.js +51 -0
- package/dist/vue/compose.js.map +1 -0
- package/dist/vue/context-key.d.ts +6 -0
- package/dist/vue/context-key.js +6 -0
- package/dist/vue/context-key.js.map +1 -0
- package/dist/vue/context.d.ts +8 -6
- package/dist/vue/context.js +6 -5
- package/dist/vue/context.js.map +1 -1
- package/dist/vue/index.d.ts +10 -8
- package/dist/vue/index.js +10 -8
- package/dist/vue/kit/index.d.ts +2 -2
- package/dist/vue/kit/nuxt-ui.js +23 -0
- package/dist/vue/kit/nuxt-ui.js.map +1 -1
- package/dist/vue/kit/types.d.ts +40 -1
- package/package.json +30 -16
- package/dist/adapters/comments/client.d.ts +0 -64
- package/dist/adapters/comments/client.js.map +0 -1
- package/dist/adapters/routes.js.map +0 -1
- package/dist/core/toolbar.d.ts +0 -74
- package/dist/core/toolbar.js +0 -45
- package/dist/core/toolbar.js.map +0 -1
- package/dist/integrations/composite-ai/document-transcribe.d.ts +0 -14
- package/dist/integrations/composite-ai/document-transcribe.js +0 -89
- package/dist/integrations/composite-ai/document-transcribe.js.map +0 -1
- package/dist/nuxt/runtime/server/api/ai/chat.post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/ai/chat.post.js +0 -8
- package/dist/nuxt/runtime/server/api/ai/chat.post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/ai/complete.post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/ai/complete.post.js +0 -8
- package/dist/nuxt/runtime/server/api/ai/complete.post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/ai/generate.post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/ai/generate.post.js +0 -8
- package/dist/nuxt/runtime/server/api/ai/generate.post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/ai/models.get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/ai/models.get.js +0 -8
- package/dist/nuxt/runtime/server/api/ai/models.get.js.map +0 -1
- package/dist/nuxt/runtime/server/api/ai/transcribe.post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/ai/transcribe.post.js +0 -8
- package/dist/nuxt/runtime/server/api/ai/transcribe.post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.js +0 -8
- package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/assets/[id].post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/assets/[id].post.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/assets/[id].post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/settings.get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/settings.get.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/settings.get.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/settings.put.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/settings.put.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/settings.put.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/tags.get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/tags.get.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/tags.get.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/themes/[id].get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/themes/[id].get.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/themes/[id].get.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/themes/index.get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/themes/index.get.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/themes/index.get.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/themes/index.post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/themes/index.post.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/themes/index.post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/users.get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/users.get.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/users.get.js.map +0 -1
- package/dist/nuxt/runtime/server/plugins/collab.d.ts +0 -5
- package/dist/nuxt/runtime/server/plugins/collab.js +0 -10
- package/dist/nuxt/runtime/server/plugins/collab.js.map +0 -1
- package/dist/nuxt/runtime/server/routes/collab/[id].d.ts +0 -5
- package/dist/nuxt/runtime/server/routes/collab/[id].js +0 -35
- package/dist/nuxt/runtime/server/routes/collab/[id].js.map +0 -1
- package/dist/nuxt/runtime/server/utils/editor-route.d.ts +0 -11
- package/dist/nuxt/runtime/server/utils/editor-route.js.map +0 -1
- package/dist/presets/advanced.d.ts +0 -33
- package/dist/presets/advanced.js +0 -50
- package/dist/presets/advanced.js.map +0 -1
- package/dist/presets/simple.d.ts +0 -9
- package/dist/presets/simple.js +0 -12
- package/dist/presets/simple.js.map +0 -1
- package/dist/react/advanced-preset.d.ts +0 -11
- package/dist/react/advanced-preset.js +0 -31
- package/dist/react/advanced-preset.js.map +0 -1
- package/dist/vue/advanced-preset.d.ts +0 -13
- package/dist/vue/advanced-preset.js +0 -33
- package/dist/vue/advanced-preset.js.map +0 -1
- package/docs/extending.md +0 -538
- package/docs/integration.md +0 -630
- package/docs/llms.md +0 -383
- package/docs/usage.md +0 -1076
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import "../i18n/index.js";
|
|
2
|
+
//#region src/config/index.ts
|
|
3
|
+
const DEFAULT_PRESETS = {
|
|
4
|
+
sonnet: {
|
|
5
|
+
label: "Claude Sonnet 4.5 (OpenRouter)",
|
|
6
|
+
endpoint: "https://openrouter.ai/api/v1",
|
|
7
|
+
model: "anthropic/claude-sonnet-4.5"
|
|
8
|
+
},
|
|
9
|
+
flashLite: {
|
|
10
|
+
label: "Gemini 2.5 Flash Lite (OpenRouter)",
|
|
11
|
+
endpoint: "https://openrouter.ai/api/v1",
|
|
12
|
+
model: "google/gemini-2.5-flash-lite"
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const DEFAULT_SLOTS = {
|
|
16
|
+
complete: "flashLite",
|
|
17
|
+
rewrite: "sonnet",
|
|
18
|
+
generate: "sonnet"
|
|
19
|
+
};
|
|
20
|
+
const DEFAULT_RATE_LIMIT = {
|
|
21
|
+
max: 30,
|
|
22
|
+
windowMs: 6e4
|
|
23
|
+
};
|
|
24
|
+
/** Drops `undefined` values so an unset input never overwrites a default. */
|
|
25
|
+
function defined(value) {
|
|
26
|
+
return Object.fromEntries(Object.entries(value ?? {}).filter(([, v]) => v !== void 0));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Applies every default once: locale `'de'`, the OpenRouter presets `sonnet` and `flashLite` with the slots that use
|
|
30
|
+
* them, 30 AI requests per user and minute, no upgrade authentication. Every preset and the transcription get an empty
|
|
31
|
+
* `apiKey` unless one is given, so an environment variable has a key to override.
|
|
32
|
+
*/
|
|
33
|
+
function defineEditorConfig(input = {}) {
|
|
34
|
+
const ai = input.ai ?? {};
|
|
35
|
+
const presets = {};
|
|
36
|
+
for (const id of /* @__PURE__ */ new Set([...Object.keys(DEFAULT_PRESETS), ...Object.keys(ai.presets ?? {})])) {
|
|
37
|
+
const preset = {
|
|
38
|
+
...DEFAULT_PRESETS[id],
|
|
39
|
+
...defined(ai.presets?.[id])
|
|
40
|
+
};
|
|
41
|
+
presets[id] = {
|
|
42
|
+
...preset,
|
|
43
|
+
apiKey: preset.apiKey ?? ""
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const transcription = ai.transcription && { ...defined(ai.transcription) };
|
|
47
|
+
return {
|
|
48
|
+
locale: input.locale ?? "de",
|
|
49
|
+
...input.messages && { messages: input.messages },
|
|
50
|
+
ai: {
|
|
51
|
+
presets,
|
|
52
|
+
apiKey: ai.apiKey ?? "",
|
|
53
|
+
slots: {
|
|
54
|
+
...DEFAULT_SLOTS,
|
|
55
|
+
...defined(ai.slots)
|
|
56
|
+
},
|
|
57
|
+
rateLimit: {
|
|
58
|
+
...DEFAULT_RATE_LIMIT,
|
|
59
|
+
...defined(ai.rateLimit)
|
|
60
|
+
},
|
|
61
|
+
...transcription && { transcription: {
|
|
62
|
+
...transcription,
|
|
63
|
+
apiKey: transcription.apiKey ?? ""
|
|
64
|
+
} }
|
|
65
|
+
},
|
|
66
|
+
collab: { authenticateUpgrade: input.collab?.authenticateUpgrade ?? false }
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function publicConfig(config) {
|
|
70
|
+
return {
|
|
71
|
+
locale: config.locale,
|
|
72
|
+
...config.messages && { messages: config.messages },
|
|
73
|
+
ai: {
|
|
74
|
+
slots: config.ai.slots,
|
|
75
|
+
transcription: Boolean(config.ai.transcription)
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function serverConfig(config) {
|
|
80
|
+
const { presets, apiKey, slots, transcription, rateLimit } = config.ai;
|
|
81
|
+
return {
|
|
82
|
+
ai: {
|
|
83
|
+
presets,
|
|
84
|
+
apiKey,
|
|
85
|
+
slots,
|
|
86
|
+
...transcription && { transcription }
|
|
87
|
+
},
|
|
88
|
+
rateLimit,
|
|
89
|
+
collab: config.collab
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
93
|
+
export { defineEditorConfig, publicConfig, serverConfig };
|
|
94
|
+
|
|
95
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/config/index.ts"],"sourcesContent":["import { DEFAULT_LOCALE, type Locale, type Messages } from '../i18n'\nimport type { ModelSlot } from '../settings'\n\n// One configuration of the editor, three views: `defineEditorConfig` applies every default once; `serverConfig` is\n// what the server needs (including the secrets), `publicConfig` what the browser may see. The Nuxt module sets its\n// runtime config from the two views; a plain Nitro host spreads `serverConfig(...)` into `installEditorServer`.\n// Framework-free: imports only the i18n and settings types, so Node, Nuxt build code and the browser can all load it.\n\n/** Server-defined model preset (any OpenAI-compatible chat completions endpoint); its key falls back to the shared `apiKey`. */\nexport interface PresetConfig { label: string, endpoint: string, model: string, apiKey?: string }\n\n/**\n * Speech-to-text endpoint. `provider` `'openai'` (default): any OpenAI-compatible `<endpoint>/audio/transcriptions`\n * (e.g. OpenAI `whisper-1`). `'deepgram'`: Deepgram's pre-recorded `<endpoint>/listen` (endpoint\n * `https://api.deepgram.com/v1`, model e.g. `nova-3`). `language` (e.g. `'de'`) fixes the spoken language; without it\n * OpenAI guesses and Deepgram detects it.\n */\nexport interface TranscriptionConfig { provider?: 'openai' | 'deepgram', endpoint: string, model: string, apiKey?: string, language?: string }\n\nexport interface EditorConfig {\n /** Language of the editor's strings: `'de'` (default) or `'en'`. Set once per app; a host that switches languages at run time recreates the editor context. */\n locale: Locale\n /** Overrides of single messages by key (see `MessageKey`), applied on top of the catalog of `locale`; must be JSON-serialisable. */\n messages?: Partial<Messages>\n ai: {\n /**\n * Server-defined model presets (any OpenAI-compatible chat completions endpoint), keyed by preset id. The key is\n * per preset or the shared `apiKey`, both from env only (Nuxt: `NUXT_TIPTAP_EDITOR_AI_PRESETS_<ID>_API_KEY`, `<ID>` =\n * the preset id in upper snake case, e.g. `flashLite` → `FLASH_LITE`, or `NUXT_TIPTAP_EDITOR_AI_API_KEY`). Preset ids\n * must be camelCase so the env names map onto them. Presets named like a default (`sonnet`, `flashLite`) override its fields.\n */\n presets: Record<string, PresetConfig>\n /** Shared key of presets without their own. Default `''` (so the env variable has a key to override). */\n apiKey: string\n /** Default preset per slot; users may override in settings. The `complete` model must support assistant prefill. */\n slots: Record<ModelSlot, string>\n /** Per-user limit shared by all AI endpoints: at most `max` requests per sliding `windowMs`. */\n rateLimit: { max: number, windowMs: number }\n /**\n * Speech-to-text for audio/video Bausteine: an OpenAI-compatible `<endpoint>/audio/transcriptions` or Deepgram\n * (`provider: 'deepgram'`; OpenRouter presets provide neither). Absent = the action and the endpoint are off.\n * The key comes from env only (Nuxt: `NUXT_TIPTAP_EDITOR_AI_TRANSCRIPTION_API_KEY`).\n */\n transcription?: TranscriptionConfig\n }\n collab: {\n /**\n * Authenticate the `/collab/:id` websocket upgrade itself (`Identity.authenticate` with the upgrade request's\n * headers) and refuse it with HTTP 401 for an unknown user. Default `false`: the upgrade always succeeds, the user\n * is authenticated afterwards from the headers or the provider's `token`, and an unauthenticated socket is closed\n * with code 4401. Enable only when every client authenticates by cookie/headers: a client that sends its identity\n * as `collaboration.token` (no cookies) cannot connect then. Nuxt env override:\n * `NUXT_TIPTAP_EDITOR_COLLAB_AUTHENTICATE_UPGRADE=true`.\n */\n authenticateUpgrade: boolean\n }\n}\n\ntype DeepPartial<T> = T extends object ? { [K in keyof T]?: DeepPartial<T[K]> } : T\n\n/** What a host writes: every key optional, `undefined` (an unset env variable) means the default. */\nexport type EditorConfigInput = DeepPartial<EditorConfig>\n\n// i18n-ignore-start: model product names, the same in every language\nconst DEFAULT_PRESETS: Record<string, PresetConfig> = {\n sonnet: { label: 'Claude Sonnet 4.5 (OpenRouter)', endpoint: 'https://openrouter.ai/api/v1', model: 'anthropic/claude-sonnet-4.5' },\n flashLite: { label: 'Gemini 2.5 Flash Lite (OpenRouter)', endpoint: 'https://openrouter.ai/api/v1', model: 'google/gemini-2.5-flash-lite' },\n}\n// i18n-ignore-end\n\nconst DEFAULT_SLOTS: Record<ModelSlot, string> = { complete: 'flashLite', rewrite: 'sonnet', generate: 'sonnet' }\n\nconst DEFAULT_RATE_LIMIT = { max: 30, windowMs: 60_000 }\n\n/** Drops `undefined` values so an unset input never overwrites a default. */\nfunction defined<T extends object>(value: T | undefined): Partial<T> {\n return Object.fromEntries(Object.entries(value ?? {}).filter(([, v]) => v !== undefined)) as Partial<T>\n}\n\n/**\n * Applies every default once: locale `'de'`, the OpenRouter presets `sonnet` and `flashLite` with the slots that use\n * them, 30 AI requests per user and minute, no upgrade authentication. Every preset and the transcription get an empty\n * `apiKey` unless one is given, so an environment variable has a key to override.\n */\nexport function defineEditorConfig(input: EditorConfigInput = {}): EditorConfig {\n const ai = input.ai ?? {}\n const presets: Record<string, PresetConfig> = {}\n for (const id of new Set([...Object.keys(DEFAULT_PRESETS), ...Object.keys(ai.presets ?? {})])) {\n const preset = { ...DEFAULT_PRESETS[id], ...defined(ai.presets?.[id]) } as PresetConfig\n presets[id] = { ...preset, apiKey: preset.apiKey ?? '' }\n }\n const transcription = ai.transcription && ({ ...defined(ai.transcription) } as TranscriptionConfig)\n return {\n locale: input.locale ?? DEFAULT_LOCALE,\n ...(input.messages && { messages: input.messages as Partial<Messages> }),\n ai: {\n presets,\n apiKey: ai.apiKey ?? '',\n slots: { ...DEFAULT_SLOTS, ...defined(ai.slots) },\n rateLimit: { ...DEFAULT_RATE_LIMIT, ...defined(ai.rateLimit) },\n ...(transcription && { transcription: { ...transcription, apiKey: transcription.apiKey ?? '' } }),\n },\n collab: { authenticateUpgrade: input.collab?.authenticateUpgrade ?? false },\n }\n}\n\n/** What the browser may see: the language and the default model slots, never a key. */\nexport interface EditorPublicConfig {\n locale: Locale\n messages?: Partial<Messages>\n /** Inert AI configuration: default preset per slot before the models list has answered, and whether transcription is on. */\n ai: { slots: Record<ModelSlot, string>, transcription: boolean }\n}\n\nexport function publicConfig(config: EditorConfig): EditorPublicConfig {\n return {\n locale: config.locale,\n ...(config.messages && { messages: config.messages }),\n ai: { slots: config.ai.slots, transcription: Boolean(config.ai.transcription) },\n }\n}\n\n/** What the server needs, secrets included: the shape `installEditorServer` takes for `ai`, `rateLimit` and `collab`. */\nexport interface EditorServerConfig {\n ai: { presets: Record<string, PresetConfig>, apiKey: string, slots: Record<ModelSlot, string>, transcription?: TranscriptionConfig }\n rateLimit: { max: number, windowMs: number }\n collab: { authenticateUpgrade: boolean }\n}\n\nexport function serverConfig(config: EditorConfig): EditorServerConfig {\n const { presets, apiKey, slots, transcription, rateLimit } = config.ai\n return {\n ai: { presets, apiKey, slots, ...(transcription && { transcription }) },\n rateLimit,\n collab: config.collab,\n }\n}\n"],"mappings":";;AAgEA,MAAM,kBAAgD;CACpD,QAAQ;EAAE,OAAO;EAAkC,UAAU;EAAgC,OAAO;CAA8B;CAClI,WAAW;EAAE,OAAO;EAAsC,UAAU;EAAgC,OAAO;CAA+B;AAC5I;AAGA,MAAM,gBAA2C;CAAE,UAAU;CAAa,SAAS;CAAU,UAAU;AAAS;AAEhH,MAAM,qBAAqB;CAAE,KAAK;CAAI,UAAU;AAAO;;AAGvD,SAAS,QAA0B,OAAkC;CACnE,OAAO,OAAO,YAAY,OAAO,QAAQ,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,OAAO,MAAM,KAAA,CAAS,CAAC;AAC1F;;;;;;AAOA,SAAgB,mBAAmB,QAA2B,CAAC,GAAiB;CAC9E,MAAM,KAAK,MAAM,MAAM,CAAC;CACxB,MAAM,UAAwC,CAAC;CAC/C,KAAK,MAAM,sBAAM,IAAI,IAAI,CAAC,GAAG,OAAO,KAAK,eAAe,GAAG,GAAG,OAAO,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG;EAC7F,MAAM,SAAS;GAAE,GAAG,gBAAgB;GAAK,GAAG,QAAQ,GAAG,UAAU,GAAG;EAAE;EACtE,QAAQ,MAAM;GAAE,GAAG;GAAQ,QAAQ,OAAO,UAAU;EAAG;CACzD;CACA,MAAM,gBAAgB,GAAG,iBAAkB,EAAE,GAAG,QAAQ,GAAG,aAAa,EAAE;CAC1E,OAAO;EACL,QAAQ,MAAM,UAAA;EACd,GAAI,MAAM,YAAY,EAAE,UAAU,MAAM,SAA8B;EACtE,IAAI;GACF;GACA,QAAQ,GAAG,UAAU;GACrB,OAAO;IAAE,GAAG;IAAe,GAAG,QAAQ,GAAG,KAAK;GAAE;GAChD,WAAW;IAAE,GAAG;IAAoB,GAAG,QAAQ,GAAG,SAAS;GAAE;GAC7D,GAAI,iBAAiB,EAAE,eAAe;IAAE,GAAG;IAAe,QAAQ,cAAc,UAAU;GAAG,EAAE;EACjG;EACA,QAAQ,EAAE,qBAAqB,MAAM,QAAQ,uBAAuB,MAAM;CAC5E;AACF;AAUA,SAAgB,aAAa,QAA0C;CACrE,OAAO;EACL,QAAQ,OAAO;EACf,GAAI,OAAO,YAAY,EAAE,UAAU,OAAO,SAAS;EACnD,IAAI;GAAE,OAAO,OAAO,GAAG;GAAO,eAAe,QAAQ,OAAO,GAAG,aAAa;EAAE;CAChF;AACF;AASA,SAAgB,aAAa,QAA0C;CACrE,MAAM,EAAE,SAAS,QAAQ,OAAO,eAAe,cAAc,OAAO;CACpE,OAAO;EACL,IAAI;GAAE;GAAS;GAAQ;GAAO,GAAI,iBAAiB,EAAE,cAAc;EAAG;EACtE;EACA,QAAQ,OAAO;CACjB;AACF"}
|
package/dist/core/abilities.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abilities.js","names":[],"sources":["../../src/core/abilities.ts"],"sourcesContent":["import { type AnyExtension, type Editor, Extension, getExtensionField, type InputRule, type KeyboardShortcutCommand } from '@tiptap/core'\nimport { keydownHandler } from '@tiptap/pm/keymap'\nimport type { Node as PMNode, ResolvedPos } from '@tiptap/pm/model'\nimport { NodeSelection, Plugin, PluginKey } from '@tiptap/pm/state'\nimport type { EditorView } from '@tiptap/pm/view'\nimport {\n ABILITY,\n type Ability,\n type AbilityRuleSource,\n resolveAbilities,\n ROOT_ABILITIES,\n TEXT_ABILITIES,\n TYPE_ABILITIES,\n} from './schema/abilities'\nimport type { AbilitiesOptions } from './extension-points'\n\nexport interface AbilitiesStorage {\n rules: Map<string, AbilityRuleSource>\n root: readonly Ability[]\n}\n\ndeclare module '@tiptap/core' {\n interface Storage {\n abilities: AbilitiesStorage\n }\n}\n\n/** Rules for StarterKit/extension nodes that cannot carry `NodeConfig.abilities` themselves. */\nexport const DEFAULT_ABILITY_RULES: Record<string, AbilityRuleSource> = {\n codeBlock: {\n revokes: [\n ABILITY.marks, ABILITY.headings, ABILITY.lists, ABILITY.blockquote, ABILITY.rule, ABILITY.blockContent, ABILITY.composite, ABILITY.transcript,\n ABILITY.media, ABILITY.record, ABILITY.mention, ABILITY.tag, ABILITY.aiAutocomplete,\n ],\n },\n image: { revokes: TEXT_ABILITIES },\n horizontalRule: { revokes: TEXT_ABILITIES },\n}\n\n/**\n * Abilities at `pos`: chain = ancestors at depth 1…depth, plus `node` when given (an atom starting at `pos`).\n * A `ResolvedPos` addresses a document other than `editor.state.doc`, e.g. a transaction's doc inside plugin `apply`.\n */\nexport function abilitiesAt(editor: Editor, pos: number | ResolvedPos, node?: PMNode): ReadonlySet<Ability> {\n const $pos = typeof pos === 'number' ? editor.state.doc.resolve(pos) : pos\n const chain: PMNode[] = []\n for (let depth = 1; depth <= $pos.depth; depth++) chain.push($pos.node(depth))\n if (node) chain.push(node)\n const { rules, root } = editor.storage.abilities\n return resolveAbilities(rules, root, chain)\n}\n\n/** Abilities of the selection: the selected node, or what both ends of a range allow. */\nexport function abilitiesAtSelection(editor: Editor): ReadonlySet<Ability> {\n const { selection } = editor.state\n if (selection instanceof NodeSelection) return abilitiesAt(editor, selection.from, selection.node)\n const from = abilitiesAt(editor, selection.$from.pos)\n if (selection.empty) return from\n const to = abilitiesAt(editor, selection.$to.pos)\n return new Set([...from].filter(ability => to.has(ability)))\n}\n\nexport function hasAbility(editor: Editor, ability: Ability): boolean {\n return abilitiesAtSelection(editor).has(ability)\n}\n\n/** Only modifier shortcuts are gated; plain Enter/Tab/Backspace keep their structural behaviour everywhere. */\nconst GATED_KEY = /(^|-)(Mod|Alt)-/\n/** How much text before the caret input rules get to see (mirrors TipTap's input-rule plugin). */\nconst MAX_MATCH = 500\n\ninterface GatedInputRule {\n find: InputRule['find']\n ability: Ability\n}\n\n/** Same `this` the ExtensionManager hands to `addKeyboardShortcuts` / `addInputRules` (core dist, `get plugins()`). */\nfunction extensionContext(ext: AnyExtension, editor: Editor) {\n return {\n name: ext.name,\n options: ext.options,\n storage: editor.extensionStorage[ext.name as keyof typeof editor.extensionStorage],\n editor,\n type: editor.schema.nodes[ext.name] ?? editor.schema.marks[ext.name] ?? null,\n }\n}\n\nfunction gatedExtensions(editor: Editor): [AnyExtension, Ability][] {\n return editor.extensionManager.extensions.flatMap((ext): [AnyExtension, Ability][] => {\n const ability = TYPE_ABILITIES[ext.name]\n return ability ? [[ext, ability]] : []\n })\n}\n\nfunction buildKeyBindings(editor: Editor) {\n const abilitiesByKey = new Map<string, Ability[]>()\n for (const [ext, ability] of gatedExtensions(editor)) {\n const addKeyboardShortcuts = getExtensionField<(() => Record<string, KeyboardShortcutCommand>) | undefined>(\n ext, 'addKeyboardShortcuts', extensionContext(ext, editor),\n )\n for (const key of Object.keys(addKeyboardShortcuts?.() ?? {})) {\n if (!GATED_KEY.test(key)) continue\n abilitiesByKey.set(key, [...(abilitiesByKey.get(key) ?? []), ability])\n }\n }\n // Returning true swallows the key, so the type's own binding never runs.\n return Object.fromEntries([...abilitiesByKey].map(([key, abilities]) => [\n key,\n () => {\n const present = abilitiesAtSelection(editor)\n return abilities.some(ability => !present.has(ability))\n },\n ]))\n}\n\nfunction buildInputRules(editor: Editor): GatedInputRule[] {\n return gatedExtensions(editor).flatMap(([ext, ability]) => {\n const addInputRules = getExtensionField<(() => InputRule[]) | undefined>(ext, 'addInputRules', extensionContext(ext, editor))\n return (addInputRules?.() ?? []).map(rule => ({ find: rule.find, ability }))\n })\n}\n\nfunction matches(find: InputRule['find'], text: string): boolean {\n if (typeof find === 'function') return find(text) != null\n find.lastIndex = 0\n return find.exec(text) !== null\n}\n\n/**\n * Hierarchical abilities (see shared/editor/abilities.ts). Resolution reads `editor.storage.abilities`; the plugin\n * swallows `Mod-`/`Alt-` shortcuts and pre-empts input rules of node/mark types whose ability is missing at the caret.\n * Paste, drop and remote changes are not filtered.\n */\nexport const Abilities = Extension.create<AbilitiesOptions, AbilitiesStorage>({\n name: 'abilities',\n // Highest priority: its plugin's handleKeyDown / handleTextInput run before the gated types' keymaps and input rules.\n priority: 1000,\n\n addOptions() {\n return { root: ROOT_ABILITIES, rules: DEFAULT_ABILITY_RULES }\n },\n\n addStorage() {\n return { rules: new Map(), root: this.options.root }\n },\n\n onBeforeCreate() {\n const rules = new Map<string, AbilityRuleSource>()\n for (const ext of this.editor.extensionManager.extensions) {\n const rule = getExtensionField<AbilityRuleSource | undefined>(ext, 'abilities')\n if (rule) rules.set(ext.name, rule)\n }\n // Host/default rules replace a node's own rule as a whole.\n for (const [name, rule] of Object.entries(this.options.rules)) rules.set(name, rule)\n this.storage.rules = rules\n this.storage.root = this.options.root\n },\n\n addProseMirrorPlugins() {\n const editor = this.editor\n // Built lazily on first use, once per plugin: needs the final extension list and schema.\n let handleKey: ((view: EditorView, event: KeyboardEvent) => boolean) | undefined\n let inputRules: GatedInputRule[] | undefined\n\n return [\n new Plugin({\n key: new PluginKey('abilities'),\n props: {\n handleKeyDown(view, event) {\n handleKey ??= keydownHandler(buildKeyBindings(editor))\n return handleKey(view, event)\n },\n handleTextInput(view, from, to, text) {\n inputRules ??= buildInputRules(editor)\n if (!inputRules.length) return false\n const $from = view.state.doc.resolve(from)\n if (!$from.parent.isTextblock) return false\n const textBefore = $from.parent.textBetween(Math.max(0, $from.parentOffset - MAX_MATCH), $from.parentOffset, undefined, '\\ufffc') + text\n let present: ReadonlySet<Ability> | undefined\n for (const rule of inputRules) {\n present ??= abilitiesAt(editor, from)\n if (present.has(rule.ability) || !matches(rule.find, textBefore)) continue\n // Type the character literally; the rule's own plugin never sees this input.\n view.dispatch(view.state.tr.insertText(text, from, to))\n return true\n }\n return false\n },\n },\n }),\n ]\n },\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"abilities.js","names":[],"sources":["../../src/core/abilities.ts"],"sourcesContent":["import { type AnyExtension, type Editor, Extension, getExtensionField, type InputRule, type KeyboardShortcutCommand } from '@tiptap/core'\nimport { keydownHandler } from '@tiptap/pm/keymap'\nimport type { Node as PMNode, ResolvedPos } from '@tiptap/pm/model'\nimport { NodeSelection, Plugin, PluginKey } from '@tiptap/pm/state'\nimport type { EditorView } from '@tiptap/pm/view'\nimport {\n ABILITY,\n type Ability,\n type AbilityRuleSource,\n resolveAbilities,\n ROOT_ABILITIES,\n TEXT_ABILITIES,\n TYPE_ABILITIES,\n} from './schema/abilities'\nimport type { AbilitiesOptions } from './extension-points'\n\nexport interface AbilitiesStorage {\n rules: Map<string, AbilityRuleSource>\n root: readonly Ability[]\n}\n\ndeclare module '@tiptap/core' {\n interface Storage {\n abilities: AbilitiesStorage\n }\n}\n\n/** Rules for StarterKit/extension nodes that cannot carry `NodeConfig.abilities` themselves. */\nexport const DEFAULT_ABILITY_RULES: Record<string, AbilityRuleSource> = {\n codeBlock: {\n revokes: [\n ABILITY.marks, ABILITY.headings, ABILITY.lists, ABILITY.blockquote, ABILITY.rule, ABILITY.blockContent, ABILITY.composite, ABILITY.transcript,\n ABILITY.media, ABILITY.record, ABILITY.mention, ABILITY.reference, ABILITY.tag, ABILITY.aiAutocomplete,\n ],\n },\n image: { revokes: TEXT_ABILITIES },\n horizontalRule: { revokes: TEXT_ABILITIES },\n}\n\n/**\n * Abilities at `pos`: chain = ancestors at depth 1…depth, plus `node` when given (an atom starting at `pos`).\n * A `ResolvedPos` addresses a document other than `editor.state.doc`, e.g. a transaction's doc inside plugin `apply`.\n */\nexport function abilitiesAt(editor: Editor, pos: number | ResolvedPos, node?: PMNode): ReadonlySet<Ability> {\n const $pos = typeof pos === 'number' ? editor.state.doc.resolve(pos) : pos\n const chain: PMNode[] = []\n for (let depth = 1; depth <= $pos.depth; depth++) chain.push($pos.node(depth))\n if (node) chain.push(node)\n const { rules, root } = editor.storage.abilities\n return resolveAbilities(rules, root, chain)\n}\n\n/** Abilities of the selection: the selected node, or what both ends of a range allow. */\nexport function abilitiesAtSelection(editor: Editor): ReadonlySet<Ability> {\n const { selection } = editor.state\n if (selection instanceof NodeSelection) return abilitiesAt(editor, selection.from, selection.node)\n const from = abilitiesAt(editor, selection.$from.pos)\n if (selection.empty) return from\n const to = abilitiesAt(editor, selection.$to.pos)\n return new Set([...from].filter(ability => to.has(ability)))\n}\n\nexport function hasAbility(editor: Editor, ability: Ability): boolean {\n return abilitiesAtSelection(editor).has(ability)\n}\n\n/** Only modifier shortcuts are gated; plain Enter/Tab/Backspace keep their structural behaviour everywhere. */\nconst GATED_KEY = /(^|-)(Mod|Alt)-/\n/** How much text before the caret input rules get to see (mirrors TipTap's input-rule plugin). */\nconst MAX_MATCH = 500\n\ninterface GatedInputRule {\n find: InputRule['find']\n ability: Ability\n}\n\n/** Same `this` the ExtensionManager hands to `addKeyboardShortcuts` / `addInputRules` (core dist, `get plugins()`). */\nfunction extensionContext(ext: AnyExtension, editor: Editor) {\n return {\n name: ext.name,\n options: ext.options,\n storage: editor.extensionStorage[ext.name as keyof typeof editor.extensionStorage],\n editor,\n type: editor.schema.nodes[ext.name] ?? editor.schema.marks[ext.name] ?? null,\n }\n}\n\nfunction gatedExtensions(editor: Editor): [AnyExtension, Ability][] {\n return editor.extensionManager.extensions.flatMap((ext): [AnyExtension, Ability][] => {\n const ability = TYPE_ABILITIES[ext.name]\n return ability ? [[ext, ability]] : []\n })\n}\n\nfunction buildKeyBindings(editor: Editor) {\n const abilitiesByKey = new Map<string, Ability[]>()\n for (const [ext, ability] of gatedExtensions(editor)) {\n const addKeyboardShortcuts = getExtensionField<(() => Record<string, KeyboardShortcutCommand>) | undefined>(\n ext, 'addKeyboardShortcuts', extensionContext(ext, editor),\n )\n for (const key of Object.keys(addKeyboardShortcuts?.() ?? {})) {\n if (!GATED_KEY.test(key)) continue\n abilitiesByKey.set(key, [...(abilitiesByKey.get(key) ?? []), ability])\n }\n }\n // Returning true swallows the key, so the type's own binding never runs.\n return Object.fromEntries([...abilitiesByKey].map(([key, abilities]) => [\n key,\n () => {\n const present = abilitiesAtSelection(editor)\n return abilities.some(ability => !present.has(ability))\n },\n ]))\n}\n\nfunction buildInputRules(editor: Editor): GatedInputRule[] {\n return gatedExtensions(editor).flatMap(([ext, ability]) => {\n const addInputRules = getExtensionField<(() => InputRule[]) | undefined>(ext, 'addInputRules', extensionContext(ext, editor))\n return (addInputRules?.() ?? []).map(rule => ({ find: rule.find, ability }))\n })\n}\n\nfunction matches(find: InputRule['find'], text: string): boolean {\n if (typeof find === 'function') return find(text) != null\n find.lastIndex = 0\n return find.exec(text) !== null\n}\n\n/**\n * Hierarchical abilities (see shared/editor/abilities.ts). Resolution reads `editor.storage.abilities`; the plugin\n * swallows `Mod-`/`Alt-` shortcuts and pre-empts input rules of node/mark types whose ability is missing at the caret.\n * Paste, drop and remote changes are not filtered.\n */\nexport const Abilities = Extension.create<AbilitiesOptions, AbilitiesStorage>({\n name: 'abilities',\n // Highest priority: its plugin's handleKeyDown / handleTextInput run before the gated types' keymaps and input rules.\n priority: 1000,\n\n addOptions() {\n return { root: ROOT_ABILITIES, rules: DEFAULT_ABILITY_RULES }\n },\n\n addStorage() {\n return { rules: new Map(), root: this.options.root }\n },\n\n onBeforeCreate() {\n const rules = new Map<string, AbilityRuleSource>()\n for (const ext of this.editor.extensionManager.extensions) {\n const rule = getExtensionField<AbilityRuleSource | undefined>(ext, 'abilities')\n if (rule) rules.set(ext.name, rule)\n }\n // Host/default rules replace a node's own rule as a whole.\n for (const [name, rule] of Object.entries(this.options.rules)) rules.set(name, rule)\n this.storage.rules = rules\n this.storage.root = this.options.root\n },\n\n addProseMirrorPlugins() {\n const editor = this.editor\n // Built lazily on first use, once per plugin: needs the final extension list and schema.\n let handleKey: ((view: EditorView, event: KeyboardEvent) => boolean) | undefined\n let inputRules: GatedInputRule[] | undefined\n\n return [\n new Plugin({\n key: new PluginKey('abilities'),\n props: {\n handleKeyDown(view, event) {\n handleKey ??= keydownHandler(buildKeyBindings(editor))\n return handleKey(view, event)\n },\n handleTextInput(view, from, to, text) {\n inputRules ??= buildInputRules(editor)\n if (!inputRules.length) return false\n const $from = view.state.doc.resolve(from)\n if (!$from.parent.isTextblock) return false\n const textBefore = $from.parent.textBetween(Math.max(0, $from.parentOffset - MAX_MATCH), $from.parentOffset, undefined, '\\ufffc') + text\n let present: ReadonlySet<Ability> | undefined\n for (const rule of inputRules) {\n present ??= abilitiesAt(editor, from)\n if (present.has(rule.ability) || !matches(rule.find, textBefore)) continue\n // Type the character literally; the rule's own plugin never sees this input.\n view.dispatch(view.state.tr.insertText(text, from, to))\n return true\n }\n return false\n },\n },\n }),\n ]\n },\n})\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region src/
|
|
1
|
+
//#region src/core/api-routes.ts
|
|
2
2
|
const EDITOR_API = "/api/editor";
|
|
3
3
|
const AI_API = "/api/ai";
|
|
4
4
|
const COLLAB_PATH = "/collab";
|
|
@@ -6,11 +6,13 @@ const COLLAB_PATH = "/collab";
|
|
|
6
6
|
const DOCUMENT_ROUTE = `${EDITOR_API}/documents/:id`;
|
|
7
7
|
/** Route pattern of a document's comments endpoint (`handleCommentsRequest`). */
|
|
8
8
|
const COMMENTS_ROUTE = `${EDITOR_API}/comments/:id`;
|
|
9
|
+
/** Route (`GET`) listing the capabilities the server serves (`serverCapabilities`); the HTTP backend's probe reads it. */
|
|
10
|
+
const CAPABILITIES_ROUTE = `${EDITOR_API}/capabilities`;
|
|
9
11
|
/** The content URL of document `id`. */
|
|
10
12
|
const documentUrl = (id) => DOCUMENT_ROUTE.replace(":id", encodeURIComponent(id));
|
|
11
13
|
/** The comments URL of document `id`. */
|
|
12
14
|
const commentsUrl = (id) => COMMENTS_ROUTE.replace(":id", encodeURIComponent(id));
|
|
13
15
|
//#endregion
|
|
14
|
-
export { AI_API, COLLAB_PATH, COMMENTS_ROUTE, DOCUMENT_ROUTE, EDITOR_API, commentsUrl, documentUrl };
|
|
16
|
+
export { AI_API, CAPABILITIES_ROUTE, COLLAB_PATH, COMMENTS_ROUTE, DOCUMENT_ROUTE, EDITOR_API, commentsUrl, documentUrl };
|
|
15
17
|
|
|
16
|
-
//# sourceMappingURL=routes.js.map
|
|
18
|
+
//# sourceMappingURL=api-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-routes.js","names":[],"sources":["../../src/core/api-routes.ts"],"sourcesContent":["// The wire paths shared by the clients (core's fetch backend, the HTTP adapter, the media asset URLs) and the servers\n// (`serverRoutesOf`, the Nitro host). They live in core because the editor owns the contract and adapters depend on it.\n// Pure strings: this module imports nothing, so no entry drags another's framework in.\n\nexport const EDITOR_API = '/api/editor'\nexport const AI_API = '/api/ai'\nexport const COLLAB_PATH = '/collab'\n\n/** Route pattern of a document's content (`GET` → TipTap JSON, `PUT` → stores it). */\nexport const DOCUMENT_ROUTE = `${EDITOR_API}/documents/:id`\n/** Route pattern of a document's comments endpoint (`handleCommentsRequest`). */\nexport const COMMENTS_ROUTE = `${EDITOR_API}/comments/:id`\n/** Route (`GET`) listing the capabilities the server serves (`serverCapabilities`); the HTTP backend's probe reads it. */\nexport const CAPABILITIES_ROUTE = `${EDITOR_API}/capabilities`\n\n/** The content URL of document `id`. */\nexport const documentUrl = (id: string) => DOCUMENT_ROUTE.replace(':id', encodeURIComponent(id))\n/** The comments URL of document `id`. */\nexport const commentsUrl = (id: string) => COMMENTS_ROUTE.replace(':id', encodeURIComponent(id))\n"],"mappings":";AAIA,MAAa,aAAa;AAC1B,MAAa,SAAS;AACtB,MAAa,cAAc;;AAG3B,MAAa,iBAAiB,GAAG,WAAW;;AAE5C,MAAa,iBAAiB,GAAG,WAAW;;AAE5C,MAAa,qBAAqB,GAAG,WAAW;;AAGhD,MAAa,eAAe,OAAe,eAAe,QAAQ,OAAO,mBAAmB,EAAE,CAAC;;AAE/F,MAAa,eAAe,OAAe,eAAe,QAAQ,OAAO,mBAAmB,EAAE,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
//#region src/core/backend-capability.d.ts
|
|
2
|
+
/** Every capability of a backend, in the canonical order; the server's `EditorPorts` use the same names. Its own module so server code imports it without reaching the DOM-using core. */
|
|
3
|
+
export declare const BACKEND_CAPABILITIES: readonly ["documents", "collaboration", "assets", "users", "tags", "settings", "themes", "ai", "comments"];
|
|
4
|
+
/** What a backend can do. */
|
|
5
|
+
export type BackendCapability = typeof BACKEND_CAPABILITIES[number];
|
|
6
|
+
//#endregion
|
|
7
|
+
//# sourceMappingURL=backend-capability.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/core/backend-capability.ts
|
|
2
|
+
/** Every capability of a backend, in the canonical order; the server's `EditorPorts` use the same names. Its own module so server code imports it without reaching the DOM-using core. */
|
|
3
|
+
const BACKEND_CAPABILITIES = [
|
|
4
|
+
"documents",
|
|
5
|
+
"collaboration",
|
|
6
|
+
"assets",
|
|
7
|
+
"users",
|
|
8
|
+
"tags",
|
|
9
|
+
"settings",
|
|
10
|
+
"themes",
|
|
11
|
+
"ai",
|
|
12
|
+
"comments"
|
|
13
|
+
];
|
|
14
|
+
//#endregion
|
|
15
|
+
export { BACKEND_CAPABILITIES };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=backend-capability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-capability.js","names":[],"sources":["../../src/core/backend-capability.ts"],"sourcesContent":["/** Every capability of a backend, in the canonical order; the server's `EditorPorts` use the same names. Its own module so server code imports it without reaching the DOM-using core. */\nexport const BACKEND_CAPABILITIES = ['documents', 'collaboration', 'assets', 'users', 'tags', 'settings', 'themes', 'ai', 'comments'] as const\n\n/** What a backend can do. */\nexport type BackendCapability = typeof BACKEND_CAPABILITIES[number]\n"],"mappings":";;AACA,MAAa,uBAAuB;CAAC;CAAa;CAAiB;CAAU;CAAS;CAAQ;CAAY;CAAU;CAAM;AAAU"}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { ReadonlyStore } from "./store.js";
|
|
2
|
+
import { AuthorIdentity } from "./feature.js";
|
|
3
|
+
//#region src/core/backend-types.d.ts
|
|
4
|
+
/** A user as offered for `@` mentions (`GET /api/editor/users`); never carries credentials. */
|
|
5
|
+
export interface MentionUser {
|
|
6
|
+
id: string;
|
|
7
|
+
username: string;
|
|
8
|
+
color: string;
|
|
9
|
+
}
|
|
10
|
+
/** Profile as the client sees it; presets never expose their key. */
|
|
11
|
+
export interface ModelProfile {
|
|
12
|
+
id: string;
|
|
13
|
+
label: string;
|
|
14
|
+
endpoint: string;
|
|
15
|
+
model: string;
|
|
16
|
+
source: 'preset' | 'user';
|
|
17
|
+
}
|
|
18
|
+
/** Model an AI request runs on: a server preset by id, or an OpenAI-compatible endpoint with its own key. */
|
|
19
|
+
export type ModelRef = {
|
|
20
|
+
preset: string;
|
|
21
|
+
} | {
|
|
22
|
+
endpoint: string;
|
|
23
|
+
model: string;
|
|
24
|
+
apiKey: string;
|
|
25
|
+
};
|
|
26
|
+
/** A theme in the shared library; `builtin` themes are seeded by the host and cannot be deleted. */
|
|
27
|
+
export interface ThemeRecord {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
version?: string;
|
|
31
|
+
author?: string;
|
|
32
|
+
authorUrl?: string;
|
|
33
|
+
builtin: boolean;
|
|
34
|
+
}
|
|
35
|
+
/** One transcript segment sent for cleanup. */
|
|
36
|
+
export interface TranscriptCleanupSegment {
|
|
37
|
+
/** Block ID of the segment (`blockIdOf`). */
|
|
38
|
+
id: string;
|
|
39
|
+
speaker: string;
|
|
40
|
+
/** The segment's inline content as Markdown (mentions as `@name`, tags as `#name`). */
|
|
41
|
+
text: string;
|
|
42
|
+
}
|
|
43
|
+
/** Body of the transcript-cleanup route. */
|
|
44
|
+
export interface TranscriptCleanupRequest {
|
|
45
|
+
segments: TranscriptCleanupSegment[];
|
|
46
|
+
model: ModelRef;
|
|
47
|
+
}
|
|
48
|
+
/** Cleaned text (single-line inline Markdown) of the segment with block ID `id`. */
|
|
49
|
+
export interface TranscriptCleanupResult {
|
|
50
|
+
id: string;
|
|
51
|
+
text: string;
|
|
52
|
+
}
|
|
53
|
+
/** `cleaned`: only segments whose text changed. `failed`: segments of chunks whose model answer was unusable (left as they are). */
|
|
54
|
+
export interface TranscriptCleanupResponse {
|
|
55
|
+
cleaned: TranscriptCleanupResult[];
|
|
56
|
+
failed: number;
|
|
57
|
+
}
|
|
58
|
+
/** A CSL name: `family`/`given` for a person, `literal` for an institution or an unparsed name. */
|
|
59
|
+
export interface CslName {
|
|
60
|
+
family?: string;
|
|
61
|
+
given?: string;
|
|
62
|
+
literal?: string;
|
|
63
|
+
}
|
|
64
|
+
export interface CslDate {
|
|
65
|
+
'date-parts': number[][];
|
|
66
|
+
}
|
|
67
|
+
/** The CSL item types the editor offers (select options, server-side schema). */
|
|
68
|
+
export declare const CSL_TYPES: readonly ["article-journal", "book", "chapter", "paper-conference", "thesis", "report", "webpage", "article", "dataset"];
|
|
69
|
+
export type CslType = typeof CSL_TYPES[number];
|
|
70
|
+
/** A CSL-JSON item without `id` and `title`: the Baustein's block id and title are authoritative for those and never stored in `meta.bib`. */
|
|
71
|
+
export interface CslItem {
|
|
72
|
+
type: CslType;
|
|
73
|
+
author?: CslName[];
|
|
74
|
+
editor?: CslName[];
|
|
75
|
+
issued?: CslDate;
|
|
76
|
+
'container-title'?: string;
|
|
77
|
+
volume?: string;
|
|
78
|
+
issue?: string;
|
|
79
|
+
page?: string;
|
|
80
|
+
publisher?: string;
|
|
81
|
+
'publisher-place'?: string;
|
|
82
|
+
DOI?: string;
|
|
83
|
+
ISBN?: string;
|
|
84
|
+
URL?: string;
|
|
85
|
+
abstract?: string;
|
|
86
|
+
language?: string;
|
|
87
|
+
}
|
|
88
|
+
/** What `ai.extract` makes of a stored asset; `auto` picks by the asset's MIME type. */
|
|
89
|
+
export type ExtractMethod = 'auto' | 'transcription' | 'pdf-text' | 'ocr' | 'description' | 'bibliography';
|
|
90
|
+
/** Body of the extract route: the stored asset `documentId`/`name` and what to make of it. */
|
|
91
|
+
export interface ExtractRequest {
|
|
92
|
+
documentId: string;
|
|
93
|
+
/** The asset to read; absent only for `bibliography` with a `doi` (the work is looked up by DOI alone). */
|
|
94
|
+
name?: string;
|
|
95
|
+
method: ExtractMethod;
|
|
96
|
+
/** The model of `ocr`, `description` and model-based bibliography extraction. */
|
|
97
|
+
model: ModelRef;
|
|
98
|
+
/** Also extract bibliographic data after `pdf-text`/`ocr`. */
|
|
99
|
+
bibliography?: boolean;
|
|
100
|
+
/** DOI to look up for `bibliography`; absent = found in the first pages' text. */
|
|
101
|
+
doi?: string;
|
|
102
|
+
/** PDF page cap (default 200). `ocr` reads at most 50 pages whatever this allows (one model call per page; `ocr-truncated` warns). */
|
|
103
|
+
maxPages?: number;
|
|
104
|
+
}
|
|
105
|
+
export interface ExtractResponse {
|
|
106
|
+
method: Exclude<ExtractMethod, 'auto'>;
|
|
107
|
+
/** The readable content as Markdown (empty for `bibliography`). */
|
|
108
|
+
markdown: string;
|
|
109
|
+
/** Transcription only: the timed segments `markdown` was made of. */
|
|
110
|
+
segments?: {
|
|
111
|
+
start: number;
|
|
112
|
+
end: number;
|
|
113
|
+
text: string;
|
|
114
|
+
}[];
|
|
115
|
+
/** When bibliographic data was requested or the method is `bibliography`; `title` is the work's title when found (never stored in `meta.bib`). */
|
|
116
|
+
bib?: CslItem & {
|
|
117
|
+
title?: string;
|
|
118
|
+
};
|
|
119
|
+
/** Transcription only: the speech-to-text model that wrote it (`TranscriptionConfig.model`), which the client cannot know. */
|
|
120
|
+
model?: string;
|
|
121
|
+
/** SHA-256 (hex) of the asset bytes. */
|
|
122
|
+
inputHash: string;
|
|
123
|
+
/** SHA-256 (hex) of the stored raw output (`markdown` as the asset `output` holds it). The client does not compare it: it hashes the body it writes (its re-serialised Markdown) into `Derivation.outputHash` itself. */
|
|
124
|
+
outputHash: string;
|
|
125
|
+
/** Asset name (same document) of the stored raw Markdown; `null` for `bibliography`. */
|
|
126
|
+
output: string | null;
|
|
127
|
+
warnings: string[];
|
|
128
|
+
}
|
|
129
|
+
/** Who wrote a comment or reply: the writing user's identity, copied in when writing. */
|
|
130
|
+
export type CommentAuthor = AuthorIdentity;
|
|
131
|
+
export interface CommentReply {
|
|
132
|
+
id: string;
|
|
133
|
+
author: CommentAuthor;
|
|
134
|
+
text: string;
|
|
135
|
+
/** ISO timestamps; `editedAt` once the author changed the text. */
|
|
136
|
+
createdAt: string;
|
|
137
|
+
editedAt?: string;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Where a thread's text starts, as the JSON form of a Yjs relative position (`Y.relativePositionToJSON`): bound to the
|
|
141
|
+
* first commented character, so it keeps pointing at the place after that text was deleted (and moves with the text
|
|
142
|
+
* around it). Stored in the thread's `Y.Map` under `anchor`, so every collaborator resolves the same place.
|
|
143
|
+
*/
|
|
144
|
+
export interface CommentAnchor {
|
|
145
|
+
type?: {
|
|
146
|
+
client: number;
|
|
147
|
+
clock: number;
|
|
148
|
+
};
|
|
149
|
+
tname?: string;
|
|
150
|
+
item?: {
|
|
151
|
+
client: number;
|
|
152
|
+
clock: number;
|
|
153
|
+
};
|
|
154
|
+
assoc?: number;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* A comment thread: the root comment plus its replies. Stored as a nested `Y.Map` in `ydoc.getMap(COMMENTS_FIELD)`
|
|
158
|
+
* (replies as a nested `Y.Array`), so concurrent replies and edits of different users merge. Its text range is the
|
|
159
|
+
* `comment` mark with the thread's `id`.
|
|
160
|
+
*/
|
|
161
|
+
export interface CommentThread {
|
|
162
|
+
id: string;
|
|
163
|
+
author: CommentAuthor;
|
|
164
|
+
text: string;
|
|
165
|
+
createdAt: string;
|
|
166
|
+
editedAt?: string;
|
|
167
|
+
/** The commented text when the thread was created, cut to `COMMENT_LIMITS.quote`. */
|
|
168
|
+
quote: string;
|
|
169
|
+
/** Resolved threads are kept, without highlight, until reopened. */
|
|
170
|
+
resolved: boolean;
|
|
171
|
+
/**
|
|
172
|
+
* Start of the commented text as a Yjs relative position, written when the thread is created (older threads get it
|
|
173
|
+
* once they are seen with their text still in the document). Tells where an orphaned thread's text was. Absent on threads
|
|
174
|
+
* not yet seen with a range, and when the position could not be captured.
|
|
175
|
+
*/
|
|
176
|
+
anchor?: CommentAnchor;
|
|
177
|
+
replies: CommentReply[];
|
|
178
|
+
}
|
|
179
|
+
/** A text range in the editor document. */
|
|
180
|
+
export type DocRange = {
|
|
181
|
+
from: number;
|
|
182
|
+
to: number;
|
|
183
|
+
};
|
|
184
|
+
/** What a comments UI renders: replaced (a new object) whenever any part of it changes, so a store subscriber re-renders only then. */
|
|
185
|
+
export interface CommentsSnapshot {
|
|
186
|
+
/** Comments need a collaborative editor whose `Comments` extension has a user (a host model decides for itself). */
|
|
187
|
+
available: boolean;
|
|
188
|
+
/**
|
|
189
|
+
* Whether the user may compose a comment now: the default model says `available` and the editor is editable, a host
|
|
190
|
+
* model may allow readers of a read-only document to comment.
|
|
191
|
+
*/
|
|
192
|
+
canComment: boolean;
|
|
193
|
+
user: AuthorIdentity | null;
|
|
194
|
+
/** Plain snapshots of all threads in the Y.Doc, replaced on every change. */
|
|
195
|
+
threads: readonly CommentThread[];
|
|
196
|
+
/** Current text range per thread id (threads without one are orphans). */
|
|
197
|
+
ranges: ReadonlyMap<string, DocRange>;
|
|
198
|
+
/**
|
|
199
|
+
* Where the text of an orphaned open thread was: the document position of the deletion point, resolved from the
|
|
200
|
+
* thread's stored anchor (so it is the same place for every collaborator and follows edits). Absent for orphans
|
|
201
|
+
* without a usable anchor (threads from before anchors, or whose block is gone for good).
|
|
202
|
+
*/
|
|
203
|
+
orphanAt: ReadonlyMap<string, number>;
|
|
204
|
+
active: string | null;
|
|
205
|
+
/** Current range of the draft a new comment is being written for. */
|
|
206
|
+
draft: DocRange | null;
|
|
207
|
+
/** The draft's text as the new thread will keep it (`quote`). */
|
|
208
|
+
draftQuote: string;
|
|
209
|
+
/** Unresolved threads in document order, orphans last; resolved ones newest first. */
|
|
210
|
+
open: readonly CommentThread[];
|
|
211
|
+
resolved: readonly CommentThread[];
|
|
212
|
+
}
|
|
213
|
+
/** The mutations of the comments of one editor; no-ops without collaboration or a user. */
|
|
214
|
+
export interface CommentsActions {
|
|
215
|
+
/** Creates a thread on the draft range; its id, or null without a (non-empty) draft or text. */
|
|
216
|
+
add: (text: string) => string | null;
|
|
217
|
+
reply: (threadId: string, text: string) => void;
|
|
218
|
+
/** Changes the text of the user's own thread (`replyId` null) or reply. */
|
|
219
|
+
edit: (threadId: string, replyId: string | null, text: string) => void;
|
|
220
|
+
/** Resolves or reopens a thread (anyone may). */
|
|
221
|
+
setResolved: (threadId: string, resolved: boolean) => void;
|
|
222
|
+
/** Deletes the user's own thread with its marks / the user's own reply. */
|
|
223
|
+
remove: (threadId: string) => void;
|
|
224
|
+
removeReply: (threadId: string, replyId: string) => void;
|
|
225
|
+
/** Activates a thread (`null`: none); `reveal` selects and scrolls to its text. */
|
|
226
|
+
activate: (id: string | null, options?: {
|
|
227
|
+
reveal?: boolean;
|
|
228
|
+
}) => void;
|
|
229
|
+
/** Starts a comment on the current selection (the layout shows the composer while `draft` is set). */
|
|
230
|
+
startDraft: () => void;
|
|
231
|
+
cancelDraft: () => void;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* The comments of one editor, framework-free: `state` is the observable snapshot, `refresh()` brings it up to date
|
|
235
|
+
* (the framework hook calls it when the editor it watches changes; the model itself listens to that editor's
|
|
236
|
+
* transactions from then on), `dispose()` detaches the editor and Y.Doc listeners and may be followed by `refresh()` again
|
|
237
|
+
* (StrictMode mounts twice).
|
|
238
|
+
*/
|
|
239
|
+
export interface CommentsModel extends CommentsActions {
|
|
240
|
+
readonly state: ReadonlyStore<CommentsSnapshot>;
|
|
241
|
+
refresh: () => void;
|
|
242
|
+
dispose: () => void;
|
|
243
|
+
}
|
|
244
|
+
//#endregion
|
|
245
|
+
//# sourceMappingURL=backend-types.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/core/backend-types.ts
|
|
2
|
+
/** The CSL item types the editor offers (select options, server-side schema). */
|
|
3
|
+
const CSL_TYPES = [
|
|
4
|
+
"article-journal",
|
|
5
|
+
"book",
|
|
6
|
+
"chapter",
|
|
7
|
+
"paper-conference",
|
|
8
|
+
"thesis",
|
|
9
|
+
"report",
|
|
10
|
+
"webpage",
|
|
11
|
+
"article",
|
|
12
|
+
"dataset"
|
|
13
|
+
];
|
|
14
|
+
//#endregion
|
|
15
|
+
export { CSL_TYPES };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=backend-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-types.js","names":[],"sources":["../../src/core/backend-types.ts"],"sourcesContent":["import type { ReadonlyStore } from './store'\nimport type { AuthorIdentity } from './feature'\n\n// The wire and model types that `EditorBackend` (`./backend`) names in its methods. They live in core, not in the\n// features they belong to, so the port does not depend on any feature or integration; each feature's public entry\n// (`@ecsplico/editor/mentions/schema`, `…/themes/schema`, `…/ai/protocol`, `…/comments/schema`, …) exports the names\n// it always had. Types only: DOM-free, importable from server code.\n\n/** A user as offered for `@` mentions (`GET /api/editor/users`); never carries credentials. */\nexport interface MentionUser {\n id: string\n username: string\n color: string\n}\n\n/** Profile as the client sees it; presets never expose their key. */\nexport interface ModelProfile { id: string, label: string, endpoint: string, model: string, source: 'preset' | 'user' }\n\n/** Model an AI request runs on: a server preset by id, or an OpenAI-compatible endpoint with its own key. */\nexport type ModelRef = { preset: string } | { endpoint: string, model: string, apiKey: string }\n\n/** A theme in the shared library; `builtin` themes are seeded by the host and cannot be deleted. */\nexport interface ThemeRecord {\n id: string\n name: string\n version?: string\n author?: string\n authorUrl?: string\n builtin: boolean\n}\n\n/** One transcript segment sent for cleanup. */\nexport interface TranscriptCleanupSegment {\n /** Block ID of the segment (`blockIdOf`). */\n id: string\n speaker: string\n /** The segment's inline content as Markdown (mentions as `@name`, tags as `#name`). */\n text: string\n}\n/** Body of the transcript-cleanup route. */\nexport interface TranscriptCleanupRequest { segments: TranscriptCleanupSegment[], model: ModelRef }\n/** Cleaned text (single-line inline Markdown) of the segment with block ID `id`. */\nexport interface TranscriptCleanupResult { id: string, text: string }\n/** `cleaned`: only segments whose text changed. `failed`: segments of chunks whose model answer was unusable (left as they are). */\nexport interface TranscriptCleanupResponse { cleaned: TranscriptCleanupResult[], failed: number }\n\n/** A CSL name: `family`/`given` for a person, `literal` for an institution or an unparsed name. */\nexport interface CslName { family?: string, given?: string, literal?: string }\nexport interface CslDate { 'date-parts': number[][] }\n\n/** The CSL item types the editor offers (select options, server-side schema). */\nexport const CSL_TYPES = ['article-journal', 'book', 'chapter', 'paper-conference', 'thesis', 'report', 'webpage', 'article', 'dataset'] as const\nexport type CslType = typeof CSL_TYPES[number]\n\n/** A CSL-JSON item without `id` and `title`: the Baustein's block id and title are authoritative for those and never stored in `meta.bib`. */\nexport interface CslItem {\n type: CslType\n author?: CslName[]\n editor?: CslName[]\n issued?: CslDate\n 'container-title'?: string\n volume?: string\n issue?: string\n page?: string\n publisher?: string\n 'publisher-place'?: string\n DOI?: string\n ISBN?: string\n URL?: string\n abstract?: string\n language?: string\n}\n\n/** What `ai.extract` makes of a stored asset; `auto` picks by the asset's MIME type. */\nexport type ExtractMethod = 'auto' | 'transcription' | 'pdf-text' | 'ocr' | 'description' | 'bibliography'\n/** Body of the extract route: the stored asset `documentId`/`name` and what to make of it. */\nexport interface ExtractRequest {\n documentId: string\n /** The asset to read; absent only for `bibliography` with a `doi` (the work is looked up by DOI alone). */\n name?: string\n method: ExtractMethod\n /** The model of `ocr`, `description` and model-based bibliography extraction. */\n model: ModelRef\n /** Also extract bibliographic data after `pdf-text`/`ocr`. */\n bibliography?: boolean\n /** DOI to look up for `bibliography`; absent = found in the first pages' text. */\n doi?: string\n /** PDF page cap (default 200). `ocr` reads at most 50 pages whatever this allows (one model call per page; `ocr-truncated` warns). */\n maxPages?: number\n}\nexport interface ExtractResponse {\n method: Exclude<ExtractMethod, 'auto'>\n /** The readable content as Markdown (empty for `bibliography`). */\n markdown: string\n /** Transcription only: the timed segments `markdown` was made of. */\n segments?: { start: number, end: number, text: string }[]\n /** When bibliographic data was requested or the method is `bibliography`; `title` is the work's title when found (never stored in `meta.bib`). */\n bib?: CslItem & { title?: string }\n /** Transcription only: the speech-to-text model that wrote it (`TranscriptionConfig.model`), which the client cannot know. */\n model?: string\n /** SHA-256 (hex) of the asset bytes. */\n inputHash: string\n /** SHA-256 (hex) of the stored raw output (`markdown` as the asset `output` holds it). The client does not compare it: it hashes the body it writes (its re-serialised Markdown) into `Derivation.outputHash` itself. */\n outputHash: string\n /** Asset name (same document) of the stored raw Markdown; `null` for `bibliography`. */\n output: string | null\n warnings: string[]\n}\n\n/** Who wrote a comment or reply: the writing user's identity, copied in when writing. */\nexport type CommentAuthor = AuthorIdentity\n\nexport interface CommentReply {\n id: string\n author: CommentAuthor\n text: string\n /** ISO timestamps; `editedAt` once the author changed the text. */\n createdAt: string\n editedAt?: string\n}\n\n/**\n * Where a thread's text starts, as the JSON form of a Yjs relative position (`Y.relativePositionToJSON`): bound to the\n * first commented character, so it keeps pointing at the place after that text was deleted (and moves with the text\n * around it). Stored in the thread's `Y.Map` under `anchor`, so every collaborator resolves the same place.\n */\nexport interface CommentAnchor {\n type?: { client: number, clock: number }\n tname?: string\n item?: { client: number, clock: number }\n assoc?: number\n}\n\n/**\n * A comment thread: the root comment plus its replies. Stored as a nested `Y.Map` in `ydoc.getMap(COMMENTS_FIELD)`\n * (replies as a nested `Y.Array`), so concurrent replies and edits of different users merge. Its text range is the\n * `comment` mark with the thread's `id`.\n */\nexport interface CommentThread {\n id: string\n author: CommentAuthor\n text: string\n createdAt: string\n editedAt?: string\n /** The commented text when the thread was created, cut to `COMMENT_LIMITS.quote`. */\n quote: string\n /** Resolved threads are kept, without highlight, until reopened. */\n resolved: boolean\n /**\n * Start of the commented text as a Yjs relative position, written when the thread is created (older threads get it\n * once they are seen with their text still in the document). Tells where an orphaned thread's text was. Absent on threads\n * not yet seen with a range, and when the position could not be captured.\n */\n anchor?: CommentAnchor\n replies: CommentReply[]\n}\n\n/** A text range in the editor document. */\nexport type DocRange = { from: number, to: number }\n\n/** What a comments UI renders: replaced (a new object) whenever any part of it changes, so a store subscriber re-renders only then. */\nexport interface CommentsSnapshot {\n /** Comments need a collaborative editor whose `Comments` extension has a user (a host model decides for itself). */\n available: boolean\n /**\n * Whether the user may compose a comment now: the default model says `available` and the editor is editable, a host\n * model may allow readers of a read-only document to comment.\n */\n canComment: boolean\n user: AuthorIdentity | null\n /** Plain snapshots of all threads in the Y.Doc, replaced on every change. */\n threads: readonly CommentThread[]\n /** Current text range per thread id (threads without one are orphans). */\n ranges: ReadonlyMap<string, DocRange>\n /**\n * Where the text of an orphaned open thread was: the document position of the deletion point, resolved from the\n * thread's stored anchor (so it is the same place for every collaborator and follows edits). Absent for orphans\n * without a usable anchor (threads from before anchors, or whose block is gone for good).\n */\n orphanAt: ReadonlyMap<string, number>\n active: string | null\n /** Current range of the draft a new comment is being written for. */\n draft: DocRange | null\n /** The draft's text as the new thread will keep it (`quote`). */\n draftQuote: string\n /** Unresolved threads in document order, orphans last; resolved ones newest first. */\n open: readonly CommentThread[]\n resolved: readonly CommentThread[]\n}\n\n/** The mutations of the comments of one editor; no-ops without collaboration or a user. */\nexport interface CommentsActions {\n /** Creates a thread on the draft range; its id, or null without a (non-empty) draft or text. */\n add: (text: string) => string | null\n reply: (threadId: string, text: string) => void\n /** Changes the text of the user's own thread (`replyId` null) or reply. */\n edit: (threadId: string, replyId: string | null, text: string) => void\n /** Resolves or reopens a thread (anyone may). */\n setResolved: (threadId: string, resolved: boolean) => void\n /** Deletes the user's own thread with its marks / the user's own reply. */\n remove: (threadId: string) => void\n removeReply: (threadId: string, replyId: string) => void\n /** Activates a thread (`null`: none); `reveal` selects and scrolls to its text. */\n activate: (id: string | null, options?: { reveal?: boolean }) => void\n /** Starts a comment on the current selection (the layout shows the composer while `draft` is set). */\n startDraft: () => void\n cancelDraft: () => void\n}\n\n/**\n * The comments of one editor, framework-free: `state` is the observable snapshot, `refresh()` brings it up to date\n * (the framework hook calls it when the editor it watches changes; the model itself listens to that editor's\n * transactions from then on), `dispose()` detaches the editor and Y.Doc listeners and may be followed by `refresh()` again\n * (StrictMode mounts twice).\n */\nexport interface CommentsModel extends CommentsActions {\n readonly state: ReadonlyStore<CommentsSnapshot>\n refresh: () => void\n dispose: () => void\n}\n"],"mappings":";;AAmDA,MAAa,YAAY;CAAC;CAAmB;CAAQ;CAAW;CAAoB;CAAU;CAAU;CAAW;CAAW;AAAS"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { ModelSlot } from "../settings/values.js";
|
|
2
|
+
import { EditorSettings } from "../settings/index.js";
|
|
3
|
+
import { BackendCapability } from "./backend-capability.js";
|
|
4
|
+
import { AuthorIdentity } from "./feature.js";
|
|
5
|
+
import { CommentsModel, ExtractRequest, ExtractResponse, MentionUser, ModelProfile, ModelRef, ThemeRecord, TranscriptCleanupRequest, TranscriptCleanupResponse } from "./backend-types.js";
|
|
6
|
+
import { Editor, JSONContent } from "@tiptap/core";
|
|
7
|
+
import { HocuspocusProvider } from "@hocuspocus/provider";
|
|
8
|
+
import * as Y from "yjs";
|
|
9
|
+
//#region src/core/backend.d.ts
|
|
10
|
+
/** One server-sent event of an AI stream (`delta` `{ text }`, `ops` the proposed edit operations, `done`, `error` `{ message }`). `data` is the parsed JSON payload (`{}` without one). */
|
|
11
|
+
export interface AiStreamEvent {
|
|
12
|
+
event: 'delta' | 'ops' | 'done' | 'error';
|
|
13
|
+
data: unknown;
|
|
14
|
+
}
|
|
15
|
+
/** The token a collaboration server's `authenticate` receives: a string, or a function (also async) that returns it on each connect. */
|
|
16
|
+
export type CollaborationToken = string | (() => string) | (() => Promise<string>);
|
|
17
|
+
/** A refused or failed backend request; `status` is the HTTP status (or its equivalent) and `message` the server's, when it sent one. */
|
|
18
|
+
export declare class BackendError extends Error {
|
|
19
|
+
readonly status: number;
|
|
20
|
+
constructor(message: string, status: number, options?: ErrorOptions);
|
|
21
|
+
}
|
|
22
|
+
/** What a backend needs from the host to give a comments model its anchors and its author. */
|
|
23
|
+
export interface BackendCommentsOptions {
|
|
24
|
+
/** Who writes: the author of new comments; `null` while nobody is signed in. */
|
|
25
|
+
user: () => AuthorIdentity | null;
|
|
26
|
+
/** Whether the user may compose and change comments now. */
|
|
27
|
+
canComment: () => boolean;
|
|
28
|
+
/** The editor the threads belong to; may return no editor yet or a destroyed one. */
|
|
29
|
+
getEditor: () => Editor | undefined;
|
|
30
|
+
/** Called with every failed request. */
|
|
31
|
+
onError?: (error: Error) => void;
|
|
32
|
+
}
|
|
33
|
+
export interface EditorBackend {
|
|
34
|
+
/** Names the backend in error messages (`'http'`, `'memory'`, …). */
|
|
35
|
+
readonly name: string;
|
|
36
|
+
/**
|
|
37
|
+
* Settles once the backend knows which capabilities it really has (the HTTP adapter's `probe`, which drops what the
|
|
38
|
+
* server lacks). `createEditorContext` awaits it before it reports `ready`, so a composition that prunes by capability
|
|
39
|
+
* (`composeEditor(…, { backend })`) should run after it too. Never rejects; absent: usable at once.
|
|
40
|
+
*/
|
|
41
|
+
readonly ready?: Promise<void>;
|
|
42
|
+
documents?: {
|
|
43
|
+
/** The stored content; `null` when the document does not exist (yet). */
|
|
44
|
+
load: (id: string) => Promise<JSONContent | null>;
|
|
45
|
+
save: (id: string, content: JSONContent) => Promise<void>;
|
|
46
|
+
};
|
|
47
|
+
collaboration?: {
|
|
48
|
+
/** Opens the live session of document `id`; `dispose()` closes the provider and the Y.Doc. */
|
|
49
|
+
connect: (id: string, token?: CollaborationToken) => {
|
|
50
|
+
ydoc: Y.Doc;
|
|
51
|
+
provider: HocuspocusProvider;
|
|
52
|
+
dispose: () => void;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
assets?: {
|
|
56
|
+
/** Stores `file` for document `documentId`; resolves with the URL it is addressed by and, when the backend hashes uploads, the SHA-256 (hex) of its bytes. */
|
|
57
|
+
upload: (documentId: string, file: File) => Promise<{
|
|
58
|
+
url: string;
|
|
59
|
+
sha256?: string;
|
|
60
|
+
}>;
|
|
61
|
+
};
|
|
62
|
+
users?: {
|
|
63
|
+
search: (query: string, signal?: AbortSignal) => Promise<MentionUser[]>;
|
|
64
|
+
};
|
|
65
|
+
tags?: {
|
|
66
|
+
search: (query: string, signal?: AbortSignal) => Promise<string[]>;
|
|
67
|
+
};
|
|
68
|
+
settings?: {
|
|
69
|
+
/** The account's settings; `null` when it has none stored yet. */
|
|
70
|
+
load: () => Promise<EditorSettings | null>;
|
|
71
|
+
save: (settings: EditorSettings) => Promise<void>;
|
|
72
|
+
};
|
|
73
|
+
themes?: {
|
|
74
|
+
list: () => Promise<ThemeRecord[]>;
|
|
75
|
+
/** The stylesheet of theme `id` (unscoped). */
|
|
76
|
+
css: (id: string) => Promise<string>;
|
|
77
|
+
/** Adds an Obsidian theme to the shared library: the stylesheet and, optionally, its `manifest.json`; the backend derives name and id. */
|
|
78
|
+
store: (files: {
|
|
79
|
+
css: File;
|
|
80
|
+
manifest?: File;
|
|
81
|
+
}) => Promise<ThemeRecord>;
|
|
82
|
+
/** Deletes an uploaded theme; rejects for builtins and unknown ids. */
|
|
83
|
+
remove: (id: string) => Promise<boolean>;
|
|
84
|
+
};
|
|
85
|
+
ai?: {
|
|
86
|
+
models: () => Promise<{
|
|
87
|
+
presets: ModelProfile[];
|
|
88
|
+
slots: Record<ModelSlot, string>;
|
|
89
|
+
}>;
|
|
90
|
+
complete: (body: {
|
|
91
|
+
before: string;
|
|
92
|
+
model: ModelRef;
|
|
93
|
+
}, signal: AbortSignal) => Promise<{
|
|
94
|
+
text: string;
|
|
95
|
+
}>;
|
|
96
|
+
/** Streams the SSE events of `generate` or `chat`; throws `BackendError` (with `status`) on a non-2xx answer before the stream starts. */
|
|
97
|
+
stream: (path: 'generate' | 'chat', body: object, signal: AbortSignal) => AsyncIterable<AiStreamEvent>;
|
|
98
|
+
/** Speaker-segment cleanup of a transcript (one JSON answer, not a stream). */
|
|
99
|
+
transcriptCleanup: (body: TranscriptCleanupRequest, signal: AbortSignal) => Promise<TranscriptCleanupResponse>;
|
|
100
|
+
/** Turns a stored asset into readable content: transcription (with segment timestamps), PDF text or OCR, an image description, bibliographic data. */
|
|
101
|
+
extract: (body: ExtractRequest, signal: AbortSignal) => Promise<ExtractResponse>;
|
|
102
|
+
};
|
|
103
|
+
/** The comments model of document `documentId`. */
|
|
104
|
+
comments?: (documentId: string, options: BackendCommentsOptions) => CommentsModel;
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
export type { BackendCapability };
|
|
108
|
+
//# sourceMappingURL=backend.d.ts.map
|