@skaile/forge-editor 6.4.0 → 6.4.2

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.
Files changed (68) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/code/CodeSurface.vue.d.ts +2 -2
  3. package/dist/core/block-index.js +3 -2
  4. package/dist/core/block-index.js.map +1 -1
  5. package/dist/core/document-markdown.d.ts +11 -6
  6. package/dist/core/document-markdown.js +34 -23
  7. package/dist/core/document-markdown.js.map +1 -1
  8. package/dist/core/soft-line-breaks.js +44 -0
  9. package/dist/core/soft-line-breaks.js.map +1 -0
  10. package/dist/document/DocumentSurface.vue.d.ts +2 -2
  11. package/dist/features/ai/components/AiReviewBar.js +1 -1
  12. package/dist/features/ai/components/AiSelectionMenu.js +1 -1
  13. package/dist/features/ai/components/AiSidebar.js +2 -2
  14. package/dist/features/ai/components/DocumentChatAnswer.js +1 -1
  15. package/dist/features/ai/components/SettingsModelProfiles.js +1 -1
  16. package/dist/features/ai/feature.js +1 -1
  17. package/dist/features/ai/index.js +7 -7
  18. package/dist/features/ai/react/AiSelectionMenu.js +4 -4
  19. package/dist/features/ai/react/AiSidebar.js +4 -4
  20. package/dist/features/ai/react/DocumentChatOps.js +1 -1
  21. package/dist/features/ai/react/ModelQuickSwitch.js +1 -1
  22. package/dist/features/ai/react/SettingsModelProfiles.js +1 -1
  23. package/dist/features/ai/react/use-ai-assistant.js +1 -1
  24. package/dist/features/ai/react/use-document-chat.js +1 -1
  25. package/dist/features/ai/use-ai-assistant.js +2 -2
  26. package/dist/features/ai/use-document-chat.js +1 -1
  27. package/dist/features/ai/vue.js +1 -1
  28. package/dist/features/authors/components/AuthorColorsPanel.js +1 -1
  29. package/dist/features/authors/components/SettingsAuthorsTab.js +1 -1
  30. package/dist/features/authors/index.js +1 -1
  31. package/dist/features/authors/react/AuthorColorsPanel.js +2 -2
  32. package/dist/features/authors/react/SettingsAuthorsTab.js +1 -1
  33. package/dist/features/authors/vue.js +1 -1
  34. package/dist/features/block-ui/index.js +1 -1
  35. package/dist/features/block-ui/react/BlockActionsOverlay.js +1 -1
  36. package/dist/features/block-ui/vue.js +1 -1
  37. package/dist/features/comments/react/CommentThreadView.js +1 -1
  38. package/dist/features/composites/components/ReferenceListFieldEditor.js +1 -1
  39. package/dist/features/composites/components/SettingsEditingTab.js +1 -1
  40. package/dist/features/composites/index.js +5 -5
  41. package/dist/features/composites/react/BibliographyEditor.js +1 -1
  42. package/dist/features/composites/react/CompositeChrome.js +1 -1
  43. package/dist/features/composites/react/CompositeDetails.js +1 -1
  44. package/dist/features/composites/react/CompositeInspector.js +3 -3
  45. package/dist/features/composites/react/CompositeTable.js +1 -1
  46. package/dist/features/composites/react/ReferenceListFieldEditor.js +1 -1
  47. package/dist/features/composites/react/ReferenceView.js +1 -1
  48. package/dist/features/composites/react/SettingsEditingTab.js +3 -3
  49. package/dist/features/composites/react.js +2 -2
  50. package/dist/features/composites/vue.js +1 -1
  51. package/dist/features/pruefung/vue.js +1 -1
  52. package/dist/features/themes/vue.js +1 -1
  53. package/dist/features/transfer/vue.js +1 -1
  54. package/dist/integrations/composite-ai/index.js +1 -1
  55. package/dist/markdown/MarkdownSurface.vue.d.ts +6 -6
  56. package/dist/react/EditorToolbar.js +2 -2
  57. package/dist/react/compose.js +2 -2
  58. package/dist/react/index.js +1 -1
  59. package/dist/search/react/SearchPanel.js +1 -1
  60. package/dist/server/document-tools.js +2 -18
  61. package/dist/server/document-tools.js.map +1 -1
  62. package/dist/tree/react/DocumentTree.js +3 -3
  63. package/dist/tree/react/use-tree-model.js +2 -2
  64. package/dist/vue/AdvancedEditor.vue.d.ts +4 -4
  65. package/dist/vue/SimpleEditor.vue.d.ts +4 -4
  66. package/dist/vue/components/EditorSurface.vue.d.ts +4 -4
  67. package/dist/vue/compose.js +1 -1
  68. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
1
  import { useEditorContext } from "../../vue/context.js";
2
2
  import { useStoreRef } from "../../vue/store-ref.js";
3
- import { modelProfiles } from "./model-profiles.js";
4
- import { createAiAssistant } from "./assistant.js";
5
3
  import { useNotifier } from "../../vue/use-notifier.js";
4
+ import { createAiAssistant } from "./assistant.js";
5
+ import { modelProfiles } from "./model-profiles.js";
6
6
  import { computed, getCurrentScope, onScopeDispose } from "vue";
7
7
  //#region src/features/ai/use-ai-assistant.ts
8
8
  /**
@@ -1,8 +1,8 @@
1
1
  import { useEditorContext } from "../../vue/context.js";
2
2
  import { useStoreRef } from "../../vue/store-ref.js";
3
+ import { useNotifier } from "../../vue/use-notifier.js";
3
4
  import { modelProfiles } from "./model-profiles.js";
4
5
  import { createDocumentChat } from "./document-chat-model.js";
5
- import { useNotifier } from "../../vue/use-notifier.js";
6
6
  import { computed, getCurrentScope, onScopeDispose } from "vue";
7
7
  //#region src/features/ai/use-document-chat.ts
8
8
  /**
@@ -1,4 +1,3 @@
1
- import { aiFeatureCore } from "./feature.js";
2
1
  import _sfc_main from "./components/AiReviewBar.js";
3
2
  import { useAiAssistant } from "./use-ai-assistant.js";
4
3
  import { useModelProfiles } from "./use-model-profiles.js";
@@ -6,6 +5,7 @@ import _sfc_main$4 from "./components/ModelQuickSwitch.js";
6
5
  import _sfc_main$1 from "./components/AiSelectionMenu.js";
7
6
  import _sfc_main$6 from "./components/SettingsModelProfiles.js";
8
7
  import _sfc_main$5 from "./components/SettingsAiTab.js";
8
+ import { aiFeatureCore } from "./feature.js";
9
9
  import _sfc_main$2 from "./components/DocumentChatAnswer.js";
10
10
  import _sfc_main$3 from "./components/DocumentChatOps.js";
11
11
  import { useDocumentChat } from "./use-document-chat.js";
@@ -2,8 +2,8 @@ import { documentAuthors } from "../schema.js";
2
2
  import { useUiKit } from "../../../vue/kit/use-ui-kit.js";
3
3
  import { useEditorSettings } from "../../../vue/settings.js";
4
4
  import { useEditorI18n } from "../../../vue/use-editor-i18n.js";
5
- import { currentAuthor } from "../attribution.js";
6
5
  import { authorStyleItems } from "../author-color-styles.js";
6
+ import { currentAuthor } from "../attribution.js";
7
7
  import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, renderList, toDisplayString, unref } from "vue";
8
8
  //#region src/features/authors/components/AuthorColorsPanel.vue
9
9
  const _hoisted_1 = { class: "w-72 p-3 flex flex-col gap-3" };
@@ -1,8 +1,8 @@
1
1
  import { useUiKit } from "../../../vue/kit/use-ui-kit.js";
2
2
  import { useEditorSettings } from "../../../vue/settings.js";
3
3
  import { useEditorI18n } from "../../../vue/use-editor-i18n.js";
4
- import { authorStyleItems } from "../author-color-styles.js";
5
4
  import _sfc_main$1 from "../../../vue/components/SettingsSection.js";
5
+ import { authorStyleItems } from "../author-color-styles.js";
6
6
  import { computed, createElementBlock, createElementVNode, createVNode, defineComponent, openBlock, unref, withCtx } from "vue";
7
7
  //#region src/features/authors/components/SettingsAuthorsTab.vue
8
8
  const _hoisted_1 = { class: "flex flex-col gap-8" };
@@ -1,6 +1,6 @@
1
1
  import { AUTHOR_COLOR_STYLES } from "../../settings/values.js";
2
2
  import { AuthorMark, authorsSchemaExtensions, documentAuthors } from "./schema.js";
3
+ import { authorStyleItems } from "./author-color-styles.js";
3
4
  import { AuthorAttribution, authorAttributionKey, authorAttributionPlugin, currentAuthor } from "./attribution.js";
4
5
  import { authorsFeatureCore } from "./feature.js";
5
- import { authorStyleItems } from "./author-color-styles.js";
6
6
  export { AUTHOR_COLOR_STYLES, AuthorAttribution, AuthorMark, authorAttributionKey, authorAttributionPlugin, authorStyleItems, authorsFeatureCore, authorsSchemaExtensions, currentAuthor, documentAuthors };
@@ -3,11 +3,11 @@ import { documentAuthors } from "../schema.js";
3
3
  import { cn } from "../../../react/ui/utils.js";
4
4
  import { useEditorI18n } from "../../../react/use-editor-i18n.js";
5
5
  import { useEditorSettings } from "../../../react/settings.js";
6
+ import { authorStyleItems } from "../author-color-styles.js";
7
+ import { currentAuthor } from "../attribution.js";
6
8
  import { Label } from "../../../react/ui/label.js";
7
9
  import { Switch } from "../../../react/ui/switch.js";
8
- import { currentAuthor } from "../attribution.js";
9
10
  import { RadioGroup, RadioGroupItem } from "../../../react/ui/radio-group.js";
10
- import { authorStyleItems } from "../author-color-styles.js";
11
11
  import { useId } from "react";
12
12
  import { jsx, jsxs } from "react/jsx-runtime";
13
13
  import { useEditorState } from "@tiptap/react";
@@ -1,11 +1,11 @@
1
1
  import { AUTHOR_COLOR_STYLES } from "../../../settings/values.js";
2
2
  import { useEditorI18n } from "../../../react/use-editor-i18n.js";
3
3
  import { useEditorSettings } from "../../../react/settings.js";
4
+ import { authorStyleItems } from "../author-color-styles.js";
4
5
  import { SettingsSection } from "../../../react/SettingsSection.js";
5
6
  import { Label } from "../../../react/ui/label.js";
6
7
  import { Switch } from "../../../react/ui/switch.js";
7
8
  import { RadioGroup, RadioGroupItem } from "../../../react/ui/radio-group.js";
8
- import { authorStyleItems } from "../author-color-styles.js";
9
9
  import { useId } from "react";
10
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
11
  //#region src/features/authors/react/SettingsAuthorsTab.tsx
@@ -1,7 +1,7 @@
1
- import { authorsFeatureCore } from "./feature.js";
2
1
  import _sfc_main$1 from "./components/AuthorColorsPanel.js";
3
2
  import _sfc_main from "./components/AuthorColorsButton.js";
4
3
  import _sfc_main$2 from "./components/SettingsAuthorsTab.js";
4
+ import { authorsFeatureCore } from "./feature.js";
5
5
  //#region src/features/authors/vue.ts
6
6
  /** The Vue authors feature (Nuxt UI): see `authorsFeatureCore`. */
