@ecsplico/editor 3.6.0 → 4.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 +65 -0
- package/dist/adapters/direct-ai.d.ts +4 -4
- package/dist/adapters/direct-ai.js +2 -2
- package/dist/adapters/direct-ai.js.map +1 -1
- package/dist/adapters/document-state.d.ts +1 -1
- package/dist/adapters/document-state.js.map +1 -1
- package/dist/adapters/forge.d.ts +2 -2
- package/dist/adapters/forge.js.map +1 -1
- package/dist/adapters/nitro.d.ts +11 -3
- package/dist/adapters/nitro.js +3 -1
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/shared.d.ts +6 -6
- package/dist/adapters/shared.js.map +1 -1
- package/dist/config/index.d.ts +14 -14
- package/dist/config/index.js +8 -8
- package/dist/config/index.js.map +1 -1
- package/dist/core/backend-types.d.ts +3 -3
- package/dist/core/backend-types.js.map +1 -1
- package/dist/core/backend.d.ts +4 -4
- package/dist/core/backend.js.map +1 -1
- package/dist/core/block-convert.d.ts +1 -1
- package/dist/core/block-convert.js +5 -5
- package/dist/core/block-convert.js.map +1 -1
- package/dist/core/block-transfer.d.ts +8 -4
- package/dist/core/block-transfer.js +23 -14
- package/dist/core/block-transfer.js.map +1 -1
- package/dist/core/capabilities.d.ts +113 -0
- package/dist/core/capabilities.js +155 -0
- package/dist/core/capabilities.js.map +1 -0
- package/dist/core/command-types.d.ts +1 -1
- package/dist/core/context.js.map +1 -1
- package/dist/core/convert.d.ts +5 -5
- package/dist/core/convert.js +5 -5
- package/dist/core/convert.js.map +1 -1
- package/dist/core/core-feature.js +1 -1
- package/dist/core/define-editor.d.ts +2 -2
- package/dist/core/define-editor.js +34 -6
- package/dist/core/define-editor.js.map +1 -1
- package/dist/core/derivation.d.ts +119 -0
- package/dist/core/derivation.js +187 -0
- package/dist/core/derivation.js.map +1 -0
- package/dist/core/derive.d.ts +61 -0
- package/dist/core/derive.js +69 -0
- package/dist/core/derive.js.map +1 -0
- package/dist/core/extension-points.d.ts +16 -0
- package/dist/core/feature-context.d.ts +5 -1
- package/dist/core/feature-context.js +10 -3
- package/dist/core/feature-context.js.map +1 -1
- package/dist/core/feature.d.ts +41 -19
- package/dist/core/feature.js.map +1 -1
- package/dist/core/fences.js +1 -1
- package/dist/core/fences.js.map +1 -1
- package/dist/core/index.d.ts +6 -2
- package/dist/core/index.js +5 -1
- package/dist/core/pipeline.d.ts +14 -5
- package/dist/core/pipeline.js +19 -7
- package/dist/core/pipeline.js.map +1 -1
- package/dist/core/properties.d.ts +22 -0
- package/dist/core/properties.js +17 -0
- package/dist/core/properties.js.map +1 -0
- package/dist/core/schema/block-ids.js +5 -5
- package/dist/core/schema/block-ids.js.map +1 -1
- package/dist/core/schema/index.d.ts +2 -1
- package/dist/core/schema/index.js +2 -1
- package/dist/core/schema/index.js.map +1 -1
- package/dist/core/schema/opaque-fence.d.ts +4 -4
- package/dist/core/schema/opaque-fence.js +7 -7
- package/dist/core/schema/opaque-fence.js.map +1 -1
- package/dist/core/schema/persisted-names.d.ts +58 -0
- package/dist/core/schema/persisted-names.js +96 -0
- package/dist/core/schema/persisted-names.js.map +1 -0
- package/dist/core/toolbar-items.js +1 -1
- package/dist/core/toolbar-items.js.map +1 -1
- package/dist/core/util.js +5 -1
- package/dist/core/util.js.map +1 -1
- package/dist/features/ai/agent-ops.js +1 -1
- package/dist/features/ai/ai-review.js +1 -1
- package/dist/features/ai/assistant.d.ts +4 -4
- package/dist/features/ai/assistant.js +1 -1
- package/dist/features/ai/assistant.js.map +1 -1
- package/dist/features/ai/components/AiSelectionMenu.js +1 -1
- package/dist/features/ai/components/AiSelectionMenu.js.map +1 -1
- package/dist/features/ai/components/ModelQuickSwitch.js +7 -7
- package/dist/features/ai/components/ModelQuickSwitch.js.map +1 -1
- package/dist/features/ai/components/ModelQuickSwitch.vue.d.ts +4 -4
- package/dist/features/ai/components/SettingsAiTab.js +8 -8
- package/dist/features/ai/components/SettingsAiTab.js.map +1 -1
- package/dist/features/ai/components/SettingsModelProfiles.js +1 -1
- package/dist/features/ai/components/SettingsModelProfiles.js.map +1 -1
- package/dist/features/ai/document-chat-model.d.ts +2 -2
- 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 +2 -2
- package/dist/features/ai/document-chat.js.map +1 -1
- package/dist/features/ai/feature.d.ts +2 -2
- package/dist/features/ai/feature.js +2 -2
- package/dist/features/ai/feature.js.map +1 -1
- package/dist/features/ai/ghost-autocomplete.d.ts +4 -4
- package/dist/features/ai/ghost-autocomplete.js +1 -1
- package/dist/features/ai/ghost-autocomplete.js.map +1 -1
- package/dist/features/ai/index.d.ts +3 -3
- package/dist/features/ai/index.js +2 -2
- package/dist/features/ai/model-profiles.d.ts +9 -9
- package/dist/features/ai/model-profiles.js +13 -13
- package/dist/features/ai/model-profiles.js.map +1 -1
- package/dist/features/ai/protocol/agent-ops.d.ts +2 -2
- package/dist/features/ai/protocol/agent-ops.js +1 -1
- package/dist/features/ai/protocol/agent-ops.js.map +1 -1
- package/dist/features/ai/protocol/block-lines.d.ts +7 -7
- package/dist/features/ai/protocol/block-lines.js +10 -10
- package/dist/features/ai/protocol/block-lines.js.map +1 -1
- package/dist/features/ai/protocol/chat.d.ts +5 -5
- package/dist/features/ai/protocol/chat.js +12 -12
- package/dist/features/ai/protocol/chat.js.map +1 -1
- package/dist/features/ai/protocol/generate.d.ts +1 -1
- package/dist/features/ai/protocol/generate.js +1 -1
- package/dist/features/ai/protocol/generate.js.map +1 -1
- package/dist/features/ai/protocol/index.d.ts +3 -3
- package/dist/features/ai/protocol/index.js +2 -2
- package/dist/features/ai/protocol/models.d.ts +3 -3
- package/dist/features/ai/protocol/models.js +3 -3
- package/dist/features/ai/protocol/models.js.map +1 -1
- package/dist/features/ai/protocol/schemas.d.ts +1 -1
- package/dist/features/ai/protocol/schemas.js +1 -1
- package/dist/features/ai/protocol/schemas.js.map +1 -1
- package/dist/features/ai/protocol/tasks.d.ts +5 -5
- package/dist/features/ai/protocol/tasks.js +12 -12
- package/dist/features/ai/protocol/tasks.js.map +1 -1
- package/dist/features/ai/react/AiSelectionMenu.js.map +1 -1
- package/dist/features/ai/react/ModelQuickSwitch.d.ts +4 -4
- package/dist/features/ai/react/ModelQuickSwitch.js +6 -6
- package/dist/features/ai/react/ModelQuickSwitch.js.map +1 -1
- package/dist/features/ai/react/SettingsAiTab.d.ts +1 -1
- package/dist/features/ai/react/SettingsAiTab.js +8 -8
- package/dist/features/ai/react/SettingsAiTab.js.map +1 -1
- package/dist/features/ai/react/SettingsModelProfiles.d.ts +1 -1
- package/dist/features/ai/react/SettingsModelProfiles.js +1 -1
- 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 +1 -1
- package/dist/features/ai/react/use-ai-assistant.js.map +1 -1
- package/dist/features/ai/react/use-model-profiles.d.ts +5 -5
- package/dist/features/ai/react/use-model-profiles.js +2 -2
- package/dist/features/ai/react/use-model-profiles.js.map +1 -1
- package/dist/features/ai/use-ai-assistant.d.ts +1 -1
- package/dist/features/ai/use-ai-assistant.js +1 -1
- package/dist/features/ai/use-ai-assistant.js.map +1 -1
- package/dist/features/ai/use-model-profiles.d.ts +4 -4
- package/dist/features/ai/use-model-profiles.js +2 -2
- package/dist/features/ai/use-model-profiles.js.map +1 -1
- package/dist/features/block-ui/block-actions.d.ts +8 -4
- package/dist/features/block-ui/block-actions.js +38 -22
- package/dist/features/block-ui/block-actions.js.map +1 -1
- package/dist/features/block-ui/block-target.d.ts +29 -0
- package/dist/features/block-ui/block-target.js +63 -0
- package/dist/features/block-ui/block-target.js.map +1 -0
- package/dist/features/block-ui/components/BlockHandles.js +3 -3
- package/dist/features/block-ui/components/BlockHandles.js.map +1 -1
- package/dist/features/block-ui/components/BlockUi.js +11 -23
- package/dist/features/block-ui/components/BlockUi.js.map +1 -1
- package/dist/features/block-ui/feature.d.ts +3 -2
- package/dist/features/block-ui/feature.js +3 -2
- package/dist/features/block-ui/feature.js.map +1 -1
- package/dist/features/block-ui/handle-geometry.js +12 -23
- package/dist/features/block-ui/handle-geometry.js.map +1 -1
- package/dist/features/block-ui/index.d.ts +2 -1
- package/dist/features/block-ui/index.js +2 -1
- package/dist/features/block-ui/react/BlockHandles.d.ts +1 -1
- package/dist/features/block-ui/react/BlockHandles.js +4 -4
- package/dist/features/block-ui/react/BlockHandles.js.map +1 -1
- package/dist/features/block-ui/react/BlockUi.js +13 -25
- package/dist/features/block-ui/react/BlockUi.js.map +1 -1
- package/dist/features/comments/model.js +1 -1
- package/dist/features/composites/accepted-children.d.ts +5 -4
- package/dist/features/composites/accepted-children.js +26 -26
- package/dist/features/composites/accepted-children.js.map +1 -1
- package/dist/features/composites/ai-brief.d.ts +4 -4
- package/dist/features/composites/ai-brief.js +14 -12
- package/dist/features/composites/ai-brief.js.map +1 -1
- package/dist/features/composites/anchors.d.ts +1 -1
- package/dist/features/composites/anchors.js.map +1 -1
- package/dist/features/composites/baskets.d.ts +1 -1
- package/dist/features/composites/baskets.js.map +1 -1
- package/dist/features/composites/bibliography-command.d.ts +1 -1
- package/dist/features/composites/bibliography-form.js +1 -1
- package/dist/features/composites/bibliography-form.js.map +1 -1
- package/dist/features/composites/bibliography.js.map +1 -1
- package/dist/features/composites/block-types-json.d.ts +38 -0
- package/dist/features/composites/block-types-json.js +122 -0
- package/dist/features/composites/block-types-json.js.map +1 -0
- package/dist/features/composites/block-types.d.ts +119 -0
- package/dist/features/composites/block-types.js +343 -0
- package/dist/features/composites/block-types.js.map +1 -0
- package/dist/features/composites/capabilities.js +109 -0
- package/dist/features/composites/capabilities.js.map +1 -0
- package/dist/features/composites/components/BibliographyEditor.js +5 -5
- package/dist/features/composites/components/BibliographyEditor.js.map +1 -1
- package/dist/features/composites/components/CompositeBasketMenu.js +2 -2
- package/dist/features/composites/components/CompositeBasketMenu.js.map +1 -1
- package/dist/features/composites/components/CompositeChrome.js +18 -8
- package/dist/features/composites/components/CompositeChrome.js.map +1 -1
- package/dist/features/composites/components/CompositeChrome.vue.d.ts +1 -1
- package/dist/features/composites/components/CompositeDetails.js +11 -10
- package/dist/features/composites/components/CompositeDetails.js.map +1 -1
- package/dist/features/composites/components/CompositeDetails.vue.d.ts +1 -1
- package/dist/features/composites/components/CompositeFieldEditor.js +7 -7
- package/dist/features/composites/components/CompositeFieldEditor.js.map +1 -1
- package/dist/features/composites/components/CompositeFieldEditor.vue.d.ts +5 -5
- package/dist/features/composites/components/CompositeInspector.js +136 -113
- package/dist/features/composites/components/CompositeInspector.js.map +1 -1
- package/dist/features/composites/components/CompositeInspector.vue.d.ts +3 -3
- package/dist/features/composites/components/CompositeStatusMenu.js +2 -2
- package/dist/features/composites/components/CompositeStatusMenu.js.map +1 -1
- package/dist/features/composites/components/CompositeSummaryEditor.js +1 -1
- package/dist/features/composites/components/CompositeSummaryEditor.js.map +1 -1
- package/dist/features/composites/components/CompositeSummaryEditor.vue.d.ts +1 -1
- package/dist/features/composites/components/CompositeTable.js +2 -2
- package/dist/features/composites/components/CompositeTable.js.map +1 -1
- package/dist/features/composites/components/CompositeTagsEditor.js +1 -1
- package/dist/features/composites/components/CompositeTagsEditor.js.map +1 -1
- package/dist/features/composites/components/CompositeTagsEditor.vue.d.ts +1 -1
- package/dist/features/composites/components/CompositeView.js +19 -17
- package/dist/features/composites/components/CompositeView.js.map +1 -1
- package/dist/features/composites/components/DerivationBadge.js +15 -6
- package/dist/features/composites/components/DerivationBadge.js.map +1 -1
- package/dist/features/composites/components/FocusChip.js +1 -1
- package/dist/features/composites/components/FocusChip.js.map +1 -1
- package/dist/features/composites/components/FocusChip.vue.d.ts +1 -1
- package/dist/features/composites/components/ReferenceFieldSelect.js +3 -3
- package/dist/features/composites/components/ReferenceFieldSelect.js.map +1 -1
- package/dist/features/composites/components/ReferenceView.js +1 -1
- package/dist/features/composites/components/ReferenceView.js.map +1 -1
- package/dist/features/composites/components/SettingsEditingTab.js +18 -18
- package/dist/features/composites/components/SettingsEditingTab.js.map +1 -1
- package/dist/features/composites/components/SettingsEditingTab.vue.d.ts +3 -3
- package/dist/features/composites/convert.d.ts +4 -4
- package/dist/features/composites/convert.js +27 -28
- package/dist/features/composites/convert.js.map +1 -1
- package/dist/features/composites/derived-chrome.js +34 -28
- package/dist/features/composites/derived-chrome.js.map +1 -1
- package/dist/features/composites/editing-settings-keys.js +6 -6
- package/dist/features/composites/editing-settings-keys.js.map +1 -1
- package/dist/features/composites/feature.d.ts +10 -10
- package/dist/features/composites/feature.js +58 -46
- package/dist/features/composites/feature.js.map +1 -1
- package/dist/features/composites/fences.d.ts +3 -3
- package/dist/features/composites/fences.js +18 -13
- package/dist/features/composites/fences.js.map +1 -1
- package/dist/features/composites/focus.d.ts +10 -10
- package/dist/features/composites/focus.js +11 -11
- package/dist/features/composites/focus.js.map +1 -1
- package/dist/features/composites/heading-composites.d.ts +5 -5
- package/dist/features/composites/heading-composites.js +13 -16
- package/dist/features/composites/heading-composites.js.map +1 -1
- package/dist/features/composites/index.d.ts +20 -18
- package/dist/features/composites/index.js +9 -7
- package/dist/features/composites/inspector-model.d.ts +45 -22
- package/dist/features/composites/inspector-model.js +53 -14
- package/dist/features/composites/inspector-model.js.map +1 -1
- package/dist/features/composites/legacy.d.ts +5 -4
- package/dist/features/composites/legacy.js +16 -23
- package/dist/features/composites/legacy.js.map +1 -1
- package/dist/features/composites/markdown-export.js +3 -3
- package/dist/features/composites/markdown-export.js.map +1 -1
- package/dist/features/composites/merge.d.ts +8 -8
- package/dist/features/composites/merge.js +23 -22
- package/dist/features/composites/merge.js.map +1 -1
- package/dist/features/composites/meta-display.js +5 -5
- package/dist/features/composites/meta-display.js.map +1 -1
- package/dist/features/composites/meta-keys.d.ts +5 -5
- package/dist/features/composites/meta-keys.js +8 -8
- package/dist/features/composites/meta-keys.js.map +1 -1
- package/dist/features/composites/node-views.d.ts +3 -3
- package/dist/features/composites/node-views.js +2 -2
- package/dist/features/composites/node-views.js.map +1 -1
- package/dist/features/composites/nodes.d.ts +13 -13
- package/dist/features/composites/nodes.js +100 -77
- package/dist/features/composites/nodes.js.map +1 -1
- package/dist/features/composites/outline.d.ts +15 -12
- package/dist/features/composites/outline.js +24 -21
- package/dist/features/composites/outline.js.map +1 -1
- package/dist/features/composites/properties.d.ts +51 -0
- package/dist/features/composites/properties.js +89 -0
- package/dist/features/composites/properties.js.map +1 -0
- package/dist/features/composites/react/BibliographyEditor.js +5 -5
- package/dist/features/composites/react/BibliographyEditor.js.map +1 -1
- package/dist/features/composites/react/CompositeBasketMenu.js +2 -2
- package/dist/features/composites/react/CompositeBasketMenu.js.map +1 -1
- package/dist/features/composites/react/CompositeChrome.d.ts +1 -1
- package/dist/features/composites/react/CompositeChrome.js +15 -6
- package/dist/features/composites/react/CompositeChrome.js.map +1 -1
- package/dist/features/composites/react/CompositeDetails.d.ts +1 -1
- package/dist/features/composites/react/CompositeDetails.js +11 -10
- package/dist/features/composites/react/CompositeDetails.js.map +1 -1
- package/dist/features/composites/react/CompositeFieldEditor.d.ts +5 -5
- package/dist/features/composites/react/CompositeFieldEditor.js +6 -6
- package/dist/features/composites/react/CompositeFieldEditor.js.map +1 -1
- package/dist/features/composites/react/CompositeInspector.d.ts +3 -3
- package/dist/features/composites/react/CompositeInspector.js +142 -128
- package/dist/features/composites/react/CompositeInspector.js.map +1 -1
- package/dist/features/composites/react/CompositeStatusMenu.js +2 -2
- package/dist/features/composites/react/CompositeStatusMenu.js.map +1 -1
- package/dist/features/composites/react/CompositeSummaryEditor.d.ts +1 -1
- package/dist/features/composites/react/CompositeSummaryEditor.js +1 -1
- package/dist/features/composites/react/CompositeSummaryEditor.js.map +1 -1
- package/dist/features/composites/react/CompositeTable.d.ts +1 -1
- package/dist/features/composites/react/CompositeTable.js +3 -3
- package/dist/features/composites/react/CompositeTable.js.map +1 -1
- package/dist/features/composites/react/CompositeTagsEditor.d.ts +1 -1
- package/dist/features/composites/react/CompositeTagsEditor.js +1 -1
- package/dist/features/composites/react/CompositeTagsEditor.js.map +1 -1
- package/dist/features/composites/react/CompositeView.js +17 -15
- package/dist/features/composites/react/CompositeView.js.map +1 -1
- package/dist/features/composites/react/DerivationBadge.js +13 -4
- package/dist/features/composites/react/DerivationBadge.js.map +1 -1
- package/dist/features/composites/react/FocusChip.d.ts +1 -1
- package/dist/features/composites/react/FocusChip.js +1 -1
- package/dist/features/composites/react/FocusChip.js.map +1 -1
- package/dist/features/composites/react/ReferenceFieldSelect.js +3 -3
- package/dist/features/composites/react/ReferenceFieldSelect.js.map +1 -1
- package/dist/features/composites/react/ReferenceView.d.ts +1 -1
- package/dist/features/composites/react/ReferenceView.js +1 -1
- package/dist/features/composites/react/ReferenceView.js.map +1 -1
- package/dist/features/composites/react/SettingsEditingTab.d.ts +4 -4
- package/dist/features/composites/react/SettingsEditingTab.js +20 -20
- package/dist/features/composites/react/SettingsEditingTab.js.map +1 -1
- package/dist/features/composites/react.js +1 -1
- package/dist/features/composites/react.js.map +1 -1
- package/dist/features/composites/reference-ai.js +1 -1
- package/dist/features/composites/reference-ai.js.map +1 -1
- package/dist/features/composites/reference-label.d.ts +3 -3
- package/dist/features/composites/reference-label.js +6 -6
- package/dist/features/composites/reference-label.js.map +1 -1
- package/dist/features/composites/reference-suggestion.d.ts +1 -1
- package/dist/features/composites/reference-suggestion.js +3 -3
- package/dist/features/composites/reference-suggestion.js.map +1 -1
- package/dist/features/composites/reference-text.d.ts +2 -2
- package/dist/features/composites/reference-text.js +4 -4
- package/dist/features/composites/reference-text.js.map +1 -1
- package/dist/features/composites/reference.d.ts +3 -3
- package/dist/features/composites/reference.js +1 -1
- package/dist/features/composites/reference.js.map +1 -1
- package/dist/features/composites/reveal-source.d.ts +3 -3
- package/dist/features/composites/reveal-source.js +6 -6
- package/dist/features/composites/reveal-source.js.map +1 -1
- package/dist/features/composites/rows-model.d.ts +2 -2
- package/dist/features/composites/rows-model.js +4 -3
- package/dist/features/composites/rows-model.js.map +1 -1
- package/dist/features/composites/rows.d.ts +16 -28
- package/dist/features/composites/rows.js +20 -54
- package/dist/features/composites/rows.js.map +1 -1
- package/dist/features/composites/schema.d.ts +12 -11
- package/dist/features/composites/schema.js +10 -9
- package/dist/features/composites/schema.js.map +1 -1
- package/dist/features/composites/source.d.ts +20 -0
- package/dist/features/composites/source.js +40 -0
- package/dist/features/composites/source.js.map +1 -0
- package/dist/features/composites/split.d.ts +11 -11
- package/dist/features/composites/split.js +20 -20
- package/dist/features/composites/split.js.map +1 -1
- package/dist/features/composites/structure-mode.js +3 -3
- package/dist/features/composites/structure-mode.js.map +1 -1
- package/dist/features/composites/table-model.js +2 -2
- package/dist/features/composites/table-model.js.map +1 -1
- package/dist/features/composites/use-composite-inspector.js +3 -1
- package/dist/features/composites/use-composite-inspector.js.map +1 -1
- package/dist/features/composites/use-composite-rows.d.ts +2 -2
- package/dist/features/composites/use-composite-rows.js.map +1 -1
- package/dist/features/composites/vue.js +1 -1
- package/dist/features/composites/vue.js.map +1 -1
- package/dist/features/image-studio/components/ImageStudioDialog.js +1 -1
- package/dist/features/image-studio/components/ImageStudioDialog.js.map +1 -1
- package/dist/features/image-studio/components/ImageStudioDialog.vue.d.ts +1 -1
- package/dist/features/image-studio/components/ImageStudioView.js.map +1 -1
- package/dist/features/image-studio/feature.d.ts +1 -1
- package/dist/features/image-studio/feature.js +1 -1
- package/dist/features/image-studio/feature.js.map +1 -1
- package/dist/features/image-studio/node-core.d.ts +3 -3
- package/dist/features/image-studio/node-core.js +1 -1
- package/dist/features/image-studio/node-core.js.map +1 -1
- package/dist/features/image-studio/node-store.d.ts +1 -1
- package/dist/features/image-studio/node-store.js +1 -1
- package/dist/features/image-studio/node-store.js.map +1 -1
- package/dist/features/image-studio/react/ImageStudioDialog.d.ts +1 -1
- package/dist/features/image-studio/react/ImageStudioDialog.js +1 -1
- package/dist/features/image-studio/react/ImageStudioDialog.js.map +1 -1
- package/dist/features/image-studio/react/ImageStudioView.js +1 -1
- package/dist/features/image-studio/react/ImageStudioView.js.map +1 -1
- package/dist/features/image-studio/react/store.d.ts +3 -3
- package/dist/features/image-studio/react/store.js.map +1 -1
- package/dist/features/image-studio/react.d.ts +1 -1
- package/dist/features/image-studio/react.js +1 -1
- package/dist/features/image-studio/react.js.map +1 -1
- package/dist/features/image-studio/schema.d.ts +1 -1
- package/dist/features/image-studio/schema.js +1 -1
- package/dist/features/image-studio/schema.js.map +1 -1
- package/dist/features/image-studio/state.d.ts +3 -3
- package/dist/features/image-studio/state.js +2 -2
- package/dist/features/image-studio/state.js.map +1 -1
- package/dist/features/image-studio/store.d.ts +3 -3
- package/dist/features/image-studio/vue.d.ts +1 -1
- package/dist/features/image-studio/vue.js +1 -1
- package/dist/features/image-studio/vue.js.map +1 -1
- package/dist/features/media/index.js +1 -1
- package/dist/features/media/react/AudioRecorderModal.js +1 -1
- package/dist/features/media/react.js +1 -1
- package/dist/features/mentions/tag.js +2 -1
- package/dist/features/mentions/tag.js.map +1 -1
- package/dist/features/themes/components/SettingsAppearanceTab.js +1 -1
- package/dist/features/themes/components/SettingsAppearanceTab.js.map +1 -1
- package/dist/features/themes/feature.d.ts +1 -1
- package/dist/features/themes/feature.js.map +1 -1
- package/dist/features/themes/react/SettingsAppearanceTab.d.ts +1 -1
- package/dist/features/themes/react/SettingsAppearanceTab.js +1 -1
- package/dist/features/themes/react/SettingsAppearanceTab.js.map +1 -1
- package/dist/features/themes/theme-runtime.js +1 -1
- package/dist/features/themes/theme-runtime.js.map +1 -1
- package/dist/features/transcript/TranscriptSegmentView.js +1 -1
- package/dist/features/transcript/TranscriptSegmentView.js.map +1 -1
- package/dist/features/transcript/react/TranscriptSegmentView.js +1 -1
- package/dist/features/transcript/react/TranscriptSegmentView.js.map +1 -1
- package/dist/features/transcript/segment-node.js.map +1 -1
- package/dist/features/transfer/feature.js +1 -1
- package/dist/features/transfer/feature.js.map +1 -1
- package/dist/features/transfer/transforms.d.ts +4 -4
- package/dist/features/transfer/transforms.js +12 -12
- package/dist/features/transfer/transforms.js.map +1 -1
- package/dist/i18n/de/ai.js +4 -4
- package/dist/i18n/de/ai.js.map +1 -1
- package/dist/i18n/de/authors.js +1 -1
- package/dist/i18n/de/authors.js.map +1 -1
- package/dist/i18n/de/comments.js +1 -1
- package/dist/i18n/de/comments.js.map +1 -1
- package/dist/i18n/de/composites.js +62 -59
- package/dist/i18n/de/composites.js.map +1 -1
- package/dist/i18n/de/image-studio.js +2 -2
- package/dist/i18n/de/image-studio.js.map +1 -1
- package/dist/i18n/de/integrations.js +20 -20
- package/dist/i18n/de/integrations.js.map +1 -1
- package/dist/i18n/de/markdown.js +1 -1
- package/dist/i18n/de/markdown.js.map +1 -1
- package/dist/i18n/de/palette.js +1 -1
- package/dist/i18n/de/palette.js.map +1 -1
- package/dist/i18n/de/themes.js +3 -3
- package/dist/i18n/de/themes.js.map +1 -1
- package/dist/i18n/de/transfer.js +2 -2
- package/dist/i18n/de/transfer.js.map +1 -1
- package/dist/i18n/de/tree.js +6 -6
- package/dist/i18n/de/tree.js.map +1 -1
- package/dist/i18n/de.d.ts +101 -98
- package/dist/i18n/en/ai.js +2 -2
- package/dist/i18n/en/ai.js.map +1 -1
- package/dist/i18n/en/composites.js +64 -61
- package/dist/i18n/en/composites.js.map +1 -1
- package/dist/i18n/en/integrations.js +9 -9
- package/dist/i18n/en/integrations.js.map +1 -1
- package/dist/i18n/en/markdown.js +1 -1
- package/dist/i18n/en/markdown.js.map +1 -1
- package/dist/i18n/en/palette.js +1 -1
- package/dist/i18n/en/palette.js.map +1 -1
- package/dist/i18n/en/themes.js +4 -4
- package/dist/i18n/en/themes.js.map +1 -1
- package/dist/i18n/en/tree.js +5 -5
- package/dist/i18n/en/tree.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/integrations/composite-ai/bibliography-fetch.d.ts +6 -6
- package/dist/integrations/composite-ai/bibliography-fetch.js +19 -19
- package/dist/integrations/composite-ai/bibliography-fetch.js.map +1 -1
- package/dist/integrations/composite-ai/composite-fill.d.ts +4 -4
- package/dist/integrations/composite-ai/composite-fill.js +5 -5
- package/dist/integrations/composite-ai/composite-fill.js.map +1 -1
- package/dist/integrations/composite-ai/composite-summary.d.ts +2 -2
- package/dist/integrations/composite-ai/composite-summary.js +5 -5
- package/dist/integrations/composite-ai/composite-summary.js.map +1 -1
- package/dist/integrations/composite-ai/derive.d.ts +17 -17
- package/dist/integrations/composite-ai/derive.js +27 -26
- package/dist/integrations/composite-ai/derive.js.map +1 -1
- package/dist/integrations/composite-ai/index.d.ts +14 -15
- package/dist/integrations/composite-ai/index.js +98 -77
- package/dist/integrations/composite-ai/index.js.map +1 -1
- package/dist/integrations/composite-ai/outline-sanitize.d.ts +1 -1
- package/dist/integrations/composite-ai/outline-sanitize.js +1 -1
- package/dist/integrations/composite-ai/outline-sanitize.js.map +1 -1
- package/dist/integrations/composite-ai/rendition.d.ts +9 -9
- package/dist/integrations/composite-ai/rendition.js +27 -27
- package/dist/integrations/composite-ai/rendition.js.map +1 -1
- package/dist/integrations/composite-ai/split.d.ts +8 -8
- package/dist/integrations/composite-ai/split.js +12 -12
- package/dist/integrations/composite-ai/split.js.map +1 -1
- package/dist/integrations/composite-ai/transfer-transforms.d.ts +2 -2
- package/dist/integrations/composite-ai/transfer-transforms.js +12 -12
- package/dist/integrations/composite-ai/transfer-transforms.js.map +1 -1
- package/dist/integrations/composite-media/index.d.ts +4 -3
- package/dist/integrations/composite-media/index.js +20 -14
- package/dist/integrations/composite-media/index.js.map +1 -1
- package/dist/markdown/document.js +1 -1
- package/dist/markdown/document.js.map +1 -1
- package/dist/nuxt/module.d.ts +30 -24
- package/dist/nuxt/module.js.map +1 -1
- package/dist/nuxt/runtime/server/plugins/editor-server.js +3 -2
- package/dist/nuxt/runtime/server/plugins/editor-server.js.map +1 -1
- package/dist/presets/compose.d.ts +6 -6
- package/dist/presets/compose.js +8 -5
- package/dist/presets/compose.js.map +1 -1
- package/dist/react/AdvancedEditor.d.ts +2 -2
- package/dist/react/AdvancedEditor.js +1 -1
- package/dist/react/AdvancedEditor.js.map +1 -1
- package/dist/react/compose.d.ts +1 -1
- package/dist/react/compose.js +2 -2
- package/dist/react/compose.js.map +1 -1
- package/dist/react/composed-surface.d.ts +5 -5
- package/dist/react/composed-surface.js +2 -2
- package/dist/react/composed-surface.js.map +1 -1
- package/dist/server/ai.d.ts +7 -7
- package/dist/server/ai.js +1 -1
- package/dist/server/ai.js.map +1 -1
- package/dist/server/auth.d.ts +1 -1
- package/dist/server/collab-state.d.ts +1 -1
- package/dist/server/collab-state.js.map +1 -1
- package/dist/server/collab.d.ts +4 -4
- package/dist/server/collab.js +22 -17
- package/dist/server/collab.js.map +1 -1
- package/dist/server/handlers/ai.d.ts +7 -4
- package/dist/server/handlers/ai.js +13 -17
- package/dist/server/handlers/ai.js.map +1 -1
- package/dist/server/handlers/context.d.ts +4 -0
- package/dist/server/handlers/context.js.map +1 -1
- package/dist/server/handlers/editor.d.ts +33 -32
- package/dist/server/handlers/editor.js +13 -8
- package/dist/server/handlers/editor.js.map +1 -1
- package/dist/server/handlers/images.d.ts +1 -1
- package/dist/server/handlers/images.js +1 -1
- package/dist/server/handlers/images.js.map +1 -1
- package/dist/server/host.d.ts +4 -0
- package/dist/server/host.js +10 -2
- package/dist/server/host.js.map +1 -1
- package/dist/server/index.d.ts +3 -3
- package/dist/server/ports.d.ts +8 -8
- package/dist/server/ports.js.map +1 -1
- package/dist/settings/index.d.ts +20 -19
- package/dist/settings/index.js +25 -24
- package/dist/settings/index.js.map +1 -1
- package/dist/settings/migrate.d.ts +18 -0
- package/dist/settings/migrate.js +46 -0
- package/dist/settings/migrate.js.map +1 -0
- package/dist/settings/values.d.ts +12 -12
- package/dist/settings/values.js +11 -11
- package/dist/settings/values.js.map +1 -1
- package/dist/styles/composites.css +10 -10
- package/dist/tree/DocumentTree.js +12 -5
- package/dist/tree/DocumentTree.js.map +1 -1
- package/dist/tree/drop-rules.js +5 -5
- package/dist/tree/drop-rules.js.map +1 -1
- package/dist/tree/react/DocumentTree.js +14 -5
- package/dist/tree/react/DocumentTree.js.map +1 -1
- package/dist/tree/tree-host.js +6 -6
- package/dist/tree/tree-host.js.map +1 -1
- package/dist/tree/tree-items.js +34 -28
- package/dist/tree/tree-items.js.map +1 -1
- package/dist/tree/tree-model.js +16 -16
- package/dist/tree/tree-model.js.map +1 -1
- package/dist/tree/tree-rows.js +2 -2
- package/dist/tree/tree-rows.js.map +1 -1
- package/dist/tree/tree-view-model.d.ts +2 -2
- package/dist/tree/tree-view-model.js.map +1 -1
- package/dist/vue/AdvancedEditor.js +2 -2
- package/dist/vue/AdvancedEditor.js.map +1 -1
- package/dist/vue/AdvancedEditor.vue.d.ts +6 -6
- package/dist/vue/compose.d.ts +1 -1
- package/dist/vue/compose.js +2 -2
- package/dist/vue/compose.js.map +1 -1
- package/package.json +1 -1
- package/dist/features/composites/derivation.d.ts +0 -62
- package/dist/features/composites/derivation.js +0 -102
- package/dist/features/composites/derivation.js.map +0 -1
- package/dist/features/composites/kinds.d.ts +0 -89
- package/dist/features/composites/kinds.js +0 -285
- package/dist/features/composites/kinds.js.map +0 -1
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import { ABILITY } from "../../core/schema/abilities.js";
|
|
2
2
|
import { abilitiesAtSelection } from "../../core/abilities.js";
|
|
3
|
+
import { blockIdOf, findBlockById } from "../../core/schema/block-ids.js";
|
|
4
|
+
import { capabilityDataOf } from "../../core/capabilities.js";
|
|
5
|
+
import { TYPED_BLOCK } from "../../core/schema/persisted-names.js";
|
|
3
6
|
import { settingsTabsOf } from "../../core/define-editor.js";
|
|
4
7
|
import { editorEntryOf } from "../../core/editor-ui.js";
|
|
5
|
-
import {
|
|
8
|
+
import { derivationOf } from "../../core/derivation.js";
|
|
6
9
|
import { downloadText } from "../../core/download.js";
|
|
7
|
-
import {
|
|
10
|
+
import { aiBlockTypesOf, blockTypeOf, defaultBlockTypes } from "./block-types.js";
|
|
8
11
|
import { blocksFromMarkdown } from "./fences.js";
|
|
9
12
|
import { defaultBaskets } from "./baskets.js";
|
|
10
|
-
import { bodyMarkdown, derivationOf } from "./derivation.js";
|
|
11
13
|
import { structureBlocks } from "./heading-composites.js";
|
|
12
|
-
import { CompositeDescriptionNode, CompositeTitleNode,
|
|
13
|
-
import {
|
|
14
|
+
import { CompositeDescriptionNode, CompositeTitleNode, blockTypesOf, compositeAround } from "./nodes.js";
|
|
15
|
+
import { bibtexOf, cslOf } from "./bibliography.js";
|
|
14
16
|
import { compositeConversions } from "./convert.js";
|
|
17
|
+
import { bodyMarkdown } from "./source.js";
|
|
18
|
+
import { compositeBlockCapabilities } from "./capabilities.js";
|
|
15
19
|
import { migrateLegacyContent } from "./legacy.js";
|
|
16
20
|
import { compositeIdsOf, normalizeReferences } from "./reference-text.js";
|
|
17
21
|
import { compositeSchemaExtensions } from "./schema.js";
|
|
@@ -30,29 +34,32 @@ import { STRUCTURE_MODE_KEYS } from "./structure-mode.js";
|
|
|
30
34
|
/** Heading level the structure stage starts at when it turns composites into headings (below the document title). */
|
|
31
35
|
const STRUCTURE_STAGE_LEVEL = 2;
|
|
32
36
|
/**
|
|
33
|
-
* Composites (
|
|
37
|
+
* Composites (Typed blocks): the node family with its node views, the toolbar group (insert, „In Block umwandeln“,
|
|
34
38
|
* „Gliederung umwandeln“), `/` commands, the conversion providers (wrap into / switch kind of / unwrap composites),
|
|
35
39
|
* Markdown `:::` fences, legacy `section` migration, the preferred-structure setting and its `editing` settings tab,
|
|
36
40
|
* the chips on each title line (status, tags) and the details popover on the kind icon (the binding's `chrome` overlay), focus mode on one
|
|
37
|
-
*
|
|
38
|
-
* the AI view of
|
|
41
|
+
* Typed block (`CompositeFocus`, the „Fokussieren“ block action and the binding's `focusChip` overlay), and
|
|
42
|
+
* the AI view of Block types and structure, and the Block types' accepted children (`AcceptedChildren`: an edit that nests a Typed block
|
|
39
43
|
* into one that does not accept its kind is refused with a notice). Contributes the `parseMarkdown`,
|
|
40
44
|
* `structure` and `migrateContent` stages. Imports no AI, media or transcript code.
|
|
41
45
|
*/
|
|
42
46
|
function compositeFeatureCore(ui, options = {}) {
|
|
43
|
-
const
|
|
47
|
+
const hostBlockTypes = options.blockTypes;
|
|
48
|
+
const kindsOf = (ctx) => hostBlockTypes ?? defaultBlockTypes(ctx.t);
|
|
44
49
|
const basketsOf = (ctx) => options.baskets ?? defaultBaskets(ctx.t);
|
|
45
50
|
const { Composite, CompositeTags, Reference } = compositeNodes(ui.nodeViews);
|
|
46
51
|
return {
|
|
47
52
|
id: "composites",
|
|
48
53
|
dimension: "content",
|
|
49
54
|
schemaExtensions: () => compositeSchemaExtensions({
|
|
50
|
-
...
|
|
55
|
+
...hostBlockTypes && { blockTypes: hostBlockTypes },
|
|
51
56
|
...options.baskets && { baskets: options.baskets }
|
|
52
57
|
}),
|
|
58
|
+
blockCapabilities: compositeBlockCapabilities(),
|
|
59
|
+
blockTypes: blockTypesOf,
|
|
53
60
|
extensions: (ctx) => [
|
|
54
61
|
Composite.configure({
|
|
55
|
-
|
|
62
|
+
blockTypes: kindsOf(ctx),
|
|
56
63
|
baskets: basketsOf(ctx)
|
|
57
64
|
}),
|
|
58
65
|
CompositeTitleNode,
|
|
@@ -67,7 +74,7 @@ function compositeFeatureCore(ui, options = {}) {
|
|
|
67
74
|
CompositeFocus,
|
|
68
75
|
CompositeMerge,
|
|
69
76
|
CompositeSplit.configure({
|
|
70
|
-
|
|
77
|
+
defaultBlockType: () => ctx.settings.get().blocks.defaultBlockType,
|
|
71
78
|
targetChars: () => ctx.settings.get().blocks.splitTargetChars
|
|
72
79
|
}),
|
|
73
80
|
Reference.configure({ suggestion: referenceSuggestion(ctx.t) })
|
|
@@ -78,28 +85,32 @@ function compositeFeatureCore(ui, options = {}) {
|
|
|
78
85
|
blockActions: (ctx) => [
|
|
79
86
|
{
|
|
80
87
|
id: "document-export",
|
|
88
|
+
target: "typedBlock",
|
|
81
89
|
label: ctx.t("composites.blockAction.export"),
|
|
82
90
|
icon: "i-lucide-download",
|
|
83
91
|
ability: ABILITY.compositeExport,
|
|
84
92
|
order: 400,
|
|
85
|
-
|
|
93
|
+
requires: ["export"],
|
|
86
94
|
run: ({ editor, node }) => downloadText(markdownFileName(node), documentCompositeMarkdown(editor, node))
|
|
87
95
|
},
|
|
88
96
|
{
|
|
89
97
|
id: "bibliography-export",
|
|
98
|
+
target: "typedBlock",
|
|
90
99
|
label: ctx.t("composites.blockAction.bibtex"),
|
|
91
100
|
icon: "i-lucide-book-marked",
|
|
92
101
|
ability: ABILITY.compositeExport,
|
|
93
102
|
order: 410,
|
|
94
|
-
|
|
103
|
+
requires: ["bibliography"],
|
|
104
|
+
isVisible: ({ editor, node }) => capabilityDataOf(editor, node, "bibliography") !== null,
|
|
95
105
|
run: ({ node }) => downloadText(`${markdownFileName(node).replace(/\.md$/, "")}.bib`, bibtexOf(cslOf(node)), "text/x-bibtex;charset=utf-8")
|
|
96
106
|
},
|
|
97
107
|
{
|
|
98
108
|
id: "composite-focus",
|
|
99
109
|
label: ctx.t("composites.focus.action"),
|
|
110
|
+
target: "typedBlock",
|
|
100
111
|
icon: "i-lucide-focus",
|
|
101
112
|
order: 420,
|
|
102
|
-
|
|
113
|
+
requires: ["container"],
|
|
103
114
|
run: ({ editor, node }) => {
|
|
104
115
|
const id = blockIdOf(node);
|
|
105
116
|
if (id) editor.commands.focusComposite(id);
|
|
@@ -108,9 +119,11 @@ function compositeFeatureCore(ui, options = {}) {
|
|
|
108
119
|
...splitBlockActions(ctx),
|
|
109
120
|
{
|
|
110
121
|
id: "composite-merge-next",
|
|
122
|
+
target: "typedBlock",
|
|
111
123
|
label: ctx.t("composites.merge.next"),
|
|
112
124
|
icon: "i-lucide-merge",
|
|
113
125
|
ability: ABILITY.compositeMeta,
|
|
126
|
+
requires: ["container", "title"],
|
|
114
127
|
order: 470,
|
|
115
128
|
isVisible: ({ editor, pos }) => editor.can().mergeCompositeWithNext(pos),
|
|
116
129
|
run: ({ editor, pos }) => void editor.chain().focus().mergeCompositeWithNext(pos).run()
|
|
@@ -122,32 +135,27 @@ function compositeFeatureCore(ui, options = {}) {
|
|
|
122
135
|
label: ctx.t("composites.tab"),
|
|
123
136
|
icon: "i-lucide-pencil",
|
|
124
137
|
component: ui.settingsTab,
|
|
125
|
-
props: {
|
|
138
|
+
props: { blockTypes: kindsOf(ctx) }
|
|
126
139
|
}],
|
|
127
140
|
blocks: {
|
|
128
|
-
parseMarkdown: (editor, markdown) => blocksFromMarkdown((md) => editor.markdown.parse(md), markdown,
|
|
141
|
+
parseMarkdown: (editor, markdown) => blocksFromMarkdown((md) => editor.markdown.parse(md), markdown, blockTypesOf(editor)),
|
|
129
142
|
structure: (editor, blocks) => {
|
|
130
143
|
const { schema } = editor;
|
|
131
|
-
return structureBlocks(schema, blocks.map((block) => schema.nodeFromJSON(block)), structureOf(editor), STRUCTURE_STAGE_LEVEL,
|
|
144
|
+
return structureBlocks(schema, blocks.map((block) => schema.nodeFromJSON(block)), structureOf(editor), STRUCTURE_STAGE_LEVEL, blockTypesOf(editor)).map((node) => node.toJSON());
|
|
132
145
|
},
|
|
133
146
|
migrateContent: migrateLegacyContent,
|
|
134
147
|
normalize: (editor, blocks) => normalizeReferences(blocks, compositeIdsOf(editor.state.doc))
|
|
135
148
|
},
|
|
136
|
-
conversions: compositeConversions(
|
|
149
|
+
conversions: compositeConversions(hostBlockTypes),
|
|
137
150
|
aiContext: (editor) => ({
|
|
138
|
-
|
|
139
|
-
id,
|
|
140
|
-
label,
|
|
141
|
-
fields,
|
|
142
|
-
...ai?.purpose && { purpose: ai.purpose }
|
|
143
|
-
})),
|
|
151
|
+
blockTypes: aiBlockTypesOf(blockTypesOf(editor)),
|
|
144
152
|
structure: structureOf(editor),
|
|
145
153
|
blocks: [REFERENCE_AI_BLOCK]
|
|
146
154
|
}),
|
|
147
155
|
aiBlockData: ({ editor, node }) => {
|
|
148
156
|
const from = derivationOf(node)?.from;
|
|
149
157
|
const source = from && "block" in from ? findBlockById(editor.state.doc, from.block)?.node : void 0;
|
|
150
|
-
return source?.type.name === "
|
|
158
|
+
return source?.type.name === "typedBlock" ? [{
|
|
151
159
|
label: `Quelle: ${source.child(0).textContent.trim()}`,
|
|
152
160
|
text: bodyMarkdown(editor, source)
|
|
153
161
|
}] : [];
|
|
@@ -155,8 +163,8 @@ function compositeFeatureCore(ui, options = {}) {
|
|
|
155
163
|
};
|
|
156
164
|
}
|
|
157
165
|
/**
|
|
158
|
-
* The four split actions of a
|
|
159
|
-
* caret while the caret is past the first body block) and by length (as
|
|
166
|
+
* The four split actions of a Typed block: at the caret (as sibling or nested Typed blocks; offered on the Typed block around the
|
|
167
|
+
* caret while the caret is past the first body block) and by length (as nested Typed blocks or siblings; offered while the
|
|
160
168
|
* body falls into two parts or more). Each is hidden when the command refuses, so a kind that accepts no child kind
|
|
161
169
|
* never shows the `children` variants.
|
|
162
170
|
*/
|
|
@@ -165,7 +173,9 @@ function splitBlockActions({ t }) {
|
|
|
165
173
|
id,
|
|
166
174
|
label: t(labelKey),
|
|
167
175
|
icon,
|
|
176
|
+
target: "typedBlock",
|
|
168
177
|
ability: ABILITY.compositeMeta,
|
|
178
|
+
requires: ["container", "title"],
|
|
169
179
|
order,
|
|
170
180
|
isVisible: ({ editor, pos }) => {
|
|
171
181
|
const { $head } = editor.state.selection;
|
|
@@ -178,7 +188,9 @@ function splitBlockActions({ t }) {
|
|
|
178
188
|
id,
|
|
179
189
|
label: t(labelKey),
|
|
180
190
|
icon,
|
|
191
|
+
target: "typedBlock",
|
|
181
192
|
ability: ABILITY.compositeMeta,
|
|
193
|
+
requires: ["container", "title"],
|
|
182
194
|
order,
|
|
183
195
|
isVisible: ({ editor, pos }) => editor.can().splitCompositeByLength({
|
|
184
196
|
mode,
|
|
@@ -202,7 +214,7 @@ const COMPOSITE_TOOLBAR_GROUPS = [{
|
|
|
202
214
|
labelKey: "palette.group.composites"
|
|
203
215
|
}];
|
|
204
216
|
/**
|
|
205
|
-
* Converting headings to
|
|
217
|
+
* Converting headings to Typed blocks and back: the checks and actions the toolbar's „Gliederung umwandeln“ menu and the
|
|
206
218
|
* `/gliedern*` and `/aufloesen*` commands share, so both placements gate and act identically. They read the scope and
|
|
207
219
|
* default kind from the settings at call time.
|
|
208
220
|
*/
|
|
@@ -210,7 +222,7 @@ function structureActions({ settings }) {
|
|
|
210
222
|
const groupOptions = (recursive) => ({
|
|
211
223
|
recursive,
|
|
212
224
|
scope: settings.get().editing.headingConversionScope,
|
|
213
|
-
kind: settings.get().blocks.
|
|
225
|
+
kind: settings.get().blocks.defaultBlockType
|
|
214
226
|
});
|
|
215
227
|
const flattenOptions = (recursive) => ({
|
|
216
228
|
recursive,
|
|
@@ -226,22 +238,22 @@ function structureActions({ settings }) {
|
|
|
226
238
|
/**
|
|
227
239
|
* The commands of the composites feature, each declared once. Toolbar group beside the inserts: the default kind's
|
|
228
240
|
* insert button (it follows the setting, so label/icon/shortcut/`creates` are getters read at render time), „In
|
|
229
|
-
*
|
|
241
|
+
* Block umwandeln“ (one entry per kind for the caret's block) and „Gliederung umwandeln“ (headings <-> composites in
|
|
230
242
|
* both directions, the preferred structure's direction first). `/` menu: one command per kind (`creates` that kind, so
|
|
231
|
-
* the insert guard hides
|
|
243
|
+
* the insert guard hides Block types the surrounding Typed block does not accept) and the four heading conversions.
|
|
232
244
|
*/
|
|
233
245
|
function compositeCommands(ctx, kinds) {
|
|
234
246
|
const { settings, t } = ctx;
|
|
235
|
-
const
|
|
247
|
+
const defaultBlockType = () => blockTypeOf(kinds, settings.get().blocks.defaultBlockType);
|
|
236
248
|
const { canGroup, canFlatten, group, flatten } = structureActions(ctx);
|
|
237
249
|
function kindItems(editor) {
|
|
238
250
|
return [{
|
|
239
251
|
type: "label",
|
|
240
252
|
label: t("composites.menu.kindHeading")
|
|
241
|
-
}, ...
|
|
253
|
+
}, ...blockTypesOf(editor).map((kind) => {
|
|
242
254
|
const target = {
|
|
243
|
-
type:
|
|
244
|
-
|
|
255
|
+
type: TYPED_BLOCK,
|
|
256
|
+
blockType: kind.id
|
|
245
257
|
};
|
|
246
258
|
return {
|
|
247
259
|
label: kind.label,
|
|
@@ -308,7 +320,7 @@ function compositeCommands(ctx, kinds) {
|
|
|
308
320
|
type: "label",
|
|
309
321
|
label: t("composites.menu.preferred", { mode: t(STRUCTURE_MODE_KEYS[structure].labelKey) })
|
|
310
322
|
},
|
|
311
|
-
...structure === "
|
|
323
|
+
...structure === "structured" ? [
|
|
312
324
|
...toComposites,
|
|
313
325
|
sep,
|
|
314
326
|
...toHeadings
|
|
@@ -324,8 +336,8 @@ function compositeCommands(ctx, kinds) {
|
|
|
324
336
|
id: `composite.${kind}`,
|
|
325
337
|
slash: { id: slashId },
|
|
326
338
|
creates: {
|
|
327
|
-
type:
|
|
328
|
-
attrs: { kind }
|
|
339
|
+
type: TYPED_BLOCK,
|
|
340
|
+
attrs: { blockType: kind }
|
|
329
341
|
},
|
|
330
342
|
icon,
|
|
331
343
|
label,
|
|
@@ -342,13 +354,13 @@ function compositeCommands(ctx, kinds) {
|
|
|
342
354
|
order: 10
|
|
343
355
|
},
|
|
344
356
|
get icon() {
|
|
345
|
-
return
|
|
357
|
+
return defaultBlockType().icon;
|
|
346
358
|
},
|
|
347
359
|
get label() {
|
|
348
|
-
return
|
|
360
|
+
return defaultBlockType().label;
|
|
349
361
|
},
|
|
350
362
|
get kbds() {
|
|
351
|
-
return
|
|
363
|
+
return defaultBlockType().id === "section" ? [
|
|
352
364
|
"meta",
|
|
353
365
|
"shift",
|
|
354
366
|
"a"
|
|
@@ -356,14 +368,14 @@ function compositeCommands(ctx, kinds) {
|
|
|
356
368
|
},
|
|
357
369
|
get creates() {
|
|
358
370
|
return {
|
|
359
|
-
type:
|
|
360
|
-
attrs: {
|
|
371
|
+
type: TYPED_BLOCK,
|
|
372
|
+
attrs: { blockType: defaultBlockType().id }
|
|
361
373
|
};
|
|
362
374
|
},
|
|
363
375
|
ability: ABILITY.composite,
|
|
364
|
-
can: (editor) => editor.can().insertComposite(
|
|
376
|
+
can: (editor) => editor.can().insertComposite(defaultBlockType().id),
|
|
365
377
|
run: (editor) => {
|
|
366
|
-
editor.chain().focus().insertComposite(
|
|
378
|
+
editor.chain().focus().insertComposite(defaultBlockType().id).run();
|
|
367
379
|
}
|
|
368
380
|
},
|
|
369
381
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature.js","names":[],"sources":["../../../src/features/composites/feature.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { BlockAction, CommandDef, EditorFeature, FeatureContext, MenuItem, ToolbarGroupDef } from '../../core'\nimport { abilitiesAtSelection, downloadText, editorEntryOf, settingsTabsOf } from '../../core'\nimport type { Translate } from '../../i18n'\nimport { ABILITY, blockIdOf, findBlockById } from '../../core/schema'\nimport { AcceptedChildren, compositeInsertGuard } from './accepted-children'\nimport { type Basket, defaultBaskets } from './baskets'\nimport { bibOf, bibtexOf, cslOf } from './bibliography'\nimport { compositeConversions } from './convert'\nimport { bodyMarkdown, derivationOf } from './derivation'\nimport { blocksFromMarkdown } from './fences'\nimport { structureBlocks } from './heading-composites'\nimport { type CompositeKind, compositeKind, defaultCompositeKinds } from './kinds'\nimport { migrateLegacyContent } from './legacy'\nimport { compositeSchemaExtensions } from './schema'\nimport { documentCompositeMarkdown, markdownFileName } from './markdown-export'\nimport { type CompositeNodeViews, compositeNodes } from './node-views'\nimport { COMPOSITE_CHROME_COUNT, CompositeDescriptionNode, CompositeTitleNode, compositeAround, compositeKindsOf } from './nodes'\nimport { CompositeFocus } from './focus'\nimport { CompositeMerge } from './merge'\nimport { REFERENCE_TRIGGER } from './reference'\nimport { REFERENCE_AI_BLOCK } from './reference-ai'\nimport { referenceSuggestion } from './reference-suggestion'\nimport { compositeIdsOf, normalizeReferences } from './reference-text'\nimport { SourceReveal } from './reveal-source'\nimport { CompositeSplit, type SplitMode } from './split'\nimport { Structure, structureOf } from './structure'\nimport { STRUCTURE_MODE_KEYS } from './structure-mode'\n\n/** What a framework binding supplies to the composites feature. */\nexport interface CompositesUi<C> {\n /** The chips on each title line and the details popover on the kind icon; mounted as an overlay. */\n chrome: C\n /** The focus chip („Fokus: <Titel> · Aufheben“) shown while a Baustein is focused; mounted as an overlay. Absent: no chip (the focus mode itself works). */\n focusChip?: C\n /** The „Bearbeiten“ settings tab; receives `{ kinds }` as props. */\n settingsTab: C\n /** The composite block view of the framework. */\n nodeViews: CompositeNodeViews\n}\n\n/** Options of `compositeFeature`. */\nexport interface CompositeFeatureOptions {\n /** The composite kinds („Bausteine“) offered in the editor, with their own labels (default: `defaultCompositeKinds(t)`, the built-in kinds in the editor's language); read once. */\n kinds?: readonly CompositeKind[]\n /** The colour baskets a Baustein can be put into (default: `defaultBaskets(t)`, red/orange/yellow/green/blue in the editor's language; colours are the `--sk-basket-<id>` CSS variables); read once. */\n baskets?: readonly Basket[]\n}\n\n/** Heading level the structure stage starts at when it turns composites into headings (below the document title). */\nconst STRUCTURE_STAGE_LEVEL = 2\n\n/**\n * Composites („Bausteine“): the node family with its node views, the toolbar group (insert, „In Baustein umwandeln“,\n * „Gliederung umwandeln“), `/` commands, the conversion providers (wrap into / switch kind of / unwrap composites),\n * Markdown `:::` fences, legacy `section` migration, the preferred-structure setting and its `editing` settings tab,\n * the chips on each title line (status, tags) and the details popover on the kind icon (the binding's `chrome` overlay), focus mode on one\n * Baustein (`CompositeFocus`, the „Fokussieren“ block action and the binding's `focusChip` overlay), and\n * the AI view of kinds and structure, and the kinds' accepted children (`AcceptedChildren`: an edit that nests a Baustein\n * into one that does not accept its kind is refused with a notice). Contributes the `parseMarkdown`,\n * `structure` and `migrateContent` stages. Imports no AI, media or transcript code.\n */\nexport function compositeFeatureCore<C>(ui: CompositesUi<C>, options: CompositeFeatureOptions = {}): EditorFeature<C> {\n // Host kinds keep their labels; the built-in ones are produced from the context's translator (memoized per `t`).\n const kindsOf = (ctx: { t: Translate }) => options.kinds ?? defaultCompositeKinds(ctx.t)\n const basketsOf = (ctx: { t: Translate }) => options.baskets ?? defaultBaskets(ctx.t)\n const { Composite, CompositeTags, Reference } = compositeNodes(ui.nodeViews)\n return {\n id: 'composites',\n dimension: 'content',\n schemaExtensions: () => compositeSchemaExtensions({ ...(options.kinds && { kinds: options.kinds }), ...(options.baskets && { baskets: options.baskets }) }),\n extensions: ctx => [\n Composite.configure({ kinds: kindsOf(ctx), baskets: basketsOf(ctx) }),\n CompositeTitleNode,\n CompositeDescriptionNode,\n CompositeTags,\n Structure.configure({ mode: () => ctx.settings.get().blocks.structure }),\n AcceptedChildren.configure({ notify: ctx.notify, t: ctx.t }),\n SourceReveal,\n CompositeFocus,\n CompositeMerge,\n CompositeSplit.configure({ defaultKind: () => ctx.settings.get().blocks.defaultKind, targetChars: () => ctx.settings.get().blocks.splitTargetChars }),\n Reference.configure({ suggestion: referenceSuggestion(ctx.t) }),\n ],\n toolbarGroups: COMPOSITE_TOOLBAR_GROUPS,\n commands: ctx => compositeCommands(ctx, kindsOf(ctx)),\n insertGuards: () => [compositeInsertGuard],\n blockActions: ctx => [{\n id: 'document-export',\n label: ctx.t('composites.blockAction.export'),\n icon: 'i-lucide-download',\n ability: ABILITY.compositeExport,\n order: 400,\n isVisible: ({ node }) => node.attrs.kind === 'document',\n run: ({ editor, node }) => downloadText(markdownFileName(node), documentCompositeMarkdown(editor, node)),\n }, {\n id: 'bibliography-export',\n label: ctx.t('composites.blockAction.bibtex'),\n icon: 'i-lucide-book-marked',\n ability: ABILITY.compositeExport,\n order: 410,\n isVisible: ({ node }) => bibOf(node) !== null,\n run: ({ node }) => downloadText(`${markdownFileName(node).replace(/\\.md$/, '')}.bib`, bibtexOf(cslOf(node)!), 'text/x-bibtex;charset=utf-8'),\n }, {\n id: 'composite-focus',\n label: ctx.t('composites.focus.action'),\n icon: 'i-lucide-focus',\n order: 420,\n isVisible: ({ node }) => node.type.name === 'composite',\n run: ({ editor, node }) => {\n const id = blockIdOf(node)\n if (id) editor.commands.focusComposite(id)\n },\n }, ...splitBlockActions(ctx), {\n id: 'composite-merge-next',\n label: ctx.t('composites.merge.next'),\n icon: 'i-lucide-merge',\n ability: ABILITY.compositeMeta,\n order: 470,\n isVisible: ({ editor, pos }) => editor.can().mergeCompositeWithNext(pos),\n run: ({ editor, pos }) => void editor.chain().focus().mergeCompositeWithNext(pos).run(),\n }],\n overlays: [ui.chrome, ui.focusChip].filter(overlay => overlay !== undefined),\n settingsTabs: ctx => [{ id: 'editing', label: ctx.t('composites.tab'), icon: 'i-lucide-pencil', component: ui.settingsTab, props: { kinds: kindsOf(ctx) } }],\n blocks: {\n parseMarkdown: (editor, markdown) => blocksFromMarkdown(md => editor.markdown!.parse(md), markdown, compositeKindsOf(editor)),\n structure: (editor, blocks) => {\n const { schema } = editor\n return structureBlocks(schema, blocks.map(block => schema.nodeFromJSON(block)), structureOf(editor), STRUCTURE_STAGE_LEVEL, compositeKindsOf(editor)).map(node => node.toJSON())\n },\n migrateContent: migrateLegacyContent,\n normalize: (editor, blocks) => normalizeReferences(blocks, compositeIdsOf(editor.state.doc)),\n },\n conversions: compositeConversions(options.kinds),\n aiContext: editor => ({\n kinds: compositeKindsOf(editor).map(({ id, label, fields, ai }) => ({ id, label, fields, ...(ai?.purpose && { purpose: ai.purpose }) })),\n structure: structureOf(editor),\n blocks: [REFERENCE_AI_BLOCK],\n }),\n // A Baustein derived from another block hands the model that source block's Markdown.\n aiBlockData: ({ editor, node }) => {\n const from = derivationOf(node)?.from\n const source = from && 'block' in from ? findBlockById(editor.state.doc, from.block)?.node : undefined\n // i18n-ignore: model-facing data label (German prompt text, not UI)\n return source?.type.name === 'composite' ? [{ label: `Quelle: ${source.child(0).textContent.trim()}`, text: bodyMarkdown(editor, source) }] : []\n },\n }\n}\n\n/**\n * The four split actions of a Baustein: at the caret (as sibling or sub-Bausteine; offered on the Baustein around the\n * caret while the caret is past the first body block) and by length (as sub-Bausteine or siblings; offered while the\n * body falls into two parts or more). Each is hidden when the command refuses, so a kind that accepts no child kind\n * never shows the `children` variants.\n */\nfunction splitBlockActions({ t }: FeatureContext): BlockAction[] {\n const atCaret = (id: string, labelKey: 'composites.split.here' | 'composites.split.children', icon: string, order: number, mode: SplitMode): BlockAction => ({\n id,\n label: t(labelKey),\n icon,\n ability: ABILITY.compositeMeta,\n order,\n isVisible: ({ editor, pos }) => {\n const { $head } = editor.state.selection\n const found = compositeAround($head)\n return found?.pos === pos && $head.index(found.depth) > COMPOSITE_CHROME_COUNT && editor.can().splitCompositeAtCaret({ mode })\n },\n run: ({ editor }) => void editor.chain().focus().splitCompositeAtCaret({ mode }).run(),\n })\n const byLength = (id: string, labelKey: 'composites.split.lengthChildren' | 'composites.split.lengthSiblings', icon: string, order: number, mode: SplitMode): BlockAction => ({\n id,\n label: t(labelKey),\n icon,\n ability: ABILITY.compositeMeta,\n order,\n isVisible: ({ editor, pos }) => editor.can().splitCompositeByLength({ mode, pos }),\n run: ({ editor, pos }) => void editor.chain().focus().splitCompositeByLength({ mode, pos }).run(),\n })\n return [\n atCaret('composite-split-here', 'composites.split.here', 'i-lucide-scissors', 430, 'siblings'),\n atCaret('composite-split-children', 'composites.split.children', 'i-lucide-split', 440, 'children'),\n byLength('composite-split-length-children', 'composites.split.lengthChildren', 'i-lucide-ruler', 450, 'children'),\n byLength('composite-split-length-siblings', 'composites.split.lengthSiblings', 'i-lucide-ruler', 460, 'siblings'),\n ]\n}\n\nconst COMPOSITE_TOOLBAR_GROUPS: ToolbarGroupDef[] = [{ id: 'composites', order: 60, labelKey: 'palette.group.composites' }]\n\n/**\n * Converting headings to Bausteine and back: the checks and actions the toolbar's „Gliederung umwandeln“ menu and the\n * `/gliedern*` and `/aufloesen*` commands share, so both placements gate and act identically. They read the scope and\n * default kind from the settings at call time.\n */\nfunction structureActions({ settings }: FeatureContext) {\n const groupOptions = (recursive: boolean) => ({ recursive, scope: settings.get().editing.headingConversionScope, kind: settings.get().blocks.defaultKind })\n const flattenOptions = (recursive: boolean) => ({ recursive, scope: settings.get().editing.headingConversionScope })\n return {\n canGroup: (editor: Editor, recursive: boolean) => editor.can().convertHeadingsToComposites(groupOptions(recursive)),\n canFlatten: (editor: Editor, recursive: boolean) => editor.can().convertCompositesToHeadings(flattenOptions(recursive)),\n group: (editor: Editor, recursive: boolean) => void editor.chain().focus().convertHeadingsToComposites(groupOptions(recursive)).run(),\n flatten: (editor: Editor, recursive: boolean) => void editor.chain().focus().convertCompositesToHeadings(flattenOptions(recursive)).run(),\n }\n}\n\n/**\n * The commands of the composites feature, each declared once. Toolbar group beside the inserts: the default kind's\n * insert button (it follows the setting, so label/icon/shortcut/`creates` are getters read at render time), „In\n * Baustein umwandeln“ (one entry per kind for the caret's block) and „Gliederung umwandeln“ (headings <-> composites in\n * both directions, the preferred structure's direction first). `/` menu: one command per kind (`creates` that kind, so\n * the insert guard hides kinds the surrounding Baustein does not accept) and the four heading conversions.\n */\nfunction compositeCommands<C>(ctx: FeatureContext, kinds: readonly CompositeKind[]): CommandDef<C>[] {\n const { settings, t } = ctx\n const defaultKind = () => compositeKind(kinds, settings.get().blocks.defaultKind)\n const { canGroup, canFlatten, group, flatten } = structureActions(ctx)\n\n function kindItems(editor: Editor): MenuItem[] {\n return [\n { type: 'label', label: t('composites.menu.kindHeading') },\n ...compositeKindsOf(editor).map((kind): MenuItem => {\n const target = { type: 'composite', kind: kind.id } as const\n return { label: kind.label, icon: kind.icon, disabled: !editor.can().convertBlockTo(target), onSelect: () => editor.chain().focus().convertBlockTo(target).run() }\n }),\n ]\n }\n\n function structureItems(editor: Editor): MenuItem[] {\n const structure = settings.get().blocks.structure\n const abilities = abilitiesAtSelection(editor)\n const composite = abilities.has(ABILITY.composite)\n const headings = abilities.has(ABILITY.headings)\n const sep: MenuItem = { type: 'separator' }\n const toComposites: MenuItem[] = [\n { type: 'label', label: t('composites.menu.toComposites') },\n { label: t('composites.menu.toComposites.top'), description: t('composites.menu.toComposites.top.description'), icon: 'i-lucide-layers', disabled: !composite || !canGroup(editor, false), onSelect: () => group(editor, false) },\n { label: t('composites.menu.toComposites.all'), description: t('composites.menu.toComposites.all.description'), icon: 'i-lucide-list-tree', disabled: !composite || !canGroup(editor, true), onSelect: () => group(editor, true) },\n ]\n const toHeadings: MenuItem[] = [\n { type: 'label', label: t('composites.menu.toHeadings') },\n { label: t('composites.menu.toHeadings.top'), description: t('composites.menu.toHeadings.top.description'), icon: 'i-lucide-heading', disabled: !headings || !canFlatten(editor, false), onSelect: () => flatten(editor, false) },\n { label: t('composites.menu.toHeadings.all'), description: t('composites.menu.toHeadings.all.description'), icon: 'i-lucide-align-left', disabled: !headings || !canFlatten(editor, true), onSelect: () => flatten(editor, true) },\n ]\n const entry = editorEntryOf(editor)\n // The settings entry exists only while some feature contributes a tab to open.\n const settingsEntry: MenuItem[] = entry && settingsTabsOf(entry.preset, entry.ctx.app).length\n ? [sep, { label: t('composites.menu.settings'), icon: 'i-lucide-settings-2', onSelect: () => entry.ui.openSettings('editing') }]\n : []\n return [\n { type: 'label', label: t('composites.menu.preferred', { mode: t(STRUCTURE_MODE_KEYS[structure].labelKey) }) },\n ...(structure === 'composite' ? [...toComposites, sep, ...toHeadings] : [...toHeadings, sep, ...toComposites]),\n ...settingsEntry,\n ]\n }\n\n const insertKind = (kind: string, slashId: string, label: string, icon: string): CommandDef<C> => ({\n id: `composite.${kind}`,\n slash: { id: slashId },\n creates: { type: 'composite', attrs: { kind } },\n icon,\n label,\n ability: ABILITY.composite,\n run: (editor) => { editor.chain().focus().insertComposite(kind).run() },\n })\n\n return [\n {\n id: 'insert',\n toolbar: { group: 'composites', order: 10 },\n // Getters: the default kind arrives with the server settings; the toolbar reads them at render time.\n get icon() { return defaultKind().icon },\n get label() { return defaultKind().label },\n // Mod-Shift-a (CompositeNode) always inserts a `section`, so only then is it shown as the shortcut.\n get kbds() { return defaultKind().id === 'section' ? ['meta', 'shift', 'a'] : undefined },\n get creates() { return { type: 'composite', attrs: { kind: defaultKind().id } } },\n ability: ABILITY.composite,\n can: editor => editor.can().insertComposite(defaultKind().id),\n run: (editor) => { editor.chain().focus().insertComposite(defaultKind().id).run() },\n },\n {\n id: 'to-kind',\n toolbar: { group: 'composites', order: 20 },\n icon: 'i-lucide-replace',\n label: t('composites.toolbar.toKind'),\n ability: ABILITY.composite,\n can: editor => kindItems(editor).some(item => item.type !== 'label' && !item.disabled),\n menu: kindItems,\n },\n {\n id: 'structure',\n toolbar: { group: 'composites', order: 30 },\n icon: 'i-lucide-list-tree',\n label: t('composites.toolbar.structure'),\n can: editor => canGroup(editor, true) || canFlatten(editor, true),\n menu: structureItems,\n },\n insertKind('section', 'abschnitt', t('composites.slash.section'), 'i-lucide-layers'),\n ...kinds.filter(kind => kind.id !== 'section').map(kind => insertKind(kind.id, kind.id, kind.label, kind.icon)),\n { id: 'gliedern', slash: {}, label: t('composites.slash.group'), icon: 'i-lucide-layers', ability: ABILITY.composite, can: editor => canGroup(editor, false), run: editor => group(editor, false) },\n { id: 'gliedern-alle', slash: {}, label: t('composites.slash.groupAll'), icon: 'i-lucide-list-tree', ability: ABILITY.composite, can: editor => canGroup(editor, true), run: editor => group(editor, true) },\n { id: 'aufloesen', slash: {}, label: t('composites.slash.flatten'), icon: 'i-lucide-heading', ability: ABILITY.headings, can: editor => canFlatten(editor, false), run: editor => flatten(editor, false) },\n { id: 'aufloesen-alle', slash: {}, label: t('composites.slash.flattenAll'), icon: 'i-lucide-align-left', ability: ABILITY.headings, can: editor => canFlatten(editor, true), run: editor => flatten(editor, true) },\n { id: 'verweis', slash: {}, label: t('composites.reference.insert'), icon: 'i-lucide-link-2', ability: ABILITY.reference, run: (editor) => { editor.chain().focus().insertContent(REFERENCE_TRIGGER).run() } },\n ]\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"feature.js","names":[],"sources":["../../../src/features/composites/feature.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { BlockAction, CommandDef, EditorFeature, FeatureContext, MenuItem, ToolbarGroupDef } from '../../core'\nimport { abilitiesAtSelection, capabilityDataOf, downloadText, editorEntryOf, settingsTabsOf } from '../../core'\nimport type { Translate } from '../../i18n'\nimport { ABILITY, blockIdOf, findBlockById, TYPED_BLOCK } from '../../core/schema'\nimport { AcceptedChildren, compositeInsertGuard } from './accepted-children'\nimport { type Basket, defaultBaskets } from './baskets'\nimport { bibtexOf, cslOf } from './bibliography'\nimport { compositeConversions } from './convert'\nimport { derivationOf } from '../../core/derivation'\nimport { bodyMarkdown } from './source'\nimport { blocksFromMarkdown } from './fences'\nimport { structureBlocks } from './heading-composites'\nimport { type BlockType, aiBlockTypesOf, blockTypeOf, defaultBlockTypes } from './block-types'\nimport { compositeBlockCapabilities } from './capabilities'\nimport { migrateLegacyContent } from './legacy'\nimport { compositeSchemaExtensions } from './schema'\nimport { documentCompositeMarkdown, markdownFileName } from './markdown-export'\nimport { type CompositeNodeViews, compositeNodes } from './node-views'\nimport { COMPOSITE_CHROME_COUNT, CompositeDescriptionNode, CompositeTitleNode, compositeAround, blockTypesOf } from './nodes'\nimport { CompositeFocus } from './focus'\nimport { CompositeMerge } from './merge'\nimport { REFERENCE_TRIGGER } from './reference'\nimport { REFERENCE_AI_BLOCK } from './reference-ai'\nimport { referenceSuggestion } from './reference-suggestion'\nimport { compositeIdsOf, normalizeReferences } from './reference-text'\nimport { SourceReveal } from './reveal-source'\nimport { CompositeSplit, type SplitMode } from './split'\nimport { Structure, structureOf } from './structure'\nimport { STRUCTURE_MODE_KEYS } from './structure-mode'\n\n/** What a framework binding supplies to the composites feature. */\nexport interface CompositesUi<C> {\n /** The chips on each title line and the details popover on the kind icon; mounted as an overlay. */\n chrome: C\n /** The focus chip („Fokus: <Titel> · Aufheben“) shown while a Typed block is focused; mounted as an overlay. Absent: no chip (the focus mode itself works). */\n focusChip?: C\n /** The „Bearbeiten“ settings tab; receives `{ blockTypes }` as props. */\n settingsTab: C\n /** The composite block view of the framework. */\n nodeViews: CompositeNodeViews\n}\n\n/** Options of `compositeFeature`. */\nexport interface CompositeFeatureOptions {\n /** The Block types offered in the editor, with their own labels (default: `defaultBlockTypes(t)`, the built-in Block types in the editor's language); read once. */\n blockTypes?: readonly BlockType[]\n /** The colour baskets a Typed block can be put into (default: `defaultBaskets(t)`, red/orange/yellow/green/blue in the editor's language; colours are the `--sk-basket-<id>` CSS variables); read once. */\n baskets?: readonly Basket[]\n}\n\n/** Heading level the structure stage starts at when it turns composites into headings (below the document title). */\nconst STRUCTURE_STAGE_LEVEL = 2\n\n/**\n * Composites (Typed blocks): the node family with its node views, the toolbar group (insert, „In Block umwandeln“,\n * „Gliederung umwandeln“), `/` commands, the conversion providers (wrap into / switch kind of / unwrap composites),\n * Markdown `:::` fences, legacy `section` migration, the preferred-structure setting and its `editing` settings tab,\n * the chips on each title line (status, tags) and the details popover on the kind icon (the binding's `chrome` overlay), focus mode on one\n * Typed block (`CompositeFocus`, the „Fokussieren“ block action and the binding's `focusChip` overlay), and\n * the AI view of Block types and structure, and the Block types' accepted children (`AcceptedChildren`: an edit that nests a Typed block\n * into one that does not accept its kind is refused with a notice). Contributes the `parseMarkdown`,\n * `structure` and `migrateContent` stages. Imports no AI, media or transcript code.\n */\nexport function compositeFeatureCore<C>(ui: CompositesUi<C>, options: CompositeFeatureOptions = {}): EditorFeature<C> {\n // Host Block types keep their labels; the built-in ones are produced from the context's translator (memoized per `t`).\n const hostBlockTypes = options.blockTypes\n const kindsOf = (ctx: { t: Translate }) => hostBlockTypes ?? defaultBlockTypes(ctx.t)\n const basketsOf = (ctx: { t: Translate }) => options.baskets ?? defaultBaskets(ctx.t)\n const { Composite, CompositeTags, Reference } = compositeNodes(ui.nodeViews)\n return {\n id: 'composites',\n dimension: 'content',\n schemaExtensions: () => compositeSchemaExtensions({ ...(hostBlockTypes && { blockTypes: hostBlockTypes }), ...(options.baskets && { baskets: options.baskets }) }),\n blockCapabilities: compositeBlockCapabilities(),\n blockTypes: blockTypesOf,\n extensions: ctx => [\n Composite.configure({ blockTypes: kindsOf(ctx), baskets: basketsOf(ctx) }),\n CompositeTitleNode,\n CompositeDescriptionNode,\n CompositeTags,\n Structure.configure({ mode: () => ctx.settings.get().blocks.structure }),\n AcceptedChildren.configure({ notify: ctx.notify, t: ctx.t }),\n SourceReveal,\n CompositeFocus,\n CompositeMerge,\n CompositeSplit.configure({ defaultBlockType: () => ctx.settings.get().blocks.defaultBlockType, targetChars: () => ctx.settings.get().blocks.splitTargetChars }),\n Reference.configure({ suggestion: referenceSuggestion(ctx.t) }),\n ],\n toolbarGroups: COMPOSITE_TOOLBAR_GROUPS,\n commands: ctx => compositeCommands(ctx, kindsOf(ctx)),\n insertGuards: () => [compositeInsertGuard],\n blockActions: ctx => [{\n id: 'document-export',\n target: 'typedBlock',\n label: ctx.t('composites.blockAction.export'),\n icon: 'i-lucide-download',\n ability: ABILITY.compositeExport,\n order: 400,\n requires: ['export'],\n run: ({ editor, node }) => downloadText(markdownFileName(node), documentCompositeMarkdown(editor, node)),\n }, {\n id: 'bibliography-export',\n target: 'typedBlock',\n label: ctx.t('composites.blockAction.bibtex'),\n icon: 'i-lucide-book-marked',\n ability: ABILITY.compositeExport,\n order: 410,\n requires: ['bibliography'],\n isVisible: ({ editor, node }) => capabilityDataOf(editor, node, 'bibliography') !== null,\n run: ({ node }) => downloadText(`${markdownFileName(node).replace(/\\.md$/, '')}.bib`, bibtexOf(cslOf(node)!), 'text/x-bibtex;charset=utf-8'),\n }, {\n id: 'composite-focus',\n label: ctx.t('composites.focus.action'),\n target: 'typedBlock',\n icon: 'i-lucide-focus',\n order: 420,\n requires: ['container'],\n run: ({ editor, node }) => {\n const id = blockIdOf(node)\n if (id) editor.commands.focusComposite(id)\n },\n }, ...splitBlockActions(ctx), {\n id: 'composite-merge-next',\n target: 'typedBlock',\n label: ctx.t('composites.merge.next'),\n icon: 'i-lucide-merge',\n ability: ABILITY.compositeMeta,\n requires: ['container', 'title'],\n order: 470,\n isVisible: ({ editor, pos }) => editor.can().mergeCompositeWithNext(pos),\n run: ({ editor, pos }) => void editor.chain().focus().mergeCompositeWithNext(pos).run(),\n }],\n overlays: [ui.chrome, ui.focusChip].filter(overlay => overlay !== undefined),\n settingsTabs: ctx => [{ id: 'editing', label: ctx.t('composites.tab'), icon: 'i-lucide-pencil', component: ui.settingsTab, props: { blockTypes: kindsOf(ctx) } }],\n blocks: {\n parseMarkdown: (editor, markdown) => blocksFromMarkdown(md => editor.markdown!.parse(md), markdown, blockTypesOf(editor)),\n structure: (editor, blocks) => {\n const { schema } = editor\n return structureBlocks(schema, blocks.map(block => schema.nodeFromJSON(block)), structureOf(editor), STRUCTURE_STAGE_LEVEL, blockTypesOf(editor)).map(node => node.toJSON())\n },\n migrateContent: migrateLegacyContent,\n normalize: (editor, blocks) => normalizeReferences(blocks, compositeIdsOf(editor.state.doc)),\n },\n conversions: compositeConversions(hostBlockTypes),\n aiContext: editor => ({\n blockTypes: aiBlockTypesOf(blockTypesOf(editor)),\n structure: structureOf(editor),\n blocks: [REFERENCE_AI_BLOCK],\n }),\n // A Typed block derived from another block hands the model that source block's Markdown.\n aiBlockData: ({ editor, node }) => {\n const from = derivationOf(node)?.from\n const source = from && 'block' in from ? findBlockById(editor.state.doc, from.block)?.node : undefined\n // i18n-ignore: model-facing data label (German prompt text, not UI)\n return source?.type.name === TYPED_BLOCK ? [{ label: `Quelle: ${source.child(0).textContent.trim()}`, text: bodyMarkdown(editor, source) }] : []\n },\n }\n}\n\n/**\n * The four split actions of a Typed block: at the caret (as sibling or nested Typed blocks; offered on the Typed block around the\n * caret while the caret is past the first body block) and by length (as nested Typed blocks or siblings; offered while the\n * body falls into two parts or more). Each is hidden when the command refuses, so a kind that accepts no child kind\n * never shows the `children` variants.\n */\nfunction splitBlockActions({ t }: FeatureContext): BlockAction[] {\n const atCaret = (id: string, labelKey: 'composites.split.here' | 'composites.split.children', icon: string, order: number, mode: SplitMode): BlockAction => ({\n id,\n label: t(labelKey),\n icon,\n target: 'typedBlock',\n ability: ABILITY.compositeMeta,\n requires: ['container', 'title'],\n order,\n isVisible: ({ editor, pos }) => {\n const { $head } = editor.state.selection\n const found = compositeAround($head)\n return found?.pos === pos && $head.index(found.depth) > COMPOSITE_CHROME_COUNT && editor.can().splitCompositeAtCaret({ mode })\n },\n run: ({ editor }) => void editor.chain().focus().splitCompositeAtCaret({ mode }).run(),\n })\n const byLength = (id: string, labelKey: 'composites.split.lengthChildren' | 'composites.split.lengthSiblings', icon: string, order: number, mode: SplitMode): BlockAction => ({\n id,\n label: t(labelKey),\n icon,\n target: 'typedBlock',\n ability: ABILITY.compositeMeta,\n requires: ['container', 'title'],\n order,\n isVisible: ({ editor, pos }) => editor.can().splitCompositeByLength({ mode, pos }),\n run: ({ editor, pos }) => void editor.chain().focus().splitCompositeByLength({ mode, pos }).run(),\n })\n return [\n atCaret('composite-split-here', 'composites.split.here', 'i-lucide-scissors', 430, 'siblings'),\n atCaret('composite-split-children', 'composites.split.children', 'i-lucide-split', 440, 'children'),\n byLength('composite-split-length-children', 'composites.split.lengthChildren', 'i-lucide-ruler', 450, 'children'),\n byLength('composite-split-length-siblings', 'composites.split.lengthSiblings', 'i-lucide-ruler', 460, 'siblings'),\n ]\n}\n\nconst COMPOSITE_TOOLBAR_GROUPS: ToolbarGroupDef[] = [{ id: 'composites', order: 60, labelKey: 'palette.group.composites' }]\n\n/**\n * Converting headings to Typed blocks and back: the checks and actions the toolbar's „Gliederung umwandeln“ menu and the\n * `/gliedern*` and `/aufloesen*` commands share, so both placements gate and act identically. They read the scope and\n * default kind from the settings at call time.\n */\nfunction structureActions({ settings }: FeatureContext) {\n const groupOptions = (recursive: boolean) => ({ recursive, scope: settings.get().editing.headingConversionScope, kind: settings.get().blocks.defaultBlockType })\n const flattenOptions = (recursive: boolean) => ({ recursive, scope: settings.get().editing.headingConversionScope })\n return {\n canGroup: (editor: Editor, recursive: boolean) => editor.can().convertHeadingsToComposites(groupOptions(recursive)),\n canFlatten: (editor: Editor, recursive: boolean) => editor.can().convertCompositesToHeadings(flattenOptions(recursive)),\n group: (editor: Editor, recursive: boolean) => void editor.chain().focus().convertHeadingsToComposites(groupOptions(recursive)).run(),\n flatten: (editor: Editor, recursive: boolean) => void editor.chain().focus().convertCompositesToHeadings(flattenOptions(recursive)).run(),\n }\n}\n\n/**\n * The commands of the composites feature, each declared once. Toolbar group beside the inserts: the default kind's\n * insert button (it follows the setting, so label/icon/shortcut/`creates` are getters read at render time), „In\n * Block umwandeln“ (one entry per kind for the caret's block) and „Gliederung umwandeln“ (headings <-> composites in\n * both directions, the preferred structure's direction first). `/` menu: one command per kind (`creates` that kind, so\n * the insert guard hides Block types the surrounding Typed block does not accept) and the four heading conversions.\n */\nfunction compositeCommands<C>(ctx: FeatureContext, kinds: readonly BlockType[]): CommandDef<C>[] {\n const { settings, t } = ctx\n const defaultBlockType = () => blockTypeOf(kinds, settings.get().blocks.defaultBlockType)\n const { canGroup, canFlatten, group, flatten } = structureActions(ctx)\n\n function kindItems(editor: Editor): MenuItem[] {\n return [\n { type: 'label', label: t('composites.menu.kindHeading') },\n ...blockTypesOf(editor).map((kind): MenuItem => {\n const target = { type: TYPED_BLOCK, blockType: kind.id } as const\n return { label: kind.label, icon: kind.icon, disabled: !editor.can().convertBlockTo(target), onSelect: () => editor.chain().focus().convertBlockTo(target).run() }\n }),\n ]\n }\n\n function structureItems(editor: Editor): MenuItem[] {\n const structure = settings.get().blocks.structure\n const abilities = abilitiesAtSelection(editor)\n const composite = abilities.has(ABILITY.composite)\n const headings = abilities.has(ABILITY.headings)\n const sep: MenuItem = { type: 'separator' }\n const toComposites: MenuItem[] = [\n { type: 'label', label: t('composites.menu.toComposites') },\n { label: t('composites.menu.toComposites.top'), description: t('composites.menu.toComposites.top.description'), icon: 'i-lucide-layers', disabled: !composite || !canGroup(editor, false), onSelect: () => group(editor, false) },\n { label: t('composites.menu.toComposites.all'), description: t('composites.menu.toComposites.all.description'), icon: 'i-lucide-list-tree', disabled: !composite || !canGroup(editor, true), onSelect: () => group(editor, true) },\n ]\n const toHeadings: MenuItem[] = [\n { type: 'label', label: t('composites.menu.toHeadings') },\n { label: t('composites.menu.toHeadings.top'), description: t('composites.menu.toHeadings.top.description'), icon: 'i-lucide-heading', disabled: !headings || !canFlatten(editor, false), onSelect: () => flatten(editor, false) },\n { label: t('composites.menu.toHeadings.all'), description: t('composites.menu.toHeadings.all.description'), icon: 'i-lucide-align-left', disabled: !headings || !canFlatten(editor, true), onSelect: () => flatten(editor, true) },\n ]\n const entry = editorEntryOf(editor)\n // The settings entry exists only while some feature contributes a tab to open.\n const settingsEntry: MenuItem[] = entry && settingsTabsOf(entry.preset, entry.ctx.app).length\n ? [sep, { label: t('composites.menu.settings'), icon: 'i-lucide-settings-2', onSelect: () => entry.ui.openSettings('editing') }]\n : []\n return [\n { type: 'label', label: t('composites.menu.preferred', { mode: t(STRUCTURE_MODE_KEYS[structure].labelKey) }) },\n ...(structure === 'structured' ? [...toComposites, sep, ...toHeadings] : [...toHeadings, sep, ...toComposites]),\n ...settingsEntry,\n ]\n }\n\n const insertKind = (kind: string, slashId: string, label: string, icon: string): CommandDef<C> => ({\n id: `composite.${kind}`,\n slash: { id: slashId },\n creates: { type: TYPED_BLOCK, attrs: { blockType: kind } },\n icon,\n label,\n ability: ABILITY.composite,\n run: (editor) => { editor.chain().focus().insertComposite(kind).run() },\n })\n\n return [\n {\n id: 'insert',\n toolbar: { group: 'composites', order: 10 },\n // Getters: the default kind arrives with the server settings; the toolbar reads them at render time.\n get icon() { return defaultBlockType().icon },\n get label() { return defaultBlockType().label },\n // Mod-Shift-a (CompositeNode) always inserts a `section`, so only then is it shown as the shortcut.\n get kbds() { return defaultBlockType().id === 'section' ? ['meta', 'shift', 'a'] : undefined },\n get creates() { return { type: TYPED_BLOCK, attrs: { blockType: defaultBlockType().id } } },\n ability: ABILITY.composite,\n can: editor => editor.can().insertComposite(defaultBlockType().id),\n run: (editor) => { editor.chain().focus().insertComposite(defaultBlockType().id).run() },\n },\n {\n id: 'to-kind',\n toolbar: { group: 'composites', order: 20 },\n icon: 'i-lucide-replace',\n label: t('composites.toolbar.toKind'),\n ability: ABILITY.composite,\n can: editor => kindItems(editor).some(item => item.type !== 'label' && !item.disabled),\n menu: kindItems,\n },\n {\n id: 'structure',\n toolbar: { group: 'composites', order: 30 },\n icon: 'i-lucide-list-tree',\n label: t('composites.toolbar.structure'),\n can: editor => canGroup(editor, true) || canFlatten(editor, true),\n menu: structureItems,\n },\n insertKind('section', 'abschnitt', t('composites.slash.section'), 'i-lucide-layers'),\n ...kinds.filter(kind => kind.id !== 'section').map(kind => insertKind(kind.id, kind.id, kind.label, kind.icon)),\n { id: 'gliedern', slash: {}, label: t('composites.slash.group'), icon: 'i-lucide-layers', ability: ABILITY.composite, can: editor => canGroup(editor, false), run: editor => group(editor, false) },\n { id: 'gliedern-alle', slash: {}, label: t('composites.slash.groupAll'), icon: 'i-lucide-list-tree', ability: ABILITY.composite, can: editor => canGroup(editor, true), run: editor => group(editor, true) },\n { id: 'aufloesen', slash: {}, label: t('composites.slash.flatten'), icon: 'i-lucide-heading', ability: ABILITY.headings, can: editor => canFlatten(editor, false), run: editor => flatten(editor, false) },\n { id: 'aufloesen-alle', slash: {}, label: t('composites.slash.flattenAll'), icon: 'i-lucide-align-left', ability: ABILITY.headings, can: editor => canFlatten(editor, true), run: editor => flatten(editor, true) },\n { id: 'verweis', slash: {}, label: t('composites.reference.insert'), icon: 'i-lucide-link-2', ability: ABILITY.reference, run: (editor) => { editor.chain().focus().insertContent(REFERENCE_TRIGGER).run() } },\n ]\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BlockType } from "./block-types.js";
|
|
2
2
|
import { CompositeFence, FenceSegment, splitCompositeFences } from "../../core/fences.js";
|
|
3
3
|
import { JSONContent } from "@tiptap/core";
|
|
4
4
|
//#region src/features/composites/fences.d.ts
|
|
@@ -8,14 +8,14 @@ export declare function compositeFence(kind: string, meta: Record<string, unknow
|
|
|
8
8
|
* Markdown segments parsed, fences of a registered kind turned into composites, in order. A fence of any other kind
|
|
9
9
|
* becomes an `opaqueFence` that keeps its text verbatim.
|
|
10
10
|
*/
|
|
11
|
-
export declare function blocksFromMarkdown(parse: (md: string) => JSONContent, markdown: string, kinds: readonly
|
|
11
|
+
export declare function blocksFromMarkdown(parse: (md: string) => JSONContent, markdown: string, kinds: readonly BlockType[]): JSONContent[];
|
|
12
12
|
/**
|
|
13
13
|
* JSON of a composite built from the fence body: first `#`-heading → title, first blockquote directly after →
|
|
14
14
|
* description, a `Tags:` line → tags, rest → body (recursing for nested fences). Missing title → empty title; empty
|
|
15
15
|
* body → [paragraph]. Meta of a known kind keeps only that kind's fields, plus provenance (`derivation`) and the
|
|
16
16
|
* bibliographic record (`bib`), which any kind may carry.
|
|
17
17
|
*/
|
|
18
|
-
export declare function compositeFromMarkdown(parse: (md: string) => JSONContent, fence: CompositeFence, kinds: readonly
|
|
18
|
+
export declare function compositeFromMarkdown(parse: (md: string) => JSONContent, fence: CompositeFence, kinds: readonly BlockType[]): JSONContent;
|
|
19
19
|
//#endregion
|
|
20
20
|
export { type CompositeFence, type FenceSegment, splitCompositeFences };
|
|
21
21
|
//# sourceMappingURL=fences.d.ts.map
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { opaqueFenceJSON, splitCompositeFences } from "../../core/fences.js";
|
|
2
|
-
import { DERIVATION_KEY
|
|
2
|
+
import { DERIVATION_KEY } from "../../core/derivation.js";
|
|
3
|
+
import { propertiesOf } from "./block-types.js";
|
|
4
|
+
import { keptMeta } from "./meta-keys.js";
|
|
3
5
|
//#region src/features/composites/fences.ts
|
|
4
6
|
/** `inner` fenced as composite of `kind`: `::: kind #id {meta}` (`#id` only with an `id`, meta JSON only when non-empty), `inner`, `:::`. */
|
|
5
7
|
function compositeFence(kind, meta, inner, id) {
|
|
@@ -18,12 +20,15 @@ function withReferencedFenceIds(json, kinds) {
|
|
|
18
20
|
let anyId = false;
|
|
19
21
|
const collect = (node) => {
|
|
20
22
|
if (node.type === "reference" && typeof node.attrs?.target === "string") referenced.add(node.attrs.target);
|
|
21
|
-
if (node.type === "
|
|
23
|
+
if (node.type === "typedBlock") {
|
|
22
24
|
if (typeof node.attrs?.id === "string" && node.attrs.id) anyId = true;
|
|
23
25
|
const meta = node.attrs?.meta;
|
|
24
|
-
if (meta && typeof meta === "object")
|
|
25
|
-
const
|
|
26
|
-
|
|
26
|
+
if (meta && typeof meta === "object") {
|
|
27
|
+
const kind = kinds.find((candidate) => candidate.id === node.attrs?.blockType);
|
|
28
|
+
for (const field of kind ? propertiesOf(kind) : []) {
|
|
29
|
+
const value = meta[field.key];
|
|
30
|
+
if (field.type === "reference" && typeof value === "string" && value) referenced.add(value);
|
|
31
|
+
}
|
|
27
32
|
}
|
|
28
33
|
const sourceBlock = node.attrs?.meta?.[DERIVATION_KEY]?.from?.block;
|
|
29
34
|
if (typeof sourceBlock === "string" && sourceBlock) referenced.add(sourceBlock);
|
|
@@ -35,7 +40,7 @@ function withReferencedFenceIds(json, kinds) {
|
|
|
35
40
|
const strip = (node) => {
|
|
36
41
|
const content = node.content?.map(strip);
|
|
37
42
|
const changed = content?.some((child, index) => child !== node.content[index]);
|
|
38
|
-
const dropId = node.type === "
|
|
43
|
+
const dropId = node.type === "typedBlock" && typeof node.attrs?.id === "string" && !referenced.has(node.attrs.id);
|
|
39
44
|
if (!dropId && !changed) return node;
|
|
40
45
|
const { id: _id, ...attrs } = node.attrs ?? {};
|
|
41
46
|
return {
|
|
@@ -101,23 +106,23 @@ function compositeFromMarkdown(parse, fence, kinds) {
|
|
|
101
106
|
const kind = kinds.find((candidate) => candidate.id === fence.kind);
|
|
102
107
|
const meta = kind ? keptMeta(kind, fence.meta) : fence.meta;
|
|
103
108
|
return {
|
|
104
|
-
type: "
|
|
109
|
+
type: "typedBlock",
|
|
105
110
|
attrs: {
|
|
106
|
-
|
|
111
|
+
blockType: fence.kind,
|
|
107
112
|
...fence.id && { id: fence.id },
|
|
108
113
|
meta
|
|
109
114
|
},
|
|
110
115
|
content: [
|
|
111
116
|
title ? {
|
|
112
|
-
type: "
|
|
117
|
+
type: "typedBlockTitle",
|
|
113
118
|
content: title
|
|
114
|
-
} : { type: "
|
|
119
|
+
} : { type: "typedBlockTitle" },
|
|
115
120
|
description ? {
|
|
116
|
-
type: "
|
|
121
|
+
type: "typedBlockDescription",
|
|
117
122
|
content: description
|
|
118
|
-
} : { type: "
|
|
123
|
+
} : { type: "typedBlockDescription" },
|
|
119
124
|
{
|
|
120
|
-
type: "
|
|
125
|
+
type: "typedBlockTags",
|
|
121
126
|
attrs: { tags }
|
|
122
127
|
},
|
|
123
128
|
...body.length ? body : [{ type: "paragraph" }]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fences.js","names":[],"sources":["../../../src/features/composites/fences.ts"],"sourcesContent":["import type { JSONContent } from '@tiptap/core'\nimport { type CompositeFence, opaqueFenceJSON, splitCompositeFences } from '../../core/fences'\nimport { DERIVATION_KEY, keptMeta } from './meta-keys'\nimport type { CompositeKind } from './kinds'\n\n// Inverse of the composite nodes' renderMarkdown: `::: kind #id {meta}`, `## title`, `> description`, `Tags: #a #b`, body,\n// `:::`. The fence grammar itself (`splitCompositeFences`) is shared with the Markdown entry (`core/fences`).\n//\n// Block ids in fences: a Baustein written to Markdown carries its block id in the opener (`::: paper #<uuid> {meta}`,\n// Pandoc-like `#id` between kind and meta) only when something in the same serialized content points at it — a `reference`\n// chip (`[@<id>, S. 3]`) or a `reference` meta field. Every other fence stays `::: kind {meta}`. Parsing restores the id\n// as `attrs.id`, so after a Markdown round trip (source-mode commit, import) the `[@<id>]` tokens still resolve to\n// the same Bausteine. `withReferencedFenceIds` is the pre-pass that decides which ids are written.\nexport { type CompositeFence, type FenceSegment, splitCompositeFences } from '../../core/fences'\n\n/** `inner` fenced as composite of `kind`: `::: kind #id {meta}` (`#id` only with an `id`, meta JSON only when non-empty), `inner`, `:::`. */\nexport function compositeFence(kind: string, meta: Record<string, unknown>, inner: string, id?: string): string {\n const parts = [`::: ${kind}`]\n if (id) parts.push(`#${id}`)\n if (Object.keys(meta).length) parts.push(JSON.stringify(meta))\n return `${parts.join(' ')}\\n${inner}\\n:::`\n}\n\n/**\n * `json` with the `id` attr removed from every composite that nothing in `json` references: the Markdown renderer writes\n * the id of the composites that still have one. References are `reference` nodes (`target`) and meta values of `reference`\n * fields of the composite's kind. The input is not modified; unchanged subtrees are shared.\n */\nexport function withReferencedFenceIds(json: JSONContent, kinds: readonly CompositeKind[]): JSONContent {\n const referenced = new Set<string>()\n let anyId = false\n const collect = (node: JSONContent): void => {\n if (node.type === 'reference' && typeof node.attrs?.target === 'string') referenced.add(node.attrs.target)\n if (node.type === 'composite') {\n if (typeof node.attrs?.id === 'string' && node.attrs.id) anyId = true\n const meta: unknown = node.attrs?.meta\n if (meta && typeof meta === 'object') {\n for (const field of kinds.find(kind => kind.id === node.attrs?.kind)?.fields ?? []) {\n const value = (meta as Record<string, unknown>)[field.key]\n if (field.type === 'reference' && typeof value === 'string' && value) referenced.add(value)\n }\n }\n // A block-derived Baustein points at its source (`meta.derivation.from.block`): the source keeps its id across a round trip.\n const sourceBlock: unknown = node.attrs?.meta?.[DERIVATION_KEY]?.from?.block\n if (typeof sourceBlock === 'string' && sourceBlock) referenced.add(sourceBlock)\n }\n node.content?.forEach(collect)\n }\n collect(json)\n if (!anyId) return json\n const strip = (node: JSONContent): JSONContent => {\n const content = node.content?.map(strip)\n const changed = content?.some((child, index) => child !== node.content![index])\n const dropId = node.type === 'composite' && typeof node.attrs?.id === 'string' && !referenced.has(node.attrs.id)\n if (!dropId && !changed) return node\n const { id: _id, ...attrs } = node.attrs ?? {}\n return { ...node, ...(dropId ? { attrs } : {}), ...(changed ? { content } : {}) }\n }\n return strip(json)\n}\n\n/**\n * Markdown segments parsed, fences of a registered kind turned into composites, in order. A fence of any other kind\n * becomes an `opaqueFence` that keeps its text verbatim.\n */\nexport function blocksFromMarkdown(parse: (md: string) => JSONContent, markdown: string, kinds: readonly CompositeKind[]): JSONContent[] {\n return splitCompositeFences(markdown).flatMap((segment) => {\n if (!('inner' in segment)) return parse(segment.markdown).content ?? []\n return kinds.some(kind => kind.id === segment.kind) ? [compositeFromMarkdown(parse, segment, kinds)] : [opaqueFenceJSON(segment)]\n })\n}\n\n/** Inline content of the first textblock `parse` makes of `md`. */\nfunction inlineOf(parse: (md: string) => JSONContent, md: string): JSONContent[] | undefined {\n let found: JSONContent[] | undefined\n const walk = (node: JSONContent): void => {\n if (found) return\n if (node.content?.some(child => child.type === 'text')) found = node.content\n else node.content?.forEach(walk)\n }\n if (md.trim()) walk(parse(md))\n return found?.length ? found : undefined\n}\n\n/**\n * JSON of a composite built from the fence body: first `#`-heading → title, first blockquote directly after →\n * description, a `Tags:` line → tags, rest → body (recursing for nested fences). Missing title → empty title; empty\n * body → [paragraph]. Meta of a known kind keeps only that kind's fields, plus provenance (`derivation`) and the\n * bibliographic record (`bib`), which any kind may carry.\n */\nexport function compositeFromMarkdown(parse: (md: string) => JSONContent, fence: CompositeFence, kinds: readonly CompositeKind[]): JSONContent {\n const lines = fence.inner.split('\\n')\n let i = 0\n const skipBlank = () => {\n while (i < lines.length && !lines[i]!.trim()) i++\n }\n skipBlank()\n let title: JSONContent[] | undefined\n const heading = /^\\s*#{1,6}(?:\\s+(.*?))?\\s*#*\\s*$/.exec(lines[i] ?? '')\n if (heading) {\n title = inlineOf(parse, heading[1] ?? '')\n i++\n skipBlank()\n }\n const quote: string[] = []\n while (i < lines.length && /^\\s*>/.test(lines[i]!)) quote.push(lines[i++]!.replace(/^\\s*>\\s?/, ''))\n const description = quote.length ? inlineOf(parse, quote.join('\\n')) : undefined\n skipBlank()\n let tags: string[] = []\n const tagLine = /^\\s*Tags:\\s*(.*)$/i.exec(lines[i] ?? '')\n if (tagLine) {\n tags = [...new Set([...tagLine[1]!.matchAll(/#?([\\p{L}\\p{N}_-]+)/gu)].map(m => m[1]!.toLowerCase()))]\n i++\n }\n const body = blocksFromMarkdown(parse, lines.slice(i).join('\\n'), kinds)\n\n // A kind outside `kinds` (only reachable when called directly; `blocksFromMarkdown` makes those fences opaque) keeps its id (the views fall back via `compositeKind()`) and its meta as given.\n const kind = kinds.find(candidate => candidate.id === fence.kind)\n const meta = kind ? keptMeta(kind, fence.meta) : fence.meta\n return {\n type: 'composite',\n attrs: { kind: fence.kind, ...(fence.id && { id: fence.id }), meta },\n content: [\n title ? { type: 'compositeTitle', content: title } : { type: 'compositeTitle' },\n description ? { type: 'compositeDescription', content: description } : { type: 'compositeDescription' },\n { type: 'compositeTags', attrs: { tags } },\n ...(body.length ? body : [{ type: 'paragraph' }]),\n ],\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fences.js","names":[],"sources":["../../../src/features/composites/fences.ts"],"sourcesContent":["import type { JSONContent } from '@tiptap/core'\nimport { type CompositeFence, opaqueFenceJSON, splitCompositeFences } from '../../core/fences'\nimport { DERIVATION_KEY, keptMeta } from './meta-keys'\nimport { type BlockType, propertiesOf } from './block-types'\n\n// Inverse of the composite nodes' renderMarkdown: `::: kind #id {meta}`, `## title`, `> description`, `Tags: #a #b`, body,\n// `:::`. The fence grammar itself (`splitCompositeFences`) is shared with the Markdown entry (`core/fences`).\n//\n// Block ids in fences: a Typed block written to Markdown carries its block id in the opener (`::: paper #<uuid> {meta}`,\n// Pandoc-like `#id` between kind and meta) only when something in the same serialized content points at it — a `reference`\n// chip (`[@<id>, S. 3]`) or a `reference` meta field. Every other fence stays `::: kind {meta}`. Parsing restores the id\n// as `attrs.id`, so after a Markdown round trip (source-mode commit, import) the `[@<id>]` tokens still resolve to\n// the same Typed blocks. `withReferencedFenceIds` is the pre-pass that decides which ids are written.\nexport { type CompositeFence, type FenceSegment, splitCompositeFences } from '../../core/fences'\n\n/** `inner` fenced as composite of `kind`: `::: kind #id {meta}` (`#id` only with an `id`, meta JSON only when non-empty), `inner`, `:::`. */\nexport function compositeFence(kind: string, meta: Record<string, unknown>, inner: string, id?: string): string {\n const parts = [`::: ${kind}`]\n if (id) parts.push(`#${id}`)\n if (Object.keys(meta).length) parts.push(JSON.stringify(meta))\n return `${parts.join(' ')}\\n${inner}\\n:::`\n}\n\n/**\n * `json` with the `id` attr removed from every composite that nothing in `json` references: the Markdown renderer writes\n * the id of the composites that still have one. References are `reference` nodes (`target`) and meta values of `reference`\n * fields of the composite's kind. The input is not modified; unchanged subtrees are shared.\n */\nexport function withReferencedFenceIds(json: JSONContent, kinds: readonly BlockType[]): JSONContent {\n const referenced = new Set<string>()\n let anyId = false\n const collect = (node: JSONContent): void => {\n if (node.type === 'reference' && typeof node.attrs?.target === 'string') referenced.add(node.attrs.target)\n if (node.type === 'typedBlock') {\n if (typeof node.attrs?.id === 'string' && node.attrs.id) anyId = true\n const meta: unknown = node.attrs?.meta\n if (meta && typeof meta === 'object') {\n const kind = kinds.find(candidate => candidate.id === node.attrs?.blockType)\n for (const field of kind ? propertiesOf(kind) : []) {\n const value = (meta as Record<string, unknown>)[field.key]\n if (field.type === 'reference' && typeof value === 'string' && value) referenced.add(value)\n }\n }\n // A block-derived Typed block points at its source (`meta.derivation.from.block`): the source keeps its id across a round trip.\n const sourceBlock: unknown = node.attrs?.meta?.[DERIVATION_KEY]?.from?.block\n if (typeof sourceBlock === 'string' && sourceBlock) referenced.add(sourceBlock)\n }\n node.content?.forEach(collect)\n }\n collect(json)\n if (!anyId) return json\n const strip = (node: JSONContent): JSONContent => {\n const content = node.content?.map(strip)\n const changed = content?.some((child, index) => child !== node.content![index])\n const dropId = node.type === 'typedBlock' && typeof node.attrs?.id === 'string' && !referenced.has(node.attrs.id)\n if (!dropId && !changed) return node\n const { id: _id, ...attrs } = node.attrs ?? {}\n return { ...node, ...(dropId ? { attrs } : {}), ...(changed ? { content } : {}) }\n }\n return strip(json)\n}\n\n/**\n * Markdown segments parsed, fences of a registered kind turned into composites, in order. A fence of any other kind\n * becomes an `opaqueFence` that keeps its text verbatim.\n */\nexport function blocksFromMarkdown(parse: (md: string) => JSONContent, markdown: string, kinds: readonly BlockType[]): JSONContent[] {\n return splitCompositeFences(markdown).flatMap((segment) => {\n if (!('inner' in segment)) return parse(segment.markdown).content ?? []\n return kinds.some(kind => kind.id === segment.kind) ? [compositeFromMarkdown(parse, segment, kinds)] : [opaqueFenceJSON(segment)]\n })\n}\n\n/** Inline content of the first textblock `parse` makes of `md`. */\nfunction inlineOf(parse: (md: string) => JSONContent, md: string): JSONContent[] | undefined {\n let found: JSONContent[] | undefined\n const walk = (node: JSONContent): void => {\n if (found) return\n if (node.content?.some(child => child.type === 'text')) found = node.content\n else node.content?.forEach(walk)\n }\n if (md.trim()) walk(parse(md))\n return found?.length ? found : undefined\n}\n\n/**\n * JSON of a composite built from the fence body: first `#`-heading → title, first blockquote directly after →\n * description, a `Tags:` line → tags, rest → body (recursing for nested fences). Missing title → empty title; empty\n * body → [paragraph]. Meta of a known kind keeps only that kind's fields, plus provenance (`derivation`) and the\n * bibliographic record (`bib`), which any kind may carry.\n */\nexport function compositeFromMarkdown(parse: (md: string) => JSONContent, fence: CompositeFence, kinds: readonly BlockType[]): JSONContent {\n const lines = fence.inner.split('\\n')\n let i = 0\n const skipBlank = () => {\n while (i < lines.length && !lines[i]!.trim()) i++\n }\n skipBlank()\n let title: JSONContent[] | undefined\n const heading = /^\\s*#{1,6}(?:\\s+(.*?))?\\s*#*\\s*$/.exec(lines[i] ?? '')\n if (heading) {\n title = inlineOf(parse, heading[1] ?? '')\n i++\n skipBlank()\n }\n const quote: string[] = []\n while (i < lines.length && /^\\s*>/.test(lines[i]!)) quote.push(lines[i++]!.replace(/^\\s*>\\s?/, ''))\n const description = quote.length ? inlineOf(parse, quote.join('\\n')) : undefined\n skipBlank()\n let tags: string[] = []\n const tagLine = /^\\s*Tags:\\s*(.*)$/i.exec(lines[i] ?? '')\n if (tagLine) {\n tags = [...new Set([...tagLine[1]!.matchAll(/#?([\\p{L}\\p{N}_-]+)/gu)].map(m => m[1]!.toLowerCase()))]\n i++\n }\n const body = blocksFromMarkdown(parse, lines.slice(i).join('\\n'), kinds)\n\n // A kind outside `kinds` (only reachable when called directly; `blocksFromMarkdown` makes those fences opaque) keeps its id (the views fall back via `blockTypeOf()`) and its meta as given.\n const kind = kinds.find(candidate => candidate.id === fence.kind)\n const meta = kind ? keptMeta(kind, fence.meta) : fence.meta\n return {\n type: 'typedBlock',\n attrs: { blockType: fence.kind, ...(fence.id && { id: fence.id }), meta },\n content: [\n title ? { type: 'typedBlockTitle', content: title } : { type: 'typedBlockTitle' },\n description ? { type: 'typedBlockDescription', content: description } : { type: 'typedBlockDescription' },\n { type: 'typedBlockTags', attrs: { tags } },\n ...(body.length ? body : [{ type: 'paragraph' }]),\n ],\n }\n}\n"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { EditorState, PluginKey } from "@tiptap/pm/state";
|
|
|
3
3
|
import { Node as Node$1 } from "@tiptap/pm/model";
|
|
4
4
|
import { DecorationSet } from "@tiptap/pm/view";
|
|
5
5
|
//#region src/features/composites/focus.d.ts
|
|
6
|
-
/** State of `compositeFocusKey`: the focused
|
|
6
|
+
/** State of `compositeFocusKey`: the focused Typed block's block id (`null` = no focus) and the decorations that hide the rest. */
|
|
7
7
|
export interface CompositeFocusState {
|
|
8
8
|
id: string | null;
|
|
9
9
|
decorations: DecorationSet;
|
|
@@ -12,26 +12,26 @@ declare module '@tiptap/core' {
|
|
|
12
12
|
interface Commands<ReturnType> {
|
|
13
13
|
compositeFocus: {
|
|
14
14
|
/**
|
|
15
|
-
* Focus mode: show only the
|
|
16
|
-
* and of every ancestor are hidden); `null` ends it. False when `id` is not a
|
|
17
|
-
* the focused
|
|
15
|
+
* Focus mode: show only the Typed block with block id `id` and the titles of the Typed blocks around it (the siblings of it
|
|
16
|
+
* and of every ancestor are hidden); `null` ends it. False when `id` is not a Typed block of the document. A caret outside
|
|
17
|
+
* the focused Typed block moves into its title, so no edit lands in hidden content. Resets by itself when the Typed block is gone.
|
|
18
18
|
*/
|
|
19
19
|
focusComposite: (id: string | null) => ReturnType;
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
export declare const compositeFocusKey: PluginKey<CompositeFocusState>;
|
|
24
|
-
/** The block id of the focused
|
|
24
|
+
/** The block id of the focused Typed block in `state`, `null` without focus (or without the extension). */
|
|
25
25
|
export declare const compositeFocusOf: (state: EditorState) => string | null;
|
|
26
26
|
/**
|
|
27
|
-
* The decorations of focus mode on
|
|
28
|
-
* `sk-focus-hidden` (a
|
|
29
|
-
* keep their titles), the
|
|
27
|
+
* The decorations of focus mode on Typed block `id` in `doc`: every sibling of the Typed block and of each of its ancestors gets
|
|
28
|
+
* `sk-focus-hidden` (a Typed block's title, description and tags are not siblings in this sense: they stay, so the ancestors
|
|
29
|
+
* keep their titles), the Typed block itself `sk-focus-target`, each ancestor `sk-focus-ancestor`. Empty when `id` is not in `doc`.
|
|
30
30
|
*/
|
|
31
31
|
export declare function focusDecorations(doc: Node$1, id: string): DecorationSet;
|
|
32
32
|
/**
|
|
33
|
-
* Focus mode of
|
|
34
|
-
* when the focused
|
|
33
|
+
* Focus mode of Typed blocks (client-only, no schema): the `focusComposite` command, the plugin behind it and a reset
|
|
34
|
+
* when the focused Typed block disappears. The hiding itself is CSS on the classes the decorations carry (`composites.css`).
|
|
35
35
|
*/
|
|
36
36
|
export declare const CompositeFocus: Extension<any, any>;
|
|
37
37
|
//#endregion
|