@ecsplico/editor 3.6.0 → 4.1.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 +73 -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/code/CodeSurface.vue.d.ts +3 -3
- 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/document/DocumentSurface.vue.d.ts +3 -3
- 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 +150 -87
- package/dist/features/image-studio/components/ImageStudioDialog.js.map +1 -1
- package/dist/features/image-studio/components/ImageStudioDialog.vue.d.ts +5 -1
- package/dist/features/image-studio/components/ImageStudioLibraryPanel.js +186 -0
- package/dist/features/image-studio/components/ImageStudioLibraryPanel.js.map +1 -0
- package/dist/features/image-studio/components/ImageStudioLibraryTile.js +134 -0
- package/dist/features/image-studio/components/ImageStudioLibraryTile.js.map +1 -0
- 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/index.d.ts +3 -2
- package/dist/features/image-studio/index.js +2 -2
- package/dist/features/image-studio/library.d.ts +35 -0
- 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 +46 -5
- package/dist/features/image-studio/react/ImageStudioDialog.js.map +1 -1
- package/dist/features/image-studio/react/ImageStudioLibraryPanel.js +141 -0
- package/dist/features/image-studio/react/ImageStudioLibraryPanel.js.map +1 -0
- package/dist/features/image-studio/react/ImageStudioLibraryTile.js +105 -0
- package/dist/features/image-studio/react/ImageStudioLibraryTile.js.map +1 -0
- 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 +8 -3
- package/dist/features/image-studio/react/store.js.map +1 -1
- package/dist/features/image-studio/react.d.ts +4 -3
- package/dist/features/image-studio/react.js +3 -3
- 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 +8 -3
- package/dist/features/image-studio/state.js +11 -3
- package/dist/features/image-studio/state.js.map +1 -1
- package/dist/features/image-studio/store.d.ts +8 -3
- package/dist/features/image-studio/vue.d.ts +4 -3
- package/dist/features/image-studio/vue.js +3 -3
- package/dist/features/image-studio/vue.js.map +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 +11 -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 +110 -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/image-studio.js +9 -0
- package/dist/i18n/en/image-studio.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 +11 -11
- 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/MarkdownSurface.vue.d.ts +7 -7
- package/dist/markdown/document.js +1 -1
- package/dist/markdown/document.js.map +1 -1
- package/dist/nuxt/module.d.ts +48 -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 +7 -4
- 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 +1 -1
- 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 +9 -6
- 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 +5 -5
- 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 +10 -10
- package/dist/vue/SimpleEditor.vue.d.ts +4 -4
- package/dist/vue/components/EditorSurface.vue.d.ts +4 -4
- package/dist/vue/compose.d.ts +1 -1
- package/dist/vue/compose.js +1 -1
- 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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reveal-source.js","names":[],"sources":["../../../src/features/composites/reveal-source.ts"],"sourcesContent":["// Client-only: show a
|
|
1
|
+
{"version":3,"file":"reveal-source.js","names":[],"sources":["../../../src/features/composites/reveal-source.ts"],"sourcesContent":["// Client-only: show a Typed block's source (the media block of a source-holding Block type) at a spot. A time seeks and plays the\n// audio/video; a page number reloads the PDF viewer at that page. Composites must not import media or transcript, so\n// `seekSource` is also registered as an editor command (`SourceReveal`) for the transcript node view to call.\nimport { Extension, type Editor } from '@tiptap/core'\nimport type { Node as PMNode } from '@tiptap/pm/model'\nimport { blockIdOf, findBlockById } from '../../core/schema'\nimport { sourceOf } from './source'\nimport { blockTypesOf } from './nodes'\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n sourceReveal: {\n /** Seek and play the media of the source-holding Typed block enclosing `pos` to `seconds`; silent when there is none. */\n seekSource: (pos: number, seconds: number) => ReturnType\n }\n }\n}\n\n/** DOM event the PDF file view listens for; `detail` is the 1-based page to open the viewer at. */\nexport const REVEAL_PAGE_EVENT = 'sk-reveal-page'\n\n/** Where in the source a locator points: a time in seconds (`3:07`) or a PDF page (`S. 12`, `p. 12`, `12`). */\nexport type SourceLocator = { seconds: number } | { page: number }\n\nconst TIME_LOCATOR = /^(\\d+):(\\d{2})$/\nconst PAGE_LOCATOR = /^(?:S\\.|p\\.)?\\s*(\\d+)$/i\n\n/** Parses a reference locator; null for anything that is not a time or a page number. */\nexport function parseLocator(locator: string | null | undefined): SourceLocator | null {\n const text = locator?.trim()\n if (!text) return null\n const time = TIME_LOCATOR.exec(text)\n if (time) return { seconds: Number(time[1]) * 60 + Number(time[2]) }\n const page = PAGE_LOCATOR.exec(text)\n if (page && Number(page[1]) > 0) return { page: Number(page[1]) }\n return null\n}\n\n/** The source block of the composite `composite` at `pos` with its document position, or null. */\nfunction sourceAt(editor: Editor, composite: PMNode, pos: number): { node: PMNode, pos: number } | null {\n const source = sourceOf(composite, blockTypesOf(editor))\n if (!source) return null\n let sourcePos = pos + 1\n for (let i = 0; i < source.index; i++) sourcePos += composite.child(i).nodeSize\n return { node: source.node, pos: sourcePos }\n}\n\n/** The element of the node view at `pos` that carries the view's own listeners (the framework's wrapper), or null. */\nfunction viewElement(editor: Editor, pos: number): HTMLElement | null {\n const dom = editor.view.nodeDOM(pos)\n if (!(dom instanceof HTMLElement)) return null\n return dom.matches('[data-node-view-wrapper]') ? dom : dom.querySelector<HTMLElement>('[data-node-view-wrapper]') ?? dom\n}\n\nfunction playAt(editor: Editor, sourcePos: number, seconds: number): boolean {\n const dom = editor.view.nodeDOM(sourcePos)\n if (!(dom instanceof HTMLElement)) return false\n const media = dom.matches('audio,video') ? dom as HTMLMediaElement : dom.querySelector<HTMLMediaElement>('audio,video')\n if (!media) return false\n media.currentTime = seconds\n media.play().catch(() => { /* autoplay refused: the seek still happened */ })\n return true\n}\n\n/**\n * Seeks and plays the audio/video of the nearest source-holding Typed block around `pos` (a transcript segment inside a\n * rendition reaches the recording that way). Silent when there is no source or no media element.\n */\nexport function seekSource(editor: Editor, pos: number, seconds: number): void {\n if (!Number.isFinite(seconds) || seconds < 0) return\n const $pos = editor.state.doc.resolve(pos)\n for (let depth = $pos.depth; depth >= 0; depth--) {\n const composite = $pos.node(depth)\n if (composite.type.name !== 'typedBlock') continue\n const source = sourceAt(editor, composite, $pos.before(depth))\n if (!source) continue\n playAt(editor, source.pos, seconds)\n return\n }\n}\n\n/**\n * Shows the source of Typed block `targetId` at `locator`: a `mm:ss` time seeks the media, a page number opens a PDF source\n * at that page; then the source block flashes. Silent when the target or its source is gone.\n */\nexport function revealSource(editor: Editor, targetId: string, locator: string | null): void {\n const target = findBlockById(editor.state.doc, targetId)\n if (!target) return\n const source = sourceAt(editor, target.node, target.pos)\n if (!source) return\n const parsed = parseLocator(locator)\n if (parsed && 'seconds' in parsed) {\n playAt(editor, source.pos, parsed.seconds)\n } else if (parsed && source.node.type.name === 'file' && source.node.attrs.mimeType === 'application/pdf') {\n viewElement(editor, source.pos)?.dispatchEvent(new CustomEvent<number>(REVEAL_PAGE_EVENT, { detail: parsed.page }))\n }\n editor.commands.revealBlock(blockIdOf(source.node) ?? targetId)\n}\n\n/** Registers `seekSource` as an editor command, so features that must not import composites (transcript) can call it. */\nexport const SourceReveal = Extension.create({\n name: 'sourceReveal',\n\n addCommands() {\n return {\n // Does not dispatch: a nested dispatch would leave the command's own transaction stale.\n seekSource: (pos, seconds) => ({ editor }) => {\n seekSource(editor, pos, seconds)\n return true\n },\n }\n },\n})\n"],"mappings":";;;;;;AAmBA,MAAa,oBAAoB;AAKjC,MAAM,eAAe;AACrB,MAAM,eAAe;;AAGrB,SAAgB,aAAa,SAA0D;CACrF,MAAM,OAAO,SAAS,KAAK;CAC3B,IAAI,CAAC,MAAM,OAAO;CAClB,MAAM,OAAO,aAAa,KAAK,IAAI;CACnC,IAAI,MAAM,OAAO,EAAE,SAAS,OAAO,KAAK,EAAE,IAAI,KAAK,OAAO,KAAK,EAAE,EAAE;CACnE,MAAM,OAAO,aAAa,KAAK,IAAI;CACnC,IAAI,QAAQ,OAAO,KAAK,EAAE,IAAI,GAAG,OAAO,EAAE,MAAM,OAAO,KAAK,EAAE,EAAE;CAChE,OAAO;AACT;;AAGA,SAAS,SAAS,QAAgB,WAAmB,KAAmD;CACtG,MAAM,SAAS,SAAS,WAAW,aAAa,MAAM,CAAC;CACvD,IAAI,CAAC,QAAQ,OAAO;CACpB,IAAI,YAAY,MAAM;CACtB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,OAAO,KAAK,aAAa,UAAU,MAAM,CAAC,CAAC,CAAC;CACvE,OAAO;EAAE,MAAM,OAAO;EAAM,KAAK;CAAU;AAC7C;;AAGA,SAAS,YAAY,QAAgB,KAAiC;CACpE,MAAM,MAAM,OAAO,KAAK,QAAQ,GAAG;CACnC,IAAI,EAAE,eAAe,cAAc,OAAO;CAC1C,OAAO,IAAI,QAAQ,0BAA0B,IAAI,MAAM,IAAI,cAA2B,0BAA0B,KAAK;AACvH;AAEA,SAAS,OAAO,QAAgB,WAAmB,SAA0B;CAC3E,MAAM,MAAM,OAAO,KAAK,QAAQ,SAAS;CACzC,IAAI,EAAE,eAAe,cAAc,OAAO;CAC1C,MAAM,QAAQ,IAAI,QAAQ,aAAa,IAAI,MAA0B,IAAI,cAAgC,aAAa;CACtH,IAAI,CAAC,OAAO,OAAO;CACnB,MAAM,cAAc;CACpB,MAAM,KAAK,CAAC,CAAC,YAAY,CAAkD,CAAC;CAC5E,OAAO;AACT;;;;;AAMA,SAAgB,WAAW,QAAgB,KAAa,SAAuB;CAC7E,IAAI,CAAC,OAAO,SAAS,OAAO,KAAK,UAAU,GAAG;CAC9C,MAAM,OAAO,OAAO,MAAM,IAAI,QAAQ,GAAG;CACzC,KAAK,IAAI,QAAQ,KAAK,OAAO,SAAS,GAAG,SAAS;EAChD,MAAM,YAAY,KAAK,KAAK,KAAK;EACjC,IAAI,UAAU,KAAK,SAAS,cAAc;EAC1C,MAAM,SAAS,SAAS,QAAQ,WAAW,KAAK,OAAO,KAAK,CAAC;EAC7D,IAAI,CAAC,QAAQ;EACb,OAAO,QAAQ,OAAO,KAAK,OAAO;EAClC;CACF;AACF;;;;;AAMA,SAAgB,aAAa,QAAgB,UAAkB,SAA8B;CAC3F,MAAM,SAAS,cAAc,OAAO,MAAM,KAAK,QAAQ;CACvD,IAAI,CAAC,QAAQ;CACb,MAAM,SAAS,SAAS,QAAQ,OAAO,MAAM,OAAO,GAAG;CACvD,IAAI,CAAC,QAAQ;CACb,MAAM,SAAS,aAAa,OAAO;CACnC,IAAI,UAAU,aAAa,QACzB,OAAO,QAAQ,OAAO,KAAK,OAAO,OAAO;MACpC,IAAI,UAAU,OAAO,KAAK,KAAK,SAAS,UAAU,OAAO,KAAK,MAAM,aAAa,mBACtF,YAAY,QAAQ,OAAO,GAAG,CAAC,EAAE,cAAc,IAAI,YAAoB,mBAAmB,EAAE,QAAQ,OAAO,KAAK,CAAC,CAAC;CAEpH,OAAO,SAAS,YAAY,UAAU,OAAO,IAAI,KAAK,QAAQ;AAChE;;AAGA,MAAa,eAAe,UAAU,OAAO;CAC3C,MAAM;CAEN,cAAc;EACZ,OAAO,EAEL,aAAa,KAAK,aAAa,EAAE,aAAa;GAC5C,WAAW,QAAQ,KAAK,OAAO;GAC/B,OAAO;EACT,EACF;CACF;AACF,CAAC"}
|
|
@@ -3,7 +3,7 @@ import { CompositeMention, CompositeRow } from "./rows.js";
|
|
|
3
3
|
import { Editor } from "@tiptap/core";
|
|
4
4
|
//#region src/features/composites/rows-model.d.ts
|
|
5
5
|
/** A kind in use in the document, with how many composites have it. */
|
|
6
|
-
export interface
|
|
6
|
+
export interface BlockTypeCount {
|
|
7
7
|
id: string;
|
|
8
8
|
label: string;
|
|
9
9
|
icon: string;
|
|
@@ -16,7 +16,7 @@ export interface CompositeRowsState {
|
|
|
16
16
|
/** Distinct tags of all composites, sorted (German collation). */
|
|
17
17
|
tags: readonly string[];
|
|
18
18
|
/** Kinds in use with their counts: configured kinds in their configured order, then unknown ones in order of appearance. */
|
|
19
|
-
kinds: readonly
|
|
19
|
+
kinds: readonly BlockTypeCount[];
|
|
20
20
|
/** Distinct `@mention` chips of the document. */
|
|
21
21
|
mentions: readonly CompositeMention[];
|
|
22
22
|
/** The innermost composite around the selection head, `null` outside of any. */
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { capabilitiesOf } from "../../core/capabilities.js";
|
|
1
2
|
import { createStore } from "../../core/store.js";
|
|
2
|
-
import {
|
|
3
|
+
import { blockTypesOf } from "./nodes.js";
|
|
3
4
|
import { compositeRowAt, compositeRows } from "./rows.js";
|
|
4
5
|
//#region src/features/composites/rows-model.ts
|
|
5
6
|
const EMPTY = {
|
|
@@ -42,7 +43,7 @@ function createCompositeRows(editor) {
|
|
|
42
43
|
state: store,
|
|
43
44
|
dispose() {}
|
|
44
45
|
};
|
|
45
|
-
const kinds =
|
|
46
|
+
const kinds = blockTypesOf(editor);
|
|
46
47
|
const order = kinds.map((kind) => kind.id);
|
|
47
48
|
let frame = 0;
|
|
48
49
|
let lastDoc;
|
|
@@ -54,7 +55,7 @@ function createCompositeRows(editor) {
|
|
|
54
55
|
const current = store.get();
|
|
55
56
|
if (doc !== lastDoc) {
|
|
56
57
|
lastDoc = doc;
|
|
57
|
-
const read = compositeRows(doc, kinds);
|
|
58
|
+
const read = compositeRows(doc, kinds, (node) => capabilitiesOf(editor, node));
|
|
58
59
|
store.set({
|
|
59
60
|
rows: read.rows,
|
|
60
61
|
tags: tagsOf(read.rows),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rows-model.js","names":[],"sources":["../../../src/features/composites/rows-model.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { Node as PMNode } from '@tiptap/pm/model'\nimport { createStore, type ReadonlyStore } from '../../core/store'\nimport {
|
|
1
|
+
{"version":3,"file":"rows-model.js","names":[],"sources":["../../../src/features/composites/rows-model.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { Node as PMNode } from '@tiptap/pm/model'\nimport { capabilitiesOf } from '../../core/capabilities'\nimport { createStore, type ReadonlyStore } from '../../core/store'\nimport { blockTypesOf } from './nodes'\nimport { type CompositeMention, type CompositeRow, compositeRowAt, compositeRows } from './rows'\n\n/** A kind in use in the document, with how many composites have it. */\nexport interface BlockTypeCount {\n id: string\n label: string\n icon: string\n count: number\n}\n\n/** The live metadata read model of an editor's document (see `createCompositeRows`). */\nexport interface CompositeRowsState {\n /** Every composite in document order. */\n rows: readonly CompositeRow[]\n /** Distinct tags of all composites, sorted (German collation). */\n tags: readonly string[]\n /** Kinds in use with their counts: configured kinds in their configured order, then unknown ones in order of appearance. */\n kinds: readonly BlockTypeCount[]\n /** Distinct `@mention` chips of the document. */\n mentions: readonly CompositeMention[]\n /** The innermost composite around the selection head, `null` outside of any. */\n focused: CompositeRow | null\n}\n\n/** The composites of an editor's document as an observable state; `dispose()` detaches the editor listener (idempotent). */\nexport interface CompositeRowsHandle {\n readonly state: ReadonlyStore<CompositeRowsState>\n dispose: () => void\n}\n\nconst EMPTY: CompositeRowsState = { rows: [], tags: [], kinds: [], mentions: [], focused: null }\n\nfunction tagsOf(rows: readonly CompositeRow[]): string[] {\n return [...new Set(rows.flatMap(row => row.tags))].sort((a, b) => a.localeCompare(b, 'de'))\n}\n\nfunction kindCounts(rows: readonly CompositeRow[], order: readonly string[]): BlockTypeCount[] {\n const counts = new Map<string, BlockTypeCount>()\n for (const row of rows) {\n const entry = counts.get(row.kind)\n if (entry) entry.count++\n else counts.set(row.kind, { id: row.kind, label: row.kindLabel, icon: row.icon, count: 1 })\n }\n const rank = (id: string) => {\n const index = order.indexOf(id)\n return index < 0 ? order.length : index\n }\n // Array.sort is stable: unknown kinds (equal rank) keep their order of appearance.\n return [...counts.values()].sort((a, b) => rank(a.id) - rank(b.id))\n}\n\n/**\n * The composites of `editor`'s document as rows, kept current: re-read once per animation frame after a transaction\n * that changed the document (a selection-only change just moves `focused`). A missing or destroyed editor yields empty\n * lists. Create one model per editor (a framework hook follows an editor that changes). Use the `setComposite*` helpers\n * to write.\n */\nexport function createCompositeRows(editor: Editor | undefined): CompositeRowsHandle {\n const store = createStore<CompositeRowsState>(EMPTY)\n if (!editor || editor.isDestroyed) return { state: store, dispose() {} }\n\n const kinds = blockTypesOf(editor)\n const order = kinds.map(kind => kind.id)\n let frame = 0\n let lastDoc: PMNode | undefined\n let disposed = false\n\n const run = () => {\n frame = 0\n if (disposed || editor.isDestroyed) return\n const { doc, selection } = editor.state\n const current = store.get()\n if (doc !== lastDoc) {\n lastDoc = doc\n const read = compositeRows(doc, kinds, node => capabilitiesOf(editor, node))\n store.set({\n rows: read.rows,\n tags: tagsOf(read.rows),\n kinds: kindCounts(read.rows, order),\n mentions: read.mentions,\n focused: compositeRowAt(read.rows, selection.head),\n })\n return\n }\n const focused = compositeRowAt(current.rows, selection.head)\n if (focused !== current.focused) store.set({ ...current, focused })\n }\n const schedule = () => {\n if (!frame) frame = requestAnimationFrame(run)\n }\n\n run()\n editor.on('transaction', schedule)\n\n return {\n state: store,\n dispose() {\n if (disposed) return\n disposed = true\n editor.off('transaction', schedule)\n if (frame) cancelAnimationFrame(frame)\n frame = 0\n },\n }\n}\n"],"mappings":";;;;;AAmCA,MAAM,QAA4B;CAAE,MAAM,CAAC;CAAG,MAAM,CAAC;CAAG,OAAO,CAAC;CAAG,UAAU,CAAC;CAAG,SAAS;AAAK;AAE/F,SAAS,OAAO,MAAyC;CACvD,OAAO,CAAC,GAAG,IAAI,IAAI,KAAK,SAAQ,QAAO,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;AAC5F;AAEA,SAAS,WAAW,MAA+B,OAA4C;CAC7F,MAAM,yBAAS,IAAI,IAA4B;CAC/C,KAAK,MAAM,OAAO,MAAM;EACtB,MAAM,QAAQ,OAAO,IAAI,IAAI,IAAI;EACjC,IAAI,OAAO,MAAM;OACZ,OAAO,IAAI,IAAI,MAAM;GAAE,IAAI,IAAI;GAAM,OAAO,IAAI;GAAW,MAAM,IAAI;GAAM,OAAO;EAAE,CAAC;CAC5F;CACA,MAAM,QAAQ,OAAe;EAC3B,MAAM,QAAQ,MAAM,QAAQ,EAAE;EAC9B,OAAO,QAAQ,IAAI,MAAM,SAAS;CACpC;CAEA,OAAO,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,KAAK,EAAE,EAAE,IAAI,KAAK,EAAE,EAAE,CAAC;AACpE;;;;;;;AAQA,SAAgB,oBAAoB,QAAiD;CACnF,MAAM,QAAQ,YAAgC,KAAK;CACnD,IAAI,CAAC,UAAU,OAAO,aAAa,OAAO;EAAE,OAAO;EAAO,UAAU,CAAC;CAAE;CAEvE,MAAM,QAAQ,aAAa,MAAM;CACjC,MAAM,QAAQ,MAAM,KAAI,SAAQ,KAAK,EAAE;CACvC,IAAI,QAAQ;CACZ,IAAI;CACJ,IAAI,WAAW;CAEf,MAAM,YAAY;EAChB,QAAQ;EACR,IAAI,YAAY,OAAO,aAAa;EACpC,MAAM,EAAE,KAAK,cAAc,OAAO;EAClC,MAAM,UAAU,MAAM,IAAI;EAC1B,IAAI,QAAQ,SAAS;GACnB,UAAU;GACV,MAAM,OAAO,cAAc,KAAK,QAAO,SAAQ,eAAe,QAAQ,IAAI,CAAC;GAC3E,MAAM,IAAI;IACR,MAAM,KAAK;IACX,MAAM,OAAO,KAAK,IAAI;IACtB,OAAO,WAAW,KAAK,MAAM,KAAK;IAClC,UAAU,KAAK;IACf,SAAS,eAAe,KAAK,MAAM,UAAU,IAAI;GACnD,CAAC;GACD;EACF;EACA,MAAM,UAAU,eAAe,QAAQ,MAAM,UAAU,IAAI;EAC3D,IAAI,YAAY,QAAQ,SAAS,MAAM,IAAI;GAAE,GAAG;GAAS;EAAQ,CAAC;CACpE;CACA,MAAM,iBAAiB;EACrB,IAAI,CAAC,OAAO,QAAQ,sBAAsB,GAAG;CAC/C;CAEA,IAAI;CACJ,OAAO,GAAG,eAAe,QAAQ;CAEjC,OAAO;EACL,OAAO;EACP,UAAU;GACR,IAAI,UAAU;GACd,WAAW;GACX,OAAO,IAAI,eAAe,QAAQ;GAClC,IAAI,OAAO,qBAAqB,KAAK;GACrC,QAAQ;EACV;CACF;AACF"}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BlockType } from "./block-types.js";
|
|
2
|
+
import { BlockProperties } from "./properties.js";
|
|
2
3
|
import { Editor } from "@tiptap/core";
|
|
3
4
|
import { Node as Node$1 } from "@tiptap/pm/model";
|
|
4
5
|
//#region src/features/composites/rows.d.ts
|
|
5
|
-
/** One composite (
|
|
6
|
-
export interface CompositeRow {
|
|
7
|
-
/** Block ID, or `pos:<pos>` for a composite without one yet; unique within the document. */
|
|
8
|
-
key: string;
|
|
9
|
-
id: string | null;
|
|
10
|
-
/** Position of the composite when the row was read; the write helpers re-resolve it, so a stale value is safe. */
|
|
11
|
-
pos: number;
|
|
6
|
+
/** One composite (a Typed block) of a document with its Block properties (`key`, `id`, `pos`, `meta`, `definitions`) and chrome, flattened in document order. */
|
|
7
|
+
export interface CompositeRow extends BlockProperties {
|
|
12
8
|
/** Position right after the composite, as of when the row was read. */
|
|
13
9
|
end: number;
|
|
14
10
|
kind: string;
|
|
@@ -24,10 +20,9 @@ export interface CompositeRow {
|
|
|
24
20
|
*/
|
|
25
21
|
descriptionTextOnly: boolean;
|
|
26
22
|
tags: string[];
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
/** `false` when the composite's kind hides its tag row (`CompositeKind.chrome.tags === false`): chips, the add-tag control and the tags field stay away. */
|
|
23
|
+
/** The block capabilities the composite has (`capabilitiesOf`); the chrome and the inspector offer only what these allow (basket menu, bibliography editor). */
|
|
24
|
+
capabilities: ReadonlySet<string>;
|
|
25
|
+
/** `false` when the composite's kind hides its tag row (`BlockType.chrome.tags === false`): chips, the add-tag control and the tags field stay away. */
|
|
31
26
|
tagsVisible: boolean;
|
|
32
27
|
/** `false` when the composite's kind has `chrome.controls === false`: its chrome (basket, status, title visibility, tags, drag handle) is read-only even in an editable editor. */
|
|
33
28
|
controls: boolean;
|
|
@@ -40,11 +35,11 @@ export interface CompositeMention {
|
|
|
40
35
|
label: string;
|
|
41
36
|
color: string | null;
|
|
42
37
|
}
|
|
43
|
-
/** A reference to a
|
|
38
|
+
/** A reference to a Typed block: a `reference` chip in the text of block `from`, or a `reference` field of the Typed block `from`. */
|
|
44
39
|
export interface CompositeReference {
|
|
45
|
-
/** Block ID of the referenced
|
|
40
|
+
/** Block ID of the referenced Typed block. */
|
|
46
41
|
target: string;
|
|
47
|
-
/** Block ID of the nearest block around the chip (the
|
|
42
|
+
/** Block ID of the nearest block around the chip (the Typed block itself for a field); `null` when that block has no ID yet. */
|
|
48
43
|
from: string | null;
|
|
49
44
|
/** The chip's locator (`S. 12`, `03:14`); `null` for a field or a chip without one. */
|
|
50
45
|
locator: string | null;
|
|
@@ -52,21 +47,22 @@ export interface CompositeReference {
|
|
|
52
47
|
/**
|
|
53
48
|
* Reads every composite of `doc` (also inside quotes and lists) as a row, in document order, the distinct
|
|
54
49
|
* `@mention` chips anywhere in the document and every reference (`reference` chips and `reference` fields) in document
|
|
55
|
-
* order. Unknown kinds get the `section` kind's presentation under their own ID.
|
|
50
|
+
* order. Unknown kinds get the `section` kind's presentation under their own ID. `capabilitiesOf` answers which block
|
|
51
|
+
* capabilities a composite has (`createCompositeRows` passes the editor's); without it a row has the ones its Block type lists.
|
|
56
52
|
*/
|
|
57
|
-
export declare function compositeRows(doc: Node$1, kinds: readonly
|
|
53
|
+
export declare function compositeRows(doc: Node$1, kinds: readonly BlockType[], capabilitiesOf?: (node: Node$1) => ReadonlySet<string>): {
|
|
58
54
|
rows: CompositeRow[];
|
|
59
55
|
mentions: CompositeMention[];
|
|
60
56
|
references: CompositeReference[];
|
|
61
57
|
};
|
|
62
|
-
/** A place that refers to a
|
|
58
|
+
/** A place that refers to a Typed block: the block holding the chip (or the Typed block with the field) and a short text of it. */
|
|
63
59
|
export interface CompositeBacklink {
|
|
64
60
|
from: string;
|
|
65
61
|
locator: string | null;
|
|
66
62
|
excerpt: string;
|
|
67
63
|
}
|
|
68
|
-
/** Every reference to the
|
|
69
|
-
export declare function compositeBacklinks(doc: Node$1, kinds: readonly
|
|
64
|
+
/** Every reference to the Typed block `target` in document order; references whose enclosing block has no ID (or is gone) are left out, as nothing could reveal them. */
|
|
65
|
+
export declare function compositeBacklinks(doc: Node$1, kinds: readonly BlockType[], target: string): CompositeBacklink[];
|
|
70
66
|
/** The innermost row around document position `pos`, `null` outside of any composite. */
|
|
71
67
|
export declare function compositeRowAt(rows: readonly CompositeRow[], pos: number): CompositeRow | null;
|
|
72
68
|
/**
|
|
@@ -77,14 +73,6 @@ export declare function compositeOfRow(doc: Node$1, row: Pick<CompositeRow, 'id'
|
|
|
77
73
|
pos: number;
|
|
78
74
|
node: Node$1;
|
|
79
75
|
} | null;
|
|
80
|
-
/**
|
|
81
|
-
* `meta` with `value` stored under `field.key`: a number field converts a numeric string, an empty value (`''`,
|
|
82
|
-
* `null`, `undefined`, `NaN`) removes the key. A `multiselect` field keeps the string entries of an array value and
|
|
83
|
-
* removes the key when none is left. Returns a new object; `meta` is not changed.
|
|
84
|
-
*/
|
|
85
|
-
export declare function compositeMetaWith(meta: Record<string, unknown>, field: Pick<CompositeMetaField, 'key' | 'type'>, value: unknown): Record<string, unknown>;
|
|
86
|
-
/** Stores `value` under the meta field `key` of the row's composite (see `compositeMetaWith`), in one transaction. */
|
|
87
|
-
export declare function setCompositeMetaField(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos' | 'fields'>, key: string, value: unknown): boolean;
|
|
88
76
|
/** Replaces the tags row of the row's composite (empty names are dropped), in one transaction. */
|
|
89
77
|
export declare function setCompositeTags(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos'>, tags: readonly string[]): boolean;
|
|
90
78
|
/** The text `setCompositeDescription` stores for `text`: the description is one line, so line breaks collapse to spaces. */
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { blockIdOf, findBlockById } from "../../core/schema/block-ids.js";
|
|
2
|
-
import
|
|
2
|
+
import "../../core/schema/persisted-names.js";
|
|
3
|
+
import { blockTypeOf } from "./block-types.js";
|
|
4
|
+
import { blockPropertiesOf } from "./properties.js";
|
|
3
5
|
import { referenceLabel, referenceTarget } from "./reference-label.js";
|
|
4
6
|
//#region src/features/composites/rows.ts
|
|
5
|
-
const COMPOSITE = "composite";
|
|
6
7
|
/** True when `node`'s content is empty or text only (with any marks, but no inline nodes such as mentions or tags). */
|
|
7
8
|
function isTextOnly(node) {
|
|
8
9
|
let textOnly = true;
|
|
@@ -14,24 +15,24 @@ function isTextOnly(node) {
|
|
|
14
15
|
/**
|
|
15
16
|
* Reads every composite of `doc` (also inside quotes and lists) as a row, in document order, the distinct
|
|
16
17
|
* `@mention` chips anywhere in the document and every reference (`reference` chips and `reference` fields) in document
|
|
17
|
-
* order. Unknown kinds get the `section` kind's presentation under their own ID.
|
|
18
|
+
* order. Unknown kinds get the `section` kind's presentation under their own ID. `capabilitiesOf` answers which block
|
|
19
|
+
* capabilities a composite has (`createCompositeRows` passes the editor's); without it a row has the ones its Block type lists.
|
|
18
20
|
*/
|
|
19
|
-
function compositeRows(doc, kinds) {
|
|
21
|
+
function compositeRows(doc, kinds, capabilitiesOf) {
|
|
20
22
|
const rows = [];
|
|
21
23
|
const mentions = /* @__PURE__ */ new Map();
|
|
22
24
|
const references = [];
|
|
23
25
|
function walk(parent, start, depth, block) {
|
|
24
26
|
parent.forEach((node, offset) => {
|
|
25
27
|
const pos = start + offset;
|
|
26
|
-
if (node.type.name ===
|
|
27
|
-
const kind =
|
|
28
|
+
if (node.type.name === "typedBlock") {
|
|
29
|
+
const kind = blockTypeOf(kinds, String(node.attrs.blockType));
|
|
28
30
|
const id = blockIdOf(node);
|
|
29
31
|
const tags = node.maybeChild(2)?.attrs.tags;
|
|
30
32
|
const description = node.maybeChild(1);
|
|
33
|
+
const capabilities = capabilitiesOf?.(node) ?? new Set(kind.capabilities.map((entry) => entry.id));
|
|
31
34
|
const row = {
|
|
32
|
-
|
|
33
|
-
id,
|
|
34
|
-
pos,
|
|
35
|
+
...blockPropertiesOf(node, pos, kinds, capabilities),
|
|
35
36
|
end: pos + node.nodeSize,
|
|
36
37
|
kind: kind.id,
|
|
37
38
|
kindLabel: kind.label,
|
|
@@ -40,14 +41,13 @@ function compositeRows(doc, kinds) {
|
|
|
40
41
|
description: description?.textContent ?? "",
|
|
41
42
|
descriptionTextOnly: description ? isTextOnly(description) : true,
|
|
42
43
|
tags: Array.isArray(tags) ? tags.filter((tag) => typeof tag === "string") : [],
|
|
43
|
-
|
|
44
|
-
fields: kind.fields,
|
|
44
|
+
capabilities,
|
|
45
45
|
tagsVisible: kind.chrome?.tags !== false,
|
|
46
46
|
controls: kind.chrome?.controls !== false,
|
|
47
47
|
depth
|
|
48
48
|
};
|
|
49
49
|
rows.push(row);
|
|
50
|
-
for (const field of
|
|
50
|
+
for (const field of row.definitions) {
|
|
51
51
|
const value = field.type === "reference" ? row.meta[field.key] : void 0;
|
|
52
52
|
if (typeof value === "string" && value) references.push({
|
|
53
53
|
target: value,
|
|
@@ -90,21 +90,21 @@ function visibleText(doc, kinds, node) {
|
|
|
90
90
|
case "tag": return `#${String(attrs.name ?? "")}`;
|
|
91
91
|
case "reference": {
|
|
92
92
|
const target = findBlockById(doc, String(attrs.target ?? ""));
|
|
93
|
-
const label = target?.node.type.name ===
|
|
93
|
+
const label = target?.node.type.name === "typedBlock" ? referenceLabel(referenceTarget(target.node, kinds)) : String(attrs.label ?? "");
|
|
94
94
|
return typeof attrs.locator === "string" && attrs.locator ? `${label}, ${attrs.locator}` : label;
|
|
95
95
|
}
|
|
96
96
|
default: return "";
|
|
97
97
|
}
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
|
-
/** Every reference to the
|
|
100
|
+
/** Every reference to the Typed block `target` in document order; references whose enclosing block has no ID (or is gone) are left out, as nothing could reveal them. */
|
|
101
101
|
function compositeBacklinks(doc, kinds, target) {
|
|
102
102
|
const links = [];
|
|
103
103
|
for (const reference of compositeRows(doc, kinds).references) {
|
|
104
104
|
if (reference.target !== target || !reference.from) continue;
|
|
105
105
|
const found = findBlockById(doc, reference.from);
|
|
106
106
|
if (!found) continue;
|
|
107
|
-
const source = found.node.type.name ===
|
|
107
|
+
const source = found.node.type.name === "typedBlock" ? found.node.firstChild : found.node;
|
|
108
108
|
const text = source ? visibleText(doc, kinds, source).trim() : "";
|
|
109
109
|
links.push({
|
|
110
110
|
from: reference.from,
|
|
@@ -127,48 +127,14 @@ function compositeRowAt(rows, pos) {
|
|
|
127
127
|
function compositeOfRow(doc, row) {
|
|
128
128
|
if (row.id) {
|
|
129
129
|
const found = findBlockById(doc, row.id);
|
|
130
|
-
return found?.node.type.name ===
|
|
130
|
+
return found?.node.type.name === "typedBlock" ? found : null;
|
|
131
131
|
}
|
|
132
132
|
const node = doc.nodeAt(row.pos);
|
|
133
|
-
return node?.type.name ===
|
|
133
|
+
return node?.type.name === "typedBlock" ? {
|
|
134
134
|
pos: row.pos,
|
|
135
135
|
node
|
|
136
136
|
} : null;
|
|
137
137
|
}
|
|
138
|
-
/**
|
|
139
|
-
* `meta` with `value` stored under `field.key`: a number field converts a numeric string, an empty value (`''`,
|
|
140
|
-
* `null`, `undefined`, `NaN`) removes the key. A `multiselect` field keeps the string entries of an array value and
|
|
141
|
-
* removes the key when none is left. Returns a new object; `meta` is not changed.
|
|
142
|
-
*/
|
|
143
|
-
function compositeMetaWith(meta, field, value) {
|
|
144
|
-
const next = { ...meta };
|
|
145
|
-
if (field.type === "multiselect") {
|
|
146
|
-
const chosen = Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
147
|
-
if (chosen.length) next[field.key] = chosen;
|
|
148
|
-
else delete next[field.key];
|
|
149
|
-
return next;
|
|
150
|
-
}
|
|
151
|
-
const stored = field.type === "number" && typeof value === "string" && value !== "" ? Number(value) : value;
|
|
152
|
-
if (stored === "" || stored === null || stored === void 0 || Number.isNaN(stored)) delete next[field.key];
|
|
153
|
-
else next[field.key] = stored;
|
|
154
|
-
return next;
|
|
155
|
-
}
|
|
156
|
-
/** Stores `value` under the meta field `key` of the row's composite (see `compositeMetaWith`), in one transaction. */
|
|
157
|
-
function setCompositeMetaField(editor, row, key, value) {
|
|
158
|
-
const field = row.fields.find((candidate) => candidate.key === key) ?? {
|
|
159
|
-
key,
|
|
160
|
-
type: "text"
|
|
161
|
-
};
|
|
162
|
-
return editor.commands.command(({ tr }) => {
|
|
163
|
-
const found = compositeOfRow(tr.doc, row);
|
|
164
|
-
if (!found) return false;
|
|
165
|
-
tr.setNodeMarkup(found.pos, void 0, {
|
|
166
|
-
...found.node.attrs,
|
|
167
|
-
meta: compositeMetaWith(found.node.attrs.meta ?? {}, field, value)
|
|
168
|
-
});
|
|
169
|
-
return true;
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
138
|
/** Replaces the tags row of the row's composite (empty names are dropped), in one transaction. */
|
|
173
139
|
function setCompositeTags(editor, row, tags) {
|
|
174
140
|
return editor.commands.command(({ tr }) => {
|
|
@@ -176,7 +142,7 @@ function setCompositeTags(editor, row, tags) {
|
|
|
176
142
|
const title = found?.node.maybeChild(0);
|
|
177
143
|
const description = found?.node.maybeChild(1);
|
|
178
144
|
const tagsNode = found?.node.maybeChild(2);
|
|
179
|
-
if (!found || !title || !description || tagsNode?.type.name !== "
|
|
145
|
+
if (!found || !title || !description || tagsNode?.type.name !== "typedBlockTags") return false;
|
|
180
146
|
const tagsPos = found.pos + 1 + title.nodeSize + description.nodeSize;
|
|
181
147
|
tr.setNodeMarkup(tagsPos, void 0, {
|
|
182
148
|
...tagsNode.attrs,
|
|
@@ -201,7 +167,7 @@ function setCompositeDescription(editor, row, text, expected) {
|
|
|
201
167
|
const found = compositeOfRow(tr.doc, row);
|
|
202
168
|
const title = found?.node.maybeChild(0);
|
|
203
169
|
const description = found?.node.maybeChild(1);
|
|
204
|
-
if (!found || !title || !description || description.type.name !== "
|
|
170
|
+
if (!found || !title || !description || description.type.name !== "typedBlockDescription") return false;
|
|
205
171
|
if (!isTextOnly(description)) return false;
|
|
206
172
|
const current = description.textContent;
|
|
207
173
|
if (expected !== void 0 && current !== expected) return false;
|
|
@@ -217,6 +183,6 @@ function setCompositeDescription(editor, row, text, expected) {
|
|
|
217
183
|
});
|
|
218
184
|
}
|
|
219
185
|
//#endregion
|
|
220
|
-
export { compositeBacklinks, compositeDescriptionText,
|
|
186
|
+
export { compositeBacklinks, compositeDescriptionText, compositeOfRow, compositeRowAt, compositeRows, setCompositeDescription, setCompositeTags };
|
|
221
187
|
|
|
222
188
|
//# sourceMappingURL=rows.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rows.js","names":[],"sources":["../../../src/features/composites/rows.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { Node as PMNode } from '@tiptap/pm/model'\nimport { blockIdOf, findBlockById } from '../../core/schema'\nimport { type CompositeKind, type CompositeMetaField, compositeKind } from './kinds'\nimport { referenceLabel, referenceTarget } from './reference-label'\n\n/** One composite („Baustein“) of a document with its metadata, flattened in document order. */\nexport interface CompositeRow {\n /** Block ID, or `pos:<pos>` for a composite without one yet; unique within the document. */\n key: string\n id: string | null\n /** Position of the composite when the row was read; the write helpers re-resolve it, so a stale value is safe. */\n pos: number\n /** Position right after the composite, as of when the row was read. */\n end: number\n kind: string\n kindLabel: string\n icon: string\n /** Title text, empty for an untitled composite. */\n title: string\n /** Text of the description (summary), empty when there is none. */\n description: string\n /**\n * The description holds text only (marks such as bold, author or comment allowed, no mentions or tags); only then\n * can `setCompositeDescription` write it without losing inline content.\n */\n descriptionTextOnly: boolean\n tags: string[]\n meta: Record<string, unknown>\n /** The meta fields of the composite's kind. */\n fields: readonly CompositeMetaField[]\n /** `false` when the composite's kind hides its tag row (`CompositeKind.chrome.tags === false`): chips, the add-tag control and the tags field stay away. */\n tagsVisible: boolean\n /** `false` when the composite's kind has `chrome.controls === false`: its chrome (basket, status, title visibility, tags, drag handle) is read-only even in an editable editor. */\n controls: boolean\n /** Nesting level among composites, 0 = outermost. */\n depth: number\n}\n\n/** A distinct `@mention` chip of a document. */\nexport interface CompositeMention {\n id: string\n label: string\n color: string | null\n}\n\n/** A reference to a Baustein: a `reference` chip in the text of block `from`, or a `reference` field of the Baustein `from`. */\nexport interface CompositeReference {\n /** Block ID of the referenced Baustein. */\n target: string\n /** Block ID of the nearest block around the chip (the Baustein itself for a field); `null` when that block has no ID yet. */\n from: string | null\n /** The chip's locator (`S. 12`, `03:14`); `null` for a field or a chip without one. */\n locator: string | null\n}\n\nconst COMPOSITE = 'composite'\n\n/** True when `node`'s content is empty or text only (with any marks, but no inline nodes such as mentions or tags). */\nfunction isTextOnly(node: PMNode): boolean {\n let textOnly = true\n node.forEach((child) => {\n if (!child.isText) textOnly = false\n })\n return textOnly\n}\n\n/**\n * Reads every composite of `doc` (also inside quotes and lists) as a row, in document order, the distinct\n * `@mention` chips anywhere in the document and every reference (`reference` chips and `reference` fields) in document\n * order. Unknown kinds get the `section` kind's presentation under their own ID.\n */\nexport function compositeRows(doc: PMNode, kinds: readonly CompositeKind[]): { rows: CompositeRow[], mentions: CompositeMention[], references: CompositeReference[] } {\n const rows: CompositeRow[] = []\n const mentions = new Map<string, CompositeMention>()\n const references: CompositeReference[] = []\n\n function walk(parent: PMNode, start: number, depth: number, block: string | null) {\n parent.forEach((node, offset) => {\n const pos = start + offset\n if (node.type.name === COMPOSITE) {\n const kind = compositeKind(kinds, String(node.attrs.kind))\n const id = blockIdOf(node)\n const tags: unknown = node.maybeChild(2)?.attrs.tags\n const description = node.maybeChild(1)\n const row: CompositeRow = {\n key: id ?? `pos:${pos}`,\n id,\n pos,\n end: pos + node.nodeSize,\n kind: kind.id,\n kindLabel: kind.label,\n icon: kind.icon,\n title: node.firstChild?.textContent.trim() ?? '',\n description: description?.textContent ?? '',\n descriptionTextOnly: description ? isTextOnly(description) : true,\n tags: Array.isArray(tags) ? tags.filter((tag): tag is string => typeof tag === 'string') : [],\n meta: (node.attrs.meta ?? {}) as Record<string, unknown>,\n fields: kind.fields,\n tagsVisible: kind.chrome?.tags !== false,\n controls: kind.chrome?.controls !== false,\n depth,\n }\n rows.push(row)\n for (const field of kind.fields) {\n const value = field.type === 'reference' ? row.meta[field.key] : undefined\n if (typeof value === 'string' && value) references.push({ target: value, from: id, locator: null })\n }\n walk(node, pos + 1, depth + 1, id ?? block)\n }\n else if (node.type.name === 'reference') {\n const target = String(node.attrs.target ?? '')\n if (target) references.push({ target, from: block, locator: typeof node.attrs.locator === 'string' && node.attrs.locator ? node.attrs.locator : null })\n }\n else if (node.type.name === 'mention') {\n const mentionId = String(node.attrs.id ?? '')\n if (mentionId && !mentions.has(mentionId)) {\n mentions.set(mentionId, {\n id: mentionId,\n label: String(node.attrs.label ?? mentionId),\n color: typeof node.attrs.color === 'string' ? node.attrs.color : null,\n })\n }\n }\n else if (!node.isLeaf) {\n walk(node, pos + 1, depth, blockIdOf(node) ?? block)\n }\n })\n }\n walk(doc, 0, 0, null)\n return { rows, mentions: [...mentions.values()], references }\n}\n\n/** A place that refers to a Baustein: the block holding the chip (or the Baustein with the field) and a short text of it. */\nexport interface CompositeBacklink {\n from: string\n locator: string | null\n excerpt: string\n}\n\nconst EXCERPT_LENGTH = 40\n\n/** The text of `node` as read on screen: inline atoms count as their label (`@name`, `#tag`, a reference chip's short citation + locator), not as nothing. */\nfunction visibleText(doc: PMNode, kinds: readonly CompositeKind[], node: PMNode): string {\n return node.textBetween(0, node.content.size, ' ', (leaf) => {\n const attrs = leaf.attrs\n switch (leaf.type.name) {\n case 'mention': return `@${String(attrs.label ?? attrs.id ?? '')}`\n case 'tag': return `#${String(attrs.name ?? '')}`\n case 'reference': {\n const target = findBlockById(doc, String(attrs.target ?? ''))\n const label = target?.node.type.name === COMPOSITE ? referenceLabel(referenceTarget(target.node, kinds)) : String(attrs.label ?? '')\n return typeof attrs.locator === 'string' && attrs.locator ? `${label}, ${attrs.locator}` : label\n }\n default: return ''\n }\n })\n}\n\n/** Every reference to the Baustein `target` in document order; references whose enclosing block has no ID (or is gone) are left out, as nothing could reveal them. */\nexport function compositeBacklinks(doc: PMNode, kinds: readonly CompositeKind[], target: string): CompositeBacklink[] {\n const links: CompositeBacklink[] = []\n for (const reference of compositeRows(doc, kinds).references) {\n if (reference.target !== target || !reference.from) continue\n const found = findBlockById(doc, reference.from)\n if (!found) continue\n const source = found.node.type.name === COMPOSITE ? found.node.firstChild : found.node\n const text = source ? visibleText(doc, kinds, source).trim() : ''\n links.push({ from: reference.from, locator: reference.locator, excerpt: text.length > EXCERPT_LENGTH ? `${text.slice(0, EXCERPT_LENGTH)}…` : text })\n }\n return links\n}\n\n/** The innermost row around document position `pos`, `null` outside of any composite. */\nexport function compositeRowAt(rows: readonly CompositeRow[], pos: number): CompositeRow | null {\n let found: CompositeRow | null = null\n // Pre-order: the last match is the innermost composite.\n for (const row of rows) {\n if (row.pos <= pos && pos < row.end) found = row\n }\n return found\n}\n\n/**\n * The composite `row` stands for in `doc`: by block ID, else (the row has no ID yet) by its position.\n * Positions are re-resolved on every call, so a stale `row.pos` is safe for rows with an ID.\n */\nexport function compositeOfRow(doc: PMNode, row: Pick<CompositeRow, 'id' | 'pos'>): { pos: number, node: PMNode } | null {\n if (row.id) {\n const found = findBlockById(doc, row.id)\n return found?.node.type.name === COMPOSITE ? found : null\n }\n const node = doc.nodeAt(row.pos)\n return node?.type.name === COMPOSITE ? { pos: row.pos, node } : null\n}\n\n/**\n * `meta` with `value` stored under `field.key`: a number field converts a numeric string, an empty value (`''`,\n * `null`, `undefined`, `NaN`) removes the key. A `multiselect` field keeps the string entries of an array value and\n * removes the key when none is left. Returns a new object; `meta` is not changed.\n */\nexport function compositeMetaWith(meta: Record<string, unknown>, field: Pick<CompositeMetaField, 'key' | 'type'>, value: unknown): Record<string, unknown> {\n const next = { ...meta }\n if (field.type === 'multiselect') {\n const chosen = Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string') : []\n if (chosen.length) next[field.key] = chosen\n else delete next[field.key]\n return next\n }\n const stored = field.type === 'number' && typeof value === 'string' && value !== '' ? Number(value) : value\n if (stored === '' || stored === null || stored === undefined || Number.isNaN(stored)) delete next[field.key]\n else next[field.key] = stored\n return next\n}\n\n/** Stores `value` under the meta field `key` of the row's composite (see `compositeMetaWith`), in one transaction. */\nexport function setCompositeMetaField(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos' | 'fields'>, key: string, value: unknown): boolean {\n const field = row.fields.find(candidate => candidate.key === key) ?? { key, type: 'text' as const }\n return editor.commands.command(({ tr }) => {\n const found = compositeOfRow(tr.doc, row)\n if (!found) return false\n tr.setNodeMarkup(found.pos, undefined, { ...found.node.attrs, meta: compositeMetaWith(found.node.attrs.meta ?? {}, field, value) })\n return true\n })\n}\n\n/** Replaces the tags row of the row's composite (empty names are dropped), in one transaction. */\nexport function setCompositeTags(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos'>, tags: readonly string[]): boolean {\n return editor.commands.command(({ tr }) => {\n const found = compositeOfRow(tr.doc, row)\n const title = found?.node.maybeChild(0)\n const description = found?.node.maybeChild(1)\n const tagsNode = found?.node.maybeChild(2)\n if (!found || !title || !description || tagsNode?.type.name !== 'compositeTags') return false\n const tagsPos = found.pos + 1 + title.nodeSize + description.nodeSize\n tr.setNodeMarkup(tagsPos, undefined, { ...tagsNode.attrs, tags: tags.filter(tag => tag) })\n return true\n })\n}\n\n/** The text `setCompositeDescription` stores for `text`: the description is one line, so line breaks collapse to spaces. */\nexport function compositeDescriptionText(text: string): string {\n return text.replace(/\\s*\\n\\s*/g, ' ').trim()\n}\n\n/**\n * Sets the text of the row's composite description to `compositeDescriptionText(text)`; an empty text empties it.\n * Only the changed span is replaced, so marks on the unchanged text (bold, author, comment) stay. Refuses (`false`)\n * when the description holds a mention or tag (it would be lost), and, when `expected` is given, when the\n * description no longer holds that text (a peer changed it since the caller read it; writing would drop that change).\n */\nexport function setCompositeDescription(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos'>, text: string, expected?: string): boolean {\n const value = compositeDescriptionText(text)\n return editor.commands.command(({ tr }) => {\n const found = compositeOfRow(tr.doc, row)\n const title = found?.node.maybeChild(0)\n const description = found?.node.maybeChild(1)\n if (!found || !title || !description || description.type.name !== 'compositeDescription') return false\n if (!isTextOnly(description)) return false\n const current = description.textContent\n if (expected !== undefined && current !== expected) return false\n if (current === value) return true\n // Text only: every character is one position. Keep the common prefix and suffix, replace what lies between.\n let prefix = 0\n const max = Math.min(current.length, value.length)\n while (prefix < max && current[prefix] === value[prefix]) prefix++\n let suffix = 0\n while (suffix < max - prefix && current[current.length - 1 - suffix] === value[value.length - 1 - suffix]) suffix++\n const start = found.pos + 1 + title.nodeSize + 1\n // `insertText` with an empty text deletes the range; inserted text takes the marks at its start, as typing does.\n tr.insertText(value.slice(prefix, value.length - suffix), start + prefix, start + current.length - suffix)\n return true\n })\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rows.js","names":[],"sources":["../../../src/features/composites/rows.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport type { Node as PMNode } from '@tiptap/pm/model'\nimport { blockIdOf, findBlockById, TYPED_BLOCK, TYPED_BLOCK_DESCRIPTION, TYPED_BLOCK_TAGS } from '../../core/schema'\nimport { type BlockType, blockTypeOf } from './block-types'\nimport { type BlockProperties, blockPropertiesOf } from './properties'\nimport { referenceLabel, referenceTarget } from './reference-label'\n\n/** One composite (a Typed block) of a document with its Block properties (`key`, `id`, `pos`, `meta`, `definitions`) and chrome, flattened in document order. */\nexport interface CompositeRow extends BlockProperties {\n /** Position right after the composite, as of when the row was read. */\n end: number\n kind: string\n kindLabel: string\n icon: string\n /** Title text, empty for an untitled composite. */\n title: string\n /** Text of the description (summary), empty when there is none. */\n description: string\n /**\n * The description holds text only (marks such as bold, author or comment allowed, no mentions or tags); only then\n * can `setCompositeDescription` write it without losing inline content.\n */\n descriptionTextOnly: boolean\n tags: string[]\n /** The block capabilities the composite has (`capabilitiesOf`); the chrome and the inspector offer only what these allow (basket menu, bibliography editor). */\n capabilities: ReadonlySet<string>\n /** `false` when the composite's kind hides its tag row (`BlockType.chrome.tags === false`): chips, the add-tag control and the tags field stay away. */\n tagsVisible: boolean\n /** `false` when the composite's kind has `chrome.controls === false`: its chrome (basket, status, title visibility, tags, drag handle) is read-only even in an editable editor. */\n controls: boolean\n /** Nesting level among composites, 0 = outermost. */\n depth: number\n}\n\n/** A distinct `@mention` chip of a document. */\nexport interface CompositeMention {\n id: string\n label: string\n color: string | null\n}\n\n/** A reference to a Typed block: a `reference` chip in the text of block `from`, or a `reference` field of the Typed block `from`. */\nexport interface CompositeReference {\n /** Block ID of the referenced Typed block. */\n target: string\n /** Block ID of the nearest block around the chip (the Typed block itself for a field); `null` when that block has no ID yet. */\n from: string | null\n /** The chip's locator (`S. 12`, `03:14`); `null` for a field or a chip without one. */\n locator: string | null\n}\n\n/** True when `node`'s content is empty or text only (with any marks, but no inline nodes such as mentions or tags). */\nfunction isTextOnly(node: PMNode): boolean {\n let textOnly = true\n node.forEach((child) => {\n if (!child.isText) textOnly = false\n })\n return textOnly\n}\n\n/**\n * Reads every composite of `doc` (also inside quotes and lists) as a row, in document order, the distinct\n * `@mention` chips anywhere in the document and every reference (`reference` chips and `reference` fields) in document\n * order. Unknown kinds get the `section` kind's presentation under their own ID. `capabilitiesOf` answers which block\n * capabilities a composite has (`createCompositeRows` passes the editor's); without it a row has the ones its Block type lists.\n */\nexport function compositeRows(doc: PMNode, kinds: readonly BlockType[], capabilitiesOf?: (node: PMNode) => ReadonlySet<string>): { rows: CompositeRow[], mentions: CompositeMention[], references: CompositeReference[] } {\n const rows: CompositeRow[] = []\n const mentions = new Map<string, CompositeMention>()\n const references: CompositeReference[] = []\n\n function walk(parent: PMNode, start: number, depth: number, block: string | null) {\n parent.forEach((node, offset) => {\n const pos = start + offset\n if (node.type.name === TYPED_BLOCK) {\n const kind = blockTypeOf(kinds, String(node.attrs.blockType))\n const id = blockIdOf(node)\n const tags: unknown = node.maybeChild(2)?.attrs.tags\n const description = node.maybeChild(1)\n const capabilities = capabilitiesOf?.(node) ?? new Set(kind.capabilities.map(entry => entry.id))\n const properties = blockPropertiesOf(node, pos, kinds, capabilities)\n const row: CompositeRow = {\n ...properties,\n end: pos + node.nodeSize,\n kind: kind.id,\n kindLabel: kind.label,\n icon: kind.icon,\n title: node.firstChild?.textContent.trim() ?? '',\n description: description?.textContent ?? '',\n descriptionTextOnly: description ? isTextOnly(description) : true,\n tags: Array.isArray(tags) ? tags.filter((tag): tag is string => typeof tag === 'string') : [],\n capabilities,\n tagsVisible: kind.chrome?.tags !== false,\n controls: kind.chrome?.controls !== false,\n depth,\n }\n rows.push(row)\n for (const field of row.definitions) {\n const value = field.type === 'reference' ? row.meta[field.key] : undefined\n if (typeof value === 'string' && value) references.push({ target: value, from: id, locator: null })\n }\n walk(node, pos + 1, depth + 1, id ?? block)\n }\n else if (node.type.name === 'reference') {\n const target = String(node.attrs.target ?? '')\n if (target) references.push({ target, from: block, locator: typeof node.attrs.locator === 'string' && node.attrs.locator ? node.attrs.locator : null })\n }\n else if (node.type.name === 'mention') {\n const mentionId = String(node.attrs.id ?? '')\n if (mentionId && !mentions.has(mentionId)) {\n mentions.set(mentionId, {\n id: mentionId,\n label: String(node.attrs.label ?? mentionId),\n color: typeof node.attrs.color === 'string' ? node.attrs.color : null,\n })\n }\n }\n else if (!node.isLeaf) {\n walk(node, pos + 1, depth, blockIdOf(node) ?? block)\n }\n })\n }\n walk(doc, 0, 0, null)\n return { rows, mentions: [...mentions.values()], references }\n}\n\n/** A place that refers to a Typed block: the block holding the chip (or the Typed block with the field) and a short text of it. */\nexport interface CompositeBacklink {\n from: string\n locator: string | null\n excerpt: string\n}\n\nconst EXCERPT_LENGTH = 40\n\n/** The text of `node` as read on screen: inline atoms count as their label (`@name`, `#tag`, a reference chip's short citation + locator), not as nothing. */\nfunction visibleText(doc: PMNode, kinds: readonly BlockType[], node: PMNode): string {\n return node.textBetween(0, node.content.size, ' ', (leaf) => {\n const attrs = leaf.attrs\n switch (leaf.type.name) {\n case 'mention': return `@${String(attrs.label ?? attrs.id ?? '')}`\n case 'tag': return `#${String(attrs.name ?? '')}`\n case 'reference': {\n const target = findBlockById(doc, String(attrs.target ?? ''))\n const label = target?.node.type.name === TYPED_BLOCK ? referenceLabel(referenceTarget(target.node, kinds)) : String(attrs.label ?? '')\n return typeof attrs.locator === 'string' && attrs.locator ? `${label}, ${attrs.locator}` : label\n }\n default: return ''\n }\n })\n}\n\n/** Every reference to the Typed block `target` in document order; references whose enclosing block has no ID (or is gone) are left out, as nothing could reveal them. */\nexport function compositeBacklinks(doc: PMNode, kinds: readonly BlockType[], target: string): CompositeBacklink[] {\n const links: CompositeBacklink[] = []\n for (const reference of compositeRows(doc, kinds).references) {\n if (reference.target !== target || !reference.from) continue\n const found = findBlockById(doc, reference.from)\n if (!found) continue\n const source = found.node.type.name === TYPED_BLOCK ? found.node.firstChild : found.node\n const text = source ? visibleText(doc, kinds, source).trim() : ''\n links.push({ from: reference.from, locator: reference.locator, excerpt: text.length > EXCERPT_LENGTH ? `${text.slice(0, EXCERPT_LENGTH)}…` : text })\n }\n return links\n}\n\n/** The innermost row around document position `pos`, `null` outside of any composite. */\nexport function compositeRowAt(rows: readonly CompositeRow[], pos: number): CompositeRow | null {\n let found: CompositeRow | null = null\n // Pre-order: the last match is the innermost composite.\n for (const row of rows) {\n if (row.pos <= pos && pos < row.end) found = row\n }\n return found\n}\n\n/**\n * The composite `row` stands for in `doc`: by block ID, else (the row has no ID yet) by its position.\n * Positions are re-resolved on every call, so a stale `row.pos` is safe for rows with an ID.\n */\nexport function compositeOfRow(doc: PMNode, row: Pick<CompositeRow, 'id' | 'pos'>): { pos: number, node: PMNode } | null {\n if (row.id) {\n const found = findBlockById(doc, row.id)\n return found?.node.type.name === TYPED_BLOCK ? found : null\n }\n const node = doc.nodeAt(row.pos)\n return node?.type.name === TYPED_BLOCK ? { pos: row.pos, node } : null\n}\n\n/** Replaces the tags row of the row's composite (empty names are dropped), in one transaction. */\nexport function setCompositeTags(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos'>, tags: readonly string[]): boolean {\n return editor.commands.command(({ tr }) => {\n const found = compositeOfRow(tr.doc, row)\n const title = found?.node.maybeChild(0)\n const description = found?.node.maybeChild(1)\n const tagsNode = found?.node.maybeChild(2)\n if (!found || !title || !description || tagsNode?.type.name !== TYPED_BLOCK_TAGS) return false\n const tagsPos = found.pos + 1 + title.nodeSize + description.nodeSize\n tr.setNodeMarkup(tagsPos, undefined, { ...tagsNode.attrs, tags: tags.filter(tag => tag) })\n return true\n })\n}\n\n/** The text `setCompositeDescription` stores for `text`: the description is one line, so line breaks collapse to spaces. */\nexport function compositeDescriptionText(text: string): string {\n return text.replace(/\\s*\\n\\s*/g, ' ').trim()\n}\n\n/**\n * Sets the text of the row's composite description to `compositeDescriptionText(text)`; an empty text empties it.\n * Only the changed span is replaced, so marks on the unchanged text (bold, author, comment) stay. Refuses (`false`)\n * when the description holds a mention or tag (it would be lost), and, when `expected` is given, when the\n * description no longer holds that text (a peer changed it since the caller read it; writing would drop that change).\n */\nexport function setCompositeDescription(editor: Editor, row: Pick<CompositeRow, 'id' | 'pos'>, text: string, expected?: string): boolean {\n const value = compositeDescriptionText(text)\n return editor.commands.command(({ tr }) => {\n const found = compositeOfRow(tr.doc, row)\n const title = found?.node.maybeChild(0)\n const description = found?.node.maybeChild(1)\n if (!found || !title || !description || description.type.name !== TYPED_BLOCK_DESCRIPTION) return false\n if (!isTextOnly(description)) return false\n const current = description.textContent\n if (expected !== undefined && current !== expected) return false\n if (current === value) return true\n // Text only: every character is one position. Keep the common prefix and suffix, replace what lies between.\n let prefix = 0\n const max = Math.min(current.length, value.length)\n while (prefix < max && current[prefix] === value[prefix]) prefix++\n let suffix = 0\n while (suffix < max - prefix && current[current.length - 1 - suffix] === value[value.length - 1 - suffix]) suffix++\n const start = found.pos + 1 + title.nodeSize + 1\n // `insertText` with an empty text deletes the range; inserted text takes the marks at its start, as typing does.\n tr.insertText(value.slice(prefix, value.length - suffix), start + prefix, start + current.length - suffix)\n return true\n })\n}\n"],"mappings":"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"}
|
|
@@ -1,29 +1,30 @@
|
|
|
1
1
|
import { CSL_TYPES, CslDate, CslItem, CslName, CslType } from "../../core/backend-types.js";
|
|
2
|
-
import { CompositeAiBrief, compositeAiBrief } from "./ai-brief.js";
|
|
3
|
-
import { CompositeKind, CompositeKindAi, CompositeMetaField, SOURCE_MEDIA_TYPES, compositeKind, defaultCompositeKinds, kindAccepts } from "./kinds.js";
|
|
4
2
|
import { BASKET_IDS, Basket, basketById, basketOf, defaultBaskets, titleHiddenOf } from "./baskets.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { BlockType, BlockTypeAi, ContainerConfig, ImportConfig, PropertiesConfig, SOURCE_MEDIA_TYPES, SourceConfig, SourceMedia, acceptsChild, acceptsImport, acceptsOf, aiBlockTypesOf, aiBriefOf, blockTypeOf, defaultBlockTypes, importTypeOf, isRootBlockType, nestedAfterContentOf, propertiesOf, sourceMediaOf } from "./block-types.js";
|
|
4
|
+
import { CompositeAiBrief, compositeAiBrief } from "./ai-brief.js";
|
|
7
5
|
import { compositeConversions, convertCompositeBlocks } from "./convert.js";
|
|
8
6
|
import { CompositeFence, FenceSegment, splitCompositeFences } from "../../core/fences.js";
|
|
9
7
|
import { blocksFromMarkdown, compositeFence, compositeFromMarkdown } from "./fences.js";
|
|
10
8
|
import { compositeChromeBlocks, flattenCompositesToHeadings, groupHeadingsIntoComposites, headingGroupRange, structureBlocks } from "./heading-composites.js";
|
|
11
|
-
import { BASKET_KEY, BIB_KEY,
|
|
9
|
+
import { BASKET_KEY, BIB_KEY, TITLE_HIDDEN_KEY } from "./meta-keys.js";
|
|
12
10
|
import { bibOf, bibtexOf, citeFull, citeShort, cslOf, cslTypeOptions, yearOf } from "./bibliography.js";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
11
|
+
import { bodyMarkdown, sourceOf } from "./source.js";
|
|
12
|
+
import { BlockTypeJsonError, BlockTypeJsonIssue, mergeBlockTypes, parseBlockTypes } from "./block-types-json.js";
|
|
13
|
+
import { hasFlatTranscript, migrateLegacyContent } from "./legacy.js";
|
|
14
|
+
import { REFERENCE_NODE, ReferenceAttrs, ReferenceNode, ReferenceOptions, ReferenceSuggestionPluginKey, referenceMarkdown } from "./reference.js";
|
|
15
15
|
import { collectCompositeIds, compositeIdsOf, normalizeReferences, referencesFromText } from "./reference-text.js";
|
|
16
|
+
import { COMPOSITE_CHROME_COUNT, CompositeDescriptionNode, CompositeNode, CompositeOptions, CompositeStorage, CompositeTagsNode, CompositeTitleNode, blockTypesOf, compositeBasketsOf, compositeJSON } from "./nodes.js";
|
|
16
17
|
import { AnyExtension } from "@tiptap/core";
|
|
17
18
|
//#region src/features/composites/schema.d.ts
|
|
18
19
|
/**
|
|
19
20
|
* The schema-bearing composite family (composite, title, description, tags, and the inline `reference` chip) without node views, to append to
|
|
20
|
-
* `coreSchemaExtensions()`: `getSchema([...coreSchemaExtensions(), ...compositeSchemaExtensions({
|
|
21
|
-
* is the host's
|
|
21
|
+
* `coreSchemaExtensions()`: `getSchema([...coreSchemaExtensions(), ...compositeSchemaExtensions({ blockTypes })])`. `blockTypes`
|
|
22
|
+
* is the host's Block type list (default: the built-in Block types in German, `defaultBlockTypes`); it is storage, not schema.
|
|
22
23
|
*/
|
|
23
24
|
export declare function compositeSchemaExtensions(options?: {
|
|
24
|
-
|
|
25
|
+
blockTypes?: readonly BlockType[];
|
|
25
26
|
baskets?: readonly Basket[];
|
|
26
27
|
}): AnyExtension[];
|
|
27
28
|
//#endregion
|
|
28
|
-
export { BASKET_IDS, BASKET_KEY, BIB_KEY, type Basket,
|
|
29
|
+
export { BASKET_IDS, BASKET_KEY, BIB_KEY, type Basket, type BlockType, type BlockTypeAi, BlockTypeJsonError, type BlockTypeJsonIssue, COMPOSITE_CHROME_COUNT, CSL_TYPES, type CompositeAiBrief, CompositeDescriptionNode, type CompositeFence, CompositeNode, type CompositeOptions, type CompositeStorage, CompositeTagsNode, CompositeTitleNode, type ContainerConfig, type CslDate, type CslItem, type CslName, type CslType, type FenceSegment, type ImportConfig, type PropertiesConfig, REFERENCE_NODE, type ReferenceAttrs, ReferenceNode, type ReferenceOptions, ReferenceSuggestionPluginKey, SOURCE_MEDIA_TYPES, type SourceConfig, type SourceMedia, TITLE_HIDDEN_KEY, acceptsChild, acceptsImport, acceptsOf, aiBlockTypesOf, aiBriefOf, basketById, basketOf, bibOf, bibtexOf, blockTypeOf, blockTypesOf, blocksFromMarkdown, bodyMarkdown, citeFull, citeShort, collectCompositeIds, compositeAiBrief, compositeBasketsOf, compositeChromeBlocks, compositeConversions, compositeFence, compositeFromMarkdown, compositeIdsOf, compositeJSON, convertCompositeBlocks, cslOf, cslTypeOptions, defaultBaskets, defaultBlockTypes, flattenCompositesToHeadings, groupHeadingsIntoComposites, hasFlatTranscript, headingGroupRange, importTypeOf, isRootBlockType, mergeBlockTypes, migrateLegacyContent, nestedAfterContentOf, normalizeReferences, parseBlockTypes, propertiesOf, referenceMarkdown, referencesFromText, sourceMediaOf, sourceOf, splitCompositeFences, structureBlocks, titleHiddenOf, yearOf };
|
|
29
30
|
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
import { splitCompositeFences } from "../../core/fences.js";
|
|
2
|
-
import { SOURCE_MEDIA_TYPES,
|
|
3
|
-
import { BASKET_KEY, BIB_KEY,
|
|
2
|
+
import { SOURCE_MEDIA_TYPES, acceptsChild, acceptsImport, acceptsOf, aiBlockTypesOf, aiBriefOf, blockTypeOf, defaultBlockTypes, importTypeOf, isRootBlockType, nestedAfterContentOf, propertiesOf, sourceMediaOf } from "./block-types.js";
|
|
3
|
+
import { BASKET_KEY, BIB_KEY, TITLE_HIDDEN_KEY } from "./meta-keys.js";
|
|
4
4
|
import { blocksFromMarkdown, compositeFence, compositeFromMarkdown } from "./fences.js";
|
|
5
5
|
import { BASKET_IDS, basketById, basketOf, defaultBaskets, titleHiddenOf } from "./baskets.js";
|
|
6
|
-
import { bodyMarkdown, derivationOf, derivationState, renditionsOf, sourceOf } from "./derivation.js";
|
|
7
6
|
import { compositeChromeBlocks, flattenCompositesToHeadings, groupHeadingsIntoComposites, headingGroupRange, structureBlocks } from "./heading-composites.js";
|
|
8
|
-
import { COMPOSITE_CHROME_COUNT, CompositeDescriptionNode, CompositeNode, CompositeTagsNode, CompositeTitleNode, compositeBasketsOf, compositeJSON
|
|
7
|
+
import { COMPOSITE_CHROME_COUNT, CompositeDescriptionNode, CompositeNode, CompositeTagsNode, CompositeTitleNode, blockTypesOf, compositeBasketsOf, compositeJSON } from "./nodes.js";
|
|
9
8
|
import { REFERENCE_NODE, ReferenceNode, ReferenceSuggestionPluginKey, referenceMarkdown } from "./reference.js";
|
|
10
9
|
import { CSL_TYPES } from "../../core/backend-types.js";
|
|
11
10
|
import { bibOf, bibtexOf, citeFull, citeShort, cslOf, cslTypeOptions, yearOf } from "./bibliography.js";
|
|
12
11
|
import { compositeAiBrief } from "./ai-brief.js";
|
|
13
12
|
import { compositeConversions, convertCompositeBlocks } from "./convert.js";
|
|
14
|
-
import {
|
|
13
|
+
import { bodyMarkdown, sourceOf } from "./source.js";
|
|
14
|
+
import { BlockTypeJsonError, mergeBlockTypes, parseBlockTypes } from "./block-types-json.js";
|
|
15
|
+
import { hasFlatTranscript, migrateLegacyContent } from "./legacy.js";
|
|
15
16
|
import { collectCompositeIds, compositeIdsOf, normalizeReferences, referencesFromText } from "./reference-text.js";
|
|
16
17
|
//#region src/features/composites/schema.ts
|
|
17
18
|
/**
|
|
18
19
|
* The schema-bearing composite family (composite, title, description, tags, and the inline `reference` chip) without node views, to append to
|
|
19
|
-
* `coreSchemaExtensions()`: `getSchema([...coreSchemaExtensions(), ...compositeSchemaExtensions({
|
|
20
|
-
* is the host's
|
|
20
|
+
* `coreSchemaExtensions()`: `getSchema([...coreSchemaExtensions(), ...compositeSchemaExtensions({ blockTypes })])`. `blockTypes`
|
|
21
|
+
* is the host's Block type list (default: the built-in Block types in German, `defaultBlockTypes`); it is storage, not schema.
|
|
21
22
|
*/
|
|
22
23
|
function compositeSchemaExtensions(options = {}) {
|
|
23
24
|
return [
|
|
24
25
|
CompositeNode.configure({
|
|
25
|
-
...options.
|
|
26
|
+
...options.blockTypes && { blockTypes: options.blockTypes },
|
|
26
27
|
...options.baskets && { baskets: options.baskets }
|
|
27
28
|
}),
|
|
28
29
|
CompositeTitleNode,
|
|
@@ -32,6 +33,6 @@ function compositeSchemaExtensions(options = {}) {
|
|
|
32
33
|
];
|
|
33
34
|
}
|
|
34
35
|
//#endregion
|
|
35
|
-
export { BASKET_IDS, BASKET_KEY, BIB_KEY, COMPOSITE_CHROME_COUNT, CSL_TYPES, CompositeDescriptionNode, CompositeNode, CompositeTagsNode, CompositeTitleNode,
|
|
36
|
+
export { BASKET_IDS, BASKET_KEY, BIB_KEY, BlockTypeJsonError, COMPOSITE_CHROME_COUNT, CSL_TYPES, CompositeDescriptionNode, CompositeNode, CompositeTagsNode, CompositeTitleNode, REFERENCE_NODE, ReferenceNode, ReferenceSuggestionPluginKey, SOURCE_MEDIA_TYPES, TITLE_HIDDEN_KEY, acceptsChild, acceptsImport, acceptsOf, aiBlockTypesOf, aiBriefOf, basketById, basketOf, bibOf, bibtexOf, blockTypeOf, blockTypesOf, blocksFromMarkdown, bodyMarkdown, citeFull, citeShort, collectCompositeIds, compositeAiBrief, compositeBasketsOf, compositeChromeBlocks, compositeConversions, compositeFence, compositeFromMarkdown, compositeIdsOf, compositeJSON, compositeSchemaExtensions, convertCompositeBlocks, cslOf, cslTypeOptions, defaultBaskets, defaultBlockTypes, flattenCompositesToHeadings, groupHeadingsIntoComposites, hasFlatTranscript, headingGroupRange, importTypeOf, isRootBlockType, mergeBlockTypes, migrateLegacyContent, nestedAfterContentOf, normalizeReferences, parseBlockTypes, propertiesOf, referenceMarkdown, referencesFromText, sourceMediaOf, sourceOf, splitCompositeFences, structureBlocks, titleHiddenOf, yearOf };
|
|
36
37
|
|
|
37
38
|
//# sourceMappingURL=schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","names":[],"sources":["../../../src/features/composites/schema.ts"],"sourcesContent":["// Vue-free entry of the composite feature (`@ecsplico/editor/composites/schema`): the node family,
|
|
1
|
+
{"version":3,"file":"schema.js","names":[],"sources":["../../../src/features/composites/schema.ts"],"sourcesContent":["// Vue-free entry of the composite feature (`@ecsplico/editor/composites/schema`): the node family, Block types, Markdown\n// fences, legacy migration, heading↔composite transforms and conversions. Servers build their schema from it; it never\n// imports node views, components or the feature factory.\nimport type { AnyExtension } from '@tiptap/core'\nimport type { Basket } from './baskets'\nimport { type BlockType } from './block-types'\nimport { CompositeNode, CompositeDescriptionNode, CompositeTagsNode, CompositeTitleNode } from './nodes'\nimport { ReferenceNode } from './reference'\n\nexport { type CompositeAiBrief, compositeAiBrief } from './ai-brief'\nexport { type Basket, BASKET_IDS, basketById, basketOf, defaultBaskets, titleHiddenOf } from './baskets'\nexport { compositeConversions, convertCompositeBlocks } from './convert'\nexport { blocksFromMarkdown, type CompositeFence, compositeFence, compositeFromMarkdown, type FenceSegment, splitCompositeFences } from './fences'\nexport { compositeChromeBlocks, flattenCompositesToHeadings, groupHeadingsIntoComposites, headingGroupRange, structureBlocks } from './heading-composites'\nexport { BIB_KEY, bibOf, bibtexOf, citeFull, citeShort, type CslDate, type CslItem, type CslName, type CslType, CSL_TYPES, cslOf, cslTypeOptions, yearOf } from './bibliography'\nexport { bodyMarkdown, sourceOf } from './source'\nexport { acceptsChild, acceptsImport, acceptsOf, aiBlockTypesOf, aiBriefOf, nestedAfterContentOf, type BlockType, type BlockTypeAi, blockTypeOf, type ContainerConfig, defaultBlockTypes, type ImportConfig, importTypeOf, isRootBlockType, type PropertiesConfig, propertiesOf, SOURCE_MEDIA_TYPES, type SourceConfig, type SourceMedia, sourceMediaOf } from './block-types'\nexport { BlockTypeJsonError, type BlockTypeJsonIssue, mergeBlockTypes, parseBlockTypes } from './block-types-json'\nexport { BASKET_KEY, TITLE_HIDDEN_KEY } from './meta-keys'\nexport { hasFlatTranscript, migrateLegacyContent } from './legacy'\nexport { REFERENCE_NODE, type ReferenceAttrs, referenceMarkdown, ReferenceNode, type ReferenceOptions, ReferenceSuggestionPluginKey } from './reference'\nexport { compositeIdsOf, collectCompositeIds, normalizeReferences, referencesFromText } from './reference-text'\nexport {\n COMPOSITE_CHROME_COUNT,\n compositeJSON,\n compositeBasketsOf,\n blockTypesOf,\n CompositeDescriptionNode,\n CompositeNode,\n type CompositeOptions,\n type CompositeStorage,\n CompositeTagsNode,\n CompositeTitleNode,\n} from './nodes'\n\n/**\n * The schema-bearing composite family (composite, title, description, tags, and the inline `reference` chip) without node views, to append to\n * `coreSchemaExtensions()`: `getSchema([...coreSchemaExtensions(), ...compositeSchemaExtensions({ blockTypes })])`. `blockTypes`\n * is the host's Block type list (default: the built-in Block types in German, `defaultBlockTypes`); it is storage, not schema.\n */\nexport function compositeSchemaExtensions(options: { blockTypes?: readonly BlockType[], baskets?: readonly Basket[] } = {}): AnyExtension[] {\n return [CompositeNode.configure({ ...(options.blockTypes && { blockTypes: options.blockTypes }), ...(options.baskets && { baskets: options.baskets }) }), CompositeTitleNode, CompositeDescriptionNode, CompositeTagsNode, ReferenceNode]\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,0BAA0B,UAA8E,CAAC,GAAmB;CAC1I,OAAO;EAAC,cAAc,UAAU;GAAE,GAAI,QAAQ,cAAc,EAAE,YAAY,QAAQ,WAAW;GAAI,GAAI,QAAQ,WAAW,EAAE,SAAS,QAAQ,QAAQ;EAAG,CAAC;EAAG;EAAoB;EAA0B;EAAmB;CAAa;AAC1O"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BlockType } from "./block-types.js";
|
|
2
|
+
import { Editor } from "@tiptap/core";
|
|
3
|
+
import { Node as Node$1 } from "@tiptap/pm/model";
|
|
4
|
+
//#region src/features/composites/source.d.ts
|
|
5
|
+
/** The media block a source-holding Typed block keeps its original in, with its position among the children, the stored asset behind its `src` and its content hash. */
|
|
6
|
+
export interface SourceBlock {
|
|
7
|
+
node: Node$1;
|
|
8
|
+
index: number;
|
|
9
|
+
asset: {
|
|
10
|
+
documentId: string;
|
|
11
|
+
name: string;
|
|
12
|
+
} | null;
|
|
13
|
+
hash: string | null;
|
|
14
|
+
}
|
|
15
|
+
/** The media block a source-holding Block type keeps its original in: first body child of a type in the `media` of the Block type's `source` capability. */
|
|
16
|
+
export declare function sourceOf(composite: Node$1, blockTypes: readonly BlockType[]): SourceBlock | null;
|
|
17
|
+
/** Markdown of the body of `composite` (everything after title, description and tags). */
|
|
18
|
+
export declare function bodyMarkdown(editor: Editor, composite: Node$1): string;
|
|
19
|
+
//#endregion
|
|
20
|
+
//# sourceMappingURL=source.d.ts.map
|