@skaile/forge-editor 6.2.1 → 6.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -1
- package/dist/adapters/nitro.d.ts +11 -3
- package/dist/adapters/nitro.js +2 -1
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/code/CodeSurface.vue.d.ts +1 -1
- package/dist/document/DocumentSurface.vue.d.ts +1 -1
- package/dist/features/ai/index.d.ts +2 -2
- package/dist/features/ai/index.js +2 -2
- package/dist/features/ai/protocol/chat.d.ts +5 -0
- package/dist/features/ai/protocol/chat.js +7 -4
- package/dist/features/ai/protocol/chat.js.map +1 -1
- package/dist/features/ai/protocol/index.d.ts +2 -2
- package/dist/features/ai/protocol/index.js +2 -2
- package/dist/features/composites/components/CompositeInspector.js +8 -8
- package/dist/features/composites/components/SettingsEditingTab.js +16 -3
- package/dist/features/composites/components/SettingsEditingTab.js.map +1 -1
- package/dist/features/composites/feature.js +26 -6
- package/dist/features/composites/feature.js.map +1 -1
- package/dist/features/composites/index.d.ts +2 -2
- package/dist/features/composites/index.js +2 -2
- package/dist/features/composites/react/SettingsEditingTab.js +22 -0
- package/dist/features/composites/react/SettingsEditingTab.js.map +1 -1
- package/dist/features/composites/split.d.ts +19 -1
- package/dist/features/composites/split.js +57 -4
- package/dist/features/composites/split.js.map +1 -1
- package/dist/features/composites/vue.js +1 -1
- package/dist/i18n/de/composites.js +4 -0
- package/dist/i18n/de/composites.js.map +1 -1
- package/dist/i18n/de.d.ts +4 -0
- package/dist/i18n/en/composites.js +4 -0
- package/dist/i18n/en/composites.js.map +1 -1
- package/dist/markdown/MarkdownSurface.vue.d.ts +1 -1
- package/dist/server/chat-agent.d.ts +85 -0
- package/dist/server/chat-agent.js +61 -0
- package/dist/server/chat-agent.js.map +1 -0
- package/dist/server/document-tools.d.ts +22 -0
- package/dist/server/document-tools.js +190 -0
- package/dist/server/document-tools.js.map +1 -0
- package/dist/server/handlers/ai.d.ts +2 -1
- package/dist/server/handlers/ai.js +232 -121
- package/dist/server/handlers/ai.js.map +1 -1
- package/dist/server/handlers/context.d.ts +4 -1
- package/dist/server/handlers/context.js.map +1 -1
- package/dist/server/handlers/editor.d.ts +1 -0
- package/dist/server/index.d.ts +7 -3
- package/dist/server/index.js +5 -2
- package/dist/server/workspace-tools.d.ts +1 -0
- package/dist/server/workspace-tools.js +8 -3
- package/dist/server/workspace-tools.js.map +1 -1
- package/dist/settings/index.d.ts +3 -0
- package/dist/settings/index.js +7 -3
- package/dist/settings/index.js.map +1 -1
- package/dist/tree/DocumentTree.js +1 -1
- package/dist/tree/use-tree-model.js +1 -1
- package/dist/vue/compose.js +1 -1
- package/dist/vue/index.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsEditingTab.js","names":["_openBlock","_createElementBlock","_createVNode","SettingsSection","_unref","_withCtx","_createElementVNode","_withKeys"],"sources":["../../../../src/features/composites/components/SettingsEditingTab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport SettingsSection from '../../../vue/components/SettingsSection.vue'\nimport { useUiKit } from '../../../vue/kit/use-ui-kit'\nimport { useEditorSettings } from '../../../vue/settings'\nimport { useEditorI18n } from '../../../vue/use-editor-i18n'\nimport { BLOCK_TYPE_ICON_VISIBILITIES, clampSplitTargetChars, DRAG_HANDLE_VISIBILITIES, HEADING_CONVERSION_SCOPES, SPLIT_TARGET_CHARS_MAX, SPLIT_TARGET_CHARS_MIN, STRUCTURE_MODES, TREE_ROOTS } from '../../../settings'\nimport { BLOCK_TYPE_ICON_KEYS, DRAG_HANDLE_KEYS, HEADING_SCOPE_KEYS, optionItems } from '../editing-settings-keys'\nimport type { BlockType } from '../block-types'\nimport { STRUCTURE_MODE_KEYS } from '../structure-mode'\nimport { TREE_ROOT_KEYS } from '../tree-root'\n\n/** „Bearbeiten“: Gliederung (structure mode, conversion scope), Typed blocks defaults and the visibility of the block handles. */\nconst props = defineProps<{ blockTypes: readonly BlockType[] }>()\n\nconst { FormField: UFormField, Input: UInput, RadioGroup: URadioGroup, Select: USelect } = useUiKit()\nconst { t } = useEditorI18n()\n\nconst { settings } = useEditorSettings()\n\nconst scopeItems = computed(() => optionItems(HEADING_CONVERSION_SCOPES, HEADING_SCOPE_KEYS, t))\nconst structureItems = computed(() => optionItems(STRUCTURE_MODES, STRUCTURE_MODE_KEYS, t))\nconst treeRootItems = computed(() => optionItems(TREE_ROOTS, TREE_ROOT_KEYS, t))\nconst blockTypeIconItems = computed(() => optionItems(BLOCK_TYPE_ICON_VISIBILITIES, BLOCK_TYPE_ICON_KEYS, t))\nconst dragHandleItems = computed(() => optionItems(DRAG_HANDLE_VISIBILITIES, DRAG_HANDLE_KEYS, t))\n\nconst blockTypeItems = computed(() => props.blockTypes.map(blockType => ({ label: blockType.label, icon: blockType.icon, value: blockType.id })))\n\n// The target size is edited as text and written back clamped to its range when the field is left, so a half-typed number never reaches the settings.\nconst splitTarget = ref(String(settings.value.blocks.splitTargetChars))\nwatch(() => settings.value.blocks.splitTargetChars, (value) => { splitTarget.value = String(value) })\nfunction commitSplitTarget() {\n const next = clampSplitTargetChars(splitTarget.value, settings.value.blocks.splitTargetChars)\n settings.value.blocks.splitTargetChars = next\n splitTarget.value = String(next)\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-8\">\n <SettingsSection :title=\"t('composites.settings.structure.title')\">\n <div class=\"py-3\">\n <URadioGroup v-model=\"settings.blocks.structure\" :legend=\"t('composites.settings.structure.legend')\" :items=\"structureItems\" />\n </div>\n <div class=\"py-3\">\n <URadioGroup\n v-model=\"settings.editing.headingConversionScope\"\n :legend=\"t('composites.settings.scope.legend')\"\n :items=\"scopeItems\"\n />\n </div>\n </SettingsSection>\n\n <SettingsSection :title=\"t('composites.settings.sidebar.title')\">\n <div class=\"py-3\">\n <URadioGroup v-model=\"settings.blocks.treeRoot\" :legend=\"t('composites.settings.treeRoot.legend')\" :items=\"treeRootItems\" />\n </div>\n </SettingsSection>\n\n <SettingsSection :title=\"t('composites.settings.composites.title')\">\n <UFormField\n orientation=\"horizontal\"\n class=\"py-3\"\n :label=\"t('composites.settings.defaultBlockType.label')\"\n :description=\"t('composites.settings.defaultBlockType.description')\"\n >\n <USelect v-model=\"settings.blocks.defaultBlockType\" :items=\"blockTypeItems\" class=\"w-64\" />\n </UFormField>\n <UFormField orientation=\"horizontal\" class=\"py-3\" :label=\"t('settings.editing.splitTargetChars')\">\n <UInput\n :model-value=\"splitTarget\"\n type=\"number\"\n :min=\"SPLIT_TARGET_CHARS_MIN\"\n :max=\"SPLIT_TARGET_CHARS_MAX\"\n :step=\"100\"\n :aria-label=\"t('settings.editing.splitTargetChars')\"\n class=\"w-32\"\n @blur=\"commitSplitTarget\"\n @keydown.enter=\"commitSplitTarget\"\n @update:model-value=\"(value: unknown) => { splitTarget = String(value) }\"\n />\n </UFormField>\n <div class=\"py-3\">\n <URadioGroup v-model=\"settings.blocks.blockTypeIcon\" :legend=\"t('composites.settings.blockTypeIcon.legend')\" :items=\"blockTypeIconItems\" />\n </div>\n <div class=\"py-3\">\n <URadioGroup v-model=\"settings.blocks.dragHandle\" :legend=\"t('composites.settings.dragHandle.legend')\" :items=\"dragHandleItems\" />\n </div>\n </SettingsSection>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;EAaA,MAAM,QAAQ;EAEd,MAAM,EAAE,WAAW,YAAY,OAAO,QAAQ,YAAY,aAAa,QAAQ,YAAY,SAAS;
|
|
1
|
+
{"version":3,"file":"SettingsEditingTab.js","names":["_openBlock","_createElementBlock","_createVNode","SettingsSection","_unref","_withCtx","_createElementVNode","_withKeys"],"sources":["../../../../src/features/composites/components/SettingsEditingTab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport SettingsSection from '../../../vue/components/SettingsSection.vue'\nimport { useUiKit } from '../../../vue/kit/use-ui-kit'\nimport { useEditorSettings } from '../../../vue/settings'\nimport { useEditorI18n } from '../../../vue/use-editor-i18n'\nimport { BLOCK_TYPE_ICON_VISIBILITIES, clampSplitTargetChars, DRAG_HANDLE_VISIBILITIES, HEADING_CONVERSION_SCOPES, SPLIT_TARGET_CHARS_MAX, SPLIT_TARGET_CHARS_MIN, STRUCTURE_MODES, TREE_ROOTS } from '../../../settings'\nimport { BLOCK_TYPE_ICON_KEYS, DRAG_HANDLE_KEYS, HEADING_SCOPE_KEYS, optionItems } from '../editing-settings-keys'\nimport type { BlockType } from '../block-types'\nimport { STRUCTURE_MODE_KEYS } from '../structure-mode'\nimport { TREE_ROOT_KEYS } from '../tree-root'\n\n/** „Bearbeiten“: Gliederung (structure mode, conversion scope), Typed blocks defaults and the visibility of the block handles. */\nconst props = defineProps<{ blockTypes: readonly BlockType[] }>()\n\nconst { FormField: UFormField, Input: UInput, RadioGroup: URadioGroup, Select: USelect, Switch: USwitch } = useUiKit()\nconst { t } = useEditorI18n()\n\nconst { settings } = useEditorSettings()\n\nconst scopeItems = computed(() => optionItems(HEADING_CONVERSION_SCOPES, HEADING_SCOPE_KEYS, t))\nconst structureItems = computed(() => optionItems(STRUCTURE_MODES, STRUCTURE_MODE_KEYS, t))\nconst treeRootItems = computed(() => optionItems(TREE_ROOTS, TREE_ROOT_KEYS, t))\nconst blockTypeIconItems = computed(() => optionItems(BLOCK_TYPE_ICON_VISIBILITIES, BLOCK_TYPE_ICON_KEYS, t))\nconst dragHandleItems = computed(() => optionItems(DRAG_HANDLE_VISIBILITIES, DRAG_HANDLE_KEYS, t))\n\nconst blockTypeItems = computed(() => props.blockTypes.map(blockType => ({ label: blockType.label, icon: blockType.icon, value: blockType.id })))\n\n// The target size is edited as text and written back clamped to its range when the field is left, so a half-typed number never reaches the settings.\nconst splitTarget = ref(String(settings.value.blocks.splitTargetChars))\nwatch(() => settings.value.blocks.splitTargetChars, (value) => { splitTarget.value = String(value) })\nfunction commitSplitTarget() {\n const next = clampSplitTargetChars(splitTarget.value, settings.value.blocks.splitTargetChars)\n settings.value.blocks.splitTargetChars = next\n splitTarget.value = String(next)\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-8\">\n <SettingsSection :title=\"t('composites.settings.structure.title')\">\n <div class=\"py-3\">\n <URadioGroup v-model=\"settings.blocks.structure\" :legend=\"t('composites.settings.structure.legend')\" :items=\"structureItems\" />\n </div>\n <div class=\"py-3\">\n <URadioGroup\n v-model=\"settings.editing.headingConversionScope\"\n :legend=\"t('composites.settings.scope.legend')\"\n :items=\"scopeItems\"\n />\n </div>\n </SettingsSection>\n\n <SettingsSection :title=\"t('composites.settings.sidebar.title')\">\n <div class=\"py-3\">\n <URadioGroup v-model=\"settings.blocks.treeRoot\" :legend=\"t('composites.settings.treeRoot.legend')\" :items=\"treeRootItems\" />\n </div>\n </SettingsSection>\n\n <SettingsSection :title=\"t('composites.settings.composites.title')\">\n <UFormField\n orientation=\"horizontal\"\n class=\"py-3\"\n :label=\"t('composites.settings.defaultBlockType.label')\"\n :description=\"t('composites.settings.defaultBlockType.description')\"\n >\n <USelect v-model=\"settings.blocks.defaultBlockType\" :items=\"blockTypeItems\" class=\"w-64\" />\n </UFormField>\n <UFormField orientation=\"horizontal\" class=\"py-3\" :label=\"t('settings.editing.splitTargetChars')\">\n <UInput\n :model-value=\"splitTarget\"\n type=\"number\"\n :min=\"SPLIT_TARGET_CHARS_MIN\"\n :max=\"SPLIT_TARGET_CHARS_MAX\"\n :step=\"100\"\n :aria-label=\"t('settings.editing.splitTargetChars')\"\n class=\"w-32\"\n @blur=\"commitSplitTarget\"\n @keydown.enter=\"commitSplitTarget\"\n @update:model-value=\"(value: unknown) => { splitTarget = String(value) }\"\n />\n </UFormField>\n <UFormField\n orientation=\"horizontal\"\n class=\"py-3\"\n :label=\"t('settings.editing.splitOnRule.label')\"\n :description=\"t('settings.editing.splitOnRule.description')\"\n >\n <USwitch v-model=\"settings.blocks.splitOnRule\" :aria-label=\"t('settings.editing.splitOnRule.label')\" />\n </UFormField>\n <div class=\"py-3\">\n <URadioGroup v-model=\"settings.blocks.blockTypeIcon\" :legend=\"t('composites.settings.blockTypeIcon.legend')\" :items=\"blockTypeIconItems\" />\n </div>\n <div class=\"py-3\">\n <URadioGroup v-model=\"settings.blocks.dragHandle\" :legend=\"t('composites.settings.dragHandle.legend')\" :items=\"dragHandleItems\" />\n </div>\n </SettingsSection>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -89,7 +89,8 @@ function compositeFeatureCore(ui, options = {}) {
|
|
|
89
89
|
CompositeMerge,
|
|
90
90
|
CompositeSplit.configure({
|
|
91
91
|
defaultBlockType: () => ctx.settings.get().blocks.defaultBlockType,
|
|
92
|
-
targetChars: () => ctx.settings.get().blocks.splitTargetChars
|
|
92
|
+
targetChars: () => ctx.settings.get().blocks.splitTargetChars,
|
|
93
|
+
splitOnRule: () => ctx.settings.get().blocks.splitOnRule
|
|
93
94
|
}),
|
|
94
95
|
Reference.configure({ suggestion: referenceSuggestion(ctx.t) }),
|
|
95
96
|
Cite.configure({ suggestion: citeSuggestion(ctx.t) }),
|
|
@@ -206,10 +207,10 @@ function compositeFeatureCore(ui, options = {}) {
|
|
|
206
207
|
};
|
|
207
208
|
}
|
|
208
209
|
/**
|
|
209
|
-
* The
|
|
210
|
-
* caret while the caret is past the first body block)
|
|
211
|
-
* body falls into two parts or more). Each is hidden when the command refuses, so a kind that
|
|
212
|
-
* never shows the `children` variants.
|
|
210
|
+
* The split actions of a Typed block: at the caret (as sibling or nested Typed blocks; offered on the Typed block around the
|
|
211
|
+
* caret while the caret is past the first body block), by length and at the horizontal rules (each as nested Typed blocks or
|
|
212
|
+
* siblings; offered while the body falls into two parts or more). Each is hidden when the command refuses, so a kind that
|
|
213
|
+
* accepts no child kind never shows the `children` variants.
|
|
213
214
|
*/
|
|
214
215
|
function splitBlockActions({ t }) {
|
|
215
216
|
const atCaret = (id, labelKey, icon, order, mode) => ({
|
|
@@ -244,11 +245,30 @@ function splitBlockActions({ t }) {
|
|
|
244
245
|
pos
|
|
245
246
|
}).run()
|
|
246
247
|
});
|
|
248
|
+
const atRules = (id, labelKey, order, mode) => ({
|
|
249
|
+
id,
|
|
250
|
+
label: t(labelKey),
|
|
251
|
+
icon: "i-lucide-separator-horizontal",
|
|
252
|
+
target: "typedBlock",
|
|
253
|
+
ability: ABILITY.compositeMeta,
|
|
254
|
+
requires: ["container", "title"],
|
|
255
|
+
order,
|
|
256
|
+
isVisible: ({ editor, pos }) => editor.can().splitCompositeAtRules({
|
|
257
|
+
mode,
|
|
258
|
+
pos
|
|
259
|
+
}),
|
|
260
|
+
run: ({ editor, pos }) => void editor.chain().focus().splitCompositeAtRules({
|
|
261
|
+
mode,
|
|
262
|
+
pos
|
|
263
|
+
}).run()
|
|
264
|
+
});
|
|
247
265
|
return [
|
|
248
266
|
atCaret("composite-split-here", "composites.split.here", "i-lucide-scissors", 430, "siblings"),
|
|
249
267
|
atCaret("composite-split-children", "composites.split.children", "i-lucide-split", 440, "children"),
|
|
250
268
|
byLength("composite-split-length-children", "composites.split.lengthChildren", "i-lucide-ruler", 450, "children"),
|
|
251
|
-
byLength("composite-split-length-siblings", "composites.split.lengthSiblings", "i-lucide-ruler", 460, "siblings")
|
|
269
|
+
byLength("composite-split-length-siblings", "composites.split.lengthSiblings", "i-lucide-ruler", 460, "siblings"),
|
|
270
|
+
atRules("composite-split-rules-children", "composites.split.rulesChildren", 462, "children"),
|
|
271
|
+
atRules("composite-split-rules-siblings", "composites.split.rulesSiblings", 464, "siblings")
|
|
252
272
|
];
|
|
253
273
|
}
|
|
254
274
|
const COMPOSITE_TOOLBAR_GROUPS = [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature.js","names":[],"sources":["../../../src/features/composites/feature.ts"],"sourcesContent":["import type { Editor, NodeViewRenderer } from '@tiptap/core'\nimport type { BlockAction, CommandDef, EditorFeature, FeatureContext, MenuItem, ToolbarGroupDef } from '../../core'\nimport { abilitiesAtSelection, capabilityDataOf, downloadText, editorEntryOf, settingsTabsOf } from '../../core'\nimport type { BlockAddress } from '../../core/block-index'\nimport type { Translate } from '../../i18n'\nimport { ABILITY, blockIdOf, findBlockById } from '../../core/schema'\nimport { AcceptedChildren, compositeInsertGuard } from './accepted-children'\nimport { derivedRowBadge } from './badges'\nimport { exportCheckInspectorSection, exportIssuesOf } from './export-check'\nimport { edgesInspectorSection } from './edges-model'\nimport { type Basket, defaultBaskets } from './baskets'\nimport { bibtexOf, cslOf } from './bibliography'\nimport { compositeConversions } from './convert'\nimport { derivationOf, isTypedBlock, TYPED_BLOCK } from '../../core/typed-block'\nimport { bodyMarkdown } from './source'\nimport { blocksFromMarkdown } from './fences'\nimport { DATA_VIEW_TYPE } from './views/data-view'\nimport { insertDataView } from './views/data-view-model'\nimport { structureBlocks } from './heading-composites'\nimport { type BlockType, aiBlockTypesOf, blockTypeOf, defaultBlockTypes } from './block-types'\nimport { compositeBlockCapabilities } from './capabilities'\nimport { migrateLegacyContent } from './legacy'\nimport { compositeSchemaExtensions } from './schema'\nimport { documentCompositeMarkdown, markdownFileName } from './markdown-export'\nimport { collectionAddAction } from './collection-actions'\nimport { openCompositeDetails } from './details-model'\nimport { renderBlockAction, renderDocumentCommand } from './render-actions'\nimport { type CompositeNodeViews, compositeNodes } from './node-views'\nimport { COMPOSITE_CHROME_COUNT, CompositeDescriptionNode, CompositeTitleNode, compositeAround, blockTypesOf } from './nodes'\nimport { CompositeFocus } from './focus'\nimport { CompositeMerge } from './merge'\nimport { BLOCK_EMBED_TRIGGER } from './embed'\nimport { CITE_TRIGGER } from './cite'\nimport { REFERENCE_TRIGGER } from './reference'\nimport { REFERENCE_AI_BLOCK } from './reference-ai'\nimport { blockEmbedSuggestion } from './embed-suggestion'\nimport { referenceSuggestion } from './reference-suggestion'\nimport { citeSuggestion } from './cite-suggestion'\nimport { compositeIdsOf, normalizeReferences } from './reference-text'\nimport { SourceReveal } from './reveal-source'\nimport { CompositeSplit, type SplitMode } from './split'\nimport { Structure, structureOf } from './structure'\nimport { STRUCTURE_MODE_KEYS } from './structure-mode'\n\n/** What a framework binding supplies to the composites feature. */\nexport interface CompositesUi<C> {\n /** The chips on each title line and the details popover on the kind icon; mounted as an overlay. */\n chrome: C\n /** The focus chip („Fokus: <Titel> · Aufheben“) shown while a Typed block is focused; mounted as an overlay. Absent: no chip (the focus mode itself works). */\n focusChip?: C\n /** The „Export-Hinweise“ section of the inspector and the details card (receives `{ editor, node }`): what to look at before a Typed block is exported. Absent: no section (the export still tells the count). */\n exportCheck?: C\n /** The „Kanten“ section of the inspector and the details card (receives `{ editor, node }`): the Edges a person added to a Typed block (`meta.edges`), with a form to add and remove them. Absent: no section. */\n edges?: C\n /** The „Bearbeiten“ settings tab; receives `{ blockTypes }` as props. */\n settingsTab: C\n /** The composite block view of the framework. */\n nodeViews: CompositeNodeViews\n}\n\n/** Options of `compositeFeature`. */\nexport interface CompositeFeatureOptions {\n /** The Block types offered in the editor, with their own labels (default: `defaultBlockTypes(t)`, the built-in Block types in the editor's language); read once. */\n blockTypes?: readonly BlockType[]\n /** The colour baskets a Typed block can be put into (default: `defaultBaskets(t)`, red/orange/yellow/green/blue in the editor's language; colours are the `--sk-basket-<id>` CSS variables); read once. */\n baskets?: readonly Basket[]\n /**\n * „Am Ursprung bearbeiten“ on a `blockEmbed`: the host opens the Document the Block lives in with that Block in focus\n * with that Block revealed (`revealBlock(blockId)`; `focusComposite(blockId)` hides the rest of the Document, so a host may use it instead), or reveals it when that Document is the open one. Absent: the embed shows no such action.\n */\n openBlock?: (address: BlockAddress) => void\n /**\n * Node views of further Block types by Block type id: what an add-on that draws its own Block type brings (the charts add-on's `chart`);\n * see `CompositeNodeViews.byType`. Read once. Absent: every Block type without its own view renders as a Typed block.\n */\n blockNodeViews?: Readonly<Record<string, NodeViewRenderer>>\n}\n\n/** Heading level the structure stage starts at when it turns composites into headings (below the document title). */\nconst STRUCTURE_STAGE_LEVEL = 2\n\n/**\n * Composites (Typed blocks): the node family with its node views, the toolbar group (insert, „In Block umwandeln“,\n * „Gliederung umwandeln“), `/` commands, the conversion providers (wrap into / switch kind of / unwrap composites),\n * Markdown `:::` fences, legacy `section` migration, the preferred-structure setting and its `editing` settings tab,\n * the chips on each title line (status, tags) and the details popover on the kind icon (the binding's `chrome` overlay), focus mode on one\n * Typed block (`CompositeFocus`, the „Fokussieren“ block action and the binding's `focusChip` overlay), and\n * the AI view of Block types and structure, and the Block types' accepted children (`AcceptedChildren`: an edit that nests a Typed block\n * into one that does not accept its kind is refused with a notice). Contributes the `parseMarkdown`,\n * `structure` and `migrateContent` stages. Imports no AI, media or transcript code.\n */\nexport function compositeFeatureCore<C>(ui: CompositesUi<C>, options: CompositeFeatureOptions = {}): EditorFeature<C> {\n // Host Block types keep their labels; the built-in ones are produced from the context's translator (memoized per `t`).\n const hostBlockTypes = options.blockTypes\n const kindsOf = (ctx: { t: Translate }) => hostBlockTypes ?? defaultBlockTypes(ctx.t)\n const basketsOf = (ctx: { t: Translate }) => options.baskets ?? defaultBaskets(ctx.t)\n const { Composite, CompositeTags, Reference, Cite, BlockEmbed } = compositeNodes(options.blockNodeViews ? { ...ui.nodeViews, byType: options.blockNodeViews } : ui.nodeViews)\n const { exportCheck, edges } = ui\n return {\n id: 'composites',\n dimension: 'content',\n schemaExtensions: () => compositeSchemaExtensions({ ...(hostBlockTypes && { blockTypes: hostBlockTypes }), ...(options.baskets && { baskets: options.baskets }) }),\n blockCapabilities: compositeBlockCapabilities(),\n blockTypes: blockTypesOf,\n extensions: ctx => [\n Composite.configure({ blockTypes: kindsOf(ctx), baskets: basketsOf(ctx) }),\n CompositeTitleNode,\n CompositeDescriptionNode,\n CompositeTags,\n Structure.configure({ mode: () => ctx.settings.get().blocks.structure }),\n AcceptedChildren.configure({ notify: ctx.notify, t: ctx.t }),\n SourceReveal,\n CompositeFocus,\n CompositeMerge,\n CompositeSplit.configure({ defaultBlockType: () => ctx.settings.get().blocks.defaultBlockType, targetChars: () => ctx.settings.get().blocks.splitTargetChars }),\n Reference.configure({ suggestion: referenceSuggestion(ctx.t) }),\n Cite.configure({ suggestion: citeSuggestion(ctx.t) }),\n BlockEmbed.configure({ suggestion: blockEmbedSuggestion(ctx.t), openBlock: options.openBlock ?? null }),\n ],\n toolbarGroups: COMPOSITE_TOOLBAR_GROUPS,\n commands: ctx => compositeCommands(ctx, kindsOf(ctx)),\n insertGuards: () => [compositeInsertGuard],\n blockActions: ctx => [{\n id: 'document-export',\n target: 'typedBlock',\n label: ctx.t('composites.blockAction.export'),\n icon: 'i-lucide-download',\n ability: ABILITY.compositeExport,\n order: 400,\n requires: ['export'],\n run: ({ editor, node }) => {\n // The export never waits for the check: it tells how many things to look at and runs anyway.\n const { length } = exportIssuesOf(editor, node)\n if (length) ctx.notify({ id: 'document-export-issues', kind: 'warning', title: ctx.t(length === 1 ? 'composites.export.issues.one' : 'composites.export.issues.other', { n: length }), description: ctx.t('composites.export.issues.description') })\n downloadText(markdownFileName(node), documentCompositeMarkdown(editor, node))\n },\n }, {\n id: 'composite-details',\n target: 'typedBlock',\n label: ctx.t('composites.blockAction.details'),\n icon: 'i-lucide-info',\n ability: ABILITY.compositeMeta,\n order: 405,\n placement: 'hover',\n readOnly: true,\n run: ({ editor, node }) => openCompositeDetails(editor, node),\n }, {\n id: 'bibliography-export',\n target: 'typedBlock',\n label: ctx.t('composites.blockAction.bibtex'),\n icon: 'i-lucide-book-marked',\n ability: ABILITY.compositeExport,\n order: 410,\n requires: ['bibliography'],\n isVisible: ({ editor, node }) => capabilityDataOf(editor, node, 'bibliography') !== null,\n run: ({ node }) => downloadText(`${markdownFileName(node).replace(/\\.md$/, '')}.bib`, bibtexOf(cslOf(node)!), 'text/x-bibtex;charset=utf-8'),\n }, {\n id: 'composite-focus',\n label: ctx.t('composites.focus.action'),\n target: 'typedBlock',\n icon: 'i-lucide-focus',\n order: 420,\n requires: ['container'],\n run: ({ editor, node }) => {\n const id = blockIdOf(node)\n if (id) editor.commands.focusComposite(id)\n },\n }, renderBlockAction(ctx), collectionAddAction(ctx), ...splitBlockActions(ctx), {\n id: 'composite-merge-next',\n target: 'typedBlock',\n label: ctx.t('composites.merge.next'),\n icon: 'i-lucide-merge',\n ability: ABILITY.compositeMeta,\n requires: ['container', 'title'],\n order: 470,\n isVisible: ({ editor, pos }) => editor.can().mergeCompositeWithNext(pos),\n run: ({ editor, pos }) => void editor.chain().focus().mergeCompositeWithNext(pos).run(),\n }],\n rowBadges: ctx => [derivedRowBadge(ctx.t)],\n ...((exportCheck !== undefined || edges !== undefined) && {\n inspectorSections: (ctx: FeatureContext) => [\n ...(exportCheck !== undefined ? [exportCheckInspectorSection(exportCheck, ctx.t)] : []),\n ...(edges !== undefined ? [edgesInspectorSection(edges, ctx.t)] : []),\n ],\n }),\n overlays: [ui.chrome, ui.focusChip].filter(overlay => overlay !== undefined),\n settingsTabs: ctx => [{ id: 'editing', label: ctx.t('composites.tab'), icon: 'i-lucide-pencil', component: ui.settingsTab, props: { blockTypes: kindsOf(ctx) } }],\n blocks: {\n parseMarkdown: (editor, markdown) => blocksFromMarkdown(md => editor.markdown!.parse(md), markdown, blockTypesOf(editor)),\n structure: (editor, blocks) => {\n const { schema } = editor\n return structureBlocks(schema, blocks.map(block => schema.nodeFromJSON(block)), structureOf(editor), STRUCTURE_STAGE_LEVEL, blockTypesOf(editor)).map(node => node.toJSON())\n },\n migrateContent: migrateLegacyContent,\n normalize: (editor, blocks) => normalizeReferences(blocks, compositeIdsOf(editor.state.doc)),\n },\n conversions: compositeConversions(hostBlockTypes),\n aiContext: editor => ({\n blockTypes: aiBlockTypesOf(blockTypesOf(editor)),\n structure: structureOf(editor),\n blocks: [REFERENCE_AI_BLOCK],\n }),\n // A Typed block derived from another block hands the model that source block's Markdown.\n aiBlockData: ({ editor, node }) => {\n const from = derivationOf(node)?.from\n const source = from && 'block' in from ? findBlockById(editor.state.doc, from.block)?.node : undefined\n // i18n-ignore: model-facing data label (German prompt text, not UI)\n return isTypedBlock(source) ? [{ label: `Quelle: ${source.child(0).textContent.trim()}`, text: bodyMarkdown(editor, source) }] : []\n },\n }\n}\n\n/**\n * The four split actions of a Typed block: at the caret (as sibling or nested Typed blocks; offered on the Typed block around the\n * caret while the caret is past the first body block) and by length (as nested Typed blocks or siblings; offered while the\n * body falls into two parts or more). Each is hidden when the command refuses, so a kind that accepts no child kind\n * never shows the `children` variants.\n */\nfunction splitBlockActions({ t }: FeatureContext): BlockAction[] {\n const atCaret = (id: string, labelKey: 'composites.split.here' | 'composites.split.children', icon: string, order: number, mode: SplitMode): BlockAction => ({\n id,\n label: t(labelKey),\n icon,\n target: 'typedBlock',\n ability: ABILITY.compositeMeta,\n requires: ['container', 'title'],\n order,\n isVisible: ({ editor, pos }) => {\n const { $head } = editor.state.selection\n const found = compositeAround($head)\n return found?.pos === pos && $head.index(found.depth) > COMPOSITE_CHROME_COUNT && editor.can().splitCompositeAtCaret({ mode })\n },\n run: ({ editor }) => void editor.chain().focus().splitCompositeAtCaret({ mode }).run(),\n })\n const byLength = (id: string, labelKey: 'composites.split.lengthChildren' | 'composites.split.lengthSiblings', icon: string, order: number, mode: SplitMode): BlockAction => ({\n id,\n label: t(labelKey),\n icon,\n target: 'typedBlock',\n ability: ABILITY.compositeMeta,\n requires: ['container', 'title'],\n order,\n isVisible: ({ editor, pos }) => editor.can().splitCompositeByLength({ mode, pos }),\n run: ({ editor, pos }) => void editor.chain().focus().splitCompositeByLength({ mode, pos }).run(),\n })\n return [\n atCaret('composite-split-here', 'composites.split.here', 'i-lucide-scissors', 430, 'siblings'),\n atCaret('composite-split-children', 'composites.split.children', 'i-lucide-split', 440, 'children'),\n byLength('composite-split-length-children', 'composites.split.lengthChildren', 'i-lucide-ruler', 450, 'children'),\n byLength('composite-split-length-siblings', 'composites.split.lengthSiblings', 'i-lucide-ruler', 460, 'siblings'),\n ]\n}\n\nconst COMPOSITE_TOOLBAR_GROUPS: ToolbarGroupDef[] = [{ id: 'composites', order: 60, labelKey: 'palette.group.composites' }]\n\n/**\n * Converting headings to Typed blocks and back: the checks and actions the toolbar's „Gliederung umwandeln“ menu and the\n * `/gliedern*` and `/aufloesen*` commands share, so both placements gate and act identically. They read the scope and\n * default kind from the settings at call time.\n */\nfunction structureActions({ settings }: FeatureContext) {\n const groupOptions = (recursive: boolean) => ({ recursive, scope: settings.get().editing.headingConversionScope, kind: settings.get().blocks.defaultBlockType })\n const flattenOptions = (recursive: boolean) => ({ recursive, scope: settings.get().editing.headingConversionScope })\n return {\n canGroup: (editor: Editor, recursive: boolean) => editor.can().convertHeadingsToComposites(groupOptions(recursive)),\n canFlatten: (editor: Editor, recursive: boolean) => editor.can().convertCompositesToHeadings(flattenOptions(recursive)),\n group: (editor: Editor, recursive: boolean) => void editor.chain().focus().convertHeadingsToComposites(groupOptions(recursive)).run(),\n flatten: (editor: Editor, recursive: boolean) => void editor.chain().focus().convertCompositesToHeadings(flattenOptions(recursive)).run(),\n }\n}\n\n/**\n * The commands of the composites feature, each declared once. Toolbar group beside the inserts: the default kind's\n * insert button (it follows the setting, so label/icon/shortcut/`creates` are getters read at render time), „In\n * Block umwandeln“ (one entry per kind for the caret's block) and „Gliederung umwandeln“ (headings <-> composites in\n * both directions, the preferred structure's direction first). `/` menu: one command per kind (`creates` that kind, so\n * the insert guard hides Block types the surrounding Typed block does not accept) and the four heading conversions.\n */\nfunction compositeCommands<C>(ctx: FeatureContext, kinds: readonly BlockType[]): CommandDef<C>[] {\n const { settings, t } = ctx\n const defaultBlockType = () => blockTypeOf(kinds, settings.get().blocks.defaultBlockType)\n const { canGroup, canFlatten, group, flatten } = structureActions(ctx)\n\n function kindItems(editor: Editor): MenuItem[] {\n return [\n { type: 'label', label: t('composites.menu.kindHeading') },\n ...blockTypesOf(editor).map((kind): MenuItem => {\n const target = { type: TYPED_BLOCK, blockType: kind.id } as const\n return { label: kind.label, icon: kind.icon, disabled: !editor.can().convertBlockTo(target), onSelect: () => editor.chain().focus().convertBlockTo(target).run() }\n }),\n ]\n }\n\n function structureItems(editor: Editor): MenuItem[] {\n const structure = settings.get().blocks.structure\n const abilities = abilitiesAtSelection(editor)\n const composite = abilities.has(ABILITY.composite)\n const headings = abilities.has(ABILITY.headings)\n const sep: MenuItem = { type: 'separator' }\n const toComposites: MenuItem[] = [\n { type: 'label', label: t('composites.menu.toComposites') },\n { label: t('composites.menu.toComposites.top'), description: t('composites.menu.toComposites.top.description'), icon: 'i-lucide-layers', disabled: !composite || !canGroup(editor, false), onSelect: () => group(editor, false) },\n { label: t('composites.menu.toComposites.all'), description: t('composites.menu.toComposites.all.description'), icon: 'i-lucide-list-tree', disabled: !composite || !canGroup(editor, true), onSelect: () => group(editor, true) },\n ]\n const toHeadings: MenuItem[] = [\n { type: 'label', label: t('composites.menu.toHeadings') },\n { label: t('composites.menu.toHeadings.top'), description: t('composites.menu.toHeadings.top.description'), icon: 'i-lucide-heading', disabled: !headings || !canFlatten(editor, false), onSelect: () => flatten(editor, false) },\n { label: t('composites.menu.toHeadings.all'), description: t('composites.menu.toHeadings.all.description'), icon: 'i-lucide-align-left', disabled: !headings || !canFlatten(editor, true), onSelect: () => flatten(editor, true) },\n ]\n const entry = editorEntryOf(editor)\n // The settings entry exists only while some feature contributes a tab to open.\n const settingsEntry: MenuItem[] = entry && settingsTabsOf(entry.preset, entry.ctx.app).length\n ? [sep, { label: t('composites.menu.settings'), icon: 'i-lucide-settings-2', onSelect: () => entry.ui.openSettings('editing') }]\n : []\n return [\n { type: 'label', label: t('composites.menu.preferred', { mode: t(STRUCTURE_MODE_KEYS[structure].labelKey) }) },\n ...(structure === 'structured' ? [...toComposites, sep, ...toHeadings] : [...toHeadings, sep, ...toComposites]),\n ...settingsEntry,\n ]\n }\n\n const insertKind = (kind: string, slashId: string, label: string, icon: string): CommandDef<C> => ({\n id: `composite.${kind}`,\n slash: { id: slashId },\n creates: { type: TYPED_BLOCK, attrs: { blockType: kind } },\n icon,\n label,\n ability: ABILITY.composite,\n run: (editor) => { editor.chain().focus().insertComposite(kind).run() },\n })\n\n return [\n {\n id: 'insert',\n toolbar: { group: 'composites', order: 10 },\n // Getters: the default kind arrives with the server settings; the toolbar reads them at render time.\n get icon() { return defaultBlockType().icon },\n get label() { return defaultBlockType().label },\n // Mod-Shift-a (CompositeNode) always inserts a `section`, so only then is it shown as the shortcut.\n get kbds() { return defaultBlockType().id === 'section' ? ['meta', 'shift', 'a'] : undefined },\n get creates() { return { type: TYPED_BLOCK, attrs: { blockType: defaultBlockType().id } } },\n ability: ABILITY.composite,\n can: editor => editor.can().insertComposite(defaultBlockType().id),\n run: (editor) => { editor.chain().focus().insertComposite(defaultBlockType().id).run() },\n },\n {\n id: 'to-kind',\n toolbar: { group: 'composites', order: 20 },\n icon: 'i-lucide-replace',\n label: t('composites.toolbar.toKind'),\n ability: ABILITY.composite,\n can: editor => kindItems(editor).some(item => item.type !== 'label' && !item.disabled),\n menu: kindItems,\n },\n {\n id: 'structure',\n toolbar: { group: 'composites', order: 30 },\n icon: 'i-lucide-list-tree',\n label: t('composites.toolbar.structure'),\n can: editor => canGroup(editor, true) || canFlatten(editor, true),\n menu: structureItems,\n },\n insertKind('section', 'abschnitt', t('composites.slash.section'), 'i-lucide-layers'),\n ...kinds.filter(kind => kind.id !== 'section' && kind.id !== DATA_VIEW_TYPE).map(kind => insertKind(kind.id, kind.id, kind.label, kind.icon)),\n // A view over the Block type the Document uses most (`/ansicht`), not an empty one.\n {\n id: 'ansicht',\n slash: {},\n creates: { type: TYPED_BLOCK, attrs: { blockType: DATA_VIEW_TYPE } },\n icon: 'i-lucide-table-properties',\n label: t('composites.slash.dataView'),\n ability: ABILITY.composite,\n can: editor => editor.can().insertComposite(DATA_VIEW_TYPE),\n run: (editor) => { insertDataView(editor, defaultBlockType().id) },\n },\n { id: 'gliedern', slash: {}, label: t('composites.slash.group'), icon: 'i-lucide-layers', ability: ABILITY.composite, can: editor => canGroup(editor, false), run: editor => group(editor, false) },\n { id: 'gliedern-alle', slash: {}, label: t('composites.slash.groupAll'), icon: 'i-lucide-list-tree', ability: ABILITY.composite, can: editor => canGroup(editor, true), run: editor => group(editor, true) },\n { id: 'aufloesen', slash: {}, label: t('composites.slash.flatten'), icon: 'i-lucide-heading', ability: ABILITY.headings, can: editor => canFlatten(editor, false), run: editor => flatten(editor, false) },\n { id: 'aufloesen-alle', slash: {}, label: t('composites.slash.flattenAll'), icon: 'i-lucide-align-left', ability: ABILITY.headings, can: editor => canFlatten(editor, true), run: editor => flatten(editor, true) },\n { id: 'verweis', slash: {}, label: t('composites.reference.insert'), icon: 'i-lucide-link-2', ability: ABILITY.reference, run: (editor) => { editor.chain().focus().insertContent(REFERENCE_TRIGGER).run() } },\n { id: 'zitat', slash: {}, label: t('composites.cite.insert'), icon: 'i-lucide-quote', ability: ABILITY.reference, run: (editor) => { editor.chain().focus().insertContent(CITE_TRIGGER).run() } },\n { id: 'einbetten', slash: {}, label: t('composites.embed.insert'), icon: 'i-lucide-square-arrow-out-down-right', ability: ABILITY.reference, run: (editor) => { editor.chain().focus().insertContent(BLOCK_EMBED_TRIGGER).run() } },\n renderDocumentCommand(ctx),\n ]\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"feature.js","names":[],"sources":["../../../src/features/composites/feature.ts"],"sourcesContent":["import type { Editor, NodeViewRenderer } from '@tiptap/core'\nimport type { BlockAction, CommandDef, EditorFeature, FeatureContext, MenuItem, ToolbarGroupDef } from '../../core'\nimport { abilitiesAtSelection, capabilityDataOf, downloadText, editorEntryOf, settingsTabsOf } from '../../core'\nimport type { BlockAddress } from '../../core/block-index'\nimport type { Translate } from '../../i18n'\nimport { ABILITY, blockIdOf, findBlockById } from '../../core/schema'\nimport { AcceptedChildren, compositeInsertGuard } from './accepted-children'\nimport { derivedRowBadge } from './badges'\nimport { exportCheckInspectorSection, exportIssuesOf } from './export-check'\nimport { edgesInspectorSection } from './edges-model'\nimport { type Basket, defaultBaskets } from './baskets'\nimport { bibtexOf, cslOf } from './bibliography'\nimport { compositeConversions } from './convert'\nimport { derivationOf, isTypedBlock, TYPED_BLOCK } from '../../core/typed-block'\nimport { bodyMarkdown } from './source'\nimport { blocksFromMarkdown } from './fences'\nimport { DATA_VIEW_TYPE } from './views/data-view'\nimport { insertDataView } from './views/data-view-model'\nimport { structureBlocks } from './heading-composites'\nimport { type BlockType, aiBlockTypesOf, blockTypeOf, defaultBlockTypes } from './block-types'\nimport { compositeBlockCapabilities } from './capabilities'\nimport { migrateLegacyContent } from './legacy'\nimport { compositeSchemaExtensions } from './schema'\nimport { documentCompositeMarkdown, markdownFileName } from './markdown-export'\nimport { collectionAddAction } from './collection-actions'\nimport { openCompositeDetails } from './details-model'\nimport { renderBlockAction, renderDocumentCommand } from './render-actions'\nimport { type CompositeNodeViews, compositeNodes } from './node-views'\nimport { COMPOSITE_CHROME_COUNT, CompositeDescriptionNode, CompositeTitleNode, compositeAround, blockTypesOf } from './nodes'\nimport { CompositeFocus } from './focus'\nimport { CompositeMerge } from './merge'\nimport { BLOCK_EMBED_TRIGGER } from './embed'\nimport { CITE_TRIGGER } from './cite'\nimport { REFERENCE_TRIGGER } from './reference'\nimport { REFERENCE_AI_BLOCK } from './reference-ai'\nimport { blockEmbedSuggestion } from './embed-suggestion'\nimport { referenceSuggestion } from './reference-suggestion'\nimport { citeSuggestion } from './cite-suggestion'\nimport { compositeIdsOf, normalizeReferences } from './reference-text'\nimport { SourceReveal } from './reveal-source'\nimport { CompositeSplit, type SplitMode } from './split'\nimport { Structure, structureOf } from './structure'\nimport { STRUCTURE_MODE_KEYS } from './structure-mode'\n\n/** What a framework binding supplies to the composites feature. */\nexport interface CompositesUi<C> {\n /** The chips on each title line and the details popover on the kind icon; mounted as an overlay. */\n chrome: C\n /** The focus chip („Fokus: <Titel> · Aufheben“) shown while a Typed block is focused; mounted as an overlay. Absent: no chip (the focus mode itself works). */\n focusChip?: C\n /** The „Export-Hinweise“ section of the inspector and the details card (receives `{ editor, node }`): what to look at before a Typed block is exported. Absent: no section (the export still tells the count). */\n exportCheck?: C\n /** The „Kanten“ section of the inspector and the details card (receives `{ editor, node }`): the Edges a person added to a Typed block (`meta.edges`), with a form to add and remove them. Absent: no section. */\n edges?: C\n /** The „Bearbeiten“ settings tab; receives `{ blockTypes }` as props. */\n settingsTab: C\n /** The composite block view of the framework. */\n nodeViews: CompositeNodeViews\n}\n\n/** Options of `compositeFeature`. */\nexport interface CompositeFeatureOptions {\n /** The Block types offered in the editor, with their own labels (default: `defaultBlockTypes(t)`, the built-in Block types in the editor's language); read once. */\n blockTypes?: readonly BlockType[]\n /** The colour baskets a Typed block can be put into (default: `defaultBaskets(t)`, red/orange/yellow/green/blue in the editor's language; colours are the `--sk-basket-<id>` CSS variables); read once. */\n baskets?: readonly Basket[]\n /**\n * „Am Ursprung bearbeiten“ on a `blockEmbed`: the host opens the Document the Block lives in with that Block in focus\n * with that Block revealed (`revealBlock(blockId)`; `focusComposite(blockId)` hides the rest of the Document, so a host may use it instead), or reveals it when that Document is the open one. Absent: the embed shows no such action.\n */\n openBlock?: (address: BlockAddress) => void\n /**\n * Node views of further Block types by Block type id: what an add-on that draws its own Block type brings (the charts add-on's `chart`);\n * see `CompositeNodeViews.byType`. Read once. Absent: every Block type without its own view renders as a Typed block.\n */\n blockNodeViews?: Readonly<Record<string, NodeViewRenderer>>\n}\n\n/** Heading level the structure stage starts at when it turns composites into headings (below the document title). */\nconst STRUCTURE_STAGE_LEVEL = 2\n\n/**\n * Composites (Typed blocks): the node family with its node views, the toolbar group (insert, „In Block umwandeln“,\n * „Gliederung umwandeln“), `/` commands, the conversion providers (wrap into / switch kind of / unwrap composites),\n * Markdown `:::` fences, legacy `section` migration, the preferred-structure setting and its `editing` settings tab,\n * the chips on each title line (status, tags) and the details popover on the kind icon (the binding's `chrome` overlay), focus mode on one\n * Typed block (`CompositeFocus`, the „Fokussieren“ block action and the binding's `focusChip` overlay), and\n * the AI view of Block types and structure, and the Block types' accepted children (`AcceptedChildren`: an edit that nests a Typed block\n * into one that does not accept its kind is refused with a notice). Contributes the `parseMarkdown`,\n * `structure` and `migrateContent` stages. Imports no AI, media or transcript code.\n */\nexport function compositeFeatureCore<C>(ui: CompositesUi<C>, options: CompositeFeatureOptions = {}): EditorFeature<C> {\n // Host Block types keep their labels; the built-in ones are produced from the context's translator (memoized per `t`).\n const hostBlockTypes = options.blockTypes\n const kindsOf = (ctx: { t: Translate }) => hostBlockTypes ?? defaultBlockTypes(ctx.t)\n const basketsOf = (ctx: { t: Translate }) => options.baskets ?? defaultBaskets(ctx.t)\n const { Composite, CompositeTags, Reference, Cite, BlockEmbed } = compositeNodes(options.blockNodeViews ? { ...ui.nodeViews, byType: options.blockNodeViews } : ui.nodeViews)\n const { exportCheck, edges } = ui\n return {\n id: 'composites',\n dimension: 'content',\n schemaExtensions: () => compositeSchemaExtensions({ ...(hostBlockTypes && { blockTypes: hostBlockTypes }), ...(options.baskets && { baskets: options.baskets }) }),\n blockCapabilities: compositeBlockCapabilities(),\n blockTypes: blockTypesOf,\n extensions: ctx => [\n Composite.configure({ blockTypes: kindsOf(ctx), baskets: basketsOf(ctx) }),\n CompositeTitleNode,\n CompositeDescriptionNode,\n CompositeTags,\n Structure.configure({ mode: () => ctx.settings.get().blocks.structure }),\n AcceptedChildren.configure({ notify: ctx.notify, t: ctx.t }),\n SourceReveal,\n CompositeFocus,\n CompositeMerge,\n CompositeSplit.configure({\n defaultBlockType: () => ctx.settings.get().blocks.defaultBlockType,\n targetChars: () => ctx.settings.get().blocks.splitTargetChars,\n splitOnRule: () => ctx.settings.get().blocks.splitOnRule,\n }),\n Reference.configure({ suggestion: referenceSuggestion(ctx.t) }),\n Cite.configure({ suggestion: citeSuggestion(ctx.t) }),\n BlockEmbed.configure({ suggestion: blockEmbedSuggestion(ctx.t), openBlock: options.openBlock ?? null }),\n ],\n toolbarGroups: COMPOSITE_TOOLBAR_GROUPS,\n commands: ctx => compositeCommands(ctx, kindsOf(ctx)),\n insertGuards: () => [compositeInsertGuard],\n blockActions: ctx => [{\n id: 'document-export',\n target: 'typedBlock',\n label: ctx.t('composites.blockAction.export'),\n icon: 'i-lucide-download',\n ability: ABILITY.compositeExport,\n order: 400,\n requires: ['export'],\n run: ({ editor, node }) => {\n // The export never waits for the check: it tells how many things to look at and runs anyway.\n const { length } = exportIssuesOf(editor, node)\n if (length) ctx.notify({ id: 'document-export-issues', kind: 'warning', title: ctx.t(length === 1 ? 'composites.export.issues.one' : 'composites.export.issues.other', { n: length }), description: ctx.t('composites.export.issues.description') })\n downloadText(markdownFileName(node), documentCompositeMarkdown(editor, node))\n },\n }, {\n id: 'composite-details',\n target: 'typedBlock',\n label: ctx.t('composites.blockAction.details'),\n icon: 'i-lucide-info',\n ability: ABILITY.compositeMeta,\n order: 405,\n placement: 'hover',\n readOnly: true,\n run: ({ editor, node }) => openCompositeDetails(editor, node),\n }, {\n id: 'bibliography-export',\n target: 'typedBlock',\n label: ctx.t('composites.blockAction.bibtex'),\n icon: 'i-lucide-book-marked',\n ability: ABILITY.compositeExport,\n order: 410,\n requires: ['bibliography'],\n isVisible: ({ editor, node }) => capabilityDataOf(editor, node, 'bibliography') !== null,\n run: ({ node }) => downloadText(`${markdownFileName(node).replace(/\\.md$/, '')}.bib`, bibtexOf(cslOf(node)!), 'text/x-bibtex;charset=utf-8'),\n }, {\n id: 'composite-focus',\n label: ctx.t('composites.focus.action'),\n target: 'typedBlock',\n icon: 'i-lucide-focus',\n order: 420,\n requires: ['container'],\n run: ({ editor, node }) => {\n const id = blockIdOf(node)\n if (id) editor.commands.focusComposite(id)\n },\n }, renderBlockAction(ctx), collectionAddAction(ctx), ...splitBlockActions(ctx), {\n id: 'composite-merge-next',\n target: 'typedBlock',\n label: ctx.t('composites.merge.next'),\n icon: 'i-lucide-merge',\n ability: ABILITY.compositeMeta,\n requires: ['container', 'title'],\n order: 470,\n isVisible: ({ editor, pos }) => editor.can().mergeCompositeWithNext(pos),\n run: ({ editor, pos }) => void editor.chain().focus().mergeCompositeWithNext(pos).run(),\n }],\n rowBadges: ctx => [derivedRowBadge(ctx.t)],\n ...((exportCheck !== undefined || edges !== undefined) && {\n inspectorSections: (ctx: FeatureContext) => [\n ...(exportCheck !== undefined ? [exportCheckInspectorSection(exportCheck, ctx.t)] : []),\n ...(edges !== undefined ? [edgesInspectorSection(edges, ctx.t)] : []),\n ],\n }),\n overlays: [ui.chrome, ui.focusChip].filter(overlay => overlay !== undefined),\n settingsTabs: ctx => [{ id: 'editing', label: ctx.t('composites.tab'), icon: 'i-lucide-pencil', component: ui.settingsTab, props: { blockTypes: kindsOf(ctx) } }],\n blocks: {\n parseMarkdown: (editor, markdown) => blocksFromMarkdown(md => editor.markdown!.parse(md), markdown, blockTypesOf(editor)),\n structure: (editor, blocks) => {\n const { schema } = editor\n return structureBlocks(schema, blocks.map(block => schema.nodeFromJSON(block)), structureOf(editor), STRUCTURE_STAGE_LEVEL, blockTypesOf(editor)).map(node => node.toJSON())\n },\n migrateContent: migrateLegacyContent,\n normalize: (editor, blocks) => normalizeReferences(blocks, compositeIdsOf(editor.state.doc)),\n },\n conversions: compositeConversions(hostBlockTypes),\n aiContext: editor => ({\n blockTypes: aiBlockTypesOf(blockTypesOf(editor)),\n structure: structureOf(editor),\n blocks: [REFERENCE_AI_BLOCK],\n }),\n // A Typed block derived from another block hands the model that source block's Markdown.\n aiBlockData: ({ editor, node }) => {\n const from = derivationOf(node)?.from\n const source = from && 'block' in from ? findBlockById(editor.state.doc, from.block)?.node : undefined\n // i18n-ignore: model-facing data label (German prompt text, not UI)\n return isTypedBlock(source) ? [{ label: `Quelle: ${source.child(0).textContent.trim()}`, text: bodyMarkdown(editor, source) }] : []\n },\n }\n}\n\n/**\n * The split actions of a Typed block: at the caret (as sibling or nested Typed blocks; offered on the Typed block around the\n * caret while the caret is past the first body block), by length and at the horizontal rules (each as nested Typed blocks or\n * siblings; offered while the body falls into two parts or more). Each is hidden when the command refuses, so a kind that\n * accepts no child kind never shows the `children` variants.\n */\nfunction splitBlockActions({ t }: FeatureContext): BlockAction[] {\n const atCaret = (id: string, labelKey: 'composites.split.here' | 'composites.split.children', icon: string, order: number, mode: SplitMode): BlockAction => ({\n id,\n label: t(labelKey),\n icon,\n target: 'typedBlock',\n ability: ABILITY.compositeMeta,\n requires: ['container', 'title'],\n order,\n isVisible: ({ editor, pos }) => {\n const { $head } = editor.state.selection\n const found = compositeAround($head)\n return found?.pos === pos && $head.index(found.depth) > COMPOSITE_CHROME_COUNT && editor.can().splitCompositeAtCaret({ mode })\n },\n run: ({ editor }) => void editor.chain().focus().splitCompositeAtCaret({ mode }).run(),\n })\n const byLength = (id: string, labelKey: 'composites.split.lengthChildren' | 'composites.split.lengthSiblings', icon: string, order: number, mode: SplitMode): BlockAction => ({\n id,\n label: t(labelKey),\n icon,\n target: 'typedBlock',\n ability: ABILITY.compositeMeta,\n requires: ['container', 'title'],\n order,\n isVisible: ({ editor, pos }) => editor.can().splitCompositeByLength({ mode, pos }),\n run: ({ editor, pos }) => void editor.chain().focus().splitCompositeByLength({ mode, pos }).run(),\n })\n const atRules = (id: string, labelKey: 'composites.split.rulesChildren' | 'composites.split.rulesSiblings', order: number, mode: SplitMode): BlockAction => ({\n id,\n label: t(labelKey),\n icon: 'i-lucide-separator-horizontal',\n target: 'typedBlock',\n ability: ABILITY.compositeMeta,\n requires: ['container', 'title'],\n order,\n isVisible: ({ editor, pos }) => editor.can().splitCompositeAtRules({ mode, pos }),\n run: ({ editor, pos }) => void editor.chain().focus().splitCompositeAtRules({ mode, pos }).run(),\n })\n return [\n atCaret('composite-split-here', 'composites.split.here', 'i-lucide-scissors', 430, 'siblings'),\n atCaret('composite-split-children', 'composites.split.children', 'i-lucide-split', 440, 'children'),\n byLength('composite-split-length-children', 'composites.split.lengthChildren', 'i-lucide-ruler', 450, 'children'),\n byLength('composite-split-length-siblings', 'composites.split.lengthSiblings', 'i-lucide-ruler', 460, 'siblings'),\n atRules('composite-split-rules-children', 'composites.split.rulesChildren', 462, 'children'),\n atRules('composite-split-rules-siblings', 'composites.split.rulesSiblings', 464, 'siblings'),\n ]\n}\n\nconst COMPOSITE_TOOLBAR_GROUPS: ToolbarGroupDef[] = [{ id: 'composites', order: 60, labelKey: 'palette.group.composites' }]\n\n/**\n * Converting headings to Typed blocks and back: the checks and actions the toolbar's „Gliederung umwandeln“ menu and the\n * `/gliedern*` and `/aufloesen*` commands share, so both placements gate and act identically. They read the scope and\n * default kind from the settings at call time.\n */\nfunction structureActions({ settings }: FeatureContext) {\n const groupOptions = (recursive: boolean) => ({ recursive, scope: settings.get().editing.headingConversionScope, kind: settings.get().blocks.defaultBlockType })\n const flattenOptions = (recursive: boolean) => ({ recursive, scope: settings.get().editing.headingConversionScope })\n return {\n canGroup: (editor: Editor, recursive: boolean) => editor.can().convertHeadingsToComposites(groupOptions(recursive)),\n canFlatten: (editor: Editor, recursive: boolean) => editor.can().convertCompositesToHeadings(flattenOptions(recursive)),\n group: (editor: Editor, recursive: boolean) => void editor.chain().focus().convertHeadingsToComposites(groupOptions(recursive)).run(),\n flatten: (editor: Editor, recursive: boolean) => void editor.chain().focus().convertCompositesToHeadings(flattenOptions(recursive)).run(),\n }\n}\n\n/**\n * The commands of the composites feature, each declared once. Toolbar group beside the inserts: the default kind's\n * insert button (it follows the setting, so label/icon/shortcut/`creates` are getters read at render time), „In\n * Block umwandeln“ (one entry per kind for the caret's block) and „Gliederung umwandeln“ (headings <-> composites in\n * both directions, the preferred structure's direction first). `/` menu: one command per kind (`creates` that kind, so\n * the insert guard hides Block types the surrounding Typed block does not accept) and the four heading conversions.\n */\nfunction compositeCommands<C>(ctx: FeatureContext, kinds: readonly BlockType[]): CommandDef<C>[] {\n const { settings, t } = ctx\n const defaultBlockType = () => blockTypeOf(kinds, settings.get().blocks.defaultBlockType)\n const { canGroup, canFlatten, group, flatten } = structureActions(ctx)\n\n function kindItems(editor: Editor): MenuItem[] {\n return [\n { type: 'label', label: t('composites.menu.kindHeading') },\n ...blockTypesOf(editor).map((kind): MenuItem => {\n const target = { type: TYPED_BLOCK, blockType: kind.id } as const\n return { label: kind.label, icon: kind.icon, disabled: !editor.can().convertBlockTo(target), onSelect: () => editor.chain().focus().convertBlockTo(target).run() }\n }),\n ]\n }\n\n function structureItems(editor: Editor): MenuItem[] {\n const structure = settings.get().blocks.structure\n const abilities = abilitiesAtSelection(editor)\n const composite = abilities.has(ABILITY.composite)\n const headings = abilities.has(ABILITY.headings)\n const sep: MenuItem = { type: 'separator' }\n const toComposites: MenuItem[] = [\n { type: 'label', label: t('composites.menu.toComposites') },\n { label: t('composites.menu.toComposites.top'), description: t('composites.menu.toComposites.top.description'), icon: 'i-lucide-layers', disabled: !composite || !canGroup(editor, false), onSelect: () => group(editor, false) },\n { label: t('composites.menu.toComposites.all'), description: t('composites.menu.toComposites.all.description'), icon: 'i-lucide-list-tree', disabled: !composite || !canGroup(editor, true), onSelect: () => group(editor, true) },\n ]\n const toHeadings: MenuItem[] = [\n { type: 'label', label: t('composites.menu.toHeadings') },\n { label: t('composites.menu.toHeadings.top'), description: t('composites.menu.toHeadings.top.description'), icon: 'i-lucide-heading', disabled: !headings || !canFlatten(editor, false), onSelect: () => flatten(editor, false) },\n { label: t('composites.menu.toHeadings.all'), description: t('composites.menu.toHeadings.all.description'), icon: 'i-lucide-align-left', disabled: !headings || !canFlatten(editor, true), onSelect: () => flatten(editor, true) },\n ]\n const entry = editorEntryOf(editor)\n // The settings entry exists only while some feature contributes a tab to open.\n const settingsEntry: MenuItem[] = entry && settingsTabsOf(entry.preset, entry.ctx.app).length\n ? [sep, { label: t('composites.menu.settings'), icon: 'i-lucide-settings-2', onSelect: () => entry.ui.openSettings('editing') }]\n : []\n return [\n { type: 'label', label: t('composites.menu.preferred', { mode: t(STRUCTURE_MODE_KEYS[structure].labelKey) }) },\n ...(structure === 'structured' ? [...toComposites, sep, ...toHeadings] : [...toHeadings, sep, ...toComposites]),\n ...settingsEntry,\n ]\n }\n\n const insertKind = (kind: string, slashId: string, label: string, icon: string): CommandDef<C> => ({\n id: `composite.${kind}`,\n slash: { id: slashId },\n creates: { type: TYPED_BLOCK, attrs: { blockType: kind } },\n icon,\n label,\n ability: ABILITY.composite,\n run: (editor) => { editor.chain().focus().insertComposite(kind).run() },\n })\n\n return [\n {\n id: 'insert',\n toolbar: { group: 'composites', order: 10 },\n // Getters: the default kind arrives with the server settings; the toolbar reads them at render time.\n get icon() { return defaultBlockType().icon },\n get label() { return defaultBlockType().label },\n // Mod-Shift-a (CompositeNode) always inserts a `section`, so only then is it shown as the shortcut.\n get kbds() { return defaultBlockType().id === 'section' ? ['meta', 'shift', 'a'] : undefined },\n get creates() { return { type: TYPED_BLOCK, attrs: { blockType: defaultBlockType().id } } },\n ability: ABILITY.composite,\n can: editor => editor.can().insertComposite(defaultBlockType().id),\n run: (editor) => { editor.chain().focus().insertComposite(defaultBlockType().id).run() },\n },\n {\n id: 'to-kind',\n toolbar: { group: 'composites', order: 20 },\n icon: 'i-lucide-replace',\n label: t('composites.toolbar.toKind'),\n ability: ABILITY.composite,\n can: editor => kindItems(editor).some(item => item.type !== 'label' && !item.disabled),\n menu: kindItems,\n },\n {\n id: 'structure',\n toolbar: { group: 'composites', order: 30 },\n icon: 'i-lucide-list-tree',\n label: t('composites.toolbar.structure'),\n can: editor => canGroup(editor, true) || canFlatten(editor, true),\n menu: structureItems,\n },\n insertKind('section', 'abschnitt', t('composites.slash.section'), 'i-lucide-layers'),\n ...kinds.filter(kind => kind.id !== 'section' && kind.id !== DATA_VIEW_TYPE).map(kind => insertKind(kind.id, kind.id, kind.label, kind.icon)),\n // A view over the Block type the Document uses most (`/ansicht`), not an empty one.\n {\n id: 'ansicht',\n slash: {},\n creates: { type: TYPED_BLOCK, attrs: { blockType: DATA_VIEW_TYPE } },\n icon: 'i-lucide-table-properties',\n label: t('composites.slash.dataView'),\n ability: ABILITY.composite,\n can: editor => editor.can().insertComposite(DATA_VIEW_TYPE),\n run: (editor) => { insertDataView(editor, defaultBlockType().id) },\n },\n { id: 'gliedern', slash: {}, label: t('composites.slash.group'), icon: 'i-lucide-layers', ability: ABILITY.composite, can: editor => canGroup(editor, false), run: editor => group(editor, false) },\n { id: 'gliedern-alle', slash: {}, label: t('composites.slash.groupAll'), icon: 'i-lucide-list-tree', ability: ABILITY.composite, can: editor => canGroup(editor, true), run: editor => group(editor, true) },\n { id: 'aufloesen', slash: {}, label: t('composites.slash.flatten'), icon: 'i-lucide-heading', ability: ABILITY.headings, can: editor => canFlatten(editor, false), run: editor => flatten(editor, false) },\n { id: 'aufloesen-alle', slash: {}, label: t('composites.slash.flattenAll'), icon: 'i-lucide-align-left', ability: ABILITY.headings, can: editor => canFlatten(editor, true), run: editor => flatten(editor, true) },\n { id: 'verweis', slash: {}, label: t('composites.reference.insert'), icon: 'i-lucide-link-2', ability: ABILITY.reference, run: (editor) => { editor.chain().focus().insertContent(REFERENCE_TRIGGER).run() } },\n { id: 'zitat', slash: {}, label: t('composites.cite.insert'), icon: 'i-lucide-quote', ability: ABILITY.reference, run: (editor) => { editor.chain().focus().insertContent(CITE_TRIGGER).run() } },\n { id: 'einbetten', slash: {}, label: t('composites.embed.insert'), icon: 'i-lucide-square-arrow-out-down-right', ability: ABILITY.reference, run: (editor) => { editor.chain().focus().insertContent(BLOCK_EMBED_TRIGGER).run() } },\n renderDocumentCommand(ctx),\n ]\n}\n"],"mappings":"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"}
|
|
@@ -47,8 +47,8 @@ import { EMBED_CLASS, embedViewOptions, mountEmbed } from "./embed-dom.js";
|
|
|
47
47
|
import { referenceSuggestion } from "./reference-suggestion.js";
|
|
48
48
|
import { citeSuggestion } from "./cite-suggestion.js";
|
|
49
49
|
import { CompositeMerge, mergeBody } from "./merge.js";
|
|
50
|
-
import { CompositeSplit, CompositeSplitOptions, SplitMode, childKindFor, generatedTitle, splitBodyByLength, splitComposite } from "./split.js";
|
|
50
|
+
import { CompositeSplit, CompositeSplitOptions, SplitMode, childKindFor, generatedTitle, splitBodyAtRules, splitBodyByLength, splitComposite } from "./split.js";
|
|
51
51
|
import { Structure, StructureStorage, structureOf } from "./structure.js";
|
|
52
52
|
import { STRUCTURE_MODE_KEYS } from "./structure-mode.js";
|
|
53
53
|
import { TREE_ROOT_KEYS } from "./tree-root.js";
|
|
54
|
-
export { AcceptedChildren, type AcceptedChildrenOptions, BASKET_IDS, BASKET_KEY, BLOCK_EMBED_NODE, type Basket, type BlockEmbedAttrs, type BlockEmbedItem, BlockEmbedNode, type BlockEmbedOptions, BlockEmbedSuggestionPluginKey, type BlockProperties, type BlockType, type BlockTypeAi, type BlockTypeCount, BlockTypeJsonError, type BlockTypeJsonIssue, type BlockTypeOption, CITE_NODE, COLLECTION_ITEMS_KEY, COLLECTION_QUERY_KEY, COLLECTION_TYPE, COMPOSITE_CHROME_COUNT, CSL_TYPES, type CellText, type CheckProbe, type CiteAttrs, type CiteEntry, type CiteItem, CiteNode, type CiteOptions, CiteSuggestionPluginKey, type CollectionChoice, type CollectionItem, type CollectionView, type CollectionViewModel, type CollectionViewState, type ColumnInput, type CompositeAiBrief, type CompositeAnchor, type CompositeAnchorsHandle, type CompositeBacklink, CompositeDescriptionNode, type CompositeFeatureOptions, CompositeFocus, type CompositeFocusState, type CompositeFrame, type CompositeInspector, type CompositeInspectorSection, type CompositeInspectorState, type CompositeMention, CompositeMerge, CompositeNode, type CompositeNodeViews, type CompositeOptions, type CompositeReference, type CompositeRow, type CompositeRowsHandle, type CompositeRowsState, CompositeSplit, type CompositeSplitOptions, type CompositeStorage, CompositeTagsNode, CompositeTitleNode, type CompositesUi, type ConditionDraft, type ConditionRow, type CslDate, type CslItem, type CslName, type CslType, DATA_VIEW_DEBOUNCE_MS, DATA_VIEW_LAYOUT_KEY, DATA_VIEW_QUERY_KEY, DATA_VIEW_TYPE, DEFAULT_LAYOUT, type DataViewBackend, type DataViewInput, type DataViewModel, type DataViewState, type DataViewStatus, type DocumentOutlineBlock, type DocumentOutlineEntry, type DocumentOutlineHeading, EMBED_CLASS, type EmbedChain, type EmbedState, type ExportCheckView, type ExportIssue, type ExportIssueCode, FOREIGN_CONTENT_REFRESH_MS, type FieldChoice, type FieldViewColumn, type InspectorDerivation, LAYOUT_IDS, type Lane, type LayoutId, type LayoutInput, type LayoutRequirement, type ModelOf, type MoveVerdict, type OutlineNode, type QueryBuilderInput, type QueryBuilderModel, type QueryBuilderState, REVEAL_ANCHOR_EVENT, REVEAL_PAGE_EVENT, type ReferenceAttrs, type ReferenceItem, ReferenceNode, type ReferenceOptions, ReferenceSuggestionPluginKey, type ReferenceTarget, SOURCE_MEDIA_TYPES, STRUCTURE_MODE_KEYS, type SourceLocator, SourceReveal, type SplitMode, Structure, type StructureStorage, TITLE_HIDDEN_KEY, TREE_ROOT_KEYS, VIEW_LAYOUTS, type ValueInput, type ViewColumn, type ViewLayout, type ViewModel, type ViewModelOutcome, acceptsChild, acceptsImport, addToCollection, aiBlockTypesOf, basketById, basketOf, bibOf, bibtexKey, bibtexOf, blockEmbedAttrsOf, blockEmbedMarkdown, blockEmbedSuggestion, blockPropertiesAt, blockPropertiesOf, blockTypeOf, blockTypesOf, blocksFromMarkdown, bodyMarkdown, canMoveBlockInto, carriesProperties, childKindFor, chooseDataViewLayout, citeAttrsOf, citeEntriesOf, citeFull, citeMarkdown, citeShort, citeSuggestion, citeText, collectionChoicesOf, collectionItemsOf, collectionQueryOf, collectionViewOf, compositeAiBrief, compositeBacklinks, compositeBasketsOf, compositeChromeBlocks, compositeConversions, compositeDescriptionText, compositeFeatureCore, compositeFence, compositeFieldText, compositeFocusKey, compositeFocusOf, compositeNodes, compositeOfRow, compositeOutline, compositeRowAt, compositeRows, compositeSchemaExtensions, compositeSectionOf, conditionValueOf, convertCompositeBlocks, createCollectionViewModel, createCompositeInspector, createCompositeRows, createDataViewModel, createEditorDataViewModel, createEditorQueryBuilder, createQueryBuilderModel, cslOf, cslTypeOptions, dataRowKeyOf, dataViewCountLabelOf, dataViewLayoutOf, dataViewQueryOf, defaultBaskets, defaultBlockTypes, defaultGroupFieldOf, definitionsOfQuery, derivedChipOf, derivedRowBadge, displayEnv, documentCompositeMarkdown, documentOutline, embedChainOf, embedKeyOf, embedStateOf, embedViewOptions, exportCheckInspectorSection, exportCheckSectionOf, exportIssueLabel, exportIssuesOf, fieldChoicesOf, fieldColumnsOf, fillCollectionFromQuery, flattenCompositesToHeadings, focusDecorations, foreignBlockOf, generatedTitle, groupHeadingsIntoComposites, headingGroupRange, headingsMarkdown, insertDataView, isAiProposal, isRootBlockType, layoutIdOf, localRowsOf, markdownFileName, mergeBlockTypes, mergeBody, metaWithProperty, missingRequirementsOf, mostUsedBlockTypeOf, mountEmbed, moveBlockInto, moveCollectionItem, moveIntoVerdict, newDataViewMeta, normalizeReferences, observeCompositeAnchors, opsOfField, parseBlockTypes, parseLocator, propertyHostOf, provideCheckProbe, referenceLabel, referenceMarkdown, referenceSuggestion, referenceTarget, referenceTitle, referencesFromText, removeCollectionItem, resolveCite, revealSource, rowFieldsOf, seekSource, setBlockProperty, setCollectionItems, setCollectionQuery, setCompositeDescription, setCompositeTags, setDataViewQuery, sourceOf, splitBodyByLength, splitComposite, structureBlocks as structureCompositeBlocks, structureOf, subscribeBlockChanges, subscribeExportCheck, subscribeForeignBlocks, tableColumnsOf, titleHiddenOf, typedBlockViewOptions, valueInputOf, viewModelOf, withCollectionItems, withItemMoved, withNewAddresses, yearOf };
|
|
54
|
+
export { AcceptedChildren, type AcceptedChildrenOptions, BASKET_IDS, BASKET_KEY, BLOCK_EMBED_NODE, type Basket, type BlockEmbedAttrs, type BlockEmbedItem, BlockEmbedNode, type BlockEmbedOptions, BlockEmbedSuggestionPluginKey, type BlockProperties, type BlockType, type BlockTypeAi, type BlockTypeCount, BlockTypeJsonError, type BlockTypeJsonIssue, type BlockTypeOption, CITE_NODE, COLLECTION_ITEMS_KEY, COLLECTION_QUERY_KEY, COLLECTION_TYPE, COMPOSITE_CHROME_COUNT, CSL_TYPES, type CellText, type CheckProbe, type CiteAttrs, type CiteEntry, type CiteItem, CiteNode, type CiteOptions, CiteSuggestionPluginKey, type CollectionChoice, type CollectionItem, type CollectionView, type CollectionViewModel, type CollectionViewState, type ColumnInput, type CompositeAiBrief, type CompositeAnchor, type CompositeAnchorsHandle, type CompositeBacklink, CompositeDescriptionNode, type CompositeFeatureOptions, CompositeFocus, type CompositeFocusState, type CompositeFrame, type CompositeInspector, type CompositeInspectorSection, type CompositeInspectorState, type CompositeMention, CompositeMerge, CompositeNode, type CompositeNodeViews, type CompositeOptions, type CompositeReference, type CompositeRow, type CompositeRowsHandle, type CompositeRowsState, CompositeSplit, type CompositeSplitOptions, type CompositeStorage, CompositeTagsNode, CompositeTitleNode, type CompositesUi, type ConditionDraft, type ConditionRow, type CslDate, type CslItem, type CslName, type CslType, DATA_VIEW_DEBOUNCE_MS, DATA_VIEW_LAYOUT_KEY, DATA_VIEW_QUERY_KEY, DATA_VIEW_TYPE, DEFAULT_LAYOUT, type DataViewBackend, type DataViewInput, type DataViewModel, type DataViewState, type DataViewStatus, type DocumentOutlineBlock, type DocumentOutlineEntry, type DocumentOutlineHeading, EMBED_CLASS, type EmbedChain, type EmbedState, type ExportCheckView, type ExportIssue, type ExportIssueCode, FOREIGN_CONTENT_REFRESH_MS, type FieldChoice, type FieldViewColumn, type InspectorDerivation, LAYOUT_IDS, type Lane, type LayoutId, type LayoutInput, type LayoutRequirement, type ModelOf, type MoveVerdict, type OutlineNode, type QueryBuilderInput, type QueryBuilderModel, type QueryBuilderState, REVEAL_ANCHOR_EVENT, REVEAL_PAGE_EVENT, type ReferenceAttrs, type ReferenceItem, ReferenceNode, type ReferenceOptions, ReferenceSuggestionPluginKey, type ReferenceTarget, SOURCE_MEDIA_TYPES, STRUCTURE_MODE_KEYS, type SourceLocator, SourceReveal, type SplitMode, Structure, type StructureStorage, TITLE_HIDDEN_KEY, TREE_ROOT_KEYS, VIEW_LAYOUTS, type ValueInput, type ViewColumn, type ViewLayout, type ViewModel, type ViewModelOutcome, acceptsChild, acceptsImport, addToCollection, aiBlockTypesOf, basketById, basketOf, bibOf, bibtexKey, bibtexOf, blockEmbedAttrsOf, blockEmbedMarkdown, blockEmbedSuggestion, blockPropertiesAt, blockPropertiesOf, blockTypeOf, blockTypesOf, blocksFromMarkdown, bodyMarkdown, canMoveBlockInto, carriesProperties, childKindFor, chooseDataViewLayout, citeAttrsOf, citeEntriesOf, citeFull, citeMarkdown, citeShort, citeSuggestion, citeText, collectionChoicesOf, collectionItemsOf, collectionQueryOf, collectionViewOf, compositeAiBrief, compositeBacklinks, compositeBasketsOf, compositeChromeBlocks, compositeConversions, compositeDescriptionText, compositeFeatureCore, compositeFence, compositeFieldText, compositeFocusKey, compositeFocusOf, compositeNodes, compositeOfRow, compositeOutline, compositeRowAt, compositeRows, compositeSchemaExtensions, compositeSectionOf, conditionValueOf, convertCompositeBlocks, createCollectionViewModel, createCompositeInspector, createCompositeRows, createDataViewModel, createEditorDataViewModel, createEditorQueryBuilder, createQueryBuilderModel, cslOf, cslTypeOptions, dataRowKeyOf, dataViewCountLabelOf, dataViewLayoutOf, dataViewQueryOf, defaultBaskets, defaultBlockTypes, defaultGroupFieldOf, definitionsOfQuery, derivedChipOf, derivedRowBadge, displayEnv, documentCompositeMarkdown, documentOutline, embedChainOf, embedKeyOf, embedStateOf, embedViewOptions, exportCheckInspectorSection, exportCheckSectionOf, exportIssueLabel, exportIssuesOf, fieldChoicesOf, fieldColumnsOf, fillCollectionFromQuery, flattenCompositesToHeadings, focusDecorations, foreignBlockOf, generatedTitle, groupHeadingsIntoComposites, headingGroupRange, headingsMarkdown, insertDataView, isAiProposal, isRootBlockType, layoutIdOf, localRowsOf, markdownFileName, mergeBlockTypes, mergeBody, metaWithProperty, missingRequirementsOf, mostUsedBlockTypeOf, mountEmbed, moveBlockInto, moveCollectionItem, moveIntoVerdict, newDataViewMeta, normalizeReferences, observeCompositeAnchors, opsOfField, parseBlockTypes, parseLocator, propertyHostOf, provideCheckProbe, referenceLabel, referenceMarkdown, referenceSuggestion, referenceTarget, referenceTitle, referencesFromText, removeCollectionItem, resolveCite, revealSource, rowFieldsOf, seekSource, setBlockProperty, setCollectionItems, setCollectionQuery, setCompositeDescription, setCompositeTags, setDataViewQuery, sourceOf, splitBodyAtRules, splitBodyByLength, splitComposite, structureBlocks as structureCompositeBlocks, structureOf, subscribeBlockChanges, subscribeExportCheck, subscribeForeignBlocks, tableColumnsOf, titleHiddenOf, typedBlockViewOptions, valueInputOf, viewModelOf, withCollectionItems, withItemMoved, withNewAddresses, yearOf };
|
|
@@ -42,7 +42,7 @@ import { CompositeMerge, mergeBody } from "./merge.js";
|
|
|
42
42
|
import { blockEmbedSuggestion } from "./embed-suggestion.js";
|
|
43
43
|
import { citeSuggestion } from "./cite-suggestion.js";
|
|
44
44
|
import { REVEAL_ANCHOR_EVENT, REVEAL_PAGE_EVENT, SourceReveal, parseLocator, revealSource, seekSource } from "./reveal-source.js";
|
|
45
|
-
import { CompositeSplit, childKindFor, generatedTitle, splitBodyByLength, splitComposite } from "./split.js";
|
|
45
|
+
import { CompositeSplit, childKindFor, generatedTitle, splitBodyAtRules, splitBodyByLength, splitComposite } from "./split.js";
|
|
46
46
|
import { Structure, structureOf } from "./structure.js";
|
|
47
47
|
import { STRUCTURE_MODE_KEYS } from "./structure-mode.js";
|
|
48
48
|
import { compositeFeatureCore } from "./feature.js";
|
|
@@ -51,4 +51,4 @@ import { createCompositeRows } from "./rows-model.js";
|
|
|
51
51
|
import { TREE_ROOT_KEYS } from "./tree-root.js";
|
|
52
52
|
import { compositeFieldText, createCompositeInspector } from "./inspector-model.js";
|
|
53
53
|
import { canMoveBlockInto, compositeOutline, documentOutline, moveBlockInto, moveIntoVerdict } from "./outline.js";
|
|
54
|
-
export { AcceptedChildren, BASKET_IDS, BASKET_KEY, BLOCK_EMBED_NODE, BlockEmbedNode, BlockEmbedSuggestionPluginKey, BlockTypeJsonError, CITE_NODE, COLLECTION_ITEMS_KEY, COLLECTION_QUERY_KEY, COLLECTION_TYPE, COMPOSITE_CHROME_COUNT, CSL_TYPES, CiteNode, CiteSuggestionPluginKey, CompositeDescriptionNode, CompositeFocus, CompositeMerge, CompositeNode, CompositeSplit, CompositeTagsNode, CompositeTitleNode, DATA_VIEW_DEBOUNCE_MS, DATA_VIEW_LAYOUT_KEY, DATA_VIEW_QUERY_KEY, DATA_VIEW_TYPE, DEFAULT_LAYOUT, EMBED_CLASS, FOREIGN_CONTENT_REFRESH_MS, LAYOUT_IDS, REVEAL_ANCHOR_EVENT, REVEAL_PAGE_EVENT, ReferenceNode, ReferenceSuggestionPluginKey, SOURCE_MEDIA_TYPES, STRUCTURE_MODE_KEYS, SourceReveal, Structure, TITLE_HIDDEN_KEY, TREE_ROOT_KEYS, VIEW_LAYOUTS, acceptsChild, acceptsImport, addToCollection, aiBlockTypesOf, basketById, basketOf, bibOf, bibtexKey, bibtexOf, blockEmbedAttrsOf, blockEmbedMarkdown, blockEmbedSuggestion, blockPropertiesAt, blockPropertiesOf, blockTypeOf, blockTypesOf, blocksFromMarkdown, bodyMarkdown, canMoveBlockInto, carriesProperties, childKindFor, chooseDataViewLayout, citeAttrsOf, citeEntriesOf, citeFull, citeMarkdown, citeShort, citeSuggestion, citeText, collectionChoicesOf, collectionItemsOf, collectionQueryOf, collectionViewOf, compositeAiBrief, compositeBacklinks, compositeBasketsOf, compositeChromeBlocks, compositeConversions, compositeDescriptionText, compositeFeatureCore, compositeFence, compositeFieldText, compositeFocusKey, compositeFocusOf, compositeNodes, compositeOfRow, compositeOutline, compositeRowAt, compositeRows, compositeSchemaExtensions, compositeSectionOf, conditionValueOf, convertCompositeBlocks, createCollectionViewModel, createCompositeInspector, createCompositeRows, createDataViewModel, createEditorDataViewModel, createEditorQueryBuilder, createQueryBuilderModel, cslOf, cslTypeOptions, dataRowKeyOf, dataViewCountLabelOf, dataViewLayoutOf, dataViewQueryOf, defaultBaskets, defaultBlockTypes, defaultGroupFieldOf, definitionsOfQuery, derivedChipOf, derivedRowBadge, displayEnv, documentCompositeMarkdown, documentOutline, embedChainOf, embedKeyOf, embedStateOf, embedViewOptions, exportCheckInspectorSection, exportCheckSectionOf, exportIssueLabel, exportIssuesOf, fieldChoicesOf, fieldColumnsOf, fillCollectionFromQuery, flattenCompositesToHeadings, focusDecorations, foreignBlockOf, generatedTitle, groupHeadingsIntoComposites, headingGroupRange, headingsMarkdown, insertDataView, isAiProposal, isRootBlockType, layoutIdOf, localRowsOf, markdownFileName, mergeBlockTypes, mergeBody, metaWithProperty, missingRequirementsOf, mostUsedBlockTypeOf, mountEmbed, moveBlockInto, moveCollectionItem, moveIntoVerdict, newDataViewMeta, normalizeReferences, observeCompositeAnchors, opsOfField, parseBlockTypes, parseLocator, propertyHostOf, provideCheckProbe, referenceLabel, referenceMarkdown, referenceSuggestion, referenceTarget, referenceTitle, referencesFromText, removeCollectionItem, resolveCite, revealSource, rowFieldsOf, seekSource, setBlockProperty, setCollectionItems, setCollectionQuery, setCompositeDescription, setCompositeTags, setDataViewQuery, sourceOf, splitBodyByLength, splitComposite, structureBlocks as structureCompositeBlocks, structureOf, subscribeBlockChanges, subscribeExportCheck, subscribeForeignBlocks, tableColumnsOf, titleHiddenOf, typedBlockViewOptions, valueInputOf, viewModelOf, withCollectionItems, withItemMoved, withNewAddresses, yearOf };
|
|
54
|
+
export { AcceptedChildren, BASKET_IDS, BASKET_KEY, BLOCK_EMBED_NODE, BlockEmbedNode, BlockEmbedSuggestionPluginKey, BlockTypeJsonError, CITE_NODE, COLLECTION_ITEMS_KEY, COLLECTION_QUERY_KEY, COLLECTION_TYPE, COMPOSITE_CHROME_COUNT, CSL_TYPES, CiteNode, CiteSuggestionPluginKey, CompositeDescriptionNode, CompositeFocus, CompositeMerge, CompositeNode, CompositeSplit, CompositeTagsNode, CompositeTitleNode, DATA_VIEW_DEBOUNCE_MS, DATA_VIEW_LAYOUT_KEY, DATA_VIEW_QUERY_KEY, DATA_VIEW_TYPE, DEFAULT_LAYOUT, EMBED_CLASS, FOREIGN_CONTENT_REFRESH_MS, LAYOUT_IDS, REVEAL_ANCHOR_EVENT, REVEAL_PAGE_EVENT, ReferenceNode, ReferenceSuggestionPluginKey, SOURCE_MEDIA_TYPES, STRUCTURE_MODE_KEYS, SourceReveal, Structure, TITLE_HIDDEN_KEY, TREE_ROOT_KEYS, VIEW_LAYOUTS, acceptsChild, acceptsImport, addToCollection, aiBlockTypesOf, basketById, basketOf, bibOf, bibtexKey, bibtexOf, blockEmbedAttrsOf, blockEmbedMarkdown, blockEmbedSuggestion, blockPropertiesAt, blockPropertiesOf, blockTypeOf, blockTypesOf, blocksFromMarkdown, bodyMarkdown, canMoveBlockInto, carriesProperties, childKindFor, chooseDataViewLayout, citeAttrsOf, citeEntriesOf, citeFull, citeMarkdown, citeShort, citeSuggestion, citeText, collectionChoicesOf, collectionItemsOf, collectionQueryOf, collectionViewOf, compositeAiBrief, compositeBacklinks, compositeBasketsOf, compositeChromeBlocks, compositeConversions, compositeDescriptionText, compositeFeatureCore, compositeFence, compositeFieldText, compositeFocusKey, compositeFocusOf, compositeNodes, compositeOfRow, compositeOutline, compositeRowAt, compositeRows, compositeSchemaExtensions, compositeSectionOf, conditionValueOf, convertCompositeBlocks, createCollectionViewModel, createCompositeInspector, createCompositeRows, createDataViewModel, createEditorDataViewModel, createEditorQueryBuilder, createQueryBuilderModel, cslOf, cslTypeOptions, dataRowKeyOf, dataViewCountLabelOf, dataViewLayoutOf, dataViewQueryOf, defaultBaskets, defaultBlockTypes, defaultGroupFieldOf, definitionsOfQuery, derivedChipOf, derivedRowBadge, displayEnv, documentCompositeMarkdown, documentOutline, embedChainOf, embedKeyOf, embedStateOf, embedViewOptions, exportCheckInspectorSection, exportCheckSectionOf, exportIssueLabel, exportIssuesOf, fieldChoicesOf, fieldColumnsOf, fillCollectionFromQuery, flattenCompositesToHeadings, focusDecorations, foreignBlockOf, generatedTitle, groupHeadingsIntoComposites, headingGroupRange, headingsMarkdown, insertDataView, isAiProposal, isRootBlockType, layoutIdOf, localRowsOf, markdownFileName, mergeBlockTypes, mergeBody, metaWithProperty, missingRequirementsOf, mostUsedBlockTypeOf, mountEmbed, moveBlockInto, moveCollectionItem, moveIntoVerdict, newDataViewMeta, normalizeReferences, observeCompositeAnchors, opsOfField, parseBlockTypes, parseLocator, propertyHostOf, provideCheckProbe, referenceLabel, referenceMarkdown, referenceSuggestion, referenceTarget, referenceTitle, referencesFromText, removeCollectionItem, resolveCite, revealSource, rowFieldsOf, seekSource, setBlockProperty, setCollectionItems, setCollectionQuery, setCompositeDescription, setCompositeTags, setDataViewQuery, sourceOf, splitBodyAtRules, splitBodyByLength, splitComposite, structureBlocks as structureCompositeBlocks, structureOf, subscribeBlockChanges, subscribeExportCheck, subscribeForeignBlocks, tableColumnsOf, titleHiddenOf, typedBlockViewOptions, valueInputOf, viewModelOf, withCollectionItems, withItemMoved, withNewAddresses, yearOf };
|
|
@@ -7,6 +7,7 @@ import { Input } from "../../../react/ui/input.js";
|
|
|
7
7
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../react/ui/select.js";
|
|
8
8
|
import { SettingsSection } from "../../../react/SettingsSection.js";
|
|
9
9
|
import { Label } from "../../../react/ui/label.js";
|
|
10
|
+
import { Switch } from "../../../react/ui/switch.js";
|
|
10
11
|
import { RadioGroup, RadioGroupItem } from "../../../react/ui/radio-group.js";
|
|
11
12
|
import { STRUCTURE_MODE_KEYS } from "../structure-mode.js";
|
|
12
13
|
import { BLOCK_TYPE_ICON_KEYS, DRAG_HANDLE_KEYS, HEADING_SCOPE_KEYS, optionItems } from "../editing-settings-keys.js";
|
|
@@ -61,6 +62,7 @@ function SettingsEditingTab({ blockTypes }) {
|
|
|
61
62
|
const { settings, update } = useEditorSettings();
|
|
62
63
|
const blockTypeLabelId = useId();
|
|
63
64
|
const splitTargetId = useId();
|
|
65
|
+
const splitOnRuleId = useId();
|
|
64
66
|
const [splitTarget, setSplitTarget] = useState(String(settings.blocks.splitTargetChars));
|
|
65
67
|
useEffect(() => {
|
|
66
68
|
setSplitTarget(String(settings.blocks.splitTargetChars));
|
|
@@ -161,6 +163,26 @@ function SettingsEditingTab({ blockTypes }) {
|
|
|
161
163
|
}
|
|
162
164
|
})]
|
|
163
165
|
}),
|
|
166
|
+
/* @__PURE__ */ jsxs("div", {
|
|
167
|
+
className: "flex items-start justify-between gap-4 py-3",
|
|
168
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
169
|
+
className: "min-w-0 flex-1",
|
|
170
|
+
children: [/* @__PURE__ */ jsx(Label, {
|
|
171
|
+
htmlFor: splitOnRuleId,
|
|
172
|
+
className: "text-sm font-medium text-foreground",
|
|
173
|
+
children: t("settings.editing.splitOnRule.label")
|
|
174
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
175
|
+
className: "text-sm text-muted-foreground",
|
|
176
|
+
children: t("settings.editing.splitOnRule.description")
|
|
177
|
+
})]
|
|
178
|
+
}), /* @__PURE__ */ jsx(Switch, {
|
|
179
|
+
id: splitOnRuleId,
|
|
180
|
+
checked: settings.blocks.splitOnRule,
|
|
181
|
+
onCheckedChange: (checked) => update((draft) => {
|
|
182
|
+
draft.blocks.splitOnRule = checked;
|
|
183
|
+
})
|
|
184
|
+
})]
|
|
185
|
+
}),
|
|
164
186
|
/* @__PURE__ */ jsx(RadioField, {
|
|
165
187
|
legend: t("composites.settings.blockTypeIcon.legend"),
|
|
166
188
|
items: blockTypeIconItems,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsEditingTab.js","names":[],"sources":["../../../../src/features/composites/react/SettingsEditingTab.tsx"],"sourcesContent":["import { useEffect, useId, useState } from 'react'\nimport { Icon } from '../../../react/Icon'\nimport { useEditorSettings } from '../../../react/settings'\nimport { SettingsSection } from '../../../react/SettingsSection'\nimport { Input } from '../../../react/ui/input'\nimport { Label } from '../../../react/ui/label'\nimport { RadioGroup, RadioGroupItem } from '../../../react/ui/radio-group'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../../react/ui/select'\nimport { BLOCK_TYPE_ICON_VISIBILITIES, clampSplitTargetChars, DRAG_HANDLE_VISIBILITIES, HEADING_CONVERSION_SCOPES, SPLIT_TARGET_CHARS_MAX, SPLIT_TARGET_CHARS_MIN, STRUCTURE_MODES, TREE_ROOTS } from '../../../settings'\nimport { useEditorI18n } from '../../../react/use-editor-i18n'\nimport { BLOCK_TYPE_ICON_KEYS, DRAG_HANDLE_KEYS, HEADING_SCOPE_KEYS, optionItems } from '../editing-settings-keys'\nimport type { BlockType } from '../block-types'\nimport { STRUCTURE_MODE_KEYS } from '../structure-mode'\nimport { TREE_ROOT_KEYS } from '../tree-root'\n\n/** A group of radio options under a legend (the counterpart of Nuxt UI's `URadioGroup`), the options one above the other. */\nfunction RadioField<T extends string>({ legend, items, value, onChange }: {\n legend: string\n items: readonly { label: string, description: string, value: T }[]\n value: T\n onChange: (value: T) => void\n}) {\n const legendId = useId()\n return (\n <div className=\"py-3\">\n <p id={legendId} className=\"mb-2 text-sm font-medium text-foreground\">{legend}</p>\n <RadioGroup\n aria-labelledby={legendId}\n className=\"flex flex-col gap-2\"\n value={value}\n onValueChange={(next) => {\n const item = items.find(candidate => candidate.value === next)\n if (item) onChange(item.value)\n }}\n >\n {items.map(item => <RadioOption key={item.value} item={item} />)}\n </RadioGroup>\n </div>\n )\n}\n\nfunction RadioOption({ item }: { item: { label: string, description: string, value: string } }) {\n const id = useId()\n return (\n <div className=\"flex items-start gap-2\">\n <RadioGroupItem id={id} value={item.value} className=\"mt-0.5\" />\n <Label htmlFor={id} className=\"flex-col items-start gap-0.5\">\n <span className=\"text-sm font-medium text-foreground\">{item.label}</span>\n <span className=\"text-sm font-normal text-muted-foreground\">{item.description}</span>\n </Label>\n </div>\n )\n}\n\n/** „Bearbeiten“: Gliederung (structure mode, conversion scope), Typed blocks defaults and the visibility of the block handles. */\nexport function SettingsEditingTab({ blockTypes }: { blockTypes: readonly BlockType[] }) {\n const { settings, update } = useEditorSettings()\n const blockTypeLabelId = useId()\n const splitTargetId = useId()\n // The target size is edited as text and written back clamped to its range when the field is left, so a half-typed number never reaches the settings.\n const [splitTarget, setSplitTarget] = useState(String(settings.blocks.splitTargetChars))\n useEffect(() => { setSplitTarget(String(settings.blocks.splitTargetChars)) }, [settings.blocks.splitTargetChars])\n const commitSplitTarget = () => {\n const next = clampSplitTargetChars(splitTarget, settings.blocks.splitTargetChars)\n update((draft) => { draft.blocks.splitTargetChars = next })\n setSplitTarget(String(next))\n }\n const { t } = useEditorI18n()\n const structureItems = optionItems(STRUCTURE_MODES, STRUCTURE_MODE_KEYS, t)\n const scopeItems = optionItems(HEADING_CONVERSION_SCOPES, HEADING_SCOPE_KEYS, t)\n const treeRootItems = optionItems(TREE_ROOTS, TREE_ROOT_KEYS, t)\n const blockTypeIconItems = optionItems(BLOCK_TYPE_ICON_VISIBILITIES, BLOCK_TYPE_ICON_KEYS, t)\n const dragHandleItems = optionItems(DRAG_HANDLE_VISIBILITIES, DRAG_HANDLE_KEYS, t)\n\n return (\n <div className=\"flex flex-col gap-8\">\n <SettingsSection title={t('composites.settings.structure.title')}>\n <RadioField\n legend={t('composites.settings.structure.legend')}\n items={structureItems}\n value={settings.blocks.structure}\n onChange={value => update((draft) => { draft.blocks.structure = value })}\n />\n <RadioField\n legend={t('composites.settings.scope.legend')}\n items={scopeItems}\n value={settings.editing.headingConversionScope}\n onChange={value => update((draft) => { draft.editing.headingConversionScope = value })}\n />\n </SettingsSection>\n\n <SettingsSection title={t('composites.settings.sidebar.title')}>\n <RadioField\n legend={t('composites.settings.treeRoot.legend')}\n items={treeRootItems}\n value={settings.blocks.treeRoot}\n onChange={value => update((draft) => { draft.blocks.treeRoot = value })}\n />\n </SettingsSection>\n\n <SettingsSection title={t('composites.settings.composites.title')}>\n <div className=\"flex items-start justify-between gap-4 py-3\">\n <div className=\"min-w-0 flex-1\">\n <Label id={blockTypeLabelId} className=\"text-sm font-medium text-foreground\">{t('composites.settings.defaultBlockType.label')}</Label>\n <p className=\"text-sm text-muted-foreground\">{t('composites.settings.defaultBlockType.description')}</p>\n </div>\n <Select value={settings.blocks.defaultBlockType} onValueChange={value => update((draft) => { draft.blocks.defaultBlockType = value })}>\n <SelectTrigger aria-labelledby={blockTypeLabelId} className=\"w-64\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {blockTypes.map(blockType => (\n <SelectItem key={blockType.id} value={blockType.id}>\n <Icon name={blockType.icon} />\n {blockType.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex items-start justify-between gap-4 py-3\">\n <Label htmlFor={splitTargetId} className=\"min-w-0 flex-1 text-sm font-medium text-foreground\">{t('settings.editing.splitTargetChars')}</Label>\n <Input\n id={splitTargetId}\n type=\"number\"\n min={SPLIT_TARGET_CHARS_MIN}\n max={SPLIT_TARGET_CHARS_MAX}\n step={100}\n className=\"w-32\"\n value={splitTarget}\n onChange={event => setSplitTarget(event.target.value)}\n onBlur={commitSplitTarget}\n onKeyDown={(event) => {\n if (event.key === 'Enter') commitSplitTarget()\n }}\n />\n </div>\n <RadioField\n legend={t('composites.settings.blockTypeIcon.legend')}\n items={blockTypeIconItems}\n value={settings.blocks.blockTypeIcon}\n onChange={value => update((draft) => { draft.blocks.blockTypeIcon = value })}\n />\n <RadioField\n legend={t('composites.settings.dragHandle.legend')}\n items={dragHandleItems}\n value={settings.blocks.dragHandle}\n onChange={value => update((draft) => { draft.blocks.dragHandle = value })}\n />\n </SettingsSection>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SettingsEditingTab.js","names":[],"sources":["../../../../src/features/composites/react/SettingsEditingTab.tsx"],"sourcesContent":["import { useEffect, useId, useState } from 'react'\nimport { Icon } from '../../../react/Icon'\nimport { useEditorSettings } from '../../../react/settings'\nimport { SettingsSection } from '../../../react/SettingsSection'\nimport { Input } from '../../../react/ui/input'\nimport { Label } from '../../../react/ui/label'\nimport { RadioGroup, RadioGroupItem } from '../../../react/ui/radio-group'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../../react/ui/select'\nimport { Switch } from '../../../react/ui/switch'\nimport { BLOCK_TYPE_ICON_VISIBILITIES, clampSplitTargetChars, DRAG_HANDLE_VISIBILITIES, HEADING_CONVERSION_SCOPES, SPLIT_TARGET_CHARS_MAX, SPLIT_TARGET_CHARS_MIN, STRUCTURE_MODES, TREE_ROOTS } from '../../../settings'\nimport { useEditorI18n } from '../../../react/use-editor-i18n'\nimport { BLOCK_TYPE_ICON_KEYS, DRAG_HANDLE_KEYS, HEADING_SCOPE_KEYS, optionItems } from '../editing-settings-keys'\nimport type { BlockType } from '../block-types'\nimport { STRUCTURE_MODE_KEYS } from '../structure-mode'\nimport { TREE_ROOT_KEYS } from '../tree-root'\n\n/** A group of radio options under a legend (the counterpart of Nuxt UI's `URadioGroup`), the options one above the other. */\nfunction RadioField<T extends string>({ legend, items, value, onChange }: {\n legend: string\n items: readonly { label: string, description: string, value: T }[]\n value: T\n onChange: (value: T) => void\n}) {\n const legendId = useId()\n return (\n <div className=\"py-3\">\n <p id={legendId} className=\"mb-2 text-sm font-medium text-foreground\">{legend}</p>\n <RadioGroup\n aria-labelledby={legendId}\n className=\"flex flex-col gap-2\"\n value={value}\n onValueChange={(next) => {\n const item = items.find(candidate => candidate.value === next)\n if (item) onChange(item.value)\n }}\n >\n {items.map(item => <RadioOption key={item.value} item={item} />)}\n </RadioGroup>\n </div>\n )\n}\n\nfunction RadioOption({ item }: { item: { label: string, description: string, value: string } }) {\n const id = useId()\n return (\n <div className=\"flex items-start gap-2\">\n <RadioGroupItem id={id} value={item.value} className=\"mt-0.5\" />\n <Label htmlFor={id} className=\"flex-col items-start gap-0.5\">\n <span className=\"text-sm font-medium text-foreground\">{item.label}</span>\n <span className=\"text-sm font-normal text-muted-foreground\">{item.description}</span>\n </Label>\n </div>\n )\n}\n\n/** „Bearbeiten“: Gliederung (structure mode, conversion scope), Typed blocks defaults and the visibility of the block handles. */\nexport function SettingsEditingTab({ blockTypes }: { blockTypes: readonly BlockType[] }) {\n const { settings, update } = useEditorSettings()\n const blockTypeLabelId = useId()\n const splitTargetId = useId()\n const splitOnRuleId = useId()\n // The target size is edited as text and written back clamped to its range when the field is left, so a half-typed number never reaches the settings.\n const [splitTarget, setSplitTarget] = useState(String(settings.blocks.splitTargetChars))\n useEffect(() => { setSplitTarget(String(settings.blocks.splitTargetChars)) }, [settings.blocks.splitTargetChars])\n const commitSplitTarget = () => {\n const next = clampSplitTargetChars(splitTarget, settings.blocks.splitTargetChars)\n update((draft) => { draft.blocks.splitTargetChars = next })\n setSplitTarget(String(next))\n }\n const { t } = useEditorI18n()\n const structureItems = optionItems(STRUCTURE_MODES, STRUCTURE_MODE_KEYS, t)\n const scopeItems = optionItems(HEADING_CONVERSION_SCOPES, HEADING_SCOPE_KEYS, t)\n const treeRootItems = optionItems(TREE_ROOTS, TREE_ROOT_KEYS, t)\n const blockTypeIconItems = optionItems(BLOCK_TYPE_ICON_VISIBILITIES, BLOCK_TYPE_ICON_KEYS, t)\n const dragHandleItems = optionItems(DRAG_HANDLE_VISIBILITIES, DRAG_HANDLE_KEYS, t)\n\n return (\n <div className=\"flex flex-col gap-8\">\n <SettingsSection title={t('composites.settings.structure.title')}>\n <RadioField\n legend={t('composites.settings.structure.legend')}\n items={structureItems}\n value={settings.blocks.structure}\n onChange={value => update((draft) => { draft.blocks.structure = value })}\n />\n <RadioField\n legend={t('composites.settings.scope.legend')}\n items={scopeItems}\n value={settings.editing.headingConversionScope}\n onChange={value => update((draft) => { draft.editing.headingConversionScope = value })}\n />\n </SettingsSection>\n\n <SettingsSection title={t('composites.settings.sidebar.title')}>\n <RadioField\n legend={t('composites.settings.treeRoot.legend')}\n items={treeRootItems}\n value={settings.blocks.treeRoot}\n onChange={value => update((draft) => { draft.blocks.treeRoot = value })}\n />\n </SettingsSection>\n\n <SettingsSection title={t('composites.settings.composites.title')}>\n <div className=\"flex items-start justify-between gap-4 py-3\">\n <div className=\"min-w-0 flex-1\">\n <Label id={blockTypeLabelId} className=\"text-sm font-medium text-foreground\">{t('composites.settings.defaultBlockType.label')}</Label>\n <p className=\"text-sm text-muted-foreground\">{t('composites.settings.defaultBlockType.description')}</p>\n </div>\n <Select value={settings.blocks.defaultBlockType} onValueChange={value => update((draft) => { draft.blocks.defaultBlockType = value })}>\n <SelectTrigger aria-labelledby={blockTypeLabelId} className=\"w-64\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {blockTypes.map(blockType => (\n <SelectItem key={blockType.id} value={blockType.id}>\n <Icon name={blockType.icon} />\n {blockType.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"flex items-start justify-between gap-4 py-3\">\n <Label htmlFor={splitTargetId} className=\"min-w-0 flex-1 text-sm font-medium text-foreground\">{t('settings.editing.splitTargetChars')}</Label>\n <Input\n id={splitTargetId}\n type=\"number\"\n min={SPLIT_TARGET_CHARS_MIN}\n max={SPLIT_TARGET_CHARS_MAX}\n step={100}\n className=\"w-32\"\n value={splitTarget}\n onChange={event => setSplitTarget(event.target.value)}\n onBlur={commitSplitTarget}\n onKeyDown={(event) => {\n if (event.key === 'Enter') commitSplitTarget()\n }}\n />\n </div>\n <div className=\"flex items-start justify-between gap-4 py-3\">\n <div className=\"min-w-0 flex-1\">\n <Label htmlFor={splitOnRuleId} className=\"text-sm font-medium text-foreground\">{t('settings.editing.splitOnRule.label')}</Label>\n <p className=\"text-sm text-muted-foreground\">{t('settings.editing.splitOnRule.description')}</p>\n </div>\n <Switch\n id={splitOnRuleId}\n checked={settings.blocks.splitOnRule}\n onCheckedChange={checked => update((draft) => { draft.blocks.splitOnRule = checked })}\n />\n </div>\n <RadioField\n legend={t('composites.settings.blockTypeIcon.legend')}\n items={blockTypeIconItems}\n value={settings.blocks.blockTypeIcon}\n onChange={value => update((draft) => { draft.blocks.blockTypeIcon = value })}\n />\n <RadioField\n legend={t('composites.settings.dragHandle.legend')}\n items={dragHandleItems}\n value={settings.blocks.dragHandle}\n onChange={value => update((draft) => { draft.blocks.dragHandle = value })}\n />\n </SettingsSection>\n </div>\n )\n}\n"],"mappings":"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"}
|
|
@@ -10,6 +10,11 @@ export type SplitMode = 'siblings' | 'children';
|
|
|
10
10
|
* than the target forms a group of its own.
|
|
11
11
|
*/
|
|
12
12
|
export declare function splitBodyByLength(blocks: readonly Node$1[], targetChars: number): Node$1[][];
|
|
13
|
+
/**
|
|
14
|
+
* Groups `blocks` at their horizontal rules: the blocks between two rules form a group, the rules themselves are dropped,
|
|
15
|
+
* and so are empty groups (a rule first, last or right after another).
|
|
16
|
+
*/
|
|
17
|
+
export declare function splitBodyAtRules(blocks: readonly Node$1[]): Node$1[][];
|
|
13
18
|
/**
|
|
14
19
|
* Title for a part holding `blocks`: the first sentence of its first textblock (up to the first `.`, `!` or `?` that
|
|
15
20
|
* is followed by white space or ends the text; the mark itself is left out), at most 60 characters, `…` appended when
|
|
@@ -46,6 +51,13 @@ declare module '@tiptap/core' {
|
|
|
46
51
|
targetChars?: number;
|
|
47
52
|
pos?: number;
|
|
48
53
|
}) => ReturnType;
|
|
54
|
+
/**
|
|
55
|
+
* Split the Typed block at `pos` (default: the caret's innermost one) at the horizontal rules of its body; the rules go away. Refused with fewer than two non-empty parts, or in `children` mode when no child Block type is accepted. The generated titles are hidden.
|
|
56
|
+
*/
|
|
57
|
+
splitCompositeAtRules: (options: {
|
|
58
|
+
mode: SplitMode;
|
|
59
|
+
pos?: number;
|
|
60
|
+
}) => ReturnType;
|
|
49
61
|
};
|
|
50
62
|
}
|
|
51
63
|
}
|
|
@@ -55,8 +67,14 @@ export interface CompositeSplitOptions {
|
|
|
55
67
|
defaultBlockType: () => string;
|
|
56
68
|
/** Target size in characters of a length split (setting `blocks.splitTargetChars`). */
|
|
57
69
|
targetChars: () => number;
|
|
70
|
+
/** Typing `---` on an empty body line of a Typed block splits it there instead of inserting a rule (setting `blocks.splitOnRule`). */
|
|
71
|
+
splitOnRule: () => boolean;
|
|
58
72
|
}
|
|
59
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* Client-only, no schema: the split commands of Typed blocks and the `---` input rule. Priority above the `abilities`
|
|
75
|
+
* extension (1000) and StarterKit's horizontal rule: the abilities gate types `---` literally where rules are not allowed,
|
|
76
|
+
* and the rule's own input rule matches `---` too. This rule runs first and leaves the line to them whenever it does not split.
|
|
77
|
+
*/
|
|
60
78
|
export declare const CompositeSplit: Extension<CompositeSplitOptions, any>;
|
|
61
79
|
//#endregion
|
|
62
80
|
//# sourceMappingURL=split.d.ts.map
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { typeIdOf } from "../../core/typed-block.js";
|
|
2
|
+
import { ABILITY } from "../../core/schema/abilities.js";
|
|
3
|
+
import { abilitiesAt } from "../../core/abilities.js";
|
|
4
|
+
import { capabilitiesOf } from "../../core/capabilities.js";
|
|
2
5
|
import { EDITOR_SETTINGS_DEFAULTS } from "../../settings/index.js";
|
|
3
6
|
import { acceptsChild } from "./block-types.js";
|
|
4
7
|
import { TITLE_HIDDEN_KEY } from "./meta-keys.js";
|
|
5
8
|
import { blockTypesOf, compositeAround, compositeAt } from "./nodes.js";
|
|
6
|
-
import { Extension } from "@tiptap/core";
|
|
9
|
+
import { Extension, InputRule } from "@tiptap/core";
|
|
7
10
|
import { TextSelection } from "@tiptap/pm/state";
|
|
8
11
|
import { Fragment } from "@tiptap/pm/model";
|
|
9
12
|
//#region src/features/composites/split.ts
|
|
@@ -31,6 +34,18 @@ function splitBodyByLength(blocks, targetChars) {
|
|
|
31
34
|
if (current.length) groups.push(current);
|
|
32
35
|
return groups;
|
|
33
36
|
}
|
|
37
|
+
/** Name of the horizontal rule node (StarterKit). */
|
|
38
|
+
const RULE_NODE = "horizontalRule";
|
|
39
|
+
/**
|
|
40
|
+
* Groups `blocks` at their horizontal rules: the blocks between two rules form a group, the rules themselves are dropped,
|
|
41
|
+
* and so are empty groups (a rule first, last or right after another).
|
|
42
|
+
*/
|
|
43
|
+
function splitBodyAtRules(blocks) {
|
|
44
|
+
const groups = [[]];
|
|
45
|
+
for (const block of blocks) if (block.type.name === RULE_NODE) groups.push([]);
|
|
46
|
+
else groups[groups.length - 1].push(block);
|
|
47
|
+
return groups.filter((group) => group.length > 0);
|
|
48
|
+
}
|
|
34
49
|
/** Text of the first non-empty textblock in `blocks` (nested ones included), or ''. */
|
|
35
50
|
function firstText(blocks) {
|
|
36
51
|
let found = "";
|
|
@@ -104,6 +119,8 @@ function splitComposite(schema, composite, groups, mode, childKind, hideTitles)
|
|
|
104
119
|
const [first = [], ...rest] = groups;
|
|
105
120
|
return [composite.copy(Fragment.from([...chrome, ...first.length ? first : [schema.nodes.paragraph.create()]])), ...rest.map((group) => newPart(schema, typeIdOf(composite), group, hideTitles))];
|
|
106
121
|
}
|
|
122
|
+
/** `---` typed at the start of a line; `—-` is the same after the typography extension turned `--` into an em dash. */
|
|
123
|
+
const RULE_INPUT = /^(?:---|—-)$/;
|
|
107
124
|
/** Position right in front of the body of `composite`, which starts at `pos`. */
|
|
108
125
|
function bodyStartOf(pos, composite) {
|
|
109
126
|
return pos + 1 + chromeOf(composite).reduce((size, child) => size + child.nodeSize, 0);
|
|
@@ -118,13 +135,39 @@ function lastPartBodyStart(pos, nodes, mode) {
|
|
|
118
135
|
const last = nodes[nodes.length - 1];
|
|
119
136
|
return bodyStartOf(pos + nodes.reduce((size, node) => size + node.nodeSize, 0) - last.nodeSize, last);
|
|
120
137
|
}
|
|
121
|
-
/**
|
|
138
|
+
/**
|
|
139
|
+
* Client-only, no schema: the split commands of Typed blocks and the `---` input rule. Priority above the `abilities`
|
|
140
|
+
* extension (1000) and StarterKit's horizontal rule: the abilities gate types `---` literally where rules are not allowed,
|
|
141
|
+
* and the rule's own input rule matches `---` too. This rule runs first and leaves the line to them whenever it does not split.
|
|
142
|
+
*/
|
|
122
143
|
const CompositeSplit = Extension.create({
|
|
123
144
|
name: "compositeSplit",
|
|
145
|
+
priority: 1001,
|
|
124
146
|
addOptions: () => ({
|
|
125
147
|
defaultBlockType: () => EDITOR_SETTINGS_DEFAULTS.blocks.defaultBlockType,
|
|
126
|
-
targetChars: () => EDITOR_SETTINGS_DEFAULTS.blocks.splitTargetChars
|
|
148
|
+
targetChars: () => EDITOR_SETTINGS_DEFAULTS.blocks.splitTargetChars,
|
|
149
|
+
splitOnRule: () => EDITOR_SETTINGS_DEFAULTS.blocks.splitOnRule
|
|
127
150
|
}),
|
|
151
|
+
addInputRules() {
|
|
152
|
+
return [new InputRule({
|
|
153
|
+
find: RULE_INPUT,
|
|
154
|
+
handler: ({ state, range }) => {
|
|
155
|
+
if (!this.options.splitOnRule()) return null;
|
|
156
|
+
const $from = state.doc.resolve(range.from);
|
|
157
|
+
if ($from.parent.type.name !== "paragraph" || $from.parentOffset !== 0 || $from.end() !== range.to) return null;
|
|
158
|
+
const found = compositeAround($from);
|
|
159
|
+
if (!found || found.depth !== $from.depth - 1) return null;
|
|
160
|
+
const capabilities = capabilitiesOf(this.editor, found.node);
|
|
161
|
+
if (!capabilities.has("container") || !capabilities.has("title") || !abilitiesAt(this.editor, found.pos, found.node).has(ABILITY.compositeMeta)) return null;
|
|
162
|
+
const index = $from.index(found.depth) - 3;
|
|
163
|
+
if (index < 1) return null;
|
|
164
|
+
const body = bodyOf(found.node);
|
|
165
|
+
const nodes = splitComposite(state.schema, found.node, [body.slice(0, index), body.slice(index + 1)], "siblings", typeIdOf(found.node), true);
|
|
166
|
+
state.tr.replaceWith(found.pos, found.pos + found.node.nodeSize, nodes);
|
|
167
|
+
state.tr.setSelection(TextSelection.near(state.tr.doc.resolve(lastPartBodyStart(found.pos, nodes, "siblings"))));
|
|
168
|
+
}
|
|
169
|
+
})];
|
|
170
|
+
},
|
|
128
171
|
addCommands() {
|
|
129
172
|
/** The Block type of the nested Typed blocks (`children`) or of the composite itself (`siblings`); null when a `children` split has no accepted Block type. */
|
|
130
173
|
const partKind = (composite, mode) => mode === "siblings" ? typeIdOf(composite) : childKindFor(blockTypesOf(this.editor), typeIdOf(composite), this.options.defaultBlockType());
|
|
@@ -154,11 +197,21 @@ const CompositeSplit = Extension.create({
|
|
|
154
197
|
if (kind === null) return false;
|
|
155
198
|
if (dispatch) tr.replaceWith(found.pos, found.pos + found.node.nodeSize, splitComposite(state.schema, found.node, groups, mode, kind, true));
|
|
156
199
|
return true;
|
|
200
|
+
},
|
|
201
|
+
splitCompositeAtRules: ({ mode, pos }) => ({ state, tr, dispatch }) => {
|
|
202
|
+
const found = compositeAt(state, pos);
|
|
203
|
+
if (!found) return false;
|
|
204
|
+
const groups = splitBodyAtRules(bodyOf(found.node));
|
|
205
|
+
if (groups.length < 2) return false;
|
|
206
|
+
const kind = partKind(found.node, mode);
|
|
207
|
+
if (kind === null) return false;
|
|
208
|
+
if (dispatch) tr.replaceWith(found.pos, found.pos + found.node.nodeSize, splitComposite(state.schema, found.node, groups, mode, kind, true));
|
|
209
|
+
return true;
|
|
157
210
|
}
|
|
158
211
|
};
|
|
159
212
|
}
|
|
160
213
|
});
|
|
161
214
|
//#endregion
|
|
162
|
-
export { CompositeSplit, childKindFor, generatedTitle, splitBodyByLength, splitComposite };
|
|
215
|
+
export { CompositeSplit, childKindFor, generatedTitle, splitBodyAtRules, splitBodyByLength, splitComposite };
|
|
163
216
|
|
|
164
217
|
//# sourceMappingURL=split.js.map
|