7
7
  function authorsFeature() {
@@ -1,4 +1,4 @@
1
- import { blockUiFeatureCore } from "./feature.js";
2
1
  import { outerBlockAt, outerBlocksAt, typedBlockAround } from "./block-target.js";
3
2
  import { BLOCK_CORNER_ATTR, actionSurfacesOf, blockActionsFor, blockCornerOf, effectiveTarget, sameBlock, selectedBlockOf } from "./block-actions.js";
3
+ import { blockUiFeatureCore } from "./feature.js";
4
4
  export { BLOCK_CORNER_ATTR, actionSurfacesOf, blockActionsFor, blockCornerOf, blockUiFeatureCore, effectiveTarget, outerBlockAt, outerBlocksAt, sameBlock, selectedBlockOf, typedBlockAround };
@@ -1,9 +1,9 @@
1
1
  import { cn } from "../../../react/ui/utils.js";
2
2
  import { Icon } from "../../../react/Icon.js";
3
3
  import { Button } from "../../../react/ui/button.js";
4
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "../../../react/ui/dropdown-menu.js";
4
5
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../../../react/ui/tooltip.js";
5
6
  import { blockActionsFor, liveTargetOf, overlayPlaceOf } from "../block-actions.js";
6
- import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "../../../react/ui/dropdown-menu.js";
7
7
  import { useEffect, useLayoutEffect, useReducer, useRef, useState } from "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  //#region src/features/block-ui/react/BlockActionsOverlay.tsx
@@ -1,6 +1,6 @@
1
- import { blockUiFeatureCore } from "./feature.js";
2
1
  import _sfc_main from "./components/BlockActionsOverlay.js";
3
2
  import _sfc_main$1 from "./components/BlockUi.js";
3
+ import { blockUiFeatureCore } from "./feature.js";
4
4
  //#region src/features/block-ui/vue.ts
5
5
  /** The Vue block-ui feature: the Nuxt UI drag handle, permanent handles and the block actions (hover bar and/or selected-block toolbar, per `options.actions`). */
6
6
  function blockUiFeature(options) {
@@ -4,8 +4,8 @@ import { Icon } from "../../../react/Icon.js";
4
4
  import { useEditorI18n } from "../../../react/use-editor-i18n.js";
5
5
  import { Badge } from "../../../react/ui/badge.js";
6
6
  import { Button } from "../../../react/ui/button.js";
7
- import { Textarea } from "../../../react/ui/textarea.js";
8
7
  import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "../../../react/ui/dropdown-menu.js";
8
+ import { Textarea } from "../../../react/ui/textarea.js";
9
9
  import { CommentAvatar } from "./CommentAvatar.js";
10
10
  import { useMemo, useRef, useState } from "react";
11
11
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,8 +1,8 @@
1
1
  import { setBlockProperty } from "../properties.js";
2
2
  import { useUiKit } from "../../../vue/kit/use-ui-kit.js";
3
3
  import { useEditorI18n } from "../../../vue/use-editor-i18n.js";
4
- import { referenceListChipsOf, referenceListChoicesOf, withReferenceListEntry, withoutReferenceListEntry } from "../reference-list-model.js";
5
4
  import { useCompositeRows } from "../use-composite-rows.js";
5
+ import { referenceListChipsOf, referenceListChoicesOf, withReferenceListEntry, withoutReferenceListEntry } from "../reference-list-model.js";
6
6
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, openBlock, renderList, toDisplayString, unref } from "vue";
7
7
  //#region src/features/composites/components/ReferenceListFieldEditor.vue
8
8
  const _hoisted_1 = { class: "flex w-full flex-col gap-1.5" };
@@ -4,9 +4,9 @@ import { useUiKit } from "../../../vue/kit/use-ui-kit.js";
4
4
  import { useEditorSettings } from "../../../vue/settings.js";
5
5
  import { useEditorI18n } from "../../../vue/use-editor-i18n.js";
6
6
  import { STRUCTURE_MODE_KEYS } from "../structure-mode.js";
7
- import { BLOCK_TYPE_ICON_KEYS, DRAG_HANDLE_KEYS, HEADING_SCOPE_KEYS, optionItems } from "../editing-settings-keys.js";
8
7
  import { TREE_ROOT_KEYS } from "../tree-root.js";
9
8
  import _sfc_main$1 from "../../../vue/components/SettingsSection.js";
9
+ import { BLOCK_TYPE_ICON_KEYS, DRAG_HANDLE_KEYS, HEADING_SCOPE_KEYS, optionItems } from "../editing-settings-keys.js";
10
10
  import { computed, createElementBlock, createElementVNode, createVNode, defineComponent, openBlock, ref, unref, watch, withCtx, withKeys } from "vue";
11
11
  //#region src/features/composites/components/SettingsEditingTab.vue
12
12
  const _hoisted_1 = { class: "flex flex-col gap-8" };
@@ -25,8 +25,7 @@ import { BlockTypeJsonError, mergeBlockTypes, parseBlockTypes } from "./block-ty
25
25
  import { citeEntriesOf, citeText, resolveCite } from "./cite-label.js";
26
26
  import { normalizeReferences, referencesFromText } from "./reference-text.js";
27
27
  import { compositeSchemaExtensions } from "./schema.js";
28
- import { embedChainOf, embedKeyOf, embedStateOf } from "./embed-model.js";
29
- import { EMBED_CLASS, embedViewOptions, mountEmbed } from "./embed-dom.js";
28
+ import { compositeSectionOf, observeCompositeAnchors } from "./anchors.js";
30
29
  import { AcceptedChildren } from "./accepted-children.js";
31
30
  import { derivedChipOf, derivedRowBadge } from "./badges.js";
32
31
  import { isAiProposal } from "./ai-proposal.js";
@@ -46,9 +45,10 @@ import { CompositeSplit, childKindFor, generatedTitle, splitBodyAtRules, splitBo
46
45
  import { Structure, structureOf } from "./structure.js";
47
46
  import { STRUCTURE_MODE_KEYS } from "./structure-mode.js";
48
47
  import { compositeFeatureCore } from "./feature.js";
49
- import { compositeSectionOf, observeCompositeAnchors } from "./anchors.js";
48
+ import { canMoveBlockInto, compositeOutline, documentOutline, moveBlockInto, moveIntoVerdict } from "./outline.js";
50
49
  import { createCompositeRows } from "./rows-model.js";
51
- import { TREE_ROOT_KEYS } from "./tree-root.js";
52
50
  import { compositeFieldText, createCompositeInspector } from "./inspector-model.js";
53
- import { canMoveBlockInto, compositeOutline, documentOutline, moveBlockInto, moveIntoVerdict } from "./outline.js";
51
+ import { embedChainOf, embedKeyOf, embedStateOf } from "./embed-model.js";
52
+ import { EMBED_CLASS, embedViewOptions, mountEmbed } from "./embed-dom.js";
53
+ import { TREE_ROOT_KEYS } from "./tree-root.js";
54
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 };
@@ -4,9 +4,9 @@ import { Icon } from "../../../react/Icon.js";
4
4
  import { useEditorI18n } from "../../../react/use-editor-i18n.js";
5
5
  import { Button } from "../../../react/ui/button.js";
6
6
  import { Input } from "../../../react/ui/input.js";
7
+ import { bibFormOf, bibItemOf } from "../bibliography-form.js";
7
8
  import { Textarea } from "../../../react/ui/textarea.js";
8
9
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../react/ui/select.js";
9
- import { bibFormOf, bibItemOf } from "../bibliography-form.js";
10
10
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
11
11
  import { jsx, jsxs } from "react/jsx-runtime";
12
12
  //#region src/features/composites/react/BibliographyEditor.tsx
@@ -9,8 +9,8 @@ import { Icon } from "../../../react/Icon.js";
9
9
  import { useEditorI18n } from "../../../react/use-editor-i18n.js";
10
10
  import { useStore } from "../../../react/use-store.js";
11
11
  import { useEditorSettings } from "../../../react/settings.js";
12
- import { Popover, PopoverContent, PopoverTrigger } from "../../../react/ui/popover.js";
13
12
  import { compositeSectionOf } from "../anchors.js";
13
+ import { Popover, PopoverContent, PopoverTrigger } from "../../../react/ui/popover.js";
14
14
  import { rowChipsOf } from "../chrome-badges.js";
15
15
  import { useBadgeTick } from "./use-chrome-badges.js";
16
16
  import { CompositeBasketMenu } from "./CompositeBasketMenu.js";
@@ -4,8 +4,8 @@ import { compositeBacklinks } from "../rows.js";
4
4
  import { Icon } from "../../../react/Icon.js";
5
5
  import { useEditorI18n } from "../../../react/use-editor-i18n.js";
6
6
  import { Button } from "../../../react/ui/button.js";
7
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../react/ui/select.js";
8
7
  import { derivedNodeOf, detailFields } from "../details-model.js";
8
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../react/ui/select.js";
9
9
  import { DerivationBadge } from "./DerivationBadge.js";
10
10
  import { CompositeFieldEditor } from "./CompositeFieldEditor.js";
11
11
  import { CompositeSummaryEditor } from "./CompositeSummaryEditor.js";
@@ -6,16 +6,16 @@ import { Icon } from "../../../react/Icon.js";
6
6
  import { useEditorI18n } from "../../../react/use-editor-i18n.js";
7
7
  import { Badge } from "../../../react/ui/badge.js";
8
8
  import { Input } from "../../../react/ui/input.js";
9
+ import { compositeFieldText, isStructuredField } from "../inspector-model.js";
10
+ import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "../../../react/ui/popover.js";
11
+ import { DocumentBadges } from "./DocumentBadges.js";
9
12
  import { Textarea } from "../../../react/ui/textarea.js";
10
13
  import { Command, CommandInput, CommandItem, CommandList } from "../../../react/ui/command.js";
11
- import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "../../../react/ui/popover.js";
12
14
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../react/ui/select.js";
13
15
  import { Label } from "../../../react/ui/label.js";
14
16
  import { DerivationBadge } from "./DerivationBadge.js";
15
17
  import { CompositeFieldEditor } from "./CompositeFieldEditor.js";
16
18
  import { InspectorSections } from "./InspectorSections.js";
17
- import { DocumentBadges } from "./DocumentBadges.js";
18
- import { compositeFieldText, isStructuredField } from "../inspector-model.js";
19
19
  import { useCompositeInspector } from "./use-composite-inspector.js";
20
20
  import { useEffect, useId, useState } from "react";
21
21
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -6,8 +6,8 @@ import { useStore } from "../../../react/use-store.js";
6
6
  import { Badge } from "../../../react/ui/badge.js";
7
7
  import { Button } from "../../../react/ui/button.js";
8
8
  import { Input } from "../../../react/ui/input.js";
9
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../react/ui/select.js";
10
9
  import { createTableControls, fieldText, hasText, isLongText, sortIconOf, tableViewOf } from "../table-model.js";
10
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../react/ui/select.js";
11
11
  import { useCompositeRows } from "./use-composite-rows.js";
12
12
  import { TableBody, TableCell, TableHead, TableHeader, TableRow } from "../../../react/ui/table.js";
13
13
  import { useMemo, useState } from "react";
@@ -3,9 +3,9 @@ import { cn } from "../../../react/ui/utils.js";
3
3
  import { Icon } from "../../../react/Icon.js";
4
4
  import { useEditorI18n } from "../../../react/use-editor-i18n.js";
5
5
  import { Button } from "../../../react/ui/button.js";
6
+ import { referenceListChipsOf, referenceListChoicesOf, withReferenceListEntry, withoutReferenceListEntry } from "../reference-list-model.js";
6
7
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../react/ui/select.js";
7
8
  import { useCompositeRows } from "./use-composite-rows.js";
8
- import { referenceListChipsOf, referenceListChoicesOf, withReferenceListEntry, withoutReferenceListEntry } from "../reference-list-model.js";
9
9
  import { useMemo } from "react";
10
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
11
  //#region src/features/composites/react/ReferenceListFieldEditor.tsx
@@ -4,8 +4,8 @@ import { referenceAttrsOf, resolveReference } from "../reference-label.js";
4
4
  import { cn } from "../../../react/ui/utils.js";
5
5
  import { useEditorI18n } from "../../../react/use-editor-i18n.js";
6
6
  import { Input } from "../../../react/ui/input.js";
7
- import { Popover, PopoverAnchor, PopoverContent } from "../../../react/ui/popover.js";
8
7
  import { revealSource } from "../reveal-source.js";
8
+ import { Popover, PopoverAnchor, PopoverContent } from "../../../react/ui/popover.js";
9
9
  import { useEffect, useState } from "react";
10
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
11
  import { NodeViewWrapper } from "@tiptap/react";
@@ -4,14 +4,14 @@ import { Icon } from "../../../react/Icon.js";
4
4
  import { useEditorI18n } from "../../../react/use-editor-i18n.js";
5
5
  import { useEditorSettings } from "../../../react/settings.js";
6
6
  import { Input } from "../../../react/ui/input.js";
7
+ import { STRUCTURE_MODE_KEYS } from "../structure-mode.js";
8
+ import { TREE_ROOT_KEYS } from "../tree-root.js";
9
+ import { BLOCK_TYPE_ICON_KEYS, DRAG_HANDLE_KEYS, HEADING_SCOPE_KEYS, optionItems } from "../editing-settings-keys.js";
7
10
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../react/ui/select.js";
8
11
  import { SettingsSection } from "../../../react/SettingsSection.js";
9
12
  import { Label } from "../../../react/ui/label.js";
10
13
  import { Switch } from "../../../react/ui/switch.js";
11
14
  import { RadioGroup, RadioGroupItem } from "../../../react/ui/radio-group.js";
12
- import { STRUCTURE_MODE_KEYS } from "../structure-mode.js";
13
- import { BLOCK_TYPE_ICON_KEYS, DRAG_HANDLE_KEYS, HEADING_SCOPE_KEYS, optionItems } from "../editing-settings-keys.js";
14
- import { TREE_ROOT_KEYS } from "../tree-root.js";
15
15
  import { useEffect, useId, useState } from "react";
16
16
  import { jsx, jsxs } from "react/jsx-runtime";
17
17
  //#region src/features/composites/react/SettingsEditingTab.tsx
@@ -1,6 +1,7 @@
1
- import { embedViewOptions } from "./embed-dom.js";
2
1
  import { typedBlockViewOptions } from "./node-views.js";
3
2
  import { compositeFeatureCore } from "./feature.js";
3
+ import { embedViewOptions } from "./embed-dom.js";
4
+ import { DocumentBadges } from "./react/DocumentBadges.js";
4
5
  import { BlockEmbedView } from "./react/BlockEmbedView.js";
5
6
  import { CiteView } from "./react/CiteView.js";
6
7
  import { CompositeView } from "./react/CompositeView.js";
@@ -20,7 +21,6 @@ import { EdgesSection } from "./react/EdgesSection.js";
20
21
  import { ExportCheckSection } from "./react/ExportCheckSection.js";
21
22
  import { FocusChip } from "./react/FocusChip.js";
22
23
  import { SettingsEditingTab } from "./react/SettingsEditingTab.js";
23
- import { DocumentBadges } from "./react/DocumentBadges.js";
24
24
  import { CompositeInspector } from "./react/CompositeInspector.js";
25
25
  import { CompositeTable } from "./react/CompositeTable.js";
26
26
  import { ReactNodeViewRenderer } from "@tiptap/react";
@@ -1,6 +1,6 @@
1
- import { embedViewOptions } from "./embed-dom.js";
2
1
  import { typedBlockViewOptions } from "./node-views.js";
3
2
  import { compositeFeatureCore } from "./feature.js";
3
+ import { embedViewOptions } from "./embed-dom.js";
4
4
  import _sfc_main$13 from "./components/DocumentBadges.js";
5
5
  import _sfc_main from "./components/BlockEmbedView.js";
6
6
  import _sfc_main$1 from "./components/CiteView.js";
@@ -1,5 +1,5 @@
1
- import { pruefungFeatureCore } from "./feature.js";
2
1
  import _sfc_main from "./components/PruefungBadge.js";
2
+ import { pruefungFeatureCore } from "./feature.js";
3
3
  //#region src/features/pruefung/vue.ts
4
4
  /** The Vue Prüfung feature (Nuxt UI): see `pruefungFeatureCore`. The Prüfstand section shows in the Typed block inspector and details card. */
5
5
  function pruefungFeature(options = {}) {
@@ -1,5 +1,5 @@
1
- import { themesFeatureCore } from "./feature.js";
2
1
  import _sfc_main from "./components/SettingsAppearanceTab.js";
2
+ import { themesFeatureCore } from "./feature.js";
3
3
  import { getCurrentInstance } from "vue";
4
4
  //#region src/features/themes/vue.ts
5
5
  const started = /* @__PURE__ */ new WeakSet();
@@ -1,5 +1,5 @@
1
- import { transferFeatureCore } from "./feature.js";
2
1
  import _sfc_main from "./components/TransferMenu.js";
2
+ import { transferFeatureCore } from "./feature.js";
3
3
  //#region src/features/transfer/vue.ts
4
4
  /** The Vue transfer feature (Nuxt UI): see `transferFeatureCore`. */
5
5
  function transferFeature(options = {}) {
@@ -1,8 +1,8 @@
1
1
  import { withHeading } from "../../features/ai/protocol/tasks.js";
2
2
  import { ABILITY } from "../../core/schema/abilities.js";
3
3
  import { compositeFence } from "../../features/composites/fences.js";
4
- import { modelProfiles } from "../../features/ai/model-profiles.js";
5
4
  import { structureOf } from "../../features/composites/structure.js";
5
+ import { modelProfiles } from "../../features/ai/model-profiles.js";
6
6
  import { fillComposite, generateCompositeBody } from "./composite-fill.js";
7
7
  import { canDeriveAfter, derivableBlockTypesOf, deriveComposite, discardDerived, isDerivableSource, writeDerivedBody } from "./derive.js";
8
8
  import { canFetchBibliography, doiOf, fetchBibliography } from "./bibliography-fetch.js";
@@ -41,24 +41,24 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
41
41
  settingsOpen: import("vue").WritableComputedRef<boolean, boolean>;
42
42
  settingsTab: import("vue").WritableComputedRef<string | undefined, string | undefined>;
43
43
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
44
+ settingsOpen: (tab?: string | undefined) => any;
44
45
  "update:sidebarOpen": (value: boolean) => any;
45
46
  "update:commentsOpen": (value: boolean) => any;
46
- ready: (editor: Editor) => any;
47
47
  "update:modelValue": (markdown: string) => any;
48
+ frontmatter: (frontmatter: string | null) => any;
49
+ ready: (editor: Editor) => any;
48
50
  metadataCreate: (list: string, item: MetadataItem) => any;
49
51
  contentError: (error: Error) => any;
50
- settingsOpen: (tab?: string | undefined) => any;
51
- frontmatter: (frontmatter: string | null) => any;
52
52
  diagnostics: (diagnostics: MarkdownDiagnostic[]) => any;
53
53
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
54
+ onSettingsOpen?: ((tab?: string | undefined) => any) | undefined;
54
55
  "onUpdate:sidebarOpen"?: ((value: boolean) => any) | undefined;
55
56
  "onUpdate:commentsOpen"?: ((value: boolean) => any) | undefined;
56
- onReady?: ((editor: Editor) => any) | undefined;
57
57
  "onUpdate:modelValue"?: ((markdown: string) => any) | undefined;
58
+ onFrontmatter?: ((frontmatter: string | null) => any) | undefined;
59
+ onReady?: ((editor: Editor) => any) | undefined;
58
60
  onMetadataCreate?: ((list: string, item: MetadataItem) => any) | undefined;
59
61
  onContentError?: ((error: Error) => any) | undefined;
60
- onSettingsOpen?: ((tab?: string | undefined) => any) | undefined;
61
- onFrontmatter?: ((frontmatter: string | null) => any) | undefined;
62
62
  onDiagnostics?: ((diagnostics: MarkdownDiagnostic[]) => any) | undefined;
63
63
  }>, {
64
64
  modelValue: string;
@@ -6,10 +6,10 @@ import { Icon } from "./Icon.js";
6
6
  import { useEditorI18n } from "./use-editor-i18n.js";
7
7
  import { useStore } from "./use-store.js";
8
8
  import { Button } from "./ui/button.js";
9
- import { shortcutLabel } from "./key-labels.js";
10
- import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./ui/tooltip.js";
11
9
  import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "./ui/dropdown-menu.js";
10
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./ui/tooltip.js";
12
11
  import { collapsedGroupMenu, fitToolbar } from "../core/toolbar-fit.js";
12
+ import { shortcutLabel } from "./key-labels.js";
13
13
  import { Separator } from "./ui/separator.js";
14
14
  import { useLayoutEffect, useRef, useState } from "react";
15
15
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -1,4 +1,6 @@
1
1
  import { coreUiFeature } from "../core/core-feature.js";
2
+ import { mediaFeature } from "../features/media/react.js";
3
+ import { AI_BINDINGS, layerCompositions } from "../presets/layer.js";
2
4
  import { EditorCommandPalette } from "./EditorCommandPalette.js";
3
5
  import { aiFeature } from "../features/ai/react.js";
4
6
  import { authorsFeature } from "../features/authors/react.js";
@@ -6,13 +8,11 @@ import { blockUiFeature } from "../features/block-ui/react.js";
6
8
  import { collabFeature } from "../features/collab/react.js";
7
9
  import { commentsFeature } from "../features/comments/react.js";
8
10
  import { compositeFeature } from "../features/composites/react.js";
9
- import { mediaFeature } from "../features/media/react.js";
10
11
  import { themesFeature } from "../features/themes/react.js";
11
12
  import { pruefungFeature } from "../features/pruefung/react.js";
12
13
  import { exploreFeature } from "../features/explore/react.js";
13
14
  import { transferFeature } from "../features/transfer/react.js";
14
15
  import { transcriptFeature } from "../features/transcript/react.js";
15
- import { AI_BINDINGS, layerCompositions } from "../presets/layer.js";
16
16
  //#region src/react/compose.ts
17
17
  /** The React bindings of the UI-bound catalog features (`presets/catalog`: the rows with a `ui` part). */
18
18
  const REACT_BINDINGS = {
@@ -10,8 +10,8 @@ import { EditorUiContext, useEditorUi } from "./editor-ui.js";
10
10
  import { reactNotifier } from "./notify.js";
11
11
  import { SuggestionList, reactSuggestionRenderer } from "./suggestion-renderer.js";
12
12
  import { EditorSurface } from "./EditorSurface.js";
13
- import { EditorCommandPalette } from "./EditorCommandPalette.js";
14
13
  import { useNotifier } from "./use-notifier.js";
14
+ import { EditorCommandPalette } from "./EditorCommandPalette.js";
15
15
  import { SettingsSection } from "./SettingsSection.js";
16
16
  import { EditorToolbar } from "./EditorToolbar.js";
17
17
  import { Toaster } from "sonner";
@@ -3,8 +3,8 @@ import { cn } from "../../react/ui/utils.js";
3
3
  import { Icon } from "../../react/Icon.js";
4
4
  import { useEditorI18n } from "../../react/use-editor-i18n.js";
5
5
  import { Button } from "../../react/ui/button.js";
6
- import { Input } from "../../react/ui/input.js";
7
6
  import { hitLabel } from "../search-model.js";
7
+ import { Input } from "../../react/ui/input.js";
8
8
  import { useSearchModel } from "./use-search-model.js";
9
9
  import { jsx, jsxs } from "react/jsx-runtime";
10
10
  //#region src/search/react/SearchPanel.tsx
@@ -1,4 +1,5 @@
1
- import { TYPED_BLOCK_TITLE, isTypedBlock, typeIdOf } from "../core/typed-block.js";
1
+ import { isTypedBlock, typeIdOf } from "../core/typed-block.js";
2
+ import { inlineText, titleOf } from "../core/block-index.js";
2
3
  import { loadCurrentContent } from "./stored-content.js";
3
4
  import { createBlockMarkdown } from "./block-index.js";
4
5
  import { mayReadDocument } from "./readable-documents.js";
@@ -22,23 +23,6 @@ async function readableContent(ctx, documentId) {
22
23
  if (!await mayReadDocument(ctx.ports, ctx.user, documentId)) return null;
23
24
  return ctx.liveContent(documentId) ?? await loadCurrentContent(ctx.ports.documents, documentId);
24
25
  }
25
- const attrString = (node, key) => typeof node.attrs?.[key] === "string" ? node.attrs[key] : "";
26
- /** The plain text of an inline node or a textblock's inline content, chips as their label. */
27
- function inlineText(node) {
28
- switch (node.type) {
29
- case "text": return node.text ?? "";
30
- case "hardBreak": return " ";
31
- case "mention": return `@${attrString(node, "label") || attrString(node, "id")}`;
32
- case "tag": return `#${attrString(node, "name")}`;
33
- case "reference": return attrString(node, "label");
34
- default: return (node.content ?? []).map(inlineText).join("");
35
- }
36
- }
37
- /** The title of a Block as the Block index has it: a Typed block's title row, a heading's text, `''` for any other Block. */
38
- function titleOf(node) {
39
- if (isTypedBlock(node)) return (node.content ?? []).filter((child) => child.type === TYPED_BLOCK_TITLE).map(inlineText).join("").trim();
40
- return node.type === "heading" ? inlineText(node).trim() : "";
41
- }
42
26
  /**
43
27
  * Every Block of `content` (every non-inline node with an `id`, the rule of `blockLinesOfContent`), in document order, a Block
44
28
  * before the Blocks nested in it. A Block's `children` are the Blocks directly inside it, through nodes without an ID (a list
@@ -1 +1 @@
1
- {"version":3,"file":"document-tools.js","names":[],"sources":["../../src/server/document-tools.ts"],"sourcesContent":["// i18n-ignore-file: model-facing tool descriptions and results (German, like the chat's system prompt)\nimport type { JSONContent } from '@tiptap/core'\nimport { jsonSchema, tool } from 'ai'\nimport { z } from 'zod'\nimport type { BlockMarkdown } from '../core/block-index'\nimport { isTypedBlock, TYPED_BLOCK_TITLE, typeIdOf } from '../core/typed-block'\nimport { createBlockMarkdown } from './block-index'\nimport { findBlock, INLINE_NODES } from './document-blocks'\nimport { mayReadDocument } from './readable-documents'\nimport { loadCurrentContent } from './stored-content'\nimport type { ToolContext, ToolProvider } from './tools'\nimport { parsed, READ_BLOCK_LIMIT, unreadableBlock, type WorkspaceToolsOptions } from './workspace-tools'\n\n// Read-only tools of the document chat that look into one Document as a whole: its tree of Blocks and several Blocks at once.\n// Unlike `createWorkspaceTools` they read the Document's content directly (no Block index): the live content of a Document\n// open in the collaboration server first, else the stored content in the current shape.\n\n/** Block IDs `read_blocks` reads in one call. */\nconst READ_BLOCKS_MAX = 50\n/** Characters of all Blocks one `read_blocks` call returns; the Blocks after the one that reaches it are left out with a note. */\nconst READ_BLOCKS_TOTAL_LIMIT = 8 * READ_BLOCK_LIMIT\n\n/** The Markdown serializer `read_blocks` writes with: the options of `createWorkspaceTools`. */\nexport type DocumentToolsOptions = WorkspaceToolsOptions\n\nconst outlineInput = z.object({\n documentId: z.string().min(1).max(200).optional(),\n})\nconst readBlocksInput = z.object({\n documentId: z.string().min(1).max(200).optional(),\n blockIds: z.array(z.string().min(1).max(100)).min(1).max(READ_BLOCKS_MAX),\n})\n\nconst NO_DOCUMENT = 'Im Chat ist kein Dokument geöffnet: gib documentId an.'\n\n/** The current content of `documentId` (live first, else stored), `null` when the user may not read it or it does not exist. */\nasync function readableContent(ctx: ToolContext, documentId: string): Promise<JSONContent | null> {\n if (!await mayReadDocument(ctx.ports, ctx.user, documentId)) return null\n return ctx.liveContent(documentId) ?? await loadCurrentContent(ctx.ports.documents, documentId)\n}\n\nconst attrString = (node: JSONContent, key: string): string => typeof node.attrs?.[key] === 'string' ? node.attrs[key] as string : ''\n\n/** The plain text of an inline node or a textblock's inline content, chips as their label. */\nfunction inlineText(node: JSONContent): string {\n switch (node.type) {\n case 'text': return node.text ?? ''\n case 'hardBreak': return ' '\n case 'mention': return `@${attrString(node, 'label') || attrString(node, 'id')}`\n case 'tag': return `#${attrString(node, 'name')}`\n case 'reference': return attrString(node, 'label')\n default: return (node.content ?? []).map(inlineText).join('')\n }\n}\n\n/** The title of a Block as the Block index has it: a Typed block's title row, a heading's text, `''` for any other Block. */\nfunction titleOf(node: JSONContent): string {\n if (isTypedBlock(node)) return (node.content ?? []).filter(child => child.type === TYPED_BLOCK_TITLE).map(inlineText).join('').trim()\n return node.type === 'heading' ? inlineText(node).trim() : ''\n}\n\n/** One Block of `document_outline`. */\ninterface OutlineEntry {\n id: string\n /** Node type (`paragraph`, `heading`, `typedBlock`, …). */\n type: string\n /** Level of a heading. */\n level?: number\n /** Block type id of a Typed block. */\n blockType?: string\n /** Title of a Typed block, text of a heading. */\n title?: string\n /** IDs of the Blocks directly inside this one, in document order. */\n children?: string[]\n /** Characters of the Block's text, nested Blocks included. */\n chars: number\n}\n\n/**\n * Every Block of `content` (every non-inline node with an `id`, the rule of `blockLinesOfContent`), in document order, a Block\n * before the Blocks nested in it. A Block's `children` are the Blocks directly inside it, through nodes without an ID (a list\n * without one, say).\n */\nfunction outlineOf(content: JSONContent): OutlineEntry[] {\n const entries: OutlineEntry[] = []\n const walk = (node: JSONContent): { chars: number, blocks: string[] } => {\n let chars = 0\n const blocks: string[] = []\n for (const child of node.content ?? []) {\n if (child.type !== undefined && INLINE_NODES.has(child.type)) {\n chars += inlineText(child).length\n continue\n }\n const id = child.attrs?.id\n if (typeof id !== 'string' || !id) {\n const inner = walk(child)\n chars += inner.chars\n blocks.push(...inner.blocks)\n continue\n }\n const entry: OutlineEntry = { id, type: child.type ?? '', chars: 0 }\n if (child.type === 'heading' && typeof child.attrs?.level === 'number') entry.level = child.attrs.level\n if (isTypedBlock(child)) entry.blockType = typeIdOf(child)\n const title = titleOf(child)\n if (title) entry.title = title\n entries.push(entry)\n const inner = walk(child)\n entry.chars = inner.chars\n if (inner.blocks.length) entry.children = inner.blocks\n chars += inner.chars\n blocks.push(id)\n }\n return { chars, blocks }\n }\n walk(content)\n return entries\n}\n\n/**\n * The read-only document tools of the document chat, for `EditorServerOptions.tools` / `provideEditorServer({ tools })`, next\n * to `createWorkspaceTools`:\n *\n * - `document_outline(documentId?)`: the tree of all Blocks of the open Document (or of another one the user may read): per\n * Block its ID, node type, heading level or Block type and title, the IDs of the Blocks directly inside it and the length of\n * its text;\n * - `read_blocks(documentId?, blockIds)`: up to 50 Blocks of one Document as Markdown, each cut like `read_block`\n * (`READ_BLOCK_LIMIT`), all together at most eight times that.\n *\n * Both read the current content (live content of an open Document first, else `loadCurrentContent`) and need no index. An\n * unreadable Document and an unknown Block answer the same sentence as `read_block`, so the tools never confirm that a\n * Document or Block exists where the user may not look.\n */\nexport function createDocumentTools(options: DocumentToolsOptions = {}): ToolProvider[] {\n let markdown = options.markdown\n const markdownOf = (): BlockMarkdown => markdown ??= createBlockMarkdown({\n ...(options.schema && { schema: options.schema }),\n ...(options.blockTypes && { blockTypes: options.blockTypes }),\n })\n\n const documentOutline: ToolProvider = {\n name: 'document_outline',\n tool: tool({\n description: 'Liefert die Gliederung eines Dokuments als JSON: alle Blöcke in Dokumentreihenfolge, je mit id, type (Knotentyp), level (bei Überschriften), blockType (bei typisierten Blöcken), title (Überschriftentext bzw. Titel des typisierten Blocks), children (IDs der direkt enthaltenen Blöcke) und chars (Textlänge in Zeichen, enthaltene Blöcke eingeschlossen). Ohne documentId das im Chat geöffnete Dokument in seinem aktuellen Stand; mit documentId ein anderes lesbares Dokument. Den Inhalt einzelner Blöcke liest du mit read_blocks.',\n inputSchema: jsonSchema<{ documentId?: string }>({\n type: 'object',\n properties: {\n documentId: { type: 'string', description: 'ID des Dokuments; ohne Angabe das geöffnete Dokument.' },\n },\n }),\n }),\n async handle(ctx, input) {\n const checked = parsed(outlineInput, input)\n if ('problem' in checked) return checked.problem\n const documentId = checked.value.documentId ?? ctx.documentId\n if (!documentId) return NO_DOCUMENT\n const content = await readableContent(ctx, documentId)\n // The same sentence for an unreadable and a missing Document: the tool never confirms that a Document exists the user may not read.\n if (!content) return `Das Dokument „${documentId}“ ist nicht lesbar oder existiert nicht.`\n const blocks = outlineOf(content)\n if (!blocks.length) return `Das Dokument „${documentId}“ hat keine Blöcke.`\n return JSON.stringify({ documentId, blocks })\n },\n }\n\n const readBlocks: ToolProvider = {\n name: 'read_blocks',\n tool: tool({\n description: `Liest Blöcke eines Dokuments als Markdown, bis zu ${READ_BLOCKS_MAX} auf einmal, in der angegebenen Reihenfolge. Ohne documentId aus dem im Chat geöffneten Dokument in seinem aktuellen Stand, mit documentId aus einem anderen lesbaren Dokument. Ein Block enthält die in ihm verschachtelten Blöcke. Block-IDs stammen aus document_outline oder find_blocks. Ein Block über ${READ_BLOCK_LIMIT} Zeichen wird gekürzt; ab ${READ_BLOCKS_TOTAL_LIMIT} Zeichen insgesamt werden die übrigen Blöcke ausgelassen und sind mit einem weiteren Aufruf zu lesen.`,\n inputSchema: jsonSchema<{ documentId?: string, blockIds: string[] }>({\n type: 'object',\n properties: {\n documentId: { type: 'string', description: 'ID des Dokuments; ohne Angabe das geöffnete Dokument.' },\n blockIds: { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: READ_BLOCKS_MAX, description: 'IDs der Blöcke im Dokument.' },\n },\n required: ['blockIds'],\n }),\n }),\n async handle(ctx, input) {\n const checked = parsed(readBlocksInput, input)\n if ('problem' in checked) return checked.problem\n const documentId = checked.value.documentId ?? ctx.documentId\n if (!documentId) return NO_DOCUMENT\n const blockIds = [...new Set(checked.value.blockIds)]\n const content = await readableContent(ctx, documentId)\n const parts: string[] = []\n let total = 0\n for (const [i, blockId] of blockIds.entries()) {\n if (total >= READ_BLOCKS_TOTAL_LIMIT) {\n const rest = blockIds.slice(i)\n parts.push(`[… ${rest.length} weitere Blöcke ausgelassen, die Grenze von ${READ_BLOCKS_TOTAL_LIMIT} Zeichen ist erreicht: ${rest.join(', ')}]`)\n break\n }\n const node = content && findBlock(content, blockId)\n if (!node) {\n parts.push(unreadableBlock(documentId, blockId))\n continue\n }\n const title = titleOf(node)\n const head = `Dokument „${documentId}“, Block „${blockId}“ (${isTypedBlock(node) ? typeIdOf(node) : node.type ?? ''}${title ? `, ${title}` : ''}):`\n const body = markdownOf()([node]).trim()\n const shown = body.length > READ_BLOCK_LIMIT ? `${body.slice(0, READ_BLOCK_LIMIT)}\\n\\n[… gekürzt, ${body.length - READ_BLOCK_LIMIT} Zeichen fehlen]` : body\n total += Math.min(body.length, READ_BLOCK_LIMIT)\n parts.push(`${head}\\n\\n${shown}`)\n }\n return parts.join('\\n\\n---\\n\\n')\n },\n }\n\n return [documentOutline, readBlocks]\n}\n"],"mappings":";;;;;;;;;;AAkBA,MAAM,kBAAkB;;AAExB,MAAM,0BAA0B,IAAI;AAKpC,MAAM,eAAe,EAAE,OAAO,EAC5B,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS,EAClD,CAAC;AACD,MAAM,kBAAkB,EAAE,OAAO;CAC/B,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS;CAChD,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,eAAe;AAC1E,CAAC;AAED,MAAM,cAAc;;AAGpB,eAAe,gBAAgB,KAAkB,YAAiD;CAChG,IAAI,CAAC,MAAM,gBAAgB,IAAI,OAAO,IAAI,MAAM,UAAU,GAAG,OAAO;CACpE,OAAO,IAAI,YAAY,UAAU,KAAK,MAAM,mBAAmB,IAAI,MAAM,WAAW,UAAU;AAChG;AAEA,MAAM,cAAc,MAAmB,QAAwB,OAAO,KAAK,QAAQ,SAAS,WAAW,KAAK,MAAM,OAAiB;;AAGnI,SAAS,WAAW,MAA2B;CAC7C,QAAQ,KAAK,MAAb;EACE,KAAK,QAAQ,OAAO,KAAK,QAAQ;EACjC,KAAK,aAAa,OAAO;EACzB,KAAK,WAAW,OAAO,IAAI,WAAW,MAAM,OAAO,KAAK,WAAW,MAAM,IAAI;EAC7E,KAAK,OAAO,OAAO,IAAI,WAAW,MAAM,MAAM;EAC9C,KAAK,aAAa,OAAO,WAAW,MAAM,OAAO;EACjD,SAAS,QAAQ,KAAK,WAAW,CAAC,EAAA,CAAG,IAAI,UAAU,CAAC,CAAC,KAAK,EAAE;CAC9D;AACF;;AAGA,SAAS,QAAQ,MAA2B;CAC1C,IAAI,aAAa,IAAI,GAAG,QAAQ,KAAK,WAAW,CAAC,EAAA,CAAG,QAAO,UAAS,MAAM,SAAS,iBAAiB,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK;CACpI,OAAO,KAAK,SAAS,YAAY,WAAW,IAAI,CAAC,CAAC,KAAK,IAAI;AAC7D;;;;;;AAwBA,SAAS,UAAU,SAAsC;CACvD,MAAM,UAA0B,CAAC;CACjC,MAAM,QAAQ,SAA2D;EACvE,IAAI,QAAQ;EACZ,MAAM,SAAmB,CAAC;EAC1B,KAAK,MAAM,SAAS,KAAK,WAAW,CAAC,GAAG;GACtC,IAAI,MAAM,SAAS,KAAA,KAAa,aAAa,IAAI,MAAM,IAAI,GAAG;IAC5D,SAAS,WAAW,KAAK,CAAC,CAAC;IAC3B;GACF;GACA,MAAM,KAAK,MAAM,OAAO;GACxB,IAAI,OAAO,OAAO,YAAY,CAAC,IAAI;IACjC,MAAM,QAAQ,KAAK,KAAK;IACxB,SAAS,MAAM;IACf,OAAO,KAAK,GAAG,MAAM,MAAM;IAC3B;GACF;GACA,MAAM,QAAsB;IAAE;IAAI,MAAM,MAAM,QAAQ;IAAI,OAAO;GAAE;GACnE,IAAI,MAAM,SAAS,aAAa,OAAO,MAAM,OAAO,UAAU,UAAU,MAAM,QAAQ,MAAM,MAAM;GAClG,IAAI,aAAa,KAAK,GAAG,MAAM,YAAY,SAAS,KAAK;GACzD,MAAM,QAAQ,QAAQ,KAAK;GAC3B,IAAI,OAAO,MAAM,QAAQ;GACzB,QAAQ,KAAK,KAAK;GAClB,MAAM,QAAQ,KAAK,KAAK;GACxB,MAAM,QAAQ,MAAM;GACpB,IAAI,MAAM,OAAO,QAAQ,MAAM,WAAW,MAAM;GAChD,SAAS,MAAM;GACf,OAAO,KAAK,EAAE;EAChB;EACA,OAAO;GAAE;GAAO;EAAO;CACzB;CACA,KAAK,OAAO;CACZ,OAAO;AACT;;;;;;;;;;;;;;;AAgBA,SAAgB,oBAAoB,UAAgC,CAAC,GAAmB;CACtF,IAAI,WAAW,QAAQ;CACvB,MAAM,mBAAkC,aAAa,oBAAoB;EACvE,GAAI,QAAQ,UAAU,EAAE,QAAQ,QAAQ,OAAO;EAC/C,GAAI,QAAQ,cAAc,EAAE,YAAY,QAAQ,WAAW;CAC7D,CAAC;CAuED,OAAO,CAAC;EApEN,MAAM;EACN,MAAM,KAAK;GACT,aAAa;GACb,aAAa,WAAoC;IAC/C,MAAM;IACN,YAAY,EACV,YAAY;KAAE,MAAM;KAAU,aAAa;IAAwD,EACrG;GACF,CAAC;EACH,CAAC;EACD,MAAM,OAAO,KAAK,OAAO;GACvB,MAAM,UAAU,OAAO,cAAc,KAAK;GAC1C,IAAI,aAAa,SAAS,OAAO,QAAQ;GACzC,MAAM,aAAa,QAAQ,MAAM,cAAc,IAAI;GACnD,IAAI,CAAC,YAAY,OAAO;GACxB,MAAM,UAAU,MAAM,gBAAgB,KAAK,UAAU;GAErD,IAAI,CAAC,SAAS,OAAO,iBAAiB,WAAW;GACjD,MAAM,SAAS,UAAU,OAAO;GAChC,IAAI,CAAC,OAAO,QAAQ,OAAO,iBAAiB,WAAW;GACvD,OAAO,KAAK,UAAU;IAAE;IAAY;GAAO,CAAC;EAC9C;CA+CoB,GAAG;EA3CvB,MAAM;EACN,MAAM,KAAK;GACT,aAAa,qDAAqD,gBAAgB,+SAA+S,iBAAiB,4BAA4B,wBAAwB;GACtc,aAAa,WAAwD;IACnE,MAAM;IACN,YAAY;KACV,YAAY;MAAE,MAAM;MAAU,aAAa;KAAwD;KACnG,UAAU;MAAE,MAAM;MAAS,OAAO,EAAE,MAAM,SAAS;MAAG,UAAU;MAAG,UAAU;MAAiB,aAAa;KAA8B;IAC3I;IACA,UAAU,CAAC,UAAU;GACvB,CAAC;EACH,CAAC;EACD,MAAM,OAAO,KAAK,OAAO;GACvB,MAAM,UAAU,OAAO,iBAAiB,KAAK;GAC7C,IAAI,aAAa,SAAS,OAAO,QAAQ;GACzC,MAAM,aAAa,QAAQ,MAAM,cAAc,IAAI;GACnD,IAAI,CAAC,YAAY,OAAO;GACxB,MAAM,WAAW,CAAC,GAAG,IAAI,IAAI,QAAQ,MAAM,QAAQ,CAAC;GACpD,MAAM,UAAU,MAAM,gBAAgB,KAAK,UAAU;GACrD,MAAM,QAAkB,CAAC;GACzB,IAAI,QAAQ;GACZ,KAAK,MAAM,CAAC,GAAG,YAAY,SAAS,QAAQ,GAAG;IAC7C,IAAI,SAAS,yBAAyB;KACpC,MAAM,OAAO,SAAS,MAAM,CAAC;KAC7B,MAAM,KAAK,MAAM,KAAK,OAAO,8CAA8C,wBAAwB,yBAAyB,KAAK,KAAK,IAAI,EAAE,EAAE;KAC9I;IACF;IACA,MAAM,OAAO,WAAW,UAAU,SAAS,OAAO;IAClD,IAAI,CAAC,MAAM;KACT,MAAM,KAAK,gBAAgB,YAAY,OAAO,CAAC;KAC/C;IACF;IACA,MAAM,QAAQ,QAAQ,IAAI;IAC1B,MAAM,OAAO,aAAa,WAAW,YAAY,QAAQ,KAAK,aAAa,IAAI,IAAI,SAAS,IAAI,IAAI,KAAK,QAAQ,KAAK,QAAQ,KAAK,UAAU,GAAG;IAChJ,MAAM,OAAO,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;IACvC,MAAM,QAAQ,KAAK,SAAA,MAA4B,GAAG,KAAK,MAAM,GAAG,gBAAgB,EAAE,kBAAkB,KAAK,SAAS,iBAAiB,oBAAoB;IACvJ,SAAS,KAAK,IAAI,KAAK,QAAQ,gBAAgB;IAC/C,MAAM,KAAK,GAAG,KAAK,MAAM,OAAO;GAClC;GACA,OAAO,MAAM,KAAK,aAAa;EACjC;CAGgC,CAAC;AACrC"}
1
+ {"version":3,"file":"document-tools.js","names":[],"sources":["../../src/server/document-tools.ts"],"sourcesContent":["// i18n-ignore-file: model-facing tool descriptions and results (German, like the chat's system prompt)\nimport type { JSONContent } from '@tiptap/core'\nimport { jsonSchema, tool } from 'ai'\nimport { z } from 'zod'\nimport { type BlockMarkdown, inlineText, titleOf } from '../core/block-index'\nimport { isTypedBlock, typeIdOf } from '../core/typed-block'\nimport { createBlockMarkdown } from './block-index'\nimport { findBlock, INLINE_NODES } from './document-blocks'\nimport { mayReadDocument } from './readable-documents'\nimport { loadCurrentContent } from './stored-content'\nimport type { ToolContext, ToolProvider } from './tools'\nimport { parsed, READ_BLOCK_LIMIT, unreadableBlock, type WorkspaceToolsOptions } from './workspace-tools'\n\n// Read-only tools of the document chat that look into one Document as a whole: its tree of Blocks and several Blocks at once.\n// Unlike `createWorkspaceTools` they read the Document's content directly (no Block index): the live content of a Document\n// open in the collaboration server first, else the stored content in the current shape.\n\n/** Block IDs `read_blocks` reads in one call. */\nconst READ_BLOCKS_MAX = 50\n/** Characters of all Blocks one `read_blocks` call returns; the Blocks after the one that reaches it are left out with a note. */\nconst READ_BLOCKS_TOTAL_LIMIT = 8 * READ_BLOCK_LIMIT\n\n/** The Markdown serializer `read_blocks` writes with: the options of `createWorkspaceTools`. */\nexport type DocumentToolsOptions = WorkspaceToolsOptions\n\nconst outlineInput = z.object({\n documentId: z.string().min(1).max(200).optional(),\n})\nconst readBlocksInput = z.object({\n documentId: z.string().min(1).max(200).optional(),\n blockIds: z.array(z.string().min(1).max(100)).min(1).max(READ_BLOCKS_MAX),\n})\n\nconst NO_DOCUMENT = 'Im Chat ist kein Dokument geöffnet: gib documentId an.'\n\n/** The current content of `documentId` (live first, else stored), `null` when the user may not read it or it does not exist. */\nasync function readableContent(ctx: ToolContext, documentId: string): Promise<JSONContent | null> {\n if (!await mayReadDocument(ctx.ports, ctx.user, documentId)) return null\n return ctx.liveContent(documentId) ?? await loadCurrentContent(ctx.ports.documents, documentId)\n}\n\n/** One Block of `document_outline`. */\ninterface OutlineEntry {\n id: string\n /** Node type (`paragraph`, `heading`, `typedBlock`, …). */\n type: string\n /** Level of a heading. */\n level?: number\n /** Block type id of a Typed block. */\n blockType?: string\n /** Title of a Typed block, text of a heading. */\n title?: string\n /** IDs of the Blocks directly inside this one, in document order. */\n children?: string[]\n /** Characters of the Block's text, nested Blocks included. */\n chars: number\n}\n\n/**\n * Every Block of `content` (every non-inline node with an `id`, the rule of `blockLinesOfContent`), in document order, a Block\n * before the Blocks nested in it. A Block's `children` are the Blocks directly inside it, through nodes without an ID (a list\n * without one, say).\n */\nfunction outlineOf(content: JSONContent): OutlineEntry[] {\n const entries: OutlineEntry[] = []\n const walk = (node: JSONContent): { chars: number, blocks: string[] } => {\n let chars = 0\n const blocks: string[] = []\n for (const child of node.content ?? []) {\n if (child.type !== undefined && INLINE_NODES.has(child.type)) {\n chars += inlineText(child).length\n continue\n }\n const id = child.attrs?.id\n if (typeof id !== 'string' || !id) {\n const inner = walk(child)\n chars += inner.chars\n blocks.push(...inner.blocks)\n continue\n }\n const entry: OutlineEntry = { id, type: child.type ?? '', chars: 0 }\n if (child.type === 'heading' && typeof child.attrs?.level === 'number') entry.level = child.attrs.level\n if (isTypedBlock(child)) entry.blockType = typeIdOf(child)\n const title = titleOf(child)\n if (title) entry.title = title\n entries.push(entry)\n const inner = walk(child)\n entry.chars = inner.chars\n if (inner.blocks.length) entry.children = inner.blocks\n chars += inner.chars\n blocks.push(id)\n }\n return { chars, blocks }\n }\n walk(content)\n return entries\n}\n\n/**\n * The read-only document tools of the document chat, for `EditorServerOptions.tools` / `provideEditorServer({ tools })`, next\n * to `createWorkspaceTools`:\n *\n * - `document_outline(documentId?)`: the tree of all Blocks of the open Document (or of another one the user may read): per\n * Block its ID, node type, heading level or Block type and title, the IDs of the Blocks directly inside it and the length of\n * its text;\n * - `read_blocks(documentId?, blockIds)`: up to 50 Blocks of one Document as Markdown, each cut like `read_block`\n * (`READ_BLOCK_LIMIT`), all together at most eight times that.\n *\n * Both read the current content (live content of an open Document first, else `loadCurrentContent`) and need no index. An\n * unreadable Document and an unknown Block answer the same sentence as `read_block`, so the tools never confirm that a\n * Document or Block exists where the user may not look.\n */\nexport function createDocumentTools(options: DocumentToolsOptions = {}): ToolProvider[] {\n let markdown = options.markdown\n const markdownOf = (): BlockMarkdown => markdown ??= createBlockMarkdown({\n ...(options.schema && { schema: options.schema }),\n ...(options.blockTypes && { blockTypes: options.blockTypes }),\n })\n\n const documentOutline: ToolProvider = {\n name: 'document_outline',\n tool: tool({\n description: 'Liefert die Gliederung eines Dokuments als JSON: alle Blöcke in Dokumentreihenfolge, je mit id, type (Knotentyp), level (bei Überschriften), blockType (bei typisierten Blöcken), title (Überschriftentext bzw. Titel des typisierten Blocks), children (IDs der direkt enthaltenen Blöcke) und chars (Textlänge in Zeichen, enthaltene Blöcke eingeschlossen). Ohne documentId das im Chat geöffnete Dokument in seinem aktuellen Stand; mit documentId ein anderes lesbares Dokument. Den Inhalt einzelner Blöcke liest du mit read_blocks.',\n inputSchema: jsonSchema<{ documentId?: string }>({\n type: 'object',\n properties: {\n documentId: { type: 'string', description: 'ID des Dokuments; ohne Angabe das geöffnete Dokument.' },\n },\n }),\n }),\n async handle(ctx, input) {\n const checked = parsed(outlineInput, input)\n if ('problem' in checked) return checked.problem\n const documentId = checked.value.documentId ?? ctx.documentId\n if (!documentId) return NO_DOCUMENT\n const content = await readableContent(ctx, documentId)\n // The same sentence for an unreadable and a missing Document: the tool never confirms that a Document exists the user may not read.\n if (!content) return `Das Dokument „${documentId}“ ist nicht lesbar oder existiert nicht.`\n const blocks = outlineOf(content)\n if (!blocks.length) return `Das Dokument „${documentId}“ hat keine Blöcke.`\n return JSON.stringify({ documentId, blocks })\n },\n }\n\n const readBlocks: ToolProvider = {\n name: 'read_blocks',\n tool: tool({\n description: `Liest Blöcke eines Dokuments als Markdown, bis zu ${READ_BLOCKS_MAX} auf einmal, in der angegebenen Reihenfolge. Ohne documentId aus dem im Chat geöffneten Dokument in seinem aktuellen Stand, mit documentId aus einem anderen lesbaren Dokument. Ein Block enthält die in ihm verschachtelten Blöcke. Block-IDs stammen aus document_outline oder find_blocks. Ein Block über ${READ_BLOCK_LIMIT} Zeichen wird gekürzt; ab ${READ_BLOCKS_TOTAL_LIMIT} Zeichen insgesamt werden die übrigen Blöcke ausgelassen und sind mit einem weiteren Aufruf zu lesen.`,\n inputSchema: jsonSchema<{ documentId?: string, blockIds: string[] }>({\n type: 'object',\n properties: {\n documentId: { type: 'string', description: 'ID des Dokuments; ohne Angabe das geöffnete Dokument.' },\n blockIds: { type: 'array', items: { type: 'string' }, minItems: 1, maxItems: READ_BLOCKS_MAX, description: 'IDs der Blöcke im Dokument.' },\n },\n required: ['blockIds'],\n }),\n }),\n async handle(ctx, input) {\n const checked = parsed(readBlocksInput, input)\n if ('problem' in checked) return checked.problem\n const documentId = checked.value.documentId ?? ctx.documentId\n if (!documentId) return NO_DOCUMENT\n const blockIds = [...new Set(checked.value.blockIds)]\n const content = await readableContent(ctx, documentId)\n const parts: string[] = []\n let total = 0\n for (const [i, blockId] of blockIds.entries()) {\n if (total >= READ_BLOCKS_TOTAL_LIMIT) {\n const rest = blockIds.slice(i)\n parts.push(`[… ${rest.length} weitere Blöcke ausgelassen, die Grenze von ${READ_BLOCKS_TOTAL_LIMIT} Zeichen ist erreicht: ${rest.join(', ')}]`)\n break\n }\n const node = content && findBlock(content, blockId)\n if (!node) {\n parts.push(unreadableBlock(documentId, blockId))\n continue\n }\n const title = titleOf(node)\n const head = `Dokument „${documentId}“, Block „${blockId}“ (${isTypedBlock(node) ? typeIdOf(node) : node.type ?? ''}${title ? `, ${title}` : ''}):`\n const body = markdownOf()([node]).trim()\n const shown = body.length > READ_BLOCK_LIMIT ? `${body.slice(0, READ_BLOCK_LIMIT)}\\n\\n[… gekürzt, ${body.length - READ_BLOCK_LIMIT} Zeichen fehlen]` : body\n total += Math.min(body.length, READ_BLOCK_LIMIT)\n parts.push(`${head}\\n\\n${shown}`)\n }\n return parts.join('\\n\\n---\\n\\n')\n },\n }\n\n return [documentOutline, readBlocks]\n}\n"],"mappings":"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"}
@@ -8,12 +8,12 @@ import { useEditorI18n } from "../../react/use-editor-i18n.js";
8
8
  import { Button } from "../../react/ui/button.js";
9
9
  import { useEditorSettings } from "../../react/settings.js";
10
10
  import { Input } from "../../react/ui/input.js";
11
+ import { DRAG_MIME, focusCrumbs, isOutlineHeader, itemBasket } from "../tree-items.js";
12
+ import { Collapsible, CollapsibleContent } from "../../react/ui/collapsible.js";
13
+ import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "../../react/ui/dropdown-menu.js";
11
14
  import { Popover, PopoverContent, PopoverTrigger } from "../../react/ui/popover.js";
12
15
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../../react/ui/tooltip.js";
13
- import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "../../react/ui/dropdown-menu.js";
14
16
  import { DocumentBadges } from "../../features/composites/react/DocumentBadges.js";
15
- import { DRAG_MIME, focusCrumbs, isOutlineHeader, itemBasket } from "../tree-items.js";
16
- import { Collapsible, CollapsibleContent } from "../../react/ui/collapsible.js";
17
17
  import { refocusRow, rowPosition } from "../row-focus.js";
18
18
  import { rowOf } from "../tree-model.js";
19
19
  import { useTreeModel } from "./use-tree-model.js";