@ecsplico/editor 3.1.1 → 3.3.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 +42 -0
- package/dist/adapters/direct-ai.d.ts +36 -0
- package/dist/adapters/direct-ai.js +169 -0
- package/dist/adapters/direct-ai.js.map +1 -0
- package/dist/adapters/memory.js.map +1 -1
- package/dist/code/CodeSurface.vue.d.ts +1 -1
- package/dist/core/block-drag.js +3 -0
- package/dist/core/block-drag.js.map +1 -1
- package/dist/core/block-transfer.d.ts +44 -0
- package/dist/core/block-transfer.js +68 -0
- package/dist/core/block-transfer.js.map +1 -0
- package/dist/core/commands.js +5 -0
- package/dist/core/commands.js.map +1 -1
- package/dist/core/core-feature.d.ts +4 -1
- package/dist/core/core-feature.js +8 -3
- package/dist/core/core-feature.js.map +1 -1
- package/dist/core/editor-ui.d.ts +3 -1
- package/dist/core/editor-ui.js.map +1 -1
- package/dist/core/extension-points.d.ts +17 -1
- package/dist/core/feature.d.ts +6 -1
- package/dist/core/feature.js.map +1 -1
- package/dist/core/index.d.ts +4 -2
- package/dist/core/index.js +3 -2
- package/dist/core/schema/index.d.ts +24 -3
- package/dist/core/schema/index.js +21 -4
- package/dist/core/schema/index.js.map +1 -1
- package/dist/core/surface-session.js +3 -1
- package/dist/core/surface-session.js.map +1 -1
- package/dist/core/toolbar-items.js +1 -1
- package/dist/core/toolbar-items.js.map +1 -1
- package/dist/document/DocumentSurface.vue.d.ts +1 -1
- package/dist/features/ai/agent-op-review.js +1 -1
- package/dist/features/ai/agent-ops.js +2 -2
- package/dist/features/ai/ai-apply.js +1 -1
- package/dist/features/ai/assistant.js +1 -1
- package/dist/features/ai/components/AiSelectionMenu.js +2 -2
- package/dist/features/ai/components/AiSidebar.js +2 -2
- package/dist/features/ai/components/SettingsAiTab.js +1 -1
- package/dist/features/ai/components/SettingsModelProfiles.js +1 -1
- package/dist/features/ai/document-chat-model.js +1 -1
- package/dist/features/ai/document-chat.js +2 -2
- package/dist/features/ai/ghost-autocomplete.js +1 -1
- package/dist/features/ai/index.d.ts +4 -3
- package/dist/features/ai/index.js +6 -5
- package/dist/features/ai/protocol/complete.d.ts +19 -0
- package/dist/features/ai/protocol/complete.js +27 -1
- package/dist/features/ai/protocol/complete.js.map +1 -1
- package/dist/features/ai/protocol/generate.d.ts +95 -0
- package/dist/features/ai/protocol/generate.js +58 -0
- package/dist/features/ai/protocol/generate.js.map +1 -0
- package/dist/features/ai/protocol/index.d.ts +4 -3
- package/dist/features/ai/protocol/index.js +6 -5
- package/dist/features/ai/protocol/tasks.d.ts +3 -1
- package/dist/features/ai/protocol/tasks.js +74 -2
- package/dist/features/ai/protocol/tasks.js.map +1 -1
- package/dist/features/ai/react/AiSelectionMenu.js +2 -2
- package/dist/features/ai/react/AiSidebar.js +2 -2
- package/dist/features/ai/react/SettingsAiTab.js +1 -1
- package/dist/features/ai/react/SettingsModelProfiles.js +1 -1
- package/dist/features/ai/selection-flow.js +1 -1
- package/dist/features/ai/sidebar-flow.js +1 -1
- package/dist/features/block-ui/block-actions.d.ts +19 -3
- package/dist/features/block-ui/block-actions.js +49 -3
- package/dist/features/block-ui/block-actions.js.map +1 -1
- package/dist/features/block-ui/components/BlockActionsOverlay.js +24 -13
- package/dist/features/block-ui/components/BlockActionsOverlay.js.map +1 -1
- package/dist/features/block-ui/components/BlockActionsOverlay.vue.d.ts +12 -5
- package/dist/features/block-ui/components/BlockUi.js +52 -20
- package/dist/features/block-ui/components/BlockUi.js.map +1 -1
- package/dist/features/block-ui/components/BlockUi.vue.d.ts +6 -4
- package/dist/features/block-ui/feature.d.ts +8 -2
- package/dist/features/block-ui/feature.js +7 -2
- package/dist/features/block-ui/feature.js.map +1 -1
- package/dist/features/block-ui/index.d.ts +3 -2
- package/dist/features/block-ui/index.js +2 -2
- package/dist/features/block-ui/react/BlockActionsOverlay.d.ts +14 -7
- package/dist/features/block-ui/react/BlockActionsOverlay.js +25 -13
- package/dist/features/block-ui/react/BlockActionsOverlay.js.map +1 -1
- package/dist/features/block-ui/react/BlockUi.d.ts +6 -4
- package/dist/features/block-ui/react/BlockUi.js +43 -15
- package/dist/features/block-ui/react/BlockUi.js.map +1 -1
- package/dist/features/block-ui/react.d.ts +4 -2
- package/dist/features/block-ui/react.js +3 -3
- package/dist/features/block-ui/react.js.map +1 -1
- package/dist/features/block-ui/vue.d.ts +4 -2
- package/dist/features/block-ui/vue.js +3 -3
- package/dist/features/block-ui/vue.js.map +1 -1
- package/dist/features/composites/baskets.d.ts +27 -0
- package/dist/features/composites/baskets.js +46 -0
- package/dist/features/composites/baskets.js.map +1 -0
- package/dist/features/composites/components/CompositeBasketMenu.js +97 -0
- package/dist/features/composites/components/CompositeBasketMenu.js.map +1 -0
- package/dist/features/composites/components/CompositeChrome.js +79 -23
- package/dist/features/composites/components/CompositeChrome.js.map +1 -1
- package/dist/features/composites/components/CompositeView.js +21 -2
- package/dist/features/composites/components/CompositeView.js.map +1 -1
- package/dist/features/composites/components/DerivationBadge.js +12 -3
- package/dist/features/composites/components/DerivationBadge.js.map +1 -1
- package/dist/features/composites/components/FocusChip.js +53 -0
- package/dist/features/composites/components/FocusChip.js.map +1 -0
- package/dist/features/composites/components/FocusChip.vue.d.ts +14 -0
- package/dist/features/composites/components/SettingsEditingTab.js +40 -4
- package/dist/features/composites/components/SettingsEditingTab.js.map +1 -1
- package/dist/features/composites/derivation.d.ts +2 -1
- package/dist/features/composites/derivation.js +5 -1
- package/dist/features/composites/derivation.js.map +1 -1
- package/dist/features/composites/derived-chrome.js +13 -3
- package/dist/features/composites/derived-chrome.js.map +1 -1
- package/dist/features/composites/feature.d.ts +7 -1
- package/dist/features/composites/feature.js +107 -23
- package/dist/features/composites/feature.js.map +1 -1
- package/dist/features/composites/focus.d.ts +38 -0
- package/dist/features/composites/focus.js +86 -0
- package/dist/features/composites/focus.js.map +1 -0
- package/dist/features/composites/index.d.ts +7 -3
- package/dist/features/composites/index.js +7 -3
- package/dist/features/composites/kinds.d.ts +6 -1
- package/dist/features/composites/kinds.js.map +1 -1
- package/dist/features/composites/merge.d.ts +24 -0
- package/dist/features/composites/merge.js +47 -0
- package/dist/features/composites/merge.js.map +1 -0
- package/dist/features/composites/meta-keys.d.ts +4 -0
- package/dist/features/composites/meta-keys.js +8 -4
- package/dist/features/composites/meta-keys.js.map +1 -1
- package/dist/features/composites/nodes.d.ts +15 -2
- package/dist/features/composites/nodes.js +61 -5
- package/dist/features/composites/nodes.js.map +1 -1
- package/dist/features/composites/outline.d.ts +4 -0
- package/dist/features/composites/outline.js +3 -0
- package/dist/features/composites/outline.js.map +1 -1
- package/dist/features/composites/react/CompositeBasketMenu.js +88 -0
- package/dist/features/composites/react/CompositeBasketMenu.js.map +1 -0
- package/dist/features/composites/react/CompositeChrome.js +52 -4
- package/dist/features/composites/react/CompositeChrome.js.map +1 -1
- package/dist/features/composites/react/CompositeView.js +15 -2
- package/dist/features/composites/react/CompositeView.js.map +1 -1
- package/dist/features/composites/react/DerivationBadge.js +10 -1
- package/dist/features/composites/react/DerivationBadge.js.map +1 -1
- package/dist/features/composites/react/FocusChip.d.ts +11 -0
- package/dist/features/composites/react/FocusChip.js +50 -0
- package/dist/features/composites/react/FocusChip.js.map +1 -0
- package/dist/features/composites/react/SettingsEditingTab.js +36 -1
- package/dist/features/composites/react/SettingsEditingTab.js.map +1 -1
- package/dist/features/composites/react.d.ts +2 -1
- package/dist/features/composites/react.js +3 -1
- package/dist/features/composites/react.js.map +1 -1
- package/dist/features/composites/schema.d.ts +5 -3
- package/dist/features/composites/schema.js +8 -4
- package/dist/features/composites/schema.js.map +1 -1
- package/dist/features/composites/split.d.ts +62 -0
- package/dist/features/composites/split.js +172 -0
- package/dist/features/composites/split.js.map +1 -0
- package/dist/features/composites/vue.d.ts +4 -3
- package/dist/features/composites/vue.js +7 -5
- package/dist/features/composites/vue.js.map +1 -1
- package/dist/features/transfer/components/TransferMenu.js +93 -0
- package/dist/features/transfer/components/TransferMenu.js.map +1 -0
- package/dist/features/transfer/components/TransferMenu.vue.d.ts +15 -0
- package/dist/features/transfer/feature.d.ts +76 -0
- package/dist/features/transfer/feature.js +169 -0
- package/dist/features/transfer/feature.js.map +1 -0
- package/dist/features/transfer/index.d.ts +3 -0
- package/dist/features/transfer/index.js +3 -0
- package/dist/features/transfer/react/TransferMenu.d.ts +12 -0
- package/dist/features/transfer/react/TransferMenu.js +71 -0
- package/dist/features/transfer/react/TransferMenu.js.map +1 -0
- package/dist/features/transfer/react.d.ts +10 -0
- package/dist/features/transfer/react.js +11 -0
- package/dist/features/transfer/react.js.map +1 -0
- package/dist/features/transfer/transforms.d.ts +83 -0
- package/dist/features/transfer/transforms.js +137 -0
- package/dist/features/transfer/transforms.js.map +1 -0
- package/dist/features/transfer/vue.d.ts +9 -0
- package/dist/features/transfer/vue.js +11 -0
- package/dist/features/transfer/vue.js.map +1 -0
- package/dist/i18n/de/ai.js +4 -0
- package/dist/i18n/de/ai.js.map +1 -1
- package/dist/i18n/de/composites.js +21 -1
- package/dist/i18n/de/composites.js.map +1 -1
- package/dist/i18n/de/integrations.js +16 -0
- package/dist/i18n/de/integrations.js.map +1 -1
- package/dist/i18n/de/transfer.js +17 -0
- package/dist/i18n/de/transfer.js.map +1 -0
- package/dist/i18n/de/tree.js +7 -0
- package/dist/i18n/de/tree.js.map +1 -1
- package/dist/i18n/de.d.ts +57 -0
- package/dist/i18n/de.js +3 -1
- package/dist/i18n/de.js.map +1 -1
- package/dist/i18n/en/ai.js +4 -0
- package/dist/i18n/en/ai.js.map +1 -1
- package/dist/i18n/en/composites.js +21 -1
- package/dist/i18n/en/composites.js.map +1 -1
- package/dist/i18n/en/integrations.js +16 -0
- package/dist/i18n/en/integrations.js.map +1 -1
- package/dist/i18n/en/transfer.js +17 -0
- package/dist/i18n/en/transfer.js.map +1 -0
- package/dist/i18n/en/tree.js +7 -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/integrations/composite-ai/composite-fill.js +1 -1
- package/dist/integrations/composite-ai/composite-summary.js +1 -1
- package/dist/integrations/composite-ai/derive.d.ts +21 -0
- package/dist/integrations/composite-ai/derive.js +69 -47
- package/dist/integrations/composite-ai/derive.js.map +1 -1
- package/dist/integrations/composite-ai/index.d.ts +8 -3
- package/dist/integrations/composite-ai/index.js +50 -4
- package/dist/integrations/composite-ai/index.js.map +1 -1
- package/dist/integrations/composite-ai/outline-sanitize.d.ts +48 -0
- package/dist/integrations/composite-ai/outline-sanitize.js +175 -0
- package/dist/integrations/composite-ai/outline-sanitize.js.map +1 -0
- package/dist/integrations/composite-ai/split.d.ts +44 -0
- package/dist/integrations/composite-ai/split.js +187 -0
- package/dist/integrations/composite-ai/split.js.map +1 -0
- package/dist/integrations/composite-ai/transfer-transforms.d.ts +27 -0
- package/dist/integrations/composite-ai/transfer-transforms.js +153 -0
- package/dist/integrations/composite-ai/transfer-transforms.js.map +1 -0
- package/dist/integrations/transcript-ai/protocol.d.ts +13 -0
- package/dist/integrations/transcript-ai/protocol.js +49 -1
- package/dist/integrations/transcript-ai/protocol.js.map +1 -1
- package/dist/integrations/transcript-ai/transcript-cleanup.js +1 -1
- package/dist/markdown/MarkdownSurface.vue.d.ts +1 -1
- package/dist/nuxt/module.d.ts +114 -0
- package/dist/presets/compose.d.ts +24 -8
- package/dist/presets/compose.js +117 -58
- package/dist/presets/compose.js.map +1 -1
- package/dist/react/compose.js +5 -1
- package/dist/react/compose.js.map +1 -1
- package/dist/react/composed-surface.d.ts +9 -0
- package/dist/react/composed-surface.js +4 -1
- package/dist/react/composed-surface.js.map +1 -1
- package/dist/server/ai.d.ts +2 -5
- package/dist/server/ai.js.map +1 -1
- package/dist/server/handlers/ai.d.ts +4 -75
- package/dist/server/handlers/ai.js +30 -94
- package/dist/server/handlers/ai.js.map +1 -1
- package/dist/server/handlers/editor.d.ts +1 -0
- package/dist/server/handlers/index.d.ts +3 -1
- package/dist/server/handlers/index.js +3 -1
- package/dist/server/index.d.ts +2 -1
- package/dist/settings/index.d.ts +8 -0
- package/dist/settings/index.js +16 -4
- package/dist/settings/index.js.map +1 -1
- package/dist/styles/composites.css +41 -0
- package/dist/tree/DocumentTree.js +246 -80
- package/dist/tree/DocumentTree.js.map +1 -1
- package/dist/tree/drop-rules.js +8 -0
- package/dist/tree/drop-rules.js.map +1 -1
- package/dist/tree/react/DocumentTree.js +164 -32
- package/dist/tree/react/DocumentTree.js.map +1 -1
- package/dist/tree/tree-host.js +41 -2
- package/dist/tree/tree-host.js.map +1 -1
- package/dist/tree/tree-items.js +53 -5
- package/dist/tree/tree-items.js.map +1 -1
- package/dist/tree/tree-model.js +122 -10
- package/dist/tree/tree-model.js.map +1 -1
- package/dist/tree/tree-rows.js +20 -7
- package/dist/tree/tree-rows.js.map +1 -1
- package/dist/tree/tree-view-model.d.ts +5 -0
- package/dist/tree/tree-view-model.js +13 -0
- package/dist/tree/tree-view-model.js.map +1 -1
- package/dist/vue/AdvancedEditor.js +6 -0
- package/dist/vue/AdvancedEditor.js.map +1 -1
- package/dist/vue/AdvancedEditor.vue.d.ts +9 -1
- package/dist/vue/compose.js +5 -1
- package/dist/vue/compose.js.map +1 -1
- package/package.json +21 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature.js","names":[],"sources":["../../../src/features/transfer/feature.ts"],"sourcesContent":["import { type AnyExtension, type Editor, Extension } from '@tiptap/core'\nimport { Fragment, type Node as PMNode, Slice } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { dropPoint } from '@tiptap/pm/transform'\nimport { BLOCK_MIME, type BlockTransfer, readBlockTransfer } from '../../core'\nimport type { EditorFeature, FeatureContext } from '../../core/feature'\nimport { findBlockById } from '../../core/schema'\nimport { createStore, type Store } from '../../core/store'\nimport { availableTransforms, type BlockTransform, DEFAULT_TRANSFORMS, runTransform, type TransferEnv } from './transforms'\n\n/** One drop of a block: the dragged block, where it lands (document position), whether the transform menu opens first and where it opens (viewport pixels). */\nexport interface TransferDrop {\n payload: BlockTransfer\n pos: number\n /** `true`: the menu opens at (`x`, `y`) and the user picks the transform; `false`: the default transform runs. */\n menu: boolean\n x: number\n y: number\n}\n\n/** A drop waiting for the user to pick a transform from the menu (`TransferDrop` with `menu` on). */\nexport type PendingDrop = TransferDrop\n\nexport interface BlockDropTargetStorage {\n /** The drop the transform menu is open for; `null` while no menu is open. */\n pending: Store<PendingDrop | null>\n /** The transforms the menu offers for `drop` (those whose `available` says yes). */\n available: (drop: PendingDrop) => BlockTransform[]\n /** Closes the menu and runs the transform `id` for `drop` (a refused insert shows its notice). */\n run: (id: string, drop: PendingDrop) => Promise<void>\n}\n\ndeclare module '@tiptap/core' {\n interface Storage {\n /** Absent in an editor without the transfer feature. */\n blockDropTarget?: BlockDropTargetStorage\n }\n interface Commands<ReturnType> {\n blockTransfer: {\n /**\n * Puts the block of `payload` into the document at `pos` (a position where a block may be inserted): with `menu`\n * the transform menu opens at (`x`, `y`) and the transform the user picks runs, else the default transform runs.\n * Refuses a drop of a block onto its own position in the same document (notice). Used by the document tree's drop executor.\n */\n transferBlock: (options: { payload: BlockTransfer, pos: number, menu: boolean, x?: number, y?: number }) => ReturnType\n /** Closes the transform menu without inserting anything. */\n cancelTransfer: () => ReturnType\n }\n }\n}\n\n/**\n * Whether dropping `payload` at `pos` of `doc` lands inside the very block it was dragged from: the payload names a\n * block of this document (same `documentId`, a block with that id exists) and `pos` is strictly inside it.\n */\nexport function isSelfDrop(doc: PMNode, documentId: string | null | undefined, payload: BlockTransfer, pos: number): boolean {\n if (!payload.blockId || (payload.documentId ?? null) !== (documentId ?? null)) return false\n const found = findBlockById(doc, payload.blockId)\n return !!found && pos > found.pos && pos < found.pos + found.node.nodeSize\n}\n\n/**\n * The shared tail of a drop (DOM drop and `transferBlock`): refuses a self-drop, else opens the menu (`menu`) or runs\n * the default transform.\n */\nfunction dropBlock(env: TransferEnv, documentId: string | null, defaultId: string, pending: Store<PendingDrop | null>, drop: TransferDrop): void {\n const { payload, pos } = drop\n pending.set(null)\n if (isSelfDrop(env.editor.state.doc, documentId, payload, pos)) {\n env.notify({ kind: 'warning', title: env.t('transfer.selfDrop') })\n return\n }\n if (drop.menu) pending.set(drop)\n // The transform dispatches its own transaction, which must not collide with the one a tiptap command still holds (the command's transaction is dispatched after it returns).\n else queueMicrotask(() => { void runTransform(env, defaultId, payload, pos) })\n}\n\nconst blockDropTargetKey = new PluginKey('blockDropTarget')\n\n/**\n * The slice dropping `payload` would insert, for `dropPoint`; `null` when this schema cannot hold the block. It is closed\n * (`openStart` and `openEnd` 0): an open slice would let `dropPoint` return a position inside a paragraph, where the\n * Baustein cannot be inserted.\n */\nfunction sliceOf(editor: Editor, payload: BlockTransfer): Slice | null {\n try {\n return new Slice(Fragment.from(editor.schema.nodeFromJSON(payload.json)), 0, 0)\n }\n catch {\n return null\n }\n}\n\n/**\n * Takes blocks dragged out of another editor surface or document tree (`BLOCK_MIME`): a plain drop runs the default\n * transform, Shift opens the transform menu at the drop point. A drag that started in this editor stays ProseMirror's\n * native move. Also the commands `transferBlock` and `cancelTransfer`.\n */\nfunction blockDropTarget(ctx: FeatureContext, transforms: readonly BlockTransform[], defaultId: string): AnyExtension {\n const envOf = (editor: Editor): TransferEnv => ({ editor, transforms, ai: ctx.backend.ai, app: ctx.app, notify: ctx.notify, t: ctx.t })\n // The storage is built before the editor exists (`addStorage` has no `this.editor`); `onBeforeCreate` hands it over.\n let created: Editor | undefined\n const editorOf = (): Editor => {\n if (!created) throw new Error('blockDropTarget: the editor is not created yet')\n return created\n }\n return Extension.create<unknown, BlockDropTargetStorage>({\n name: 'blockDropTarget',\n onBeforeCreate() {\n created = this.editor\n },\n addStorage() {\n const pending = createStore<PendingDrop | null>(null)\n return {\n pending,\n available: ({ payload, pos }) => availableTransforms(envOf(editorOf()), payload, pos),\n run: async (id, { payload, pos }) => {\n pending.set(null)\n await runTransform(envOf(editorOf()), id, payload, pos)\n },\n }\n },\n addCommands() {\n return {\n transferBlock: ({ payload, pos, menu, x = 0, y = 0 }) => ({ editor, dispatch }) => {\n if (!dispatch) return true\n dropBlock(envOf(editor), ctx.documentId ?? null, defaultId, this.storage.pending, { payload, pos: Math.min(Math.max(pos, 0), editor.state.doc.content.size), menu, x, y })\n return true\n },\n cancelTransfer: () => () => {\n this.storage.pending.set(null)\n return true\n },\n }\n },\n addProseMirrorPlugins() {\n const editor = this.editor\n return [new Plugin({\n key: blockDropTargetKey,\n props: {\n handleDOMEvents: {\n dragover: (view, event) => {\n if (view.dragging || !view.editable || !event.dataTransfer?.types.includes(BLOCK_MIME)) return false\n event.preventDefault()\n event.dataTransfer.dropEffect = 'copy'\n return false\n },\n },\n handleDrop: (view, event) => {\n if (view.dragging || !view.editable || !event.dataTransfer) return false\n const payload = readBlockTransfer(event.dataTransfer)\n if (!payload) return false\n event.preventDefault()\n const env = envOf(editor)\n const slice = sliceOf(editor, payload)\n if (!slice) {\n env.notify({ kind: 'warning', title: env.t('transfer.refused') })\n return true\n }\n const at = view.posAtCoords({ left: event.clientX, top: event.clientY })?.pos ?? view.state.doc.content.size\n const pos = dropPoint(view.state.doc, at, slice) ?? view.state.doc.content.size\n dropBlock(env, ctx.documentId ?? null, defaultId, this.storage.pending, { payload, pos, menu: event.shiftKey, x: event.clientX, y: event.clientY })\n return true\n },\n },\n })]\n },\n })\n}\n\n/** Options of `transferFeature`. */\nexport interface TransferFeatureOptions {\n /** The transforms the menu offers and a drop can run; default `[copyTransform]` (`composeEditor` adds the AI transforms of `@ecsplico/editor/integrations/composite-ai` when `ai` is on). A host list replaces the default (add built-ins explicitly). */\n transforms?: readonly BlockTransform[]\n /** Id of the transform a plain drop (no Shift) runs; default `copy`. */\n defaultTransform?: string\n}\n\n/** What a framework binding supplies to `transferFeatureCore`. */\nexport interface TransferUi<C> {\n /** The transform menu (receives `{ editor }`), mounted as an overlay. */\n menu: C\n}\n\n/**\n * Block transfer between editor surfaces and document trees (the framework-free part of `transferFeature`): a block\n * dragged out of another surface lands as a copy with fresh ids and a `meta.derivation` pointing at its source, or,\n * with Shift held at the drop, as the result of a transform picked from a menu (the copy, and the AI transforms a host or `composeEditor` adds).\n * Insert guards apply; the commands `transferBlock` and `cancelTransfer` serve the document tree's drops.\n */\nexport function transferFeatureCore<C>(ui: TransferUi<C>, options: TransferFeatureOptions = {}): EditorFeature<C> {\n const transforms = options.transforms ?? DEFAULT_TRANSFORMS\n const defaultId = options.defaultTransform ?? 'copy'\n return {\n id: 'transfer',\n dimension: 'interaction',\n requires: ['composites'],\n extensions: ctx => [blockDropTarget(ctx, transforms, defaultId)],\n overlays: [ui.menu],\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { BlockTransform, DEFAULT_TRANSFORMS, TransferEnv, TransformContext, availableTransforms, copyTransform, createsOf, runTransform, transferKindOf, transferSourceHash, transformContextOf, withFreshBlockIds } from "./transforms.js";
|
|
2
|
+
import { BlockDropTargetStorage, PendingDrop, TransferDrop, TransferFeatureOptions, TransferUi, isSelfDrop, transferFeatureCore } from "./feature.js";
|
|
3
|
+
export { type BlockDropTargetStorage, type BlockTransform, DEFAULT_TRANSFORMS, type PendingDrop, type TransferDrop, type TransferEnv, type TransferFeatureOptions, type TransferUi, type TransformContext, availableTransforms, copyTransform, createsOf, isSelfDrop, runTransform, transferFeatureCore, transferKindOf, transferSourceHash, transformContextOf, withFreshBlockIds };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { DEFAULT_TRANSFORMS, availableTransforms, copyTransform, createsOf, runTransform, transferKindOf, transferSourceHash, transformContextOf, withFreshBlockIds } from "./transforms.js";
|
|
2
|
+
import { isSelfDrop, transferFeatureCore } from "./feature.js";
|
|
3
|
+
export { DEFAULT_TRANSFORMS, availableTransforms, copyTransform, createsOf, isSelfDrop, runTransform, transferFeatureCore, transferKindOf, transferSourceHash, transformContextOf, withFreshBlockIds };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/core";
|
|
2
|
+
//#region src/features/transfer/react/TransferMenu.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* The transform menu of a Shift-drop (mounted by the transfer feature): opens at the drop point while a drop waits in
|
|
5
|
+
* `editor.storage.blockDropTarget.pending`, lists the transforms available for it and runs the one picked. Escape or a
|
|
6
|
+
* click elsewhere cancels the drop.
|
|
7
|
+
*/
|
|
8
|
+
export declare function TransferMenu({ editor }: {
|
|
9
|
+
editor: Editor;
|
|
10
|
+
}): import("react").JSX.Element | null;
|
|
11
|
+
//#endregion
|
|
12
|
+
//# sourceMappingURL=TransferMenu.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { useEditorI18n } from "../../../react/use-editor-i18n.js";
|
|
2
|
+
import { Icon } from "../../../react/Icon.js";
|
|
3
|
+
import { useStore } from "../../../react/use-store.js";
|
|
4
|
+
import { Button } from "../../../react/ui/button.js";
|
|
5
|
+
import { useEffect, useRef } from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/features/transfer/react/TransferMenu.tsx
|
|
8
|
+
const ITEM_HEIGHT = 32;
|
|
9
|
+
const MENU_WIDTH = 240;
|
|
10
|
+
const EDGE = 8;
|
|
11
|
+
/**
|
|
12
|
+
* The transform menu of a Shift-drop (mounted by the transfer feature): opens at the drop point while a drop waits in
|
|
13
|
+
* `editor.storage.blockDropTarget.pending`, lists the transforms available for it and runs the one picked. Escape or a
|
|
14
|
+
* click elsewhere cancels the drop.
|
|
15
|
+
*/
|
|
16
|
+
function TransferMenu({ editor }) {
|
|
17
|
+
const { t } = useEditorI18n();
|
|
18
|
+
const storage = editor.storage.blockDropTarget;
|
|
19
|
+
const pending = useStore(storage.pending);
|
|
20
|
+
const root = useRef(null);
|
|
21
|
+
const open = pending !== null;
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!open) return;
|
|
24
|
+
const cancel = () => editor.commands.cancelTransfer();
|
|
25
|
+
const onKey = (event) => {
|
|
26
|
+
if (event.key !== "Escape") return;
|
|
27
|
+
event.preventDefault();
|
|
28
|
+
cancel();
|
|
29
|
+
};
|
|
30
|
+
const onPointerDown = (event) => {
|
|
31
|
+
if (!root.current?.contains(event.target)) cancel();
|
|
32
|
+
};
|
|
33
|
+
document.addEventListener("keydown", onKey, true);
|
|
34
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
35
|
+
return () => {
|
|
36
|
+
document.removeEventListener("keydown", onKey, true);
|
|
37
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
38
|
+
};
|
|
39
|
+
}, [open, editor]);
|
|
40
|
+
if (!pending) return null;
|
|
41
|
+
const transforms = storage.available(pending);
|
|
42
|
+
const height = transforms.length * ITEM_HEIGHT + ITEM_HEIGHT + 16;
|
|
43
|
+
const left = Math.max(EDGE, Math.min(pending.x, window.innerWidth - MENU_WIDTH - EDGE));
|
|
44
|
+
const top = Math.max(EDGE, Math.min(pending.y, window.innerHeight - height - EDGE));
|
|
45
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
46
|
+
ref: root,
|
|
47
|
+
className: "fixed z-50 rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-lg",
|
|
48
|
+
style: {
|
|
49
|
+
left,
|
|
50
|
+
top,
|
|
51
|
+
width: MENU_WIDTH
|
|
52
|
+
},
|
|
53
|
+
role: "menu",
|
|
54
|
+
"aria-label": t("transfer.menu.title"),
|
|
55
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
56
|
+
className: "px-2 py-1 text-xs text-muted-foreground",
|
|
57
|
+
children: t("transfer.menu.title")
|
|
58
|
+
}), transforms.map((transform) => /* @__PURE__ */ jsxs(Button, {
|
|
59
|
+
variant: "ghost",
|
|
60
|
+
size: "sm",
|
|
61
|
+
className: "w-full justify-start",
|
|
62
|
+
role: "menuitem",
|
|
63
|
+
onClick: () => void storage.run(transform.id, pending),
|
|
64
|
+
children: [/* @__PURE__ */ jsx(Icon, { name: transform.icon }), transform.labelKey ? t(transform.labelKey) : transform.label]
|
|
65
|
+
}, transform.id))]
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
export { TransferMenu };
|
|
70
|
+
|
|
71
|
+
//# sourceMappingURL=TransferMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TransferMenu.js","names":[],"sources":["../../../../src/features/transfer/react/TransferMenu.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { useEffect, useRef } from 'react'\nimport { Icon } from '../../../react/Icon'\nimport { Button } from '../../../react/ui/button'\nimport { useStore } from '../../../react/use-store'\nimport { useEditorI18n } from '../../../react/use-editor-i18n'\nimport type { BlockTransform } from '../transforms'\n\nconst ITEM_HEIGHT = 32\nconst MENU_WIDTH = 240\nconst EDGE = 8\n\n/**\n * The transform menu of a Shift-drop (mounted by the transfer feature): opens at the drop point while a drop waits in\n * `editor.storage.blockDropTarget.pending`, lists the transforms available for it and runs the one picked. Escape or a\n * click elsewhere cancels the drop.\n */\nexport function TransferMenu({ editor }: { editor: Editor }) {\n const { t } = useEditorI18n()\n const storage = editor.storage.blockDropTarget!\n const pending = useStore(storage.pending)\n const root = useRef<HTMLDivElement>(null)\n const open = pending !== null\n\n useEffect(() => {\n if (!open) return\n const cancel = () => editor.commands.cancelTransfer()\n const onKey = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return\n event.preventDefault()\n cancel()\n }\n const onPointerDown = (event: PointerEvent) => {\n if (!root.current?.contains(event.target as Node)) cancel()\n }\n document.addEventListener('keydown', onKey, true)\n document.addEventListener('pointerdown', onPointerDown, true)\n return () => {\n document.removeEventListener('keydown', onKey, true)\n document.removeEventListener('pointerdown', onPointerDown, true)\n }\n }, [open, editor])\n\n if (!pending) return null\n const transforms: BlockTransform[] = storage.available(pending)\n const height = transforms.length * ITEM_HEIGHT + ITEM_HEIGHT + 2 * EDGE\n const left = Math.max(EDGE, Math.min(pending.x, window.innerWidth - MENU_WIDTH - EDGE))\n const top = Math.max(EDGE, Math.min(pending.y, window.innerHeight - height - EDGE))\n return (\n <div\n ref={root}\n className=\"fixed z-50 rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-lg\"\n style={{ left, top, width: MENU_WIDTH }}\n role=\"menu\"\n aria-label={t('transfer.menu.title')}\n >\n <p className=\"px-2 py-1 text-xs text-muted-foreground\">{t('transfer.menu.title')}</p>\n {transforms.map(transform => (\n <Button key={transform.id} variant=\"ghost\" size=\"sm\" className=\"w-full justify-start\" role=\"menuitem\" onClick={() => void storage.run(transform.id, pending)}>\n <Icon name={transform.icon} />\n {transform.labelKey ? t(transform.labelKey) : transform.label}\n </Button>\n ))}\n </div>\n )\n}\n"],"mappings":";;;;;;;AAQA,MAAM,cAAc;AACpB,MAAM,aAAa;AACnB,MAAM,OAAO;;;;;;AAOb,SAAgB,aAAa,EAAE,UAA8B;CAC3D,MAAM,EAAE,MAAM,cAAc;CAC5B,MAAM,UAAU,OAAO,QAAQ;CAC/B,MAAM,UAAU,SAAS,QAAQ,OAAO;CACxC,MAAM,OAAO,OAAuB,IAAI;CACxC,MAAM,OAAO,YAAY;CAEzB,gBAAgB;EACd,IAAI,CAAC,MAAM;EACX,MAAM,eAAe,OAAO,SAAS,eAAe;EACpD,MAAM,SAAS,UAAyB;GACtC,IAAI,MAAM,QAAQ,UAAU;GAC5B,MAAM,eAAe;GACrB,OAAO;EACT;EACA,MAAM,iBAAiB,UAAwB;GAC7C,IAAI,CAAC,KAAK,SAAS,SAAS,MAAM,MAAc,GAAG,OAAO;EAC5D;EACA,SAAS,iBAAiB,WAAW,OAAO,IAAI;EAChD,SAAS,iBAAiB,eAAe,eAAe,IAAI;EAC5D,aAAa;GACX,SAAS,oBAAoB,WAAW,OAAO,IAAI;GACnD,SAAS,oBAAoB,eAAe,eAAe,IAAI;EACjE;CACF,GAAG,CAAC,MAAM,MAAM,CAAC;CAEjB,IAAI,CAAC,SAAS,OAAO;CACrB,MAAM,aAA+B,QAAQ,UAAU,OAAO;CAC9D,MAAM,SAAS,WAAW,SAAS,cAAc,cAAc;CAC/D,MAAM,OAAO,KAAK,IAAI,MAAM,KAAK,IAAI,QAAQ,GAAG,OAAO,aAAa,aAAa,IAAI,CAAC;CACtF,MAAM,MAAM,KAAK,IAAI,MAAM,KAAK,IAAI,QAAQ,GAAG,OAAO,cAAc,SAAS,IAAI,CAAC;CAClF,OACE,qBAAC,OAAD;EACE,KAAK;EACL,WAAU;EACV,OAAO;GAAE;GAAM;GAAK,OAAO;EAAW;EACtC,MAAK;EACL,cAAY,EAAE,qBAAqB;EALrC,UAAA,CAOE,oBAAC,KAAD;GAAG,WAAU;GAA2C,UAAA,EAAE,qBAAqB;EAAK,CAAA,GACnF,WAAW,KAAI,cACd,qBAAC,QAAD;GAA2B,SAAQ;GAAQ,MAAK;GAAK,WAAU;GAAuB,MAAK;GAAW,eAAe,KAAK,QAAQ,IAAI,UAAU,IAAI,OAAO;GAA3J,UAAA,CACE,oBAAC,MAAD,EAAM,MAAM,UAAU,KAAO,CAAA,GAC5B,UAAU,WAAW,EAAE,UAAU,QAAQ,IAAI,UAAU,KAClD;EAHK,GAAA,UAAU,EAGf,CACT,CACE;;AAET"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ReactFeature } from "../../react/EditorSurface.js";
|
|
2
|
+
import "../../react/index.js";
|
|
3
|
+
import { TransferFeatureOptions } from "./feature.js";
|
|
4
|
+
import { TransferMenu } from "./react/TransferMenu.js";
|
|
5
|
+
//#region src/features/transfer/react.d.ts
|
|
6
|
+
/** The React transfer feature (shadcn): see `transferFeatureCore`. */
|
|
7
|
+
export declare function transferFeature(options?: TransferFeatureOptions): ReactFeature;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { TransferMenu };
|
|
10
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { transferFeatureCore } from "./feature.js";
|
|
2
|
+
import { TransferMenu } from "./react/TransferMenu.js";
|
|
3
|
+
//#region src/features/transfer/react.ts
|
|
4
|
+
/** The React transfer feature (shadcn): see `transferFeatureCore`. */
|
|
5
|
+
function transferFeature(options = {}) {
|
|
6
|
+
return transferFeatureCore({ menu: TransferMenu }, options);
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { TransferMenu, transferFeature };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","names":[],"sources":["../../../src/features/transfer/react.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { ComponentType } from 'react'\nimport type { ReactFeature } from '../../react'\nimport { type TransferFeatureOptions, transferFeatureCore } from './feature'\nimport { TransferMenu } from './react/TransferMenu'\n\nexport { TransferMenu } from './react/TransferMenu'\n\n/** The React transfer feature (shadcn): see `transferFeatureCore`. */\nexport function transferFeature(options: TransferFeatureOptions = {}): ReactFeature {\n return transferFeatureCore<ComponentType<{ editor: Editor }>>({ menu: TransferMenu }, options)\n}\n"],"mappings":";;;;AASA,SAAgB,gBAAgB,UAAkC,CAAC,GAAiB;CAClF,OAAO,oBAAuD,EAAE,MAAM,aAAa,GAAG,OAAO;AAC/F"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { MessageKey, Translate } from "../../i18n/index.js";
|
|
2
|
+
import { EditorBackend } from "../../core/backend.js";
|
|
3
|
+
import { Notifier } from "../../core/notify.js";
|
|
4
|
+
import { EditorContext } from "../../core/context.js";
|
|
5
|
+
import { Creates } from "../../core/command-types.js";
|
|
6
|
+
import { BlockTransfer } from "../../core/block-transfer.js";
|
|
7
|
+
import "../../core/index.js";
|
|
8
|
+
import { Editor, JSONContent } from "@tiptap/core";
|
|
9
|
+
//#region src/features/transfer/transforms.d.ts
|
|
10
|
+
/** What a transform works with: the target editor, the dragged block, where it lands and the app services. */
|
|
11
|
+
export interface TransformContext {
|
|
12
|
+
editor: Editor;
|
|
13
|
+
payload: BlockTransfer;
|
|
14
|
+
/** Document position the result is inserted at (a valid drop point of `editor.state.doc`). */
|
|
15
|
+
pos: number;
|
|
16
|
+
/** The app's AI backend; absent when the app has none. */
|
|
17
|
+
ai: EditorBackend['ai'] | undefined;
|
|
18
|
+
/** The app context the editor belongs to; transforms that need app services (the AI model profiles) read them from it. */
|
|
19
|
+
app: EditorContext;
|
|
20
|
+
notify: Notifier;
|
|
21
|
+
t: Translate;
|
|
22
|
+
}
|
|
23
|
+
/** One way to put a dragged block into a surface: offered by the transform menu and run by a plain drop (the default transform). */
|
|
24
|
+
export interface BlockTransform {
|
|
25
|
+
id: string;
|
|
26
|
+
/** Menu text; shown as is unless `labelKey` is set. */
|
|
27
|
+
label: string;
|
|
28
|
+
/** Message key of the label: the menu renders it in the editor's language instead of `label`. */
|
|
29
|
+
labelKey?: MessageKey;
|
|
30
|
+
/** Iconify name (`i-lucide-…`). */
|
|
31
|
+
icon: string;
|
|
32
|
+
/** Absent = always available. */
|
|
33
|
+
available?: (ctx: TransformContext) => boolean;
|
|
34
|
+
/**
|
|
35
|
+
* What `run` inserts at `ctx.pos`, so the insert guards and the target's content rules are checked before `run`; a
|
|
36
|
+
* refused insert shows the warning „lässt sich nicht einfügen“ and runs nothing. Absent: the transform `copy` is
|
|
37
|
+
* checked as inserting the dragged block itself, every other transform checks itself.
|
|
38
|
+
*/
|
|
39
|
+
creates?: (ctx: TransformContext) => Creates | null;
|
|
40
|
+
run: (ctx: TransformContext) => Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
/** `json` with a fresh block id on every block that carries one (recursively); other nodes and attributes stay. */
|
|
43
|
+
export declare function withFreshBlockIds(editor: Editor, json: JSONContent): JSONContent;
|
|
44
|
+
/** The `Creates` a node of `json` stands for in the insert guards. */
|
|
45
|
+
export declare const createsOf: (json: JSONContent) => Creates;
|
|
46
|
+
/**
|
|
47
|
+
* The hash a derivation of the dragged block records as `inputHash`: the Markdown of a Baustein's body (the same text
|
|
48
|
+
* `derivationState` hashes for a source in the open document), else of the whole block. Without a Markdown serializer the
|
|
49
|
+
* hash of the payload's Markdown.
|
|
50
|
+
*/
|
|
51
|
+
export declare function transferSourceHash(editor: Editor, payload: BlockTransfer): string;
|
|
52
|
+
/** The kind of Baustein the AI transforms insert: the setting `blocks.defaultKind` when the editor offers it, else its first kind. */
|
|
53
|
+
export declare function transferKindOf(editor: Editor): string;
|
|
54
|
+
/**
|
|
55
|
+
* „Kopie einfügen“: inserts the dragged block with fresh block ids (the block and every block inside it). A Baustein
|
|
56
|
+
* that has a block id records its source in `meta.derivation` (`from: { block, document }`, method `copy`, the source
|
|
57
|
+
* Markdown as `inputHash`, the hash of the copy's body as `outputHash`, so the badge shows „bearbeitet“ once the copy is edited).
|
|
58
|
+
*/
|
|
59
|
+
export declare const copyTransform: BlockTransform;
|
|
60
|
+
/** The transforms `transferFeature` offers unless the host passes its own list: the copy. The AI transforms (`summaryTransform`, `bulletsTransform`) live in `@ecsplico/editor/integrations/composite-ai`; `composeEditor` adds them when `ai` is on. */
|
|
61
|
+
export declare const DEFAULT_TRANSFORMS: readonly BlockTransform[];
|
|
62
|
+
/** What `runTransform` needs: the editor, the transform list and the app services. */
|
|
63
|
+
export interface TransferEnv {
|
|
64
|
+
editor: Editor;
|
|
65
|
+
transforms: readonly BlockTransform[];
|
|
66
|
+
ai: EditorBackend['ai'] | undefined;
|
|
67
|
+
app: EditorContext;
|
|
68
|
+
notify: Notifier;
|
|
69
|
+
t: Translate;
|
|
70
|
+
}
|
|
71
|
+
/** The context a transform of `env` gets for dropping `payload` at `pos` (clamped into the document). */
|
|
72
|
+
export declare function transformContextOf(env: TransferEnv, payload: BlockTransfer, pos: number): TransformContext;
|
|
73
|
+
/** The transforms of `env` available for dropping `payload` at `pos`, in list order. */
|
|
74
|
+
export declare function availableTransforms(env: TransferEnv, payload: BlockTransfer, pos: number): BlockTransform[];
|
|
75
|
+
/**
|
|
76
|
+
* Runs the transform `id` of `env` for dropping `payload` at `pos`. Nothing runs for an unknown or unavailable
|
|
77
|
+
* transform. What the transform inserts (`BlockTransform.creates`) must pass the insert guards below `pos`'s parent and
|
|
78
|
+
* the parent's content rules, else the warning „Hier lässt sich der Baustein nicht einfügen“ is shown and the document stays
|
|
79
|
+
* unchanged. The transform's own failure is its own to report; this never throws for a refusal.
|
|
80
|
+
*/
|
|
81
|
+
export declare function runTransform(env: TransferEnv, id: string, payload: BlockTransfer, pos: number): Promise<void>;
|
|
82
|
+
//#endregion
|
|
83
|
+
//# sourceMappingURL=transforms.d.ts.map
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { de } from "../../i18n/de.js";
|
|
2
|
+
import { editorEntryOf } from "../../core/editor-ui.js";
|
|
3
|
+
import { guardsAccept } from "../../core/commands.js";
|
|
4
|
+
import { newBlockId } from "../../core/schema/block-ids.js";
|
|
5
|
+
import { sha256Hex } from "../../core/hash.js";
|
|
6
|
+
import { DERIVATION_KEY } from "../composites/meta-keys.js";
|
|
7
|
+
import { bodyMarkdown } from "../composites/derivation.js";
|
|
8
|
+
import { compositeKindsOf } from "../composites/nodes.js";
|
|
9
|
+
//#region src/features/transfer/transforms.ts
|
|
10
|
+
/** `json` with a fresh block id on every block that carries one (recursively); other nodes and attributes stay. */
|
|
11
|
+
function withFreshBlockIds(editor, json) {
|
|
12
|
+
const visit = (node) => {
|
|
13
|
+
const next = { ...node };
|
|
14
|
+
if (node.type && editor.schema.nodes[node.type]?.spec.editorBlock === true) next.attrs = {
|
|
15
|
+
...node.attrs,
|
|
16
|
+
id: newBlockId()
|
|
17
|
+
};
|
|
18
|
+
if (node.content) next.content = node.content.map(visit);
|
|
19
|
+
return next;
|
|
20
|
+
};
|
|
21
|
+
return visit(json);
|
|
22
|
+
}
|
|
23
|
+
/** The `Creates` a node of `json` stands for in the insert guards. */
|
|
24
|
+
const createsOf = (json) => ({
|
|
25
|
+
type: json.type ?? "",
|
|
26
|
+
...json.attrs && { attrs: json.attrs }
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* The hash a derivation of the dragged block records as `inputHash`: the Markdown of a Baustein's body (the same text
|
|
30
|
+
* `derivationState` hashes for a source in the open document), else of the whole block. Without a Markdown serializer the
|
|
31
|
+
* hash of the payload's Markdown.
|
|
32
|
+
*/
|
|
33
|
+
function transferSourceHash(editor, payload) {
|
|
34
|
+
const { json } = payload;
|
|
35
|
+
if (!editor.markdown || json.type !== "composite") return sha256Hex(payload.markdown);
|
|
36
|
+
return sha256Hex(editor.markdown.serialize({
|
|
37
|
+
type: "doc",
|
|
38
|
+
content: (json.content ?? []).slice(3)
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
/** The kind of Baustein the AI transforms insert: the setting `blocks.defaultKind` when the editor offers it, else its first kind. */
|
|
42
|
+
function transferKindOf(editor) {
|
|
43
|
+
const kinds = compositeKindsOf(editor);
|
|
44
|
+
const wanted = editorEntryOf(editor)?.ctx.settings.get().blocks.defaultKind;
|
|
45
|
+
return kinds.find((kind) => kind.id === wanted)?.id ?? kinds[0]?.id ?? "section";
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* „Kopie einfügen“: inserts the dragged block with fresh block ids (the block and every block inside it). A Baustein
|
|
49
|
+
* that has a block id records its source in `meta.derivation` (`from: { block, document }`, method `copy`, the source
|
|
50
|
+
* Markdown as `inputHash`, the hash of the copy's body as `outputHash`, so the badge shows „bearbeitet“ once the copy is edited).
|
|
51
|
+
*/
|
|
52
|
+
const copyTransform = {
|
|
53
|
+
id: "copy",
|
|
54
|
+
label: de["transfer.copy"],
|
|
55
|
+
labelKey: "transfer.copy",
|
|
56
|
+
icon: "i-lucide-copy",
|
|
57
|
+
creates: (ctx) => createsOf(ctx.payload.json),
|
|
58
|
+
run: async ({ editor, payload, pos }) => {
|
|
59
|
+
const json = withFreshBlockIds(editor, payload.json);
|
|
60
|
+
let node = editor.schema.nodeFromJSON(json);
|
|
61
|
+
if (json.type === "composite" && payload.blockId) {
|
|
62
|
+
const derivation = {
|
|
63
|
+
from: {
|
|
64
|
+
block: payload.blockId,
|
|
65
|
+
...payload.documentId && { document: payload.documentId }
|
|
66
|
+
},
|
|
67
|
+
method: "copy",
|
|
68
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
69
|
+
inputHash: transferSourceHash(editor, payload),
|
|
70
|
+
outputHash: editor.markdown ? sha256Hex(bodyMarkdown(editor, node)) : transferSourceHash(editor, payload)
|
|
71
|
+
};
|
|
72
|
+
node = editor.schema.nodeFromJSON({
|
|
73
|
+
...json,
|
|
74
|
+
attrs: {
|
|
75
|
+
...json.attrs,
|
|
76
|
+
meta: {
|
|
77
|
+
...json.attrs?.meta,
|
|
78
|
+
[DERIVATION_KEY]: derivation
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
editor.view.dispatch(editor.state.tr.insert(pos, node).scrollIntoView());
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
/** The transforms `transferFeature` offers unless the host passes its own list: the copy. The AI transforms (`summaryTransform`, `bulletsTransform`) live in `@ecsplico/editor/integrations/composite-ai`; `composeEditor` adds them when `ai` is on. */
|
|
87
|
+
const DEFAULT_TRANSFORMS = [copyTransform];
|
|
88
|
+
/** The context a transform of `env` gets for dropping `payload` at `pos` (clamped into the document). */
|
|
89
|
+
function transformContextOf(env, payload, pos) {
|
|
90
|
+
const { editor, ai, app, notify, t } = env;
|
|
91
|
+
return {
|
|
92
|
+
editor,
|
|
93
|
+
payload,
|
|
94
|
+
pos: Math.min(Math.max(pos, 0), editor.state.doc.content.size),
|
|
95
|
+
ai,
|
|
96
|
+
app,
|
|
97
|
+
notify,
|
|
98
|
+
t
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/** The transforms of `env` available for dropping `payload` at `pos`, in list order. */
|
|
102
|
+
function availableTransforms(env, payload, pos) {
|
|
103
|
+
const ctx = transformContextOf(env, payload, pos);
|
|
104
|
+
return env.transforms.filter((transform) => transform.available?.(ctx) ?? true);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Runs the transform `id` of `env` for dropping `payload` at `pos`. Nothing runs for an unknown or unavailable
|
|
108
|
+
* transform. What the transform inserts (`BlockTransform.creates`) must pass the insert guards below `pos`'s parent and
|
|
109
|
+
* the parent's content rules, else the warning „Hier lässt sich der Baustein nicht einfügen“ is shown and the document stays
|
|
110
|
+
* unchanged. The transform's own failure is its own to report; this never throws for a refusal.
|
|
111
|
+
*/
|
|
112
|
+
async function runTransform(env, id, payload, pos) {
|
|
113
|
+
const transform = env.transforms.find((candidate) => candidate.id === id);
|
|
114
|
+
if (!transform) return;
|
|
115
|
+
const ctx = transformContextOf(env, payload, pos);
|
|
116
|
+
if (transform.available && !transform.available(ctx)) return;
|
|
117
|
+
const creates = transform.creates?.(ctx) ?? (transform.id === "copy" ? createsOf(payload.json) : null);
|
|
118
|
+
if (creates && !canInsertAt(env.editor, ctx.pos, creates)) {
|
|
119
|
+
env.notify({
|
|
120
|
+
kind: "warning",
|
|
121
|
+
title: env.t("transfer.refused")
|
|
122
|
+
});
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
await transform.run(ctx);
|
|
126
|
+
}
|
|
127
|
+
/** Whether a node like `creates` fits the content rules below `pos`'s parent and passes every insert guard there. */
|
|
128
|
+
function canInsertAt(editor, pos, creates) {
|
|
129
|
+
const type = editor.schema.nodes[creates.type];
|
|
130
|
+
const $pos = editor.state.doc.resolve(pos);
|
|
131
|
+
if (!type || !$pos.parent.canReplaceWith($pos.index(), $pos.index(), type)) return false;
|
|
132
|
+
return guardsAccept(editor, $pos, creates);
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
export { DEFAULT_TRANSFORMS, availableTransforms, copyTransform, createsOf, runTransform, transferKindOf, transferSourceHash, transformContextOf, withFreshBlockIds };
|
|
136
|
+
|
|
137
|
+
//# sourceMappingURL=transforms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transforms.js","names":[],"sources":["../../../src/features/transfer/transforms.ts"],"sourcesContent":["// Types only: brings in the `editor.markdown` augmentation of `@tiptap/markdown` for contexts that do not otherwise load it.\nimport type {} from '@tiptap/markdown'\nimport type { Editor, JSONContent } from '@tiptap/core'\nimport type { EditorBackend } from '../../core/backend'\nimport { type BlockTransfer, editorEntryOf, guardsAccept, sha256Hex } from '../../core'\nimport type { Creates } from '../../core/command-types'\nimport type { EditorContext } from '../../core/context'\nimport type { Notifier } from '../../core/notify'\nimport { newBlockId } from '../../core/schema'\nimport { de } from '../../i18n/de'\nimport type { MessageKey, Translate } from '../../i18n'\nimport { bodyMarkdown, COMPOSITE_CHROME_COUNT, compositeKindsOf, DERIVATION_KEY, type Derivation } from '../composites/schema'\n\n/** What a transform works with: the target editor, the dragged block, where it lands and the app services. */\nexport interface TransformContext {\n editor: Editor\n payload: BlockTransfer\n /** Document position the result is inserted at (a valid drop point of `editor.state.doc`). */\n pos: number\n /** The app's AI backend; absent when the app has none. */\n ai: EditorBackend['ai'] | undefined\n /** The app context the editor belongs to; transforms that need app services (the AI model profiles) read them from it. */\n app: EditorContext\n notify: Notifier\n t: Translate\n}\n\n/** One way to put a dragged block into a surface: offered by the transform menu and run by a plain drop (the default transform). */\nexport interface BlockTransform {\n id: string\n /** Menu text; shown as is unless `labelKey` is set. */\n label: string\n /** Message key of the label: the menu renders it in the editor's language instead of `label`. */\n labelKey?: MessageKey\n /** Iconify name (`i-lucide-…`). */\n icon: string\n /** Absent = always available. */\n available?: (ctx: TransformContext) => boolean\n /**\n * What `run` inserts at `ctx.pos`, so the insert guards and the target's content rules are checked before `run`; a\n * refused insert shows the warning „lässt sich nicht einfügen“ and runs nothing. Absent: the transform `copy` is\n * checked as inserting the dragged block itself, every other transform checks itself.\n */\n creates?: (ctx: TransformContext) => Creates | null\n run: (ctx: TransformContext) => Promise<void>\n}\n\n/** `json` with a fresh block id on every block that carries one (recursively); other nodes and attributes stay. */\nexport function withFreshBlockIds(editor: Editor, json: JSONContent): JSONContent {\n const visit = (node: JSONContent): JSONContent => {\n const next: JSONContent = { ...node }\n if (node.type && editor.schema.nodes[node.type]?.spec.editorBlock === true) next.attrs = { ...node.attrs, id: newBlockId() }\n if (node.content) next.content = node.content.map(visit)\n return next\n }\n return visit(json)\n}\n\n/** The `Creates` a node of `json` stands for in the insert guards. */\nexport const createsOf = (json: JSONContent): Creates => ({ type: json.type ?? '', ...(json.attrs && { attrs: json.attrs }) })\n\n/**\n * The hash a derivation of the dragged block records as `inputHash`: the Markdown of a Baustein's body (the same text\n * `derivationState` hashes for a source in the open document), else of the whole block. Without a Markdown serializer the\n * hash of the payload's Markdown.\n */\nexport function transferSourceHash(editor: Editor, payload: BlockTransfer): string {\n const { json } = payload\n if (!editor.markdown || json.type !== 'composite') return sha256Hex(payload.markdown)\n return sha256Hex(editor.markdown.serialize({ type: 'doc', content: (json.content ?? []).slice(COMPOSITE_CHROME_COUNT) }))\n}\n\n/** The kind of Baustein the AI transforms insert: the setting `blocks.defaultKind` when the editor offers it, else its first kind. */\nexport function transferKindOf(editor: Editor): string {\n const kinds = compositeKindsOf(editor)\n const wanted = editorEntryOf(editor)?.ctx.settings.get().blocks.defaultKind\n return kinds.find(kind => kind.id === wanted)?.id ?? kinds[0]?.id ?? 'section'\n}\n\n/**\n * „Kopie einfügen“: inserts the dragged block with fresh block ids (the block and every block inside it). A Baustein\n * that has a block id records its source in `meta.derivation` (`from: { block, document }`, method `copy`, the source\n * Markdown as `inputHash`, the hash of the copy's body as `outputHash`, so the badge shows „bearbeitet“ once the copy is edited).\n */\nexport const copyTransform: BlockTransform = {\n id: 'copy',\n label: de['transfer.copy'],\n labelKey: 'transfer.copy',\n icon: 'i-lucide-copy',\n creates: ctx => createsOf(ctx.payload.json),\n run: async ({ editor, payload, pos }) => {\n const json = withFreshBlockIds(editor, payload.json)\n let node = editor.schema.nodeFromJSON(json)\n if (json.type === 'composite' && payload.blockId) {\n const derivation: Derivation = {\n from: { block: payload.blockId, ...(payload.documentId && { document: payload.documentId }) },\n method: 'copy',\n createdAt: new Date().toISOString(),\n inputHash: transferSourceHash(editor, payload),\n outputHash: editor.markdown ? sha256Hex(bodyMarkdown(editor, node)) : transferSourceHash(editor, payload),\n }\n node = editor.schema.nodeFromJSON({ ...json, attrs: { ...json.attrs, meta: { ...json.attrs?.meta, [DERIVATION_KEY]: derivation } } })\n }\n editor.view.dispatch(editor.state.tr.insert(pos, node).scrollIntoView())\n },\n}\n\n/** The transforms `transferFeature` offers unless the host passes its own list: the copy. The AI transforms (`summaryTransform`, `bulletsTransform`) live in `@ecsplico/editor/integrations/composite-ai`; `composeEditor` adds them when `ai` is on. */\nexport const DEFAULT_TRANSFORMS: readonly BlockTransform[] = [copyTransform]\n\n/** What `runTransform` needs: the editor, the transform list and the app services. */\nexport interface TransferEnv {\n editor: Editor\n transforms: readonly BlockTransform[]\n ai: EditorBackend['ai'] | undefined\n app: EditorContext\n notify: Notifier\n t: Translate\n}\n\n/** The context a transform of `env` gets for dropping `payload` at `pos` (clamped into the document). */\nexport function transformContextOf(env: TransferEnv, payload: BlockTransfer, pos: number): TransformContext {\n const { editor, ai, app, notify, t } = env\n return { editor, payload, pos: Math.min(Math.max(pos, 0), editor.state.doc.content.size), ai, app, notify, t }\n}\n\n/** The transforms of `env` available for dropping `payload` at `pos`, in list order. */\nexport function availableTransforms(env: TransferEnv, payload: BlockTransfer, pos: number): BlockTransform[] {\n const ctx = transformContextOf(env, payload, pos)\n return env.transforms.filter(transform => transform.available?.(ctx) ?? true)\n}\n\n/**\n * Runs the transform `id` of `env` for dropping `payload` at `pos`. Nothing runs for an unknown or unavailable\n * transform. What the transform inserts (`BlockTransform.creates`) must pass the insert guards below `pos`'s parent and\n * the parent's content rules, else the warning „Hier lässt sich der Baustein nicht einfügen“ is shown and the document stays\n * unchanged. The transform's own failure is its own to report; this never throws for a refusal.\n */\nexport async function runTransform(env: TransferEnv, id: string, payload: BlockTransfer, pos: number): Promise<void> {\n const transform = env.transforms.find(candidate => candidate.id === id)\n if (!transform) return\n const ctx = transformContextOf(env, payload, pos)\n if (transform.available && !transform.available(ctx)) return\n const creates = transform.creates?.(ctx) ?? (transform.id === 'copy' ? createsOf(payload.json) : null)\n if (creates && !canInsertAt(env.editor, ctx.pos, creates)) {\n env.notify({ kind: 'warning', title: env.t('transfer.refused') })\n return\n }\n await transform.run(ctx)\n}\n\n/** Whether a node like `creates` fits the content rules below `pos`'s parent and passes every insert guard there. */\nfunction canInsertAt(editor: Editor, pos: number, creates: Creates): boolean {\n const type = editor.schema.nodes[creates.type]\n const $pos = editor.state.doc.resolve(pos)\n if (!type || !$pos.parent.canReplaceWith($pos.index(), $pos.index(), type)) return false\n return guardsAccept(editor, $pos, creates)\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { VueFeature } from "../../vue/index.js";
|
|
2
|
+
import { TransferFeatureOptions } from "./feature.js";
|
|
3
|
+
import _default from "./components/TransferMenu.vue.js";
|
|
4
|
+
//#region src/features/transfer/vue.d.ts
|
|
5
|
+
/** The Vue transfer feature (Nuxt UI): see `transferFeatureCore`. */
|
|
6
|
+
export declare function transferFeature(options?: TransferFeatureOptions): VueFeature;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { _default as TransferMenu };
|
|
9
|
+
//# sourceMappingURL=vue.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { transferFeatureCore } from "./feature.js";
|
|
2
|
+
import _sfc_main from "./components/TransferMenu.js";
|
|
3
|
+
//#region src/features/transfer/vue.ts
|
|
4
|
+
/** The Vue transfer feature (Nuxt UI): see `transferFeatureCore`. */
|
|
5
|
+
function transferFeature(options = {}) {
|
|
6
|
+
return transferFeatureCore({ menu: _sfc_main }, options);
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { _sfc_main as TransferMenu, transferFeature };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vue.js","names":["TransferMenu"],"sources":["../../../src/features/transfer/vue.ts"],"sourcesContent":["import type { Component } from 'vue'\nimport type { VueFeature } from '../../vue'\nimport TransferMenu from './components/TransferMenu.vue'\nimport { type TransferFeatureOptions, transferFeatureCore } from './feature'\n\nexport { default as TransferMenu } from './components/TransferMenu.vue'\n\n/** The Vue transfer feature (Nuxt UI): see `transferFeatureCore`. */\nexport function transferFeature(options: TransferFeatureOptions = {}): VueFeature {\n return transferFeatureCore<Component>({ menu: TransferMenu }, options)\n}\n"],"mappings":";;;;AAQA,SAAgB,gBAAgB,UAAkC,CAAC,GAAe;CAChF,OAAO,oBAA+B,EAAE,MAAMA,UAAa,GAAG,OAAO;AACvE"}
|
package/dist/i18n/de/ai.js
CHANGED
|
@@ -19,6 +19,10 @@ const de = {
|
|
|
19
19
|
"ai.task.continue.label": "Weiterschreiben",
|
|
20
20
|
"ai.task.fillBlock.label": "Baustein füllen",
|
|
21
21
|
"ai.task.fillBlock.promptLabel": "Hinweis (optional)",
|
|
22
|
+
"ai.task.splitBlock.label": "Baustein gliedern",
|
|
23
|
+
"ai.task.outlineSanitize.label": "Gliederung bereinigen",
|
|
24
|
+
"ai.task.transferSummary.label": "Zusammenfassung (Übertragen)",
|
|
25
|
+
"ai.task.transferBullets.label": "Stichpunkte (Übertragen)",
|
|
22
26
|
"ai.slot.complete.label": "Vorschläge beim Tippen",
|
|
23
27
|
"ai.slot.complete.description": "Schnelles Modell; muss Assistant-Prefill unterstützen.",
|
|
24
28
|
"ai.slot.rewrite.label": "Text im Block",
|
package/dist/i18n/de/ai.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.js","names":[],"sources":["../../../src/i18n/de/ai.ts"],"sourcesContent":["export const de = {\n // Tasks (menus, sidebar chips, prompt hints, result headings)\n 'ai.task.reformulate.label': 'Umformulieren',\n 'ai.task.reformulate.promptLabel': 'Hinweis (optional), z. B. „kürzer“ oder „förmlicher“',\n 'ai.task.generate.label': 'Text generieren',\n 'ai.task.generate.promptLabel': 'Was soll geschrieben werden?',\n 'ai.task.transcript.promptLabel': 'Hinweis (optional), z. B. „nur Beschlüsse“ oder „auf Englisch“',\n 'ai.task.transcriptSummary.heading': 'Zusammenfassung',\n 'ai.task.transcriptMinutes.heading': 'Protokoll',\n 'ai.task.transcriptActionItems.heading': 'Aufgaben',\n 'ai.task.fix.label': 'Korrigieren',\n 'ai.task.shorter.label': 'Kürzer',\n 'ai.task.formal.label': 'Förmlicher',\n 'ai.task.casual.label': 'Lockerer',\n 'ai.task.translate.label': 'Übersetzen',\n 'ai.task.summarize.label': 'Zusammenfassen',\n 'ai.task.custom.label': 'Eigene Anweisung',\n 'ai.task.custom.promptLabel': 'Anweisung an die KI, z. B. „als Aufzählung“',\n 'ai.task.continue.label': 'Weiterschreiben',\n 'ai.task.fillBlock.label': 'Baustein füllen',\n 'ai.task.fillBlock.promptLabel': 'Hinweis (optional)',\n\n // Model slots and target languages\n 'ai.slot.complete.label': 'Vorschläge beim Tippen',\n 'ai.slot.complete.description': 'Schnelles Modell; muss Assistant-Prefill unterstützen.',\n 'ai.slot.rewrite.label': 'Text im Block',\n 'ai.slot.rewrite.description': 'Umformulieren, Korrigieren, Übersetzen, Zusammenfassen, Transkript bereinigen.',\n 'ai.slot.generate.label': 'Blöcke erzeugen & Chat',\n 'ai.slot.generate.description': 'Neue Blöcke, Protokolle, Chat-Agent (braucht Tool-Calling).',\n 'ai.slot.ariaLabel': 'Modell für „{slot}“',\n 'ai.slot.manage': 'Modelle verwalten…',\n 'ai.language.de': 'Deutsch',\n 'ai.language.en': 'Englisch',\n 'ai.language.fr': 'Französisch',\n 'ai.language.es': 'Spanisch',\n 'ai.language.it': 'Italienisch',\n\n // Feature entry points (toolbar, block action, slash command, settings tab)\n 'ai.tab': 'KI',\n 'ai.toolbar.sidebar': 'KI-Seitenleiste',\n 'ai.toolbar.autocomplete': 'KI-Vorschläge beim Tippen (Tab übernimmt, Esc verwirft)',\n 'ai.blockAction.label': 'Mit KI bearbeiten',\n 'ai.slash.label': 'KI',\n\n // Notices\n 'ai.rateLimited': 'Zu viele KI-Anfragen, bitte kurz warten',\n 'ai.sse.unknownError': 'Unbekannter Fehler',\n 'ai.sse.httpError': 'Fehler {status}',\n 'ai.sse.aborted': 'Verbindung abgebrochen',\n 'ai.chat.emptyScope': 'Die Auswahl enthält keine bearbeitbaren Blöcke.',\n 'ai.apply.missing.title': 'Textstelle nicht mehr gefunden',\n 'ai.apply.missing.description': 'Das Ergebnis wurde nicht übernommen.',\n 'ai.apply.empty.title': 'Leeres Ergebnis',\n 'ai.apply.empty.description': 'Das Ergebnis wurde nicht übernommen.',\n 'ai.apply.unchanged.title': 'Keine Änderungen',\n 'ai.apply.unchanged.description': 'Das Ergebnis entspricht dem vorhandenen Text.',\n 'ai.apply.overlap.title': 'Textstelle wird bereits geprüft',\n 'ai.apply.overlap.description': 'Erst die offenen KI-Änderungen übernehmen oder verwerfen.',\n\n // In-document review\n 'ai.review.accept': 'Übernehmen',\n 'ai.review.discard': 'Verwerfen',\n 'ai.review.acceptAll': 'Alle übernehmen',\n 'ai.review.rejectAll': 'Alle verwerfen',\n 'ai.review.barLabel': 'KI-Änderungen prüfen',\n 'ai.review.count.one': '1 KI-Änderung',\n 'ai.review.count.other': '{n} KI-Änderungen',\n 'ai.review.previous': 'Vorherige Änderung',\n 'ai.review.next': 'Nächste Änderung',\n 'ai.review.invalid.one': 'KI-Änderung verworfen',\n 'ai.review.invalid.other': '{n} KI-Änderungen verworfen',\n 'ai.review.invalid.description': 'Der ursprüngliche Text wurde inzwischen geändert.',\n\n // Selection / caret menu\n 'ai.menu.trigger': 'KI',\n 'ai.menu.model': 'Modell',\n 'ai.menu.targetLanguage': 'Zielsprache',\n 'ai.menu.sendInstruction': 'Anweisung senden',\n 'ai.menu.requestWithLanguage': '{task} – {language}',\n 'ai.menu.cancel': 'Abbrechen',\n 'ai.menu.discard': 'Verwerfen',\n 'ai.menu.retry': 'Erneut versuchen',\n 'ai.menu.insert': 'Einfügen',\n 'ai.menu.insertBelow': 'Darunter einfügen',\n 'ai.menu.replace': 'Ersetzen',\n 'ai.menu.missing.selection': 'Der markierte Text wurde gelöscht.',\n 'ai.menu.missing.line': 'Die Zeile wurde gelöscht.',\n 'ai.menu.missing.insert': 'Das Ergebnis wurde nicht eingefügt.',\n\n // Sidebar\n 'ai.sidebar.label': 'KI-Seitenleiste',\n 'ai.sidebar.title': 'KI',\n 'ai.sidebar.newConversation': 'Neues Gespräch',\n 'ai.sidebar.close': 'Schließen',\n 'ai.sidebar.selection.one': 'Auswahl: {n} Block',\n 'ai.sidebar.selection.other': 'Auswahl: {n} Blöcke',\n 'ai.sidebar.selection.title': 'Änderungen betreffen nur die markierten Blöcke',\n 'ai.sidebar.selection.clear': 'Auswahl aufheben',\n 'ai.sidebar.intro': 'Stelle eine Frage zum Inhalt, z. B. „Wer hat gesagt, dass das Budget nicht reicht?“, oder bitte um eine Änderung, z. B. „Kürze Abschnitt 2“. Mit einer Markierung im Text betreffen Änderungen nur die markierten Blöcke. Die Schnellaktionen unten erzeugen neue Blöcke, z. B. ein Protokoll.',\n 'ai.sidebar.stop': 'Stopp',\n 'ai.sidebar.discard': 'Verwerfen',\n 'ai.sidebar.apply': 'Übernehmen',\n 'ai.sidebar.generateGroup': 'Blöcke generieren',\n 'ai.sidebar.generate': 'Generieren',\n 'ai.sidebar.placeholder': 'Frage oder Änderungswunsch…',\n 'ai.sidebar.messageLabel': 'Nachricht zum Dokument',\n 'ai.sidebar.send': 'Senden',\n 'ai.sidebar.revealMissing': 'Textstelle nicht mehr im Dokument',\n\n // Chat edit operations\n 'ai.op.addAtStart': 'Einfügen am Dokumentanfang',\n 'ai.op.addAfter': 'Einfügen nach „{snippet}“',\n 'ai.op.convert': 'Umwandeln in {target}: „{snippet}“',\n 'ai.op.update': 'Ändern: „{snippet}“',\n 'ai.op.delete': 'Löschen: „{snippet}“',\n 'ai.op.accept': 'Übernehmen',\n 'ai.op.discard': 'Verwerfen',\n 'ai.op.problems.one': '1 Vorschlag verworfen',\n 'ai.op.problems.other': '{n} Vorschläge verworfen',\n 'ai.op.problems.description': 'Die KI hat auf Blöcke oder Blocktypen verwiesen, die es nicht gibt oder die außerhalb der Auswahl liegen.',\n 'ai.op.invalid.title': 'Änderung nicht mehr anwendbar',\n 'ai.op.invalid.description': 'Der Text wurde inzwischen anders geändert.',\n 'ai.op.snippet.documentStart': 'Dokumentanfang',\n 'ai.op.snippet.missing': 'Block nicht mehr vorhanden',\n 'ai.op.snippet.emptyBlock': 'Leerer Block',\n 'ai.op.snippet.image': 'Bild',\n 'ai.op.snippet.audio': 'Audio',\n 'ai.op.snippet.video': 'Video',\n 'ai.op.snippet.file': 'Datei',\n 'ai.opBadge.pending': 'Offen',\n 'ai.opBadge.accepted': 'Übernommen',\n 'ai.opBadge.rejected': 'Abgelehnt',\n 'ai.opBadge.partial': 'Teilweise',\n 'ai.opBadge.invalid': 'Verfallen',\n 'ai.opBadge.unchanged': 'Keine Änderung',\n 'ai.opBadge.missing': 'Block fehlt',\n 'ai.opBadge.stale': 'Block gelöscht',\n 'ai.opBadge.overlap': 'Stelle belegt',\n 'ai.opBadge.empty': 'Leer',\n 'ai.opBadge.blocked': 'Außerhalb der Auswahl',\n 'ai.opTitle.pending': 'Vorschlag noch nicht entschieden',\n 'ai.opTitle.accepted': 'Vorschlag übernommen',\n 'ai.opTitle.rejected': 'Vorschlag abgelehnt',\n 'ai.opTitle.partial': 'Vorschlag teilweise übernommen',\n 'ai.opTitle.invalid': 'Vorschlag verfallen, weil der Text inzwischen anders geändert wurde',\n 'ai.opTitle.unchanged': 'Vorschlag nicht angezeigt, weil er dem vorhandenen Text entspricht',\n 'ai.opTitle.missing': 'Vorschlag nicht angezeigt, weil der Block nicht mehr existiert',\n 'ai.opTitle.stale': 'Vorschlag nicht angezeigt: Block wurde inzwischen gelöscht',\n 'ai.opTitle.overlap': 'Vorschlag nicht angezeigt, weil an der Stelle noch andere KI-Änderungen offen sind',\n 'ai.opTitle.empty': 'Vorschlag nicht angezeigt, weil der Inhalt leer ist',\n 'ai.opTitle.blocked': 'Vorschlag blockiert, weil er außerhalb des erlaubten Bereichs liegt',\n\n // Settings tab\n 'ai.settings.writing.title': 'Beim Schreiben',\n 'ai.settings.autocomplete.label': 'KI-Vorschläge beim Tippen',\n 'ai.settings.autocomplete.description': 'Grauer Text nach dem Cursor; Tab übernimmt, Esc verwirft.',\n 'ai.settings.language.label': 'Zielsprache beim Übersetzen',\n 'ai.settings.language.description': 'Vorausgewählt; im KI-Menü pro Aufruf änderbar.',\n 'ai.settings.slots.title': 'Modell je Aufgabe',\n 'ai.settings.slots.description': 'Welches Profil die einzelnen KI-Funktionen verwenden.',\n 'ai.settings.profiles.title': 'Modellprofile',\n 'ai.settings.profiles.description': 'Server-Presets sind vorkonfiguriert. Eigene Profile werden nur in diesem Browser gespeichert; ihr API-Key wird mit jeder Anfrage gesendet und nicht auf dem Server abgelegt.',\n 'ai.profiles.server': 'Vom Server',\n 'ai.profiles.noPresets': 'Keine Presets geladen.',\n 'ai.profiles.serverBadge': 'Server',\n 'ai.profiles.own': 'Eigene Profile',\n 'ai.profiles.add': 'Profil hinzufügen',\n 'ai.profiles.edit': 'Bearbeiten',\n 'ai.profiles.delete': 'Löschen',\n 'ai.profiles.name': 'Name',\n 'ai.profiles.namePlaceholder': 'z. B. Lokal',\n 'ai.profiles.endpoint': 'Endpunkt',\n 'ai.profiles.endpointHelp': 'OpenAI-kompatible Basis-URL.',\n 'ai.profiles.endpointPlaceholder': 'https://openrouter.ai/api/v1',\n 'ai.profiles.model': 'Modell',\n 'ai.profiles.modelPlaceholder': 'google/gemini-2.5-flash',\n 'ai.profiles.apiKey': 'API-Key',\n 'ai.profiles.testOk': 'Verbindung funktioniert',\n 'ai.profiles.test': 'Testen',\n 'ai.profiles.cancel': 'Abbrechen',\n 'ai.profiles.save': 'Speichern',\n} as const\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai.js","names":[],"sources":["../../../src/i18n/de/ai.ts"],"sourcesContent":["export const de = {\n // Tasks (menus, sidebar chips, prompt hints, result headings)\n 'ai.task.reformulate.label': 'Umformulieren',\n 'ai.task.reformulate.promptLabel': 'Hinweis (optional), z. B. „kürzer“ oder „förmlicher“',\n 'ai.task.generate.label': 'Text generieren',\n 'ai.task.generate.promptLabel': 'Was soll geschrieben werden?',\n 'ai.task.transcript.promptLabel': 'Hinweis (optional), z. B. „nur Beschlüsse“ oder „auf Englisch“',\n 'ai.task.transcriptSummary.heading': 'Zusammenfassung',\n 'ai.task.transcriptMinutes.heading': 'Protokoll',\n 'ai.task.transcriptActionItems.heading': 'Aufgaben',\n 'ai.task.fix.label': 'Korrigieren',\n 'ai.task.shorter.label': 'Kürzer',\n 'ai.task.formal.label': 'Förmlicher',\n 'ai.task.casual.label': 'Lockerer',\n 'ai.task.translate.label': 'Übersetzen',\n 'ai.task.summarize.label': 'Zusammenfassen',\n 'ai.task.custom.label': 'Eigene Anweisung',\n 'ai.task.custom.promptLabel': 'Anweisung an die KI, z. B. „als Aufzählung“',\n 'ai.task.continue.label': 'Weiterschreiben',\n 'ai.task.fillBlock.label': 'Baustein füllen',\n 'ai.task.fillBlock.promptLabel': 'Hinweis (optional)',\n 'ai.task.splitBlock.label': 'Baustein gliedern',\n 'ai.task.outlineSanitize.label': 'Gliederung bereinigen',\n 'ai.task.transferSummary.label': 'Zusammenfassung (Übertragen)',\n 'ai.task.transferBullets.label': 'Stichpunkte (Übertragen)',\n\n // Model slots and target languages\n 'ai.slot.complete.label': 'Vorschläge beim Tippen',\n 'ai.slot.complete.description': 'Schnelles Modell; muss Assistant-Prefill unterstützen.',\n 'ai.slot.rewrite.label': 'Text im Block',\n 'ai.slot.rewrite.description': 'Umformulieren, Korrigieren, Übersetzen, Zusammenfassen, Transkript bereinigen.',\n 'ai.slot.generate.label': 'Blöcke erzeugen & Chat',\n 'ai.slot.generate.description': 'Neue Blöcke, Protokolle, Chat-Agent (braucht Tool-Calling).',\n 'ai.slot.ariaLabel': 'Modell für „{slot}“',\n 'ai.slot.manage': 'Modelle verwalten…',\n 'ai.language.de': 'Deutsch',\n 'ai.language.en': 'Englisch',\n 'ai.language.fr': 'Französisch',\n 'ai.language.es': 'Spanisch',\n 'ai.language.it': 'Italienisch',\n\n // Feature entry points (toolbar, block action, slash command, settings tab)\n 'ai.tab': 'KI',\n 'ai.toolbar.sidebar': 'KI-Seitenleiste',\n 'ai.toolbar.autocomplete': 'KI-Vorschläge beim Tippen (Tab übernimmt, Esc verwirft)',\n 'ai.blockAction.label': 'Mit KI bearbeiten',\n 'ai.slash.label': 'KI',\n\n // Notices\n 'ai.rateLimited': 'Zu viele KI-Anfragen, bitte kurz warten',\n 'ai.sse.unknownError': 'Unbekannter Fehler',\n 'ai.sse.httpError': 'Fehler {status}',\n 'ai.sse.aborted': 'Verbindung abgebrochen',\n 'ai.chat.emptyScope': 'Die Auswahl enthält keine bearbeitbaren Blöcke.',\n 'ai.apply.missing.title': 'Textstelle nicht mehr gefunden',\n 'ai.apply.missing.description': 'Das Ergebnis wurde nicht übernommen.',\n 'ai.apply.empty.title': 'Leeres Ergebnis',\n 'ai.apply.empty.description': 'Das Ergebnis wurde nicht übernommen.',\n 'ai.apply.unchanged.title': 'Keine Änderungen',\n 'ai.apply.unchanged.description': 'Das Ergebnis entspricht dem vorhandenen Text.',\n 'ai.apply.overlap.title': 'Textstelle wird bereits geprüft',\n 'ai.apply.overlap.description': 'Erst die offenen KI-Änderungen übernehmen oder verwerfen.',\n\n // In-document review\n 'ai.review.accept': 'Übernehmen',\n 'ai.review.discard': 'Verwerfen',\n 'ai.review.acceptAll': 'Alle übernehmen',\n 'ai.review.rejectAll': 'Alle verwerfen',\n 'ai.review.barLabel': 'KI-Änderungen prüfen',\n 'ai.review.count.one': '1 KI-Änderung',\n 'ai.review.count.other': '{n} KI-Änderungen',\n 'ai.review.previous': 'Vorherige Änderung',\n 'ai.review.next': 'Nächste Änderung',\n 'ai.review.invalid.one': 'KI-Änderung verworfen',\n 'ai.review.invalid.other': '{n} KI-Änderungen verworfen',\n 'ai.review.invalid.description': 'Der ursprüngliche Text wurde inzwischen geändert.',\n\n // Selection / caret menu\n 'ai.menu.trigger': 'KI',\n 'ai.menu.model': 'Modell',\n 'ai.menu.targetLanguage': 'Zielsprache',\n 'ai.menu.sendInstruction': 'Anweisung senden',\n 'ai.menu.requestWithLanguage': '{task} – {language}',\n 'ai.menu.cancel': 'Abbrechen',\n 'ai.menu.discard': 'Verwerfen',\n 'ai.menu.retry': 'Erneut versuchen',\n 'ai.menu.insert': 'Einfügen',\n 'ai.menu.insertBelow': 'Darunter einfügen',\n 'ai.menu.replace': 'Ersetzen',\n 'ai.menu.missing.selection': 'Der markierte Text wurde gelöscht.',\n 'ai.menu.missing.line': 'Die Zeile wurde gelöscht.',\n 'ai.menu.missing.insert': 'Das Ergebnis wurde nicht eingefügt.',\n\n // Sidebar\n 'ai.sidebar.label': 'KI-Seitenleiste',\n 'ai.sidebar.title': 'KI',\n 'ai.sidebar.newConversation': 'Neues Gespräch',\n 'ai.sidebar.close': 'Schließen',\n 'ai.sidebar.selection.one': 'Auswahl: {n} Block',\n 'ai.sidebar.selection.other': 'Auswahl: {n} Blöcke',\n 'ai.sidebar.selection.title': 'Änderungen betreffen nur die markierten Blöcke',\n 'ai.sidebar.selection.clear': 'Auswahl aufheben',\n 'ai.sidebar.intro': 'Stelle eine Frage zum Inhalt, z. B. „Wer hat gesagt, dass das Budget nicht reicht?“, oder bitte um eine Änderung, z. B. „Kürze Abschnitt 2“. Mit einer Markierung im Text betreffen Änderungen nur die markierten Blöcke. Die Schnellaktionen unten erzeugen neue Blöcke, z. B. ein Protokoll.',\n 'ai.sidebar.stop': 'Stopp',\n 'ai.sidebar.discard': 'Verwerfen',\n 'ai.sidebar.apply': 'Übernehmen',\n 'ai.sidebar.generateGroup': 'Blöcke generieren',\n 'ai.sidebar.generate': 'Generieren',\n 'ai.sidebar.placeholder': 'Frage oder Änderungswunsch…',\n 'ai.sidebar.messageLabel': 'Nachricht zum Dokument',\n 'ai.sidebar.send': 'Senden',\n 'ai.sidebar.revealMissing': 'Textstelle nicht mehr im Dokument',\n\n // Chat edit operations\n 'ai.op.addAtStart': 'Einfügen am Dokumentanfang',\n 'ai.op.addAfter': 'Einfügen nach „{snippet}“',\n 'ai.op.convert': 'Umwandeln in {target}: „{snippet}“',\n 'ai.op.update': 'Ändern: „{snippet}“',\n 'ai.op.delete': 'Löschen: „{snippet}“',\n 'ai.op.accept': 'Übernehmen',\n 'ai.op.discard': 'Verwerfen',\n 'ai.op.problems.one': '1 Vorschlag verworfen',\n 'ai.op.problems.other': '{n} Vorschläge verworfen',\n 'ai.op.problems.description': 'Die KI hat auf Blöcke oder Blocktypen verwiesen, die es nicht gibt oder die außerhalb der Auswahl liegen.',\n 'ai.op.invalid.title': 'Änderung nicht mehr anwendbar',\n 'ai.op.invalid.description': 'Der Text wurde inzwischen anders geändert.',\n 'ai.op.snippet.documentStart': 'Dokumentanfang',\n 'ai.op.snippet.missing': 'Block nicht mehr vorhanden',\n 'ai.op.snippet.emptyBlock': 'Leerer Block',\n 'ai.op.snippet.image': 'Bild',\n 'ai.op.snippet.audio': 'Audio',\n 'ai.op.snippet.video': 'Video',\n 'ai.op.snippet.file': 'Datei',\n 'ai.opBadge.pending': 'Offen',\n 'ai.opBadge.accepted': 'Übernommen',\n 'ai.opBadge.rejected': 'Abgelehnt',\n 'ai.opBadge.partial': 'Teilweise',\n 'ai.opBadge.invalid': 'Verfallen',\n 'ai.opBadge.unchanged': 'Keine Änderung',\n 'ai.opBadge.missing': 'Block fehlt',\n 'ai.opBadge.stale': 'Block gelöscht',\n 'ai.opBadge.overlap': 'Stelle belegt',\n 'ai.opBadge.empty': 'Leer',\n 'ai.opBadge.blocked': 'Außerhalb der Auswahl',\n 'ai.opTitle.pending': 'Vorschlag noch nicht entschieden',\n 'ai.opTitle.accepted': 'Vorschlag übernommen',\n 'ai.opTitle.rejected': 'Vorschlag abgelehnt',\n 'ai.opTitle.partial': 'Vorschlag teilweise übernommen',\n 'ai.opTitle.invalid': 'Vorschlag verfallen, weil der Text inzwischen anders geändert wurde',\n 'ai.opTitle.unchanged': 'Vorschlag nicht angezeigt, weil er dem vorhandenen Text entspricht',\n 'ai.opTitle.missing': 'Vorschlag nicht angezeigt, weil der Block nicht mehr existiert',\n 'ai.opTitle.stale': 'Vorschlag nicht angezeigt: Block wurde inzwischen gelöscht',\n 'ai.opTitle.overlap': 'Vorschlag nicht angezeigt, weil an der Stelle noch andere KI-Änderungen offen sind',\n 'ai.opTitle.empty': 'Vorschlag nicht angezeigt, weil der Inhalt leer ist',\n 'ai.opTitle.blocked': 'Vorschlag blockiert, weil er außerhalb des erlaubten Bereichs liegt',\n\n // Settings tab\n 'ai.settings.writing.title': 'Beim Schreiben',\n 'ai.settings.autocomplete.label': 'KI-Vorschläge beim Tippen',\n 'ai.settings.autocomplete.description': 'Grauer Text nach dem Cursor; Tab übernimmt, Esc verwirft.',\n 'ai.settings.language.label': 'Zielsprache beim Übersetzen',\n 'ai.settings.language.description': 'Vorausgewählt; im KI-Menü pro Aufruf änderbar.',\n 'ai.settings.slots.title': 'Modell je Aufgabe',\n 'ai.settings.slots.description': 'Welches Profil die einzelnen KI-Funktionen verwenden.',\n 'ai.settings.profiles.title': 'Modellprofile',\n 'ai.settings.profiles.description': 'Server-Presets sind vorkonfiguriert. Eigene Profile werden nur in diesem Browser gespeichert; ihr API-Key wird mit jeder Anfrage gesendet und nicht auf dem Server abgelegt.',\n 'ai.profiles.server': 'Vom Server',\n 'ai.profiles.noPresets': 'Keine Presets geladen.',\n 'ai.profiles.serverBadge': 'Server',\n 'ai.profiles.own': 'Eigene Profile',\n 'ai.profiles.add': 'Profil hinzufügen',\n 'ai.profiles.edit': 'Bearbeiten',\n 'ai.profiles.delete': 'Löschen',\n 'ai.profiles.name': 'Name',\n 'ai.profiles.namePlaceholder': 'z. B. Lokal',\n 'ai.profiles.endpoint': 'Endpunkt',\n 'ai.profiles.endpointHelp': 'OpenAI-kompatible Basis-URL.',\n 'ai.profiles.endpointPlaceholder': 'https://openrouter.ai/api/v1',\n 'ai.profiles.model': 'Modell',\n 'ai.profiles.modelPlaceholder': 'google/gemini-2.5-flash',\n 'ai.profiles.apiKey': 'API-Key',\n 'ai.profiles.testOk': 'Verbindung funktioniert',\n 'ai.profiles.test': 'Testen',\n 'ai.profiles.cancel': 'Abbrechen',\n 'ai.profiles.save': 'Speichern',\n} as const\n"],"mappings":"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"}
|
|
@@ -106,6 +106,12 @@ const de = {
|
|
|
106
106
|
"composites.slash.flattenAll": "Bausteine in Überschriften (alle Ebenen)",
|
|
107
107
|
"composites.blockAction.export": "Als Markdown exportieren",
|
|
108
108
|
"composites.blockAction.bibtex": "Literaturangabe exportieren (BibTeX)",
|
|
109
|
+
"composites.split.here": "Baustein hier teilen",
|
|
110
|
+
"composites.split.children": "In Unter-Bausteine teilen",
|
|
111
|
+
"composites.split.lengthChildren": "Nach Länge in Unter-Bausteine teilen",
|
|
112
|
+
"composites.split.lengthSiblings": "Nach Länge in Bausteine teilen",
|
|
113
|
+
"composites.merge.next": "Mit nächstem zusammenführen",
|
|
114
|
+
"settings.editing.splitTargetChars": "Zielgröße beim Teilen (Zeichen)",
|
|
109
115
|
"composites.toolbar.toKind": "In Baustein umwandeln",
|
|
110
116
|
"composites.toolbar.structure": "Gliederung umwandeln",
|
|
111
117
|
"composites.menu.kindHeading": "Baustein",
|
|
@@ -143,6 +149,7 @@ const de = {
|
|
|
143
149
|
"composites.reference.backlinks": "Verweise",
|
|
144
150
|
"composites.derivation.badge": "abgeleitet",
|
|
145
151
|
"composites.derivation.stale": "Quelle geändert",
|
|
152
|
+
"composites.derivation.foreign": "aus anderem Dokument",
|
|
146
153
|
"composites.derivation.edited": "bearbeitet",
|
|
147
154
|
"composites.derivation.expand": "Abgeleiteten Inhalt aufklappen",
|
|
148
155
|
"composites.derivation.collapse": "Abgeleiteten Inhalt zuklappen",
|
|
@@ -236,7 +243,20 @@ const de = {
|
|
|
236
243
|
"composites.move.targetGone": "Das Ziel existiert nicht mehr.",
|
|
237
244
|
"composites.move.targetNotBlock": "Das Ziel ist kein Baustein.",
|
|
238
245
|
"composites.move.intoSelf": "Ein Block kann nicht in sich selbst verschoben werden.",
|
|
239
|
-
"composites.move.intoOwn": "Ein Block kann nicht in einen Baustein verschoben werden, den er selbst enthält."
|
|
246
|
+
"composites.move.intoOwn": "Ein Block kann nicht in einen Baustein verschoben werden, den er selbst enthält.",
|
|
247
|
+
"composites.basket.label": "Korb",
|
|
248
|
+
"composites.basket.none": "Kein Korb",
|
|
249
|
+
"composites.basket.red": "Rot",
|
|
250
|
+
"composites.basket.orange": "Orange",
|
|
251
|
+
"composites.basket.yellow": "Gelb",
|
|
252
|
+
"composites.basket.green": "Grün",
|
|
253
|
+
"composites.basket.blue": "Blau",
|
|
254
|
+
"composites.titleHidden.hide": "Titel ausblenden",
|
|
255
|
+
"composites.titleHidden.show": "Titel einblenden",
|
|
256
|
+
"composites.focus.action": "Fokussieren",
|
|
257
|
+
"composites.focus.leave": "Fokus aufheben",
|
|
258
|
+
"composites.focus.chip": "Fokus: {title}",
|
|
259
|
+
"composites.focus.release": "Aufheben"
|
|
240
260
|
};
|
|
241
261
|
//#endregion
|
|
242
262
|
export { de };
|