@skaile/forge-editor 6.2.1 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -1
- package/dist/code/CodeSurface.vue.d.ts +2 -2
- package/dist/document/DocumentSurface.vue.d.ts +2 -2
- 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/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 +6 -6
- package/dist/server/handlers/editor.d.ts +1 -0
- 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/vue/AdvancedEditor.vue.d.ts +4 -4
- package/dist/vue/SimpleEditor.vue.d.ts +4 -4
- package/dist/vue/components/EditorSurface.vue.d.ts +4 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 6.3.0 - 2026-10-31
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Typing `---` (or `—-`) on an empty line of a Typed block's body splits the block there (`@skaile/forge-editor/composites`): the line goes away, the rest becomes a sibling Typed block of the same Block type with a hidden generated title, and the caret moves into it. On the first body line, on a line with text and outside a Typed block, `---` stays a horizontal rule; undo first returns to the typed `---`. On by default; the new setting `blocks.splitOnRule` (switch „--- teilt den Block“ in the settings tab „Bearbeiten“, Vue and React) turns it off. The rule runs above the `abilities` gate, so it also splits where a Block type allows no horizontal rule.
|
|
8
|
+
- `splitCompositeAtRules({ mode, pos? })` and the pure `splitBodyAtRules(blocks)`: split a Typed block at the horizontal rules already in its body (pasted or imported Markdown with `---`), as siblings or nested Typed blocks; the rules and empty stretches are dropped. Block actions „An Trennlinien in Blöcke teilen“ and „An Trennlinien in Unterblöcke teilen“.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- `PUT /api/editor/settings` accepts a body without `blocks.splitOnRule` (a tab from before 6.3.0) and stores the default `true`.
|
|
13
|
+
|
|
3
14
|
## 6.2.1 - 2026-10-29
|
|
4
15
|
|
|
5
16
|
### Fixed
|
|
6
17
|
|
|
7
|
-
- `POST /api/ai/chat` accepts up to 500 options per select
|
|
18
|
+
- `POST /api/ai/chat` accepts up to 500 options per select Property definition of a client Block type (was 50). A host whose select lists every slot of a template (`@skaile/forge-editor-compose`, e.g. a court-report template with 51 slots) got a 400 „Validation Error“ on every chat turn.
|
|
8
19
|
|
|
9
20
|
## 6.2.0 - 2026-10-28
|
|
10
21
|
|
|
@@ -11,12 +11,12 @@ type __VLS_Props = {
|
|
|
11
11
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
12
12
|
view: import("vue").ShallowRef<EditorView | undefined, EditorView | undefined>;
|
|
13
13
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
14
|
-
ready: (view: EditorView) => any;
|
|
15
14
|
"update:modelValue": (text: string) => any;
|
|
15
|
+
ready: (view: EditorView) => any;
|
|
16
16
|
save: (text: string) => any;
|
|
17
17
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
18
|
-
onReady?: ((view: EditorView) => any) | undefined;
|
|
19
18
|
"onUpdate:modelValue"?: ((text: string) => any) | undefined;
|
|
19
|
+
onReady?: ((view: EditorView) => any) | undefined;
|
|
20
20
|
onSave?: ((text: string) => any) | undefined;
|
|
21
21
|
}>, {
|
|
22
22
|
editable: boolean;
|
|
@@ -32,12 +32,12 @@ type __VLS_Slots = {} & { [K in NonNullable<typeof __VLS_13>]?: (props: typeof _
|
|
|
32
32
|
binary?: (props: typeof __VLS_26) => any;
|
|
33
33
|
};
|
|
34
34
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
35
|
-
ready: (target: DocumentSurfaceTarget) => any;
|
|
36
35
|
"update:modelValue": (text: string) => any;
|
|
36
|
+
ready: (target: DocumentSurfaceTarget) => any;
|
|
37
37
|
save: (text: string) => any;
|
|
38
38
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
39
|
-
onReady?: ((target: DocumentSurfaceTarget) => any) | undefined;
|
|
40
39
|
"onUpdate:modelValue"?: ((text: string) => any) | undefined;
|
|
40
|
+
onReady?: ((target: DocumentSurfaceTarget) => any) | undefined;
|
|
41
41
|
onSave?: ((text: string) => any) | undefined;
|
|
42
42
|
}>, {
|
|
43
43
|
editable: boolean;
|
|
@@ -21,7 +21,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
21
21
|
props: { blockTypes: {} },
|
|
22
22
|
setup(__props) {
|
|
23
23
|
const props = __props;
|
|
24
|
-
const { FormField: UFormField, Input: UInput, RadioGroup: URadioGroup, Select: USelect } = useUiKit();
|
|
24
|
+
const { FormField: UFormField, Input: UInput, RadioGroup: URadioGroup, Select: USelect, Switch: USwitch } = useUiKit();
|
|
25
25
|
const { t } = useEditorI18n();
|
|
26
26
|
const { settings } = useEditorSettings();
|
|
27
27
|
const scopeItems = computed(() => optionItems(HEADING_CONVERSION_SCOPES, HEADING_SCOPE_KEYS, t));
|
|
@@ -122,9 +122,22 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
122
122
|
])]),
|
|
123
123
|
_: 1
|
|
124
124
|
}, 8, ["label"]),
|
|
125
|
+
createVNode(unref(UFormField), {
|
|
126
|
+
orientation: "horizontal",
|
|
127
|
+
class: "py-3",
|
|
128
|
+
label: unref(t)("settings.editing.splitOnRule.label"),
|
|
129
|
+
description: unref(t)("settings.editing.splitOnRule.description")
|
|
130
|
+
}, {
|
|
131
|
+
default: withCtx(() => [createVNode(unref(USwitch), {
|
|
132
|
+
modelValue: unref(settings).blocks.splitOnRule,
|
|
133
|
+
"onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => unref(settings).blocks.splitOnRule = $event),
|
|
134
|
+
"aria-label": unref(t)("settings.editing.splitOnRule.label")
|
|
135
|
+
}, null, 8, ["modelValue", "aria-label"])]),
|
|
136
|
+
_: 1
|
|
137
|
+
}, 8, ["label", "description"]),
|
|
125
138
|
createElementVNode("div", _hoisted_5, [createVNode(unref(URadioGroup), {
|
|
126
139
|
modelValue: unref(settings).blocks.blockTypeIcon,
|
|
127
|
-
"onUpdate:modelValue": _cache[
|
|
140
|
+
"onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => unref(settings).blocks.blockTypeIcon = $event),
|
|
128
141
|
legend: unref(t)("composites.settings.blockTypeIcon.legend"),
|
|
129
142
|
items: blockTypeIconItems.value
|
|
130
143
|
}, null, 8, [
|
|
@@ -134,7 +147,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
|
|
|
134
147
|
])]),
|
|
135
148
|
createElementVNode("div", _hoisted_6, [createVNode(unref(URadioGroup), {
|
|
136
149
|
modelValue: unref(settings).blocks.dragHandle,
|
|
137
|
-
"onUpdate:modelValue": _cache[
|
|
150
|
+
"onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => unref(settings).blocks.dragHandle = $event),
|
|
138
151
|
legend: unref(t)("composites.settings.dragHandle.legend"),
|
|
139
152
|
items: dragHandleItems.value
|
|
140
153
|
}, null, 8, [
|
|
@@ -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
|