[{"data":1,"prerenderedAt":3200},["ShallowReactive",2],{"navigation_docs":3,"-reference-feature-contract":412,"-reference-feature-contract-surround":3195},[4,38,84,326,386],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":37},"Getting started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20,24,28,32],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-book-open",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":6},"Quick start: Nuxt","\u002Fgetting-started\u002Fquick-start-nuxt","1.getting-started\u002F3.quick-start-nuxt",{"title":25,"path":26,"stem":27,"icon":6},"Quick start: plain Vue","\u002Fgetting-started\u002Fquick-start-vue","1.getting-started\u002F4.quick-start-vue",{"title":29,"path":30,"stem":31,"icon":6},"Quick start: React","\u002Fgetting-started\u002Fquick-start-react","1.getting-started\u002F5.quick-start-react",{"title":33,"path":34,"stem":35,"icon":36},"Glossary","\u002Fgetting-started\u002Fglossary","1.getting-started\u002F6.glossary","i-lucide-book-a",false,{"title":39,"icon":40,"path":41,"stem":42,"children":43,"page":37},"Tutorial","i-lucide-graduation-cap","\u002Ftutorial","2.tutorial",[44,49,54,59,64,69,74,79],{"title":45,"path":46,"stem":47,"icon":48},"Tutorial: overview","\u002Ftutorial\u002Foverview","2.tutorial\u002F1.overview","i-lucide-map",{"title":50,"path":51,"stem":52,"icon":53},"Chapter 2: A simple editor","\u002Ftutorial\u002Fsimple-editor","2.tutorial\u002F2.simple-editor","i-lucide-pencil",{"title":55,"path":56,"stem":57,"icon":58},"Chapter 3: Compose features","\u002Ftutorial\u002Fcompose-features","2.tutorial\u002F3.compose-features","i-lucide-blocks",{"title":60,"path":61,"stem":62,"icon":63},"Chapter 4: Your own block, path A","\u002Ftutorial\u002Fown-block-path-a","2.tutorial\u002F4.own-block-path-a","i-lucide-square-plus",{"title":65,"path":66,"stem":67,"icon":68},"Chapter 5: Your own feature, path B","\u002Ftutorial\u002Fown-feature-path-b","2.tutorial\u002F5.own-feature-path-b","i-lucide-puzzle",{"title":70,"path":71,"stem":72,"icon":73},"Chapter 6: Backend and collaboration","\u002Ftutorial\u002Fbackend-and-collaboration","2.tutorial\u002F6.backend-and-collaboration","i-lucide-users",{"title":75,"path":76,"stem":77,"icon":78},"Chapter 7: AI","\u002Ftutorial\u002Fai","2.tutorial\u002F7.ai","i-lucide-sparkles",{"title":80,"path":81,"stem":82,"icon":83},"Chapter 8: The React surface","\u002Ftutorial\u002Freact-surface","2.tutorial\u002F8.react-surface","i-lucide-atom",{"title":85,"icon":14,"path":86,"stem":87,"children":88,"page":37},"Guides","\u002Fguides","3.guides",[89,93,98,103,108,112,116,121,126,130,134,139,144,149,154,159,164,169,174,179,184,189,194,199,204,209,213,218,223,228,233,237,242,247,251,256,261,266,271,276,281,286,291,295,302,307,311,316,321],{"title":90,"path":91,"stem":92,"icon":58},"Feature composition and entries","\u002Fguides\u002Fcomposition","3.guides\u002F1.composition",{"title":94,"path":95,"stem":96,"icon":97},"Media, mentions and transcript features","\u002Fguides\u002Fmedia-mentions-transcript","3.guides\u002F10.media-mentions-transcript","i-lucide-image",{"title":99,"path":100,"stem":101,"icon":102},"Authors and comments","\u002Fguides\u002Fauthors-and-comments","3.guides\u002F11.authors-and-comments","i-lucide-message-square-text",{"title":104,"path":105,"stem":106,"icon":107},"Themes (Obsidian)","\u002Fguides\u002Fthemes","3.guides\u002F12.themes","i-lucide-palette",{"title":109,"path":110,"stem":111,"icon":58},"Composites and the settings UI","\u002Fguides\u002Fcomposites","3.guides\u002F13.composites",{"title":113,"path":114,"stem":115,"icon":78},"AI","\u002Fguides\u002Fai","3.guides\u002F14.ai",{"title":117,"path":118,"stem":119,"icon":120},"Document tree","\u002Fguides\u002Fdocument-tree","3.guides\u002F15.document-tree","i-lucide-folder-tree",{"title":122,"path":123,"stem":124,"icon":125},"Markdown and code","\u002Fguides\u002Fmarkdown-and-code","3.guides\u002F16.markdown-and-code","i-lucide-file-code",{"title":127,"path":128,"stem":129,"icon":83},"Advanced editor in React","\u002Fguides\u002Fadvanced-react","3.guides\u002F17.advanced-react",{"title":131,"path":132,"stem":133,"icon":6},"Kitchen sink: learning path","\u002Fguides\u002Fadvanced-nuxt-example","3.guides\u002F18.advanced-nuxt-example",{"title":135,"path":136,"stem":137,"icon":138},"Production","\u002Fguides\u002Fproduction","3.guides\u002F19.production","i-lucide-server",{"title":140,"path":141,"stem":142,"icon":143},"Register the Nuxt module","\u002Fguides\u002Fnuxt-module","3.guides\u002F2.nuxt-module","i-lucide-package",{"title":145,"path":146,"stem":147,"icon":148},"Storage adapters, comment stores, Nitro host","\u002Fguides\u002Fstorage-adapters","3.guides\u002F20.storage-adapters","i-lucide-database",{"title":150,"path":151,"stem":152,"icon":153},"Migrating from #tiptap-editor","\u002Fguides\u002Fmigration","3.guides\u002F21.migration","i-lucide-arrow-right-left",{"title":155,"path":156,"stem":157,"icon":158},"Content tree mechanics","\u002Fguides\u002Fcontent-tree","3.guides\u002F22.content-tree","i-lucide-git-fork",{"title":160,"path":161,"stem":162,"icon":163},"Block capabilities, abilities and actions","\u002Fguides\u002Fblock-capabilities","3.guides\u002F23.block-capabilities","i-lucide-shield-check",{"title":165,"path":166,"stem":167,"icon":168},"Block types in code and JSON","\u002Fguides\u002Fblock-types","3.guides\u002F24.block-types","i-lucide-shapes",{"title":170,"path":171,"stem":172,"icon":173},"Derive methods and the Derivation index","\u002Fguides\u002Fderive-methods","3.guides\u002F25.derive-methods","i-lucide-git-branch-plus",{"title":175,"path":176,"stem":177,"icon":178},"Block properties and Property definitions","\u002Fguides\u002Fblock-properties","3.guides\u002F26.block-properties","i-lucide-sliders-horizontal",{"title":180,"path":181,"stem":182,"icon":183},"Image studio","\u002Fguides\u002Fimage-studio","3.guides\u002F27.image-studio","i-lucide-image-plus",{"title":185,"path":186,"stem":187,"icon":188},"Prüfung and Freigabestatus","\u002Fguides\u002Fpruefung","3.guides\u002F28.pruefung","i-lucide-stamp",{"title":190,"path":191,"stem":192,"icon":193},"Workspace: find, read, reference and embed Blocks across Documents","\u002Fguides\u002Fworkspace","3.guides\u002F29.workspace","i-lucide-network",{"title":195,"path":196,"stem":197,"icon":198},"EditorPorts: auth and storage","\u002Fguides\u002Feditor-ports","3.guides\u002F3.editor-ports","i-lucide-plug",{"title":200,"path":201,"stem":202,"icon":203},"Collections: an ordered list of Blocks","\u002Fguides\u002Fcollections","3.guides\u002F30.collections","i-lucide-list-checks",{"title":205,"path":206,"stem":207,"icon":208},"Data views: a query shown as table, list or board","\u002Fguides\u002Fdata-views","3.guides\u002F31.data-views","i-lucide-table-properties",{"title":210,"path":211,"stem":212,"icon":193},"Explore: backlinks, related Blocks and the trail","\u002Fguides\u002Fexplore","3.guides\u002F32.explore",{"title":214,"path":215,"stem":216,"icon":217},"Render: export a Block or a Document to a file","\u002Fguides\u002Frender","3.guides\u002F33.render","i-lucide-file-output",{"title":219,"path":220,"stem":221,"icon":222},"Importers: what a dropped file becomes","\u002Fguides\u002Fimporters","3.guides\u002F34.importers","i-lucide-file-input",{"title":224,"path":225,"stem":226,"icon":227},"Templates: start a Document from a Dokumentvorlage","\u002Fguides\u002Ftemplates","3.guides\u002F35.templates","i-lucide-file-stack",{"title":229,"path":230,"stem":231,"icon":232},"Citations","\u002Fguides\u002Fcitations","3.guides\u002F36.citations","i-lucide-quote",{"title":234,"path":235,"stem":236,"icon":163},"AI proposals and the export check","\u002Fguides\u002Fexport-check","3.guides\u002F37.export-check",{"title":238,"path":239,"stem":240,"icon":241},"Query: filter, sort, group and total Blocks","\u002Fguides\u002Fquery","3.guides\u002F38.query","i-lucide-list-filter",{"title":243,"path":244,"stem":245,"icon":246},"Edges: backlinks and authored connections","\u002Fguides\u002Fedges","3.guides\u002F39.edges","i-lucide-link-2",{"title":248,"path":249,"stem":250,"icon":163},"Server routes and authentication","\u002Fguides\u002Froutes-and-auth","3.guides\u002F4.routes-and-auth",{"title":252,"path":253,"stem":254,"icon":255},"Speech: text to audio, and subtitle files","\u002Fguides\u002Fspeech","3.guides\u002F41.speech","i-lucide-audio-lines",{"title":257,"path":258,"stem":259,"icon":260},"Graph: the Edges around a Block","\u002Fguides\u002Fgraph","3.guides\u002F42.graph","i-lucide-waypoints",{"title":262,"path":263,"stem":264,"icon":265},"PDF viewer: passages, anchors and quotes","\u002Fguides\u002Fpdf-viewer","3.guides\u002F43.pdf-viewer","i-lucide-file-search",{"title":267,"path":268,"stem":269,"icon":270},"Obsidian: import and export a vault","\u002Fguides\u002Fobsidian","3.guides\u002F44.obsidian","i-lucide-folder-input",{"title":272,"path":273,"stem":274,"icon":275},"Typst: render a Document as a PDF with citations","\u002Fguides\u002Ftypst","3.guides\u002F45.typst","i-lucide-file-text",{"title":277,"path":278,"stem":279,"icon":280},"Audio: read aloud, mixdown and ElevenLabs","\u002Fguides\u002Faudio","3.guides\u002F46.audio","i-lucide-audio-waveform",{"title":282,"path":283,"stem":284,"icon":285},"Slides: decks, slide layouts and exports","\u002Fguides\u002Fslides","3.guides\u002F47.slides","i-lucide-presentation",{"title":287,"path":288,"stem":289,"icon":290},"Knowledge graph: sources and concepts beside the Documents","\u002Fguides\u002Fknowledge-graph","3.guides\u002F49.knowledge-graph","i-lucide-share-2",{"title":292,"path":293,"stem":294,"icon":78},"AI configuration and secrets","\u002Fguides\u002Fai-configuration","3.guides\u002F5.ai-configuration",{"title":296,"path":297,"stem":298,"children":299,"icon":301},"Index on Postgres: typos, meaning and SQL pushdown","\u002Fguides\u002Findex-pg","3.guides\u002F50.index-pg",[300],{"title":296,"path":297,"stem":298,"icon":301},"i-lucide-database-zap",{"title":303,"path":304,"stem":305,"icon":306},"Charts: bar, line, pie and scatter over a query","\u002Fguides\u002Fcharts","3.guides\u002F51.charts","i-lucide-chart-column",{"title":308,"path":309,"stem":310,"icon":73},"Collaboration on the client","\u002Fguides\u002Fcollaboration","3.guides\u002F6.collaboration",{"title":312,"path":313,"stem":314,"icon":315},"Block UI (drag handle, hover actions)","\u002Fguides\u002Fblock-ui","3.guides\u002F7.block-ui","i-lucide-grip-vertical",{"title":317,"path":318,"stem":319,"icon":320},"Settings and app lifetime","\u002Fguides\u002Fsettings","3.guides\u002F8.settings","i-lucide-settings",{"title":322,"path":323,"stem":324,"icon":325},"Language","\u002Fguides\u002Flanguage","3.guides\u002F9.language","i-lucide-languages",{"title":327,"icon":14,"path":328,"stem":329,"children":330,"page":37},"Reference","\u002Freference","4.reference",[331,335,339,344,348,352,356,360,364,368,373,378,382],{"title":332,"path":333,"stem":334,"icon":143},"Public exports","\u002Freference\u002Fexports","4.reference\u002F1.exports",{"title":336,"path":337,"stem":338,"icon":173},"Derive method contract","\u002Freference\u002Fderive-methods","4.reference\u002F10.derive-methods",{"title":340,"path":341,"stem":342,"icon":343},"Changelog","\u002Freference\u002Fchangelog","4.reference\u002F11.changelog","i-lucide-history",{"title":345,"path":346,"stem":347,"icon":217},"Renderer port","\u002Freference\u002Frenderer-port","4.reference\u002F12.renderer-port",{"title":349,"path":350,"stem":351,"icon":255},"Speech port","\u002Freference\u002Fspeech-port","4.reference\u002F13.speech-port",{"title":353,"path":354,"stem":355,"icon":58},"Presets and features","\u002Freference\u002Fpresets-and-features","4.reference\u002F2.presets-and-features",{"title":357,"path":358,"stem":359,"icon":68},"Feature contract","\u002Freference\u002Ffeature-contract","4.reference\u002F3.feature-contract",{"title":361,"path":362,"stem":363,"icon":107},"CSS and UI-provider requirements","\u002Freference\u002Fcss-and-ui","4.reference\u002F4.css-and-ui",{"title":365,"path":366,"stem":367,"icon":148},"Vue-free advanced schema","\u002Freference\u002Fadvanced-schema","4.reference\u002F5.advanced-schema",{"title":369,"path":370,"stem":371,"icon":372},"Dependency rules","\u002Freference\u002Fdependency-rules","4.reference\u002F6.dependency-rules","i-lucide-git-branch",{"title":374,"path":375,"stem":376,"icon":377},"Commands","\u002Freference\u002Fcommands","4.reference\u002F7.commands","i-lucide-terminal",{"title":379,"path":380,"stem":381,"icon":163},"Block capability contract","\u002Freference\u002Fblock-capabilities","4.reference\u002F8.block-capabilities",{"title":383,"path":384,"stem":385,"icon":168},"Block type contract","\u002Freference\u002Fblock-types","4.reference\u002F9.block-types",{"title":387,"path":388,"stem":389,"children":390,"icon":393},"AI agents","\u002Fai-agents","5.ai-agents\u002F1.index",[391,394,398,402,407],{"title":392,"path":388,"stem":389,"icon":393},"Overview","i-lucide-bot",{"title":395,"path":396,"stem":397,"icon":198},"Integrate the editor","\u002Fai-agents\u002Fintegrate","5.ai-agents\u002F2.integrate",{"title":399,"path":400,"stem":401,"icon":68},"Add a block or feature","\u002Fai-agents\u002Fextend","5.ai-agents\u002F3.extend",{"title":403,"path":404,"stem":405,"icon":406},"Pitfalls and invariants","\u002Fai-agents\u002Finvariants","5.ai-agents\u002F4.invariants","i-lucide-shield-alert",{"title":408,"path":409,"stem":410,"icon":411},"Verify","\u002Fai-agents\u002Fverify","5.ai-agents\u002F5.verify","i-lucide-check-check",{"id":413,"title":357,"body":414,"description":3188,"extension":3189,"links":3190,"meta":3191,"navigation":3192,"path":358,"seo":3193,"stem":359,"__hash__":3194},"docs\u002F4.reference\u002F3.feature-contract.md",{"type":415,"value":416,"toc":3178},"minimark",[417,426,433,972,975,1313,1319,1335,1653,1659,1742,1750,1756,1811,1837,1933,1941,2560,2802,2805,2920,2924,3149,3174],[418,419,420,421,425],"p",{},"A feature is an object whose optional members are the contribution points. Fill only what you need. The types below come straight from ",[422,423,424],"code",{},"packages\u002Feditor\u002Fsrc\u002Fcore\u002Ffeature.ts",".",[427,428,430],"h2",{"id":429},"editorfeature",[422,431,432],{},"EditorFeature",[434,435,440],"pre",{"className":436,"code":437,"filename":424,"language":438,"meta":439,"style":439},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight"," *\u002F\nexport type Dimension = 'content' | 'interaction' | 'ai'\n\n\u002F** One named contribution to an editor (blocks, toolbar entries, menus, settings, AI knowledge). Every member is optional but `dimension`; identity and ordering come from the feature list. *\u002F\nexport interface EditorFeature\u003CC = unknown> {\n  id: string\n  \u002F** The feature's primary dimension. *\u002F\n  dimension: Dimension\n  \u002F**\n   * The Vue-free schema-bearing extensions of this feature (no node views, no UI), collected by `schemaExtensionsOf` for\n   * the server schema. Present on every feature whose nodes or marks the stored document can contain.\n   *\u002F\n  schemaExtensions?: () => AnyExtension[]\n  \u002F** Ids of features that must also be installed (`defineEditor` does not install them). *\u002F\n  requires?: readonly string[]\n  \u002F** Backend capabilities the feature cannot work without; a surface session over a backend lacking one throws. Optional capabilities (users and tags for mentions) are not listed. *\u002F\n  backend?: readonly BackendCapability[]\n  extensions?: (ctx: FeatureContext) => AnyExtension[]\n  blockActions?: (ctx: FeatureContext) => BlockAction[]\n  \u002F**\n   * Block capabilities the feature declares (`container` and `title` are built in): descriptors of what a block is, which a\n   * `BlockAction.requires` names and `capabilitiesAt` answers. Ids are unique across features. A capability installs nothing:\n   * schema, extensions and node views stay with the feature that owns the mechanism.\n   *\u002F\n  blockCapabilities?: readonly BlockCapability[]\n  \u002F**\n   * Ways to make a new block or text from a block (transcription, text extraction, summary, AI fill, AI derivation, bibliography fetch):\n   * one registry across all features, each method declaring the capabilities the original must have (`requires`) and its backend\n   * flags (`available`). The block actions of the methods are generated from it. Ids are unique across features and every\n   * `requires` id must be a declared capability; `defineEditor` throws otherwise.\n   *\u002F\n  deriveMethods?: readonly DeriveMethod[]\n  \u002F**\n   * The Block types the feature's editor offers: data (an id and the capabilities each type lists with their config) the capability\n   * registry answers from. Additive: the contributions of all features concatenate in feature order. An editor created from the preset\n   * checks them against the declared capabilities (`validateBlockTypes`): an unknown capability id or an invalid config throws. Block\n   * types are per editor (the composites feature builds its defaults in the surface's language).\n   *\u002F\n  blockTypes?: (editor: Editor) => readonly BlockTypeData[]\n  \u002F**\n   * Options of the block UI (`BlockUiOptions`: which surfaces render block actions). Set by the block-ui feature; the\n   * overlay components are mounted by the surface without props, so they read it from the editor entry (`EditorEntry.blockUi`).\n   *\u002F\n  blockUi?: Readonly\u003CBlockUiOptions>\n  \u002F** The feature's commands, each declared once with its toolbar and `\u002F` placements (see `CommandDef`). *\u002F\n  commands?: (ctx: FeatureContext) => CommandDef\u003CC>[]\n  \u002F** Toolbar groups the feature declares; every command's `toolbar.group` must be declared by some feature. Ids are unique across features. *\u002F\n  toolbarGroups?: ToolbarGroupDef[]\n  \u002F** Rules a command's `creates` must pass at the caret besides the schema (e.g. a Typed block's accepted children). *\u002F\n","ts","",[422,441,442,451,499,506,513,541,554,560,571,577,583,589,595,617,623,639,645,660,689,714,719,725,731,737,742,757,762,768,774,780,786,791,806,811,817,823,829,835,840,869,874,880,886,891,910,916,947,953,966],{"__ignoreMap":439},[443,444,447],"span",{"class":445,"line":446},"line",1,[443,448,450],{"class":449},"sMK4o"," *\u002F\n",[443,452,454,458,462,466,469,472,476,479,482,484,487,489,491,493,496],{"class":445,"line":453},2,[443,455,457],{"class":456},"s7zQu","export",[443,459,461],{"class":460},"spNyl"," type",[443,463,465],{"class":464},"sBMFI"," Dimension",[443,467,468],{"class":449}," =",[443,470,471],{"class":449}," '",[443,473,475],{"class":474},"sfazB","content",[443,477,478],{"class":449},"'",[443,480,481],{"class":449}," |",[443,483,471],{"class":449},[443,485,486],{"class":474},"interaction",[443,488,478],{"class":449},[443,490,481],{"class":449},[443,492,471],{"class":449},[443,494,495],{"class":474},"ai",[443,497,498],{"class":449},"'\n",[443,500,502],{"class":445,"line":501},3,[443,503,505],{"emptyLinePlaceholder":504},true,"\n",[443,507,509],{"class":445,"line":508},4,[443,510,512],{"class":511},"sHwdD","\u002F** One named contribution to an editor (blocks, toolbar entries, menus, settings, AI knowledge). Every member is optional but `dimension`; identity and ordering come from the feature list. *\u002F\n",[443,514,516,518,521,524,527,530,532,535,538],{"class":445,"line":515},5,[443,517,457],{"class":456},[443,519,520],{"class":460}," interface",[443,522,523],{"class":464}," EditorFeature",[443,525,526],{"class":449},"\u003C",[443,528,529],{"class":464},"C",[443,531,468],{"class":449},[443,533,534],{"class":464}," unknown",[443,536,537],{"class":449},">",[443,539,540],{"class":449}," {\n",[443,542,544,548,551],{"class":445,"line":543},6,[443,545,547],{"class":546},"swJcz","  id",[443,549,550],{"class":449},":",[443,552,553],{"class":464}," string\n",[443,555,557],{"class":445,"line":556},7,[443,558,559],{"class":511},"  \u002F** The feature's primary dimension. *\u002F\n",[443,561,563,566,568],{"class":445,"line":562},8,[443,564,565],{"class":546},"  dimension",[443,567,550],{"class":449},[443,569,570],{"class":464}," Dimension\n",[443,572,574],{"class":445,"line":573},9,[443,575,576],{"class":511},"  \u002F**\n",[443,578,580],{"class":445,"line":579},10,[443,581,582],{"class":511},"   * The Vue-free schema-bearing extensions of this feature (no node views, no UI), collected by `schemaExtensionsOf` for\n",[443,584,586],{"class":445,"line":585},11,[443,587,588],{"class":511},"   * the server schema. Present on every feature whose nodes or marks the stored document can contain.\n",[443,590,592],{"class":445,"line":591},12,[443,593,594],{"class":511},"   *\u002F\n",[443,596,598,601,604,607,610,613],{"class":445,"line":597},13,[443,599,600],{"class":546},"  schemaExtensions",[443,602,603],{"class":449},"?:",[443,605,606],{"class":449}," ()",[443,608,609],{"class":460}," =>",[443,611,612],{"class":464}," AnyExtension",[443,614,616],{"class":615},"sTEyZ","[]\n",[443,618,620],{"class":445,"line":619},14,[443,621,622],{"class":511},"  \u002F** Ids of features that must also be installed (`defineEditor` does not install them). *\u002F\n",[443,624,626,629,631,634,637],{"class":445,"line":625},15,[443,627,628],{"class":546},"  requires",[443,630,603],{"class":449},[443,632,633],{"class":460}," readonly",[443,635,636],{"class":464}," string",[443,638,616],{"class":615},[443,640,642],{"class":445,"line":641},16,[443,643,644],{"class":511},"  \u002F** Backend capabilities the feature cannot work without; a surface session over a backend lacking one throws. Optional capabilities (users and tags for mentions) are not listed. *\u002F\n",[443,646,648,651,653,655,658],{"class":445,"line":647},17,[443,649,650],{"class":546},"  backend",[443,652,603],{"class":449},[443,654,633],{"class":460},[443,656,657],{"class":464}," BackendCapability",[443,659,616],{"class":615},[443,661,663,666,668,671,675,677,680,683,685,687],{"class":445,"line":662},18,[443,664,665],{"class":546},"  extensions",[443,667,603],{"class":449},[443,669,670],{"class":449}," (",[443,672,674],{"class":673},"sHdIc","ctx",[443,676,550],{"class":449},[443,678,679],{"class":464}," FeatureContext",[443,681,682],{"class":449},")",[443,684,609],{"class":460},[443,686,612],{"class":464},[443,688,616],{"class":615},[443,690,692,695,697,699,701,703,705,707,709,712],{"class":445,"line":691},19,[443,693,694],{"class":546},"  blockActions",[443,696,603],{"class":449},[443,698,670],{"class":449},[443,700,674],{"class":673},[443,702,550],{"class":449},[443,704,679],{"class":464},[443,706,682],{"class":449},[443,708,609],{"class":460},[443,710,711],{"class":464}," BlockAction",[443,713,616],{"class":615},[443,715,717],{"class":445,"line":716},20,[443,718,576],{"class":511},[443,720,722],{"class":445,"line":721},21,[443,723,724],{"class":511},"   * Block capabilities the feature declares (`container` and `title` are built in): descriptors of what a block is, which a\n",[443,726,728],{"class":445,"line":727},22,[443,729,730],{"class":511},"   * `BlockAction.requires` names and `capabilitiesAt` answers. Ids are unique across features. A capability installs nothing:\n",[443,732,734],{"class":445,"line":733},23,[443,735,736],{"class":511},"   * schema, extensions and node views stay with the feature that owns the mechanism.\n",[443,738,740],{"class":445,"line":739},24,[443,741,594],{"class":511},[443,743,745,748,750,752,755],{"class":445,"line":744},25,[443,746,747],{"class":546},"  blockCapabilities",[443,749,603],{"class":449},[443,751,633],{"class":460},[443,753,754],{"class":464}," BlockCapability",[443,756,616],{"class":615},[443,758,760],{"class":445,"line":759},26,[443,761,576],{"class":511},[443,763,765],{"class":445,"line":764},27,[443,766,767],{"class":511},"   * Ways to make a new block or text from a block (transcription, text extraction, summary, AI fill, AI derivation, bibliography fetch):\n",[443,769,771],{"class":445,"line":770},28,[443,772,773],{"class":511},"   * one registry across all features, each method declaring the capabilities the original must have (`requires`) and its backend\n",[443,775,777],{"class":445,"line":776},29,[443,778,779],{"class":511},"   * flags (`available`). The block actions of the methods are generated from it. Ids are unique across features and every\n",[443,781,783],{"class":445,"line":782},30,[443,784,785],{"class":511},"   * `requires` id must be a declared capability; `defineEditor` throws otherwise.\n",[443,787,789],{"class":445,"line":788},31,[443,790,594],{"class":511},[443,792,794,797,799,801,804],{"class":445,"line":793},32,[443,795,796],{"class":546},"  deriveMethods",[443,798,603],{"class":449},[443,800,633],{"class":460},[443,802,803],{"class":464}," DeriveMethod",[443,805,616],{"class":615},[443,807,809],{"class":445,"line":808},33,[443,810,576],{"class":511},[443,812,814],{"class":445,"line":813},34,[443,815,816],{"class":511},"   * The Block types the feature's editor offers: data (an id and the capabilities each type lists with their config) the capability\n",[443,818,820],{"class":445,"line":819},35,[443,821,822],{"class":511},"   * registry answers from. Additive: the contributions of all features concatenate in feature order. An editor created from the preset\n",[443,824,826],{"class":445,"line":825},36,[443,827,828],{"class":511},"   * checks them against the declared capabilities (`validateBlockTypes`): an unknown capability id or an invalid config throws. Block\n",[443,830,832],{"class":445,"line":831},37,[443,833,834],{"class":511},"   * types are per editor (the composites feature builds its defaults in the surface's language).\n",[443,836,838],{"class":445,"line":837},38,[443,839,594],{"class":511},[443,841,843,846,848,850,853,855,858,860,862,864,867],{"class":445,"line":842},39,[443,844,845],{"class":546},"  blockTypes",[443,847,603],{"class":449},[443,849,670],{"class":449},[443,851,852],{"class":673},"editor",[443,854,550],{"class":449},[443,856,857],{"class":464}," Editor",[443,859,682],{"class":449},[443,861,609],{"class":460},[443,863,633],{"class":460},[443,865,866],{"class":464}," BlockTypeData",[443,868,616],{"class":615},[443,870,872],{"class":445,"line":871},40,[443,873,576],{"class":511},[443,875,877],{"class":445,"line":876},41,[443,878,879],{"class":511},"   * Options of the block UI (`BlockUiOptions`: which surfaces render block actions). Set by the block-ui feature; the\n",[443,881,883],{"class":445,"line":882},42,[443,884,885],{"class":511},"   * overlay components are mounted by the surface without props, so they read it from the editor entry (`EditorEntry.blockUi`).\n",[443,887,889],{"class":445,"line":888},43,[443,890,594],{"class":511},[443,892,894,897,899,902,904,907],{"class":445,"line":893},44,[443,895,896],{"class":546},"  blockUi",[443,898,603],{"class":449},[443,900,901],{"class":464}," Readonly",[443,903,526],{"class":449},[443,905,906],{"class":464},"BlockUiOptions",[443,908,909],{"class":449},">\n",[443,911,913],{"class":445,"line":912},45,[443,914,915],{"class":511},"  \u002F** The feature's commands, each declared once with its toolbar and `\u002F` placements (see `CommandDef`). *\u002F\n",[443,917,919,922,924,926,928,930,932,934,936,939,941,943,945],{"class":445,"line":918},46,[443,920,921],{"class":546},"  commands",[443,923,603],{"class":449},[443,925,670],{"class":449},[443,927,674],{"class":673},[443,929,550],{"class":449},[443,931,679],{"class":464},[443,933,682],{"class":449},[443,935,609],{"class":460},[443,937,938],{"class":464}," CommandDef",[443,940,526],{"class":449},[443,942,529],{"class":464},[443,944,537],{"class":449},[443,946,616],{"class":615},[443,948,950],{"class":445,"line":949},47,[443,951,952],{"class":511},"  \u002F** Toolbar groups the feature declares; every command's `toolbar.group` must be declared by some feature. Ids are unique across features. *\u002F\n",[443,954,956,959,961,964],{"class":445,"line":955},48,[443,957,958],{"class":546},"  toolbarGroups",[443,960,603],{"class":449},[443,962,963],{"class":464}," ToolbarGroupDef",[443,965,616],{"class":615},[443,967,969],{"class":445,"line":968},49,[443,970,971],{"class":511},"  \u002F** Rules a command's `creates` must pass at the caret besides the schema (e.g. a Typed block's accepted children). *\u002F\n",[418,973,974],{},"The members at a glance:",[976,977,978,991],"table",{},[979,980,981],"thead",{},[982,983,984,988],"tr",{},[985,986,987],"th",{},"Member",[985,989,990],{},"Contributes",[992,993,994,1005,1045,1066,1114,1135,1160,1180,1197,1216,1247,1264,1277,1293,1303],"tbody",{},[982,995,996,1002],{},[997,998,999],"td",{},[422,1000,1001],{},"extensions(ctx)",[997,1003,1004],{},"TipTap extensions (nodes, marks, plugins)",[982,1006,1007,1019],{},[997,1008,1009,1012,1013,1012,1016],{},[422,1010,1011],{},"commands(ctx)",", ",[422,1014,1015],{},"toolbarGroups",[422,1017,1018],{},"insertGuards(ctx)",[997,1020,1021,1024,1025,1028,1029,1032,1033,1036,1037,1040,1041,1044],{},[422,1022,1023],{},"CommandDef[]"," declared once with ",[422,1026,1027],{},"toolbar"," and ",[422,1030,1031],{},"slash"," placements (toolbar, ",[422,1034,1035],{},"\u002F"," menu, ⌘K palette, enabled\u002Fvisible state via ",[422,1038,1039],{},"commandState","), the groups they name, and guards a ",[422,1042,1043],{},"creates"," command must pass (e.g. a Typed block's Accepted children)",[982,1046,1047,1052],{},[997,1048,1049],{},[422,1050,1051],{},"transactionGuards(ctx)",[997,1053,1054,1057,1058,1061,1062,1065],{},[422,1055,1056],{},"TransactionGuard[]",": ",[422,1059,1060],{},"(tr, state) => true | string",", run in feature order for every transaction that changes the document (not for selection-only ones). The first string refuses the whole transaction and is shown as the notice. For rules no schema expresses (a locked paragraph, a required document shape); ",[422,1063,1064],{},"insertGuards"," only gate commands",[982,1067,1068,1073],{},[997,1069,1070],{},[422,1071,1072],{},"blockActions(ctx)",[997,1074,1075,1076,1079,1080,1083,1084,1087,1088,1091,1092,1095,1096,1091,1099,1102,1103,1106,1107,1012,1110,1113],{},"block actions (shown by ",[422,1077,1078],{},"block-ui",": hover bar, selected-block toolbar or both, per ",[422,1081,1082],{},"BlockUiOptions.actions","); ",[422,1085,1086],{},"ability"," unset = every block; ",[422,1089,1090],{},"placement: 'hover' | 'toolbar' | 'both'"," (default ",[422,1093,1094],{},"'both'",") narrows the surface; ",[422,1097,1098],{},"target: 'block' | 'typedBlock'",[422,1100,1101],{},"'block'","): with ",[422,1104,1105],{},"'typedBlock'"," the toolbar evaluates the action against the Typed block around the selected block (",[422,1108,1109],{},"ctx.node",[422,1111,1112],{},"ctx.pos"," are the Typed block's), absent when none encloses it",[982,1115,1116,1121],{},[997,1117,1118],{},[422,1119,1120],{},"overlays",[997,1122,1123,1124,1127,1128,1131,1132],{},"framework components (",[422,1125,1126],{},"EditorFeature\u003CC>","; Vue: ",[422,1129,1130],{},"VueFeature",") mounted beside the content, receiving ",[422,1133,1134],{},"{ editor }",[982,1136,1137,1142],{},[997,1138,1139],{},[422,1140,1141],{},"rowBadges(ctx)",[997,1143,1144,1147,1148,1151,1152,1155,1156,1159],{},[422,1145,1146],{},"RowBadge[]",": chips after the title of a Typed block in the composites chrome, additive in feature order (",[422,1149,1150],{},"of(editor, row)"," returns ",[422,1153,1154],{},"{ label, tone } | null","; optional ",[422,1157,1158],{},"subscribe"," for changes outside the editor's transactions). The Prüfung feature draws „Geprüft“ \u002F „Prüfung veraltet“ this way",[982,1161,1162,1167],{},[997,1163,1164],{},[422,1165,1166],{},"documentBadges(ctx)",[997,1168,1169,1172,1173,1176,1177,1179],{},[422,1170,1171],{},"DocumentBadge[]",": chips of the whole document, drawn after the „Dokument“ heading of the inspector and on the open document's row of the Block outline in the Document tree (",[422,1174,1175],{},"of(editor)",", optional ",[422,1178,1158],{},"). The Prüfung feature draws the Freigabestatus this way",[982,1181,1182,1187],{},[997,1183,1184],{},[422,1185,1186],{},"inspectorSections(ctx)",[997,1188,1189,1192,1193,1196],{},[422,1190,1191],{},"InspectorSection\u003CC>[]",": sections of the Typed block inspector and details card below the block's fields, additive in feature order (",[422,1194,1195],{},"{ id, title, component, appliesTo? }","; ids unique). The Prüfung feature adds „Prüfstand“",[982,1198,1199,1204],{},[997,1200,1201],{},[422,1202,1203],{},"setup(ctx)",[997,1205,1206,1207,1210,1211,1215],{},"per-surface side effect when the surface mounts (runtime, listener, ",[422,1208,1209],{},"\u003Chead>"," element); returns an optional ",[1212,1213,1214],"strong",{},"teardown"," the surface runs when it unmounts",[982,1217,1218,1223],{},[997,1219,1220],{},[422,1221,1222],{},"settingsTabs",[997,1224,1225,1226,1229,1230,1035,1233,670,1236,1057,1239,1242,1243,1246],{},"factory ",[422,1227,1228],{},"(ctx: EditorContext) => SettingsTab\u003CC>[]"," for the tabs of ",[422,1231,1232],{},"EditorSettingsPanel",[422,1234,1235],{},"EditorSettingsModal",[422,1237,1238],{},"SettingsTab\u003CC>",[422,1240,1241],{},"label"," is already translated, the ",[422,1244,1245],{},"component"," slot is the framework's component type)",[982,1248,1249,1254],{},[997,1250,1251],{},[422,1252,1253],{},"metadataDefaults(ctx)",[997,1255,1256,1257,1035,1260,1263],{},"built-in ",[422,1258,1259],{},"@",[422,1261,1262],{},"#","-style lists",[982,1265,1266,1274],{},[997,1267,1268,1012,1271],{},[422,1269,1270],{},"blocks",[422,1272,1273],{},"conversions",[997,1275,1276],{},"block pipeline stages, „Umwandeln in …“ providers",[982,1278,1279,1290],{},[997,1280,1281,1012,1284,1012,1287],{},[422,1282,1283],{},"anchorResolver",[422,1285,1286],{},"aiContext",[422,1288,1289],{},"formatAiResult",[997,1291,1292],{},"collaboration positions, what AI knows about the document, AI result formatting",[982,1294,1295,1300],{},[997,1296,1297],{},[422,1298,1299],{},"aiBlockData",[997,1301,1302],{},"material per Typed block for „Block füllen (KI)“ (additive; the host owns the fetch)",[982,1304,1305,1310],{},[997,1306,1307],{},[422,1308,1309],{},"requires",[997,1311,1312],{},"ids of features that must also be listed",[427,1314,1316],{"id":1315},"featurecontext",[422,1317,1318],{},"FeatureContext",[418,1320,1321,1322,1012,1325,1012,1328,1331,1332,1334],{},"Every factory (",[422,1323,1324],{},"extensions",[422,1326,1327],{},"commands",[422,1329,1330],{},"blockActions",", …) receives the ",[422,1333,1318],{}," of the surface it runs on. It is created when a surface is set up and never shared between editors.",[434,1336,1338],{"className":436,"code":1337,"filename":424,"language":438,"meta":439,"style":439},"  stopUndoCapture: (state: EditorState) => boolean\n}\n\n\u002F** Per-surface dependencies of a feature's factories. Created when a surface is set up; never shared between editors. *\u002F\nexport interface FeatureContext {\n  \u002F** The app context the surface belongs to (shared by all editors of the app): app-level models key on it. *\u002F\n  readonly app: EditorContext\n  \u002F** The app's shared settings (see `createEditorContext`): read with `get()`, write with `update()`, observe with `subscribe()`. *\u002F\n  readonly settings: Store\u003CEditorSettings>\n  readonly metadata: MetadataRegistry\n  \u002F** Chrome of the editor this context belongs to (settings, sidebar). *\u002F\n  readonly ui: EditorUi\n  \u002F** Shows a notice through the surface's framework (Nuxt UI toast, sonner). *\u002F\n  readonly notify: Notifier\n  \u002F** The app's UI language (`createEditorContext({ locale })`). *\u002F\n  readonly locale: Locale\n  \u002F** Renders a catalog message in the app's language; every label a feature contributes goes through it. *\u002F\n  readonly t: Translate\n  \u002F** The data layer of the app (`createEditorContext({ backend })`): uploads, mention lookups, themes, AI. *\u002F\n  readonly backend: EditorBackend\n  \u002F** Inert public AI configuration of the app context; absent when none was supplied. *\u002F\n  readonly ai: EditorAiConfig | undefined\n  \u002F** Document whose package stores uploads (media feature). *\u002F\n  readonly documentId: string | undefined\n  readonly collaboration: CollaborationSession | undefined\n  \u002F** The collaboration-aware position mapping of the preset's `anchorResolver` feature; null means local mapping only. *\u002F\n  readonly anchorResolver: AnchorResolver | null\n  \u002F** Host options for the ability extension (`abilities` prop). *\u002F\n  readonly abilities: Partial\u003CAbilitiesOptions>\n  \u002F** The final command list: the features' commands after the host's `commands` transformer. The `\u002F` menu lists the ones with a `slash` placement. *\u002F\n  readonly commands: () => CommandDef[]\n",[422,1339,1340,1364,1369,1373,1378,1388,1393,1406,1411,1430,1442,1447,1459,1464,1476,1481,1493,1498,1510,1515,1527,1532,1549,1554,1569,1585,1590,1607,1612,1631,1636],{"__ignoreMap":439},[443,1341,1342,1345,1347,1349,1352,1354,1357,1359,1361],{"class":445,"line":446},[443,1343,1344],{"class":464},"  stopUndoCapture",[443,1346,550],{"class":449},[443,1348,670],{"class":449},[443,1350,1351],{"class":673},"state",[443,1353,550],{"class":449},[443,1355,1356],{"class":464}," EditorState",[443,1358,682],{"class":449},[443,1360,609],{"class":460},[443,1362,1363],{"class":615}," boolean\n",[443,1365,1366],{"class":445,"line":453},[443,1367,1368],{"class":615},"}\n",[443,1370,1371],{"class":445,"line":501},[443,1372,505],{"emptyLinePlaceholder":504},[443,1374,1375],{"class":445,"line":508},[443,1376,1377],{"class":511},"\u002F** Per-surface dependencies of a feature's factories. Created when a surface is set up; never shared between editors. *\u002F\n",[443,1379,1380,1382,1384,1386],{"class":445,"line":515},[443,1381,457],{"class":456},[443,1383,520],{"class":460},[443,1385,679],{"class":464},[443,1387,540],{"class":449},[443,1389,1390],{"class":445,"line":543},[443,1391,1392],{"class":511},"  \u002F** The app context the surface belongs to (shared by all editors of the app): app-level models key on it. *\u002F\n",[443,1394,1395,1398,1401,1403],{"class":445,"line":556},[443,1396,1397],{"class":460},"  readonly",[443,1399,1400],{"class":546}," app",[443,1402,550],{"class":449},[443,1404,1405],{"class":464}," EditorContext\n",[443,1407,1408],{"class":445,"line":562},[443,1409,1410],{"class":511},"  \u002F** The app's shared settings (see `createEditorContext`): read with `get()`, write with `update()`, observe with `subscribe()`. *\u002F\n",[443,1412,1413,1415,1418,1420,1423,1425,1428],{"class":445,"line":573},[443,1414,1397],{"class":460},[443,1416,1417],{"class":546}," settings",[443,1419,550],{"class":449},[443,1421,1422],{"class":464}," Store",[443,1424,526],{"class":449},[443,1426,1427],{"class":464},"EditorSettings",[443,1429,909],{"class":449},[443,1431,1432,1434,1437,1439],{"class":445,"line":579},[443,1433,1397],{"class":460},[443,1435,1436],{"class":546}," metadata",[443,1438,550],{"class":449},[443,1440,1441],{"class":464}," MetadataRegistry\n",[443,1443,1444],{"class":445,"line":585},[443,1445,1446],{"class":511},"  \u002F** Chrome of the editor this context belongs to (settings, sidebar). *\u002F\n",[443,1448,1449,1451,1454,1456],{"class":445,"line":591},[443,1450,1397],{"class":460},[443,1452,1453],{"class":546}," ui",[443,1455,550],{"class":449},[443,1457,1458],{"class":464}," EditorUi\n",[443,1460,1461],{"class":445,"line":597},[443,1462,1463],{"class":511},"  \u002F** Shows a notice through the surface's framework (Nuxt UI toast, sonner). *\u002F\n",[443,1465,1466,1468,1471,1473],{"class":445,"line":619},[443,1467,1397],{"class":460},[443,1469,1470],{"class":546}," notify",[443,1472,550],{"class":449},[443,1474,1475],{"class":464}," Notifier\n",[443,1477,1478],{"class":445,"line":625},[443,1479,1480],{"class":511},"  \u002F** The app's UI language (`createEditorContext({ locale })`). *\u002F\n",[443,1482,1483,1485,1488,1490],{"class":445,"line":641},[443,1484,1397],{"class":460},[443,1486,1487],{"class":546}," locale",[443,1489,550],{"class":449},[443,1491,1492],{"class":464}," Locale\n",[443,1494,1495],{"class":445,"line":647},[443,1496,1497],{"class":511},"  \u002F** Renders a catalog message in the app's language; every label a feature contributes goes through it. *\u002F\n",[443,1499,1500,1502,1505,1507],{"class":445,"line":662},[443,1501,1397],{"class":460},[443,1503,1504],{"class":546}," t",[443,1506,550],{"class":449},[443,1508,1509],{"class":464}," Translate\n",[443,1511,1512],{"class":445,"line":691},[443,1513,1514],{"class":511},"  \u002F** The data layer of the app (`createEditorContext({ backend })`): uploads, mention lookups, themes, AI. *\u002F\n",[443,1516,1517,1519,1522,1524],{"class":445,"line":716},[443,1518,1397],{"class":460},[443,1520,1521],{"class":546}," backend",[443,1523,550],{"class":449},[443,1525,1526],{"class":464}," EditorBackend\n",[443,1528,1529],{"class":445,"line":721},[443,1530,1531],{"class":511},"  \u002F** Inert public AI configuration of the app context; absent when none was supplied. *\u002F\n",[443,1533,1534,1536,1539,1541,1544,1546],{"class":445,"line":727},[443,1535,1397],{"class":460},[443,1537,1538],{"class":546}," ai",[443,1540,550],{"class":449},[443,1542,1543],{"class":464}," EditorAiConfig",[443,1545,481],{"class":449},[443,1547,1548],{"class":464}," undefined\n",[443,1550,1551],{"class":445,"line":733},[443,1552,1553],{"class":511},"  \u002F** Document whose package stores uploads (media feature). *\u002F\n",[443,1555,1556,1558,1561,1563,1565,1567],{"class":445,"line":739},[443,1557,1397],{"class":460},[443,1559,1560],{"class":546}," documentId",[443,1562,550],{"class":449},[443,1564,636],{"class":464},[443,1566,481],{"class":449},[443,1568,1548],{"class":464},[443,1570,1571,1573,1576,1578,1581,1583],{"class":445,"line":744},[443,1572,1397],{"class":460},[443,1574,1575],{"class":546}," collaboration",[443,1577,550],{"class":449},[443,1579,1580],{"class":464}," CollaborationSession",[443,1582,481],{"class":449},[443,1584,1548],{"class":464},[443,1586,1587],{"class":445,"line":759},[443,1588,1589],{"class":511},"  \u002F** The collaboration-aware position mapping of the preset's `anchorResolver` feature; null means local mapping only. *\u002F\n",[443,1591,1592,1594,1597,1599,1602,1604],{"class":445,"line":764},[443,1593,1397],{"class":460},[443,1595,1596],{"class":546}," anchorResolver",[443,1598,550],{"class":449},[443,1600,1601],{"class":464}," AnchorResolver",[443,1603,481],{"class":449},[443,1605,1606],{"class":464}," null\n",[443,1608,1609],{"class":445,"line":770},[443,1610,1611],{"class":511},"  \u002F** Host options for the ability extension (`abilities` prop). *\u002F\n",[443,1613,1614,1616,1619,1621,1624,1626,1629],{"class":445,"line":776},[443,1615,1397],{"class":460},[443,1617,1618],{"class":546}," abilities",[443,1620,550],{"class":449},[443,1622,1623],{"class":464}," Partial",[443,1625,526],{"class":449},[443,1627,1628],{"class":464},"AbilitiesOptions",[443,1630,909],{"class":449},[443,1632,1633],{"class":445,"line":782},[443,1634,1635],{"class":511},"  \u002F** The final command list: the features' commands after the host's `commands` transformer. The `\u002F` menu lists the ones with a `slash` placement. *\u002F\n",[443,1637,1638,1640,1643,1645,1647,1649,1651],{"class":445,"line":788},[443,1639,1397],{"class":460},[443,1641,1642],{"class":546}," commands",[443,1644,550],{"class":449},[443,1646,606],{"class":449},[443,1648,609],{"class":460},[443,1650,938],{"class":464},[443,1652,616],{"class":615},[427,1654,1656],{"id":1655},"editorpreset",[422,1657,1658],{},"EditorPreset",[434,1660,1662],{"className":436,"code":1661,"filename":424,"language":438,"meta":439,"style":439},"  \u002F**\n   * Refusals of whole transactions: every transaction that changes the document runs through the guards of all\n   * features, in feature order; the first one answering a string refuses it and shows that string as a notice. For rules\n   * about the document as a whole that no schema expresses (a locked paragraph, a required document shape).\n   *\u002F\n  transactionGuards?: (ctx: FeatureContext) => TransactionGuard[]\n  \u002F** Components mounted beside the editor content; they receive `{ editor }`. `C` is the component type of the framework layer that renders them. *\u002F\n  overlays?: readonly C[]\n  \u002F**\n   * Chips after the title of a Typed block in the composites chrome, additive in feature order (one per `RowBadge`).\n   * The factory runs once per surface; the chrome reads the result from the editor entry (`EditorEntry.rowBadges`).\n   *\u002F\n",[422,1663,1664,1668,1673,1678,1683,1687,1709,1714,1724,1728,1733,1738],{"__ignoreMap":439},[443,1665,1666],{"class":445,"line":446},[443,1667,576],{"class":511},[443,1669,1670],{"class":445,"line":453},[443,1671,1672],{"class":511},"   * Refusals of whole transactions: every transaction that changes the document runs through the guards of all\n",[443,1674,1675],{"class":445,"line":501},[443,1676,1677],{"class":511},"   * features, in feature order; the first one answering a string refuses it and shows that string as a notice. For rules\n",[443,1679,1680],{"class":445,"line":508},[443,1681,1682],{"class":511},"   * about the document as a whole that no schema expresses (a locked paragraph, a required document shape).\n",[443,1684,1685],{"class":445,"line":515},[443,1686,594],{"class":511},[443,1688,1689,1692,1694,1696,1698,1700,1702,1704,1706],{"class":445,"line":543},[443,1690,1691],{"class":615},"  transactionGuards",[443,1693,603],{"class":449},[443,1695,670],{"class":449},[443,1697,674],{"class":673},[443,1699,550],{"class":449},[443,1701,679],{"class":464},[443,1703,682],{"class":449},[443,1705,609],{"class":460},[443,1707,1708],{"class":615}," TransactionGuard[]\n",[443,1710,1711],{"class":445,"line":556},[443,1712,1713],{"class":511},"  \u002F** Components mounted beside the editor content; they receive `{ editor }`. `C` is the component type of the framework layer that renders them. *\u002F\n",[443,1715,1716,1719,1721],{"class":445,"line":562},[443,1717,1718],{"class":615},"  overlays",[443,1720,603],{"class":449},[443,1722,1723],{"class":615}," readonly C[]\n",[443,1725,1726],{"class":445,"line":573},[443,1727,576],{"class":511},[443,1729,1730],{"class":445,"line":579},[443,1731,1732],{"class":511},"   * Chips after the title of a Typed block in the composites chrome, additive in feature order (one per `RowBadge`).\n",[443,1734,1735],{"class":445,"line":585},[443,1736,1737],{"class":511},"   * The factory runs once per surface; the chrome reads the result from the editor entry (`EditorEntry.rowBadges`).\n",[443,1739,1740],{"class":445,"line":591},[443,1741,594],{"class":511},[427,1743,1745,1746,1749],{"id":1744},"what-defineeditor-validates","What ",[422,1747,1748],{},"defineEditor"," validates",[418,1751,1752,1755],{},[422,1753,1754],{},"defineEditor({ features })"," keeps the given order, neither deduplicates nor installs missing dependencies, and throws for:",[1757,1758,1759,1767,1773,1779,1785,1804],"ul",{},[1760,1761,1762,1763,1766],"li",{},"a feature without a ",[422,1764,1765],{},"dimension",";",[1760,1768,1769,1770,1766],{},"a duplicate feature ",[422,1771,1772],{},"id",[1760,1774,1775,1776,1778],{},"a ",[422,1777,1309],{}," entry that is not installed;",[1760,1780,1781,1782,1784],{},"a toolbar group declared by two features (",[422,1783,1015],{},");",[1760,1786,1787,1788,1012,1791,1012,1794,1012,1797,1012,1800,1012,1802,1784],{},"a singleton hook contributed twice (",[422,1789,1790],{},"parseMarkdown",[422,1792,1793],{},"segment",[422,1795,1796],{},"structure",[422,1798,1799],{},"migrateContent",[422,1801,1283],{},[422,1803,1289],{},[1760,1805,1806,1807,1810],{},"an importer id declared twice (",[422,1808,1809],{},"importers",").",[418,1812,1813,1814,1817,1818,1821,1822,1824,1825,1028,1828,1830,1831,1833,1834,1836],{},"A command naming a toolbar group no feature declares needs the feature context to build the commands: ",[422,1815,1816],{},"toolbarOf"," throws it. ",[422,1819,1820],{},"normalize"," hooks chain left to right. ",[422,1823,1286],{}," contributions merge (",[422,1826,1827],{},"blockTypes",[422,1829,1270],{}," concatenated in feature order, ",[422,1832,1796],{}," from one feature only); ",[422,1835,1299],{}," contributions are additive too. The doc comment of the function:",[434,1838,1841],{"className":436,"code":1839,"filename":1840,"language":438,"meta":439,"style":439},"\nconst fail = (message: string): never => failWith(message, 'defineEditor')\n\n\u002F**\n * Validates `features` and resolves their pipeline and conversion providers. Keeps the given order; neither\n * deduplicates nor installs missing dependencies. Throws on duplicate ids, a `requires` entry that is not installed,\n * a toolbar group declared by two features (`toolbarGroups`), a block capability declared twice or with a built-in id (`blockCapabilities`), a derive method declared twice, with neither `run` nor `menu` or requiring an undeclared capability (`deriveMethods`), an importer id declared twice (`importers`) and a singleton hook (`parseMarkdown`, `segment`, `structure`, `migrateContent`, `anchorResolver`,\n * `formatAiResult`) contributed twice. A command naming a toolbar group no feature declares needs the feature context\n * to build the commands: `toolbarOf` throws it. `normalize` hooks chain left to right. `aiContext` contributions merge (`blockTypes` and `blocks`\n * concatenated in feature order, `structure` from one feature only); their conflicts surface when the merged `aiContext` reads the editor.\n","packages\u002Feditor\u002Fsrc\u002Fcore\u002Fdefine-editor.ts",[422,1842,1843,1847,1894,1898,1903,1908,1913,1918,1923,1928],{"__ignoreMap":439},[443,1844,1845],{"class":445,"line":446},[443,1846,505],{"emptyLinePlaceholder":504},[443,1848,1849,1852,1855,1858,1860,1863,1865,1867,1870,1873,1875,1879,1882,1885,1887,1889,1891],{"class":445,"line":453},[443,1850,1851],{"class":460},"const",[443,1853,1854],{"class":615}," fail ",[443,1856,1857],{"class":449},"=",[443,1859,670],{"class":449},[443,1861,1862],{"class":673},"message",[443,1864,550],{"class":449},[443,1866,636],{"class":464},[443,1868,1869],{"class":449},"):",[443,1871,1872],{"class":464}," never",[443,1874,609],{"class":460},[443,1876,1878],{"class":1877},"s2Zo4"," failWith",[443,1880,1881],{"class":615},"(message",[443,1883,1884],{"class":449},",",[443,1886,471],{"class":449},[443,1888,1748],{"class":474},[443,1890,478],{"class":449},[443,1892,1893],{"class":615},")\n",[443,1895,1896],{"class":445,"line":501},[443,1897,505],{"emptyLinePlaceholder":504},[443,1899,1900],{"class":445,"line":508},[443,1901,1902],{"class":511},"\u002F**\n",[443,1904,1905],{"class":445,"line":515},[443,1906,1907],{"class":511}," * Validates `features` and resolves their pipeline and conversion providers. Keeps the given order; neither\n",[443,1909,1910],{"class":445,"line":543},[443,1911,1912],{"class":511}," * deduplicates nor installs missing dependencies. Throws on duplicate ids, a `requires` entry that is not installed,\n",[443,1914,1915],{"class":445,"line":556},[443,1916,1917],{"class":511}," * a toolbar group declared by two features (`toolbarGroups`), a block capability declared twice or with a built-in id (`blockCapabilities`), a derive method declared twice, with neither `run` nor `menu` or requiring an undeclared capability (`deriveMethods`), an importer id declared twice (`importers`) and a singleton hook (`parseMarkdown`, `segment`, `structure`, `migrateContent`, `anchorResolver`,\n",[443,1919,1920],{"class":445,"line":562},[443,1921,1922],{"class":511}," * `formatAiResult`) contributed twice. A command naming a toolbar group no feature declares needs the feature context\n",[443,1924,1925],{"class":445,"line":573},[443,1926,1927],{"class":511}," * to build the commands: `toolbarOf` throws it. `normalize` hooks chain left to right. `aiContext` contributions merge (`blockTypes` and `blocks`\n",[443,1929,1930],{"class":445,"line":579},[443,1931,1932],{"class":511}," * concatenated in feature order, `structure` from one feature only); their conflicts surface when the merged `aiContext` reads the editor.\n",[427,1934,1936,1937,1940],{"id":1935},"example-a-notes-feature","Example: a ",[422,1938,1939],{},"notes"," feature",[434,1942,1944],{"className":436,"code":1943,"language":438,"meta":439,"style":439},"\u002F\u002F notes\u002Ffeature.ts\nimport { command } from '@skaile\u002Fforge-editor\u002Fcore'\nimport type { VueFeature } from '@skaile\u002Fforge-editor\u002Fvue'\nimport SettingsNotesTab from '.\u002FSettingsNotesTab.vue'\n\nexport function notesFeature(): VueFeature {\n  return {\n    id: 'notes',\n    dimension: 'interaction', \u002F\u002F 'content' when it adds nodes or marks, 'ai' for AI features\n    \u002F\u002F requires: ['block-ui'], \u002F\u002F fail at composition time when a dependency is missing\n    toolbarGroups: [{ id: 'notes', order: 100 }],\n    \u002F\u002F One declaration per command: the toolbar button and the `\u002Fstrich` entry share label, icon and gating.\n    commands: () => [\n      command({\n        id: 'dash',\n        toolbar: { group: 'notes' },\n        slash: { id: 'strich' },\n        icon: 'i-lucide-minus',\n        label: 'Gedankenstrich',\n        command: chain => chain.insertContent('\\u2013'),\n      }),\n    ],\n    \u002F\u002F Runs in every mounted surface's setup and returns its teardown. Several surfaces of one app share state: dedupe per app\n    \u002F\u002F inside and reference-count the release (the theme runtime keys a WeakSet by `ctx.settings`). Report problems with `ctx.notify({ title, kind })`.\n    setup: (ctx) => {\n      const onKey = (event: KeyboardEvent) => {\n        if (event.key === 'F2') ctx.ui.openSettings('notes')\n      }\n      document.addEventListener('keydown', onKey)\n      return () => document.removeEventListener('keydown', onKey)\n    },\n    \u002F\u002F Tab ids must be unique across the preset; the panel renders nothing when no feature contributes a tab.\n    settingsTabs: ctx => [{ id: 'notes', label: ctx.t('notes.tab'), icon: 'i-lucide-notebook', component: SettingsNotesTab }],\n  }\n}\n",[422,1945,1946,1951,1975,1997,2014,2018,2035,2042,2058,2076,2084,2126,2131,2145,2156,2172,2195,2217,2233,2249,2281,2290,2297,2302,2307,2324,2350,2399,2404,2429,2460,2465,2470,2551,2556],{"__ignoreMap":439},[443,1947,1948],{"class":445,"line":446},[443,1949,1950],{"class":511},"\u002F\u002F notes\u002Ffeature.ts\n",[443,1952,1953,1956,1959,1962,1965,1968,1970,1973],{"class":445,"line":453},[443,1954,1955],{"class":456},"import",[443,1957,1958],{"class":449}," {",[443,1960,1961],{"class":615}," command",[443,1963,1964],{"class":449}," }",[443,1966,1967],{"class":456}," from",[443,1969,471],{"class":449},[443,1971,1972],{"class":474},"@skaile\u002Fforge-editor\u002Fcore",[443,1974,498],{"class":449},[443,1976,1977,1979,1981,1983,1986,1988,1990,1992,1995],{"class":445,"line":501},[443,1978,1955],{"class":456},[443,1980,461],{"class":456},[443,1982,1958],{"class":449},[443,1984,1985],{"class":615}," VueFeature",[443,1987,1964],{"class":449},[443,1989,1967],{"class":456},[443,1991,471],{"class":449},[443,1993,1994],{"class":474},"@skaile\u002Fforge-editor\u002Fvue",[443,1996,498],{"class":449},[443,1998,1999,2001,2004,2007,2009,2012],{"class":445,"line":508},[443,2000,1955],{"class":456},[443,2002,2003],{"class":615}," SettingsNotesTab ",[443,2005,2006],{"class":456},"from",[443,2008,471],{"class":449},[443,2010,2011],{"class":474},".\u002FSettingsNotesTab.vue",[443,2013,498],{"class":449},[443,2015,2016],{"class":445,"line":515},[443,2017,505],{"emptyLinePlaceholder":504},[443,2019,2020,2022,2025,2028,2031,2033],{"class":445,"line":543},[443,2021,457],{"class":456},[443,2023,2024],{"class":460}," function",[443,2026,2027],{"class":1877}," notesFeature",[443,2029,2030],{"class":449},"():",[443,2032,1985],{"class":464},[443,2034,540],{"class":449},[443,2036,2037,2040],{"class":445,"line":556},[443,2038,2039],{"class":456},"  return",[443,2041,540],{"class":449},[443,2043,2044,2047,2049,2051,2053,2055],{"class":445,"line":562},[443,2045,2046],{"class":546},"    id",[443,2048,550],{"class":449},[443,2050,471],{"class":449},[443,2052,1939],{"class":474},[443,2054,478],{"class":449},[443,2056,2057],{"class":449},",\n",[443,2059,2060,2063,2065,2067,2069,2071,2073],{"class":445,"line":573},[443,2061,2062],{"class":546},"    dimension",[443,2064,550],{"class":449},[443,2066,471],{"class":449},[443,2068,486],{"class":474},[443,2070,478],{"class":449},[443,2072,1884],{"class":449},[443,2074,2075],{"class":511}," \u002F\u002F 'content' when it adds nodes or marks, 'ai' for AI features\n",[443,2077,2078,2081],{"class":445,"line":579},[443,2079,2080],{"class":511},"    \u002F\u002F requires: ['block-ui'],",[443,2082,2083],{"class":511}," \u002F\u002F fail at composition time when a dependency is missing\n",[443,2085,2086,2089,2091,2094,2097,2100,2102,2104,2106,2108,2110,2113,2115,2119,2121,2124],{"class":445,"line":585},[443,2087,2088],{"class":546},"    toolbarGroups",[443,2090,550],{"class":449},[443,2092,2093],{"class":546}," [",[443,2095,2096],{"class":449},"{",[443,2098,2099],{"class":546}," id",[443,2101,550],{"class":449},[443,2103,471],{"class":449},[443,2105,1939],{"class":474},[443,2107,478],{"class":449},[443,2109,1884],{"class":449},[443,2111,2112],{"class":546}," order",[443,2114,550],{"class":449},[443,2116,2118],{"class":2117},"sbssI"," 100",[443,2120,1964],{"class":449},[443,2122,2123],{"class":546},"]",[443,2125,2057],{"class":449},[443,2127,2128],{"class":445,"line":591},[443,2129,2130],{"class":511},"    \u002F\u002F One declaration per command: the toolbar button and the `\u002Fstrich` entry share label, icon and gating.\n",[443,2132,2133,2136,2138,2140,2142],{"class":445,"line":597},[443,2134,2135],{"class":1877},"    commands",[443,2137,550],{"class":449},[443,2139,606],{"class":449},[443,2141,609],{"class":460},[443,2143,2144],{"class":546}," [\n",[443,2146,2147,2150,2153],{"class":445,"line":619},[443,2148,2149],{"class":1877},"      command",[443,2151,2152],{"class":546},"(",[443,2154,2155],{"class":449},"{\n",[443,2157,2158,2161,2163,2165,2168,2170],{"class":445,"line":625},[443,2159,2160],{"class":546},"        id",[443,2162,550],{"class":449},[443,2164,471],{"class":449},[443,2166,2167],{"class":474},"dash",[443,2169,478],{"class":449},[443,2171,2057],{"class":449},[443,2173,2174,2177,2179,2181,2184,2186,2188,2190,2192],{"class":445,"line":641},[443,2175,2176],{"class":546},"        toolbar",[443,2178,550],{"class":449},[443,2180,1958],{"class":449},[443,2182,2183],{"class":546}," group",[443,2185,550],{"class":449},[443,2187,471],{"class":449},[443,2189,1939],{"class":474},[443,2191,478],{"class":449},[443,2193,2194],{"class":449}," },\n",[443,2196,2197,2200,2202,2204,2206,2208,2210,2213,2215],{"class":445,"line":647},[443,2198,2199],{"class":546},"        slash",[443,2201,550],{"class":449},[443,2203,1958],{"class":449},[443,2205,2099],{"class":546},[443,2207,550],{"class":449},[443,2209,471],{"class":449},[443,2211,2212],{"class":474},"strich",[443,2214,478],{"class":449},[443,2216,2194],{"class":449},[443,2218,2219,2222,2224,2226,2229,2231],{"class":445,"line":662},[443,2220,2221],{"class":546},"        icon",[443,2223,550],{"class":449},[443,2225,471],{"class":449},[443,2227,2228],{"class":474},"i-lucide-minus",[443,2230,478],{"class":449},[443,2232,2057],{"class":449},[443,2234,2235,2238,2240,2242,2245,2247],{"class":445,"line":691},[443,2236,2237],{"class":546},"        label",[443,2239,550],{"class":449},[443,2241,471],{"class":449},[443,2243,2244],{"class":474},"Gedankenstrich",[443,2246,478],{"class":449},[443,2248,2057],{"class":449},[443,2250,2251,2254,2256,2259,2261,2263,2265,2268,2270,2272,2275,2277,2279],{"class":445,"line":716},[443,2252,2253],{"class":1877},"        command",[443,2255,550],{"class":449},[443,2257,2258],{"class":673}," chain",[443,2260,609],{"class":460},[443,2262,2258],{"class":615},[443,2264,425],{"class":449},[443,2266,2267],{"class":1877},"insertContent",[443,2269,2152],{"class":546},[443,2271,478],{"class":449},[443,2273,2274],{"class":615},"\\u2013",[443,2276,478],{"class":449},[443,2278,682],{"class":546},[443,2280,2057],{"class":449},[443,2282,2283,2286,2288],{"class":445,"line":721},[443,2284,2285],{"class":449},"      }",[443,2287,682],{"class":546},[443,2289,2057],{"class":449},[443,2291,2292,2295],{"class":445,"line":727},[443,2293,2294],{"class":546},"    ]",[443,2296,2057],{"class":449},[443,2298,2299],{"class":445,"line":733},[443,2300,2301],{"class":511},"    \u002F\u002F Runs in every mounted surface's setup and returns its teardown. Several surfaces of one app share state: dedupe per app\n",[443,2303,2304],{"class":445,"line":739},[443,2305,2306],{"class":511},"    \u002F\u002F inside and reference-count the release (the theme runtime keys a WeakSet by `ctx.settings`). Report problems with `ctx.notify({ title, kind })`.\n",[443,2308,2309,2312,2314,2316,2318,2320,2322],{"class":445,"line":744},[443,2310,2311],{"class":1877},"    setup",[443,2313,550],{"class":449},[443,2315,670],{"class":449},[443,2317,674],{"class":673},[443,2319,682],{"class":449},[443,2321,609],{"class":460},[443,2323,540],{"class":449},[443,2325,2326,2329,2332,2334,2336,2339,2341,2344,2346,2348],{"class":445,"line":759},[443,2327,2328],{"class":460},"      const",[443,2330,2331],{"class":615}," onKey",[443,2333,468],{"class":449},[443,2335,670],{"class":449},[443,2337,2338],{"class":673},"event",[443,2340,550],{"class":449},[443,2342,2343],{"class":464}," KeyboardEvent",[443,2345,682],{"class":449},[443,2347,609],{"class":460},[443,2349,540],{"class":449},[443,2351,2352,2355,2357,2359,2361,2364,2367,2369,2372,2374,2377,2379,2381,2384,2386,2389,2391,2393,2395,2397],{"class":445,"line":764},[443,2353,2354],{"class":456},"        if",[443,2356,670],{"class":546},[443,2358,2338],{"class":615},[443,2360,425],{"class":449},[443,2362,2363],{"class":615},"key",[443,2365,2366],{"class":449}," ===",[443,2368,471],{"class":449},[443,2370,2371],{"class":474},"F2",[443,2373,478],{"class":449},[443,2375,2376],{"class":546},") ",[443,2378,674],{"class":615},[443,2380,425],{"class":449},[443,2382,2383],{"class":615},"ui",[443,2385,425],{"class":449},[443,2387,2388],{"class":1877},"openSettings",[443,2390,2152],{"class":546},[443,2392,478],{"class":449},[443,2394,1939],{"class":474},[443,2396,478],{"class":449},[443,2398,1893],{"class":546},[443,2400,2401],{"class":445,"line":770},[443,2402,2403],{"class":449},"      }\n",[443,2405,2406,2409,2411,2414,2416,2418,2421,2423,2425,2427],{"class":445,"line":776},[443,2407,2408],{"class":615},"      document",[443,2410,425],{"class":449},[443,2412,2413],{"class":1877},"addEventListener",[443,2415,2152],{"class":546},[443,2417,478],{"class":449},[443,2419,2420],{"class":474},"keydown",[443,2422,478],{"class":449},[443,2424,1884],{"class":449},[443,2426,2331],{"class":615},[443,2428,1893],{"class":546},[443,2430,2431,2434,2436,2438,2441,2443,2446,2448,2450,2452,2454,2456,2458],{"class":445,"line":782},[443,2432,2433],{"class":456},"      return",[443,2435,606],{"class":449},[443,2437,609],{"class":460},[443,2439,2440],{"class":615}," document",[443,2442,425],{"class":449},[443,2444,2445],{"class":1877},"removeEventListener",[443,2447,2152],{"class":546},[443,2449,478],{"class":449},[443,2451,2420],{"class":474},[443,2453,478],{"class":449},[443,2455,1884],{"class":449},[443,2457,2331],{"class":615},[443,2459,1893],{"class":546},[443,2461,2462],{"class":445,"line":788},[443,2463,2464],{"class":449},"    },\n",[443,2466,2467],{"class":445,"line":793},[443,2468,2469],{"class":511},"    \u002F\u002F Tab ids must be unique across the preset; the panel renders nothing when no feature contributes a tab.\n",[443,2471,2472,2475,2477,2480,2482,2484,2486,2488,2490,2492,2494,2496,2498,2501,2503,2505,2507,2510,2512,2514,2517,2519,2521,2523,2526,2528,2530,2533,2535,2537,2540,2542,2545,2547,2549],{"class":445,"line":808},[443,2473,2474],{"class":1877},"    settingsTabs",[443,2476,550],{"class":449},[443,2478,2479],{"class":673}," ctx",[443,2481,609],{"class":460},[443,2483,2093],{"class":546},[443,2485,2096],{"class":449},[443,2487,2099],{"class":546},[443,2489,550],{"class":449},[443,2491,471],{"class":449},[443,2493,1939],{"class":474},[443,2495,478],{"class":449},[443,2497,1884],{"class":449},[443,2499,2500],{"class":546}," label",[443,2502,550],{"class":449},[443,2504,2479],{"class":615},[443,2506,425],{"class":449},[443,2508,2509],{"class":1877},"t",[443,2511,2152],{"class":546},[443,2513,478],{"class":449},[443,2515,2516],{"class":474},"notes.tab",[443,2518,478],{"class":449},[443,2520,682],{"class":546},[443,2522,1884],{"class":449},[443,2524,2525],{"class":546}," icon",[443,2527,550],{"class":449},[443,2529,471],{"class":449},[443,2531,2532],{"class":474},"i-lucide-notebook",[443,2534,478],{"class":449},[443,2536,1884],{"class":449},[443,2538,2539],{"class":546}," component",[443,2541,550],{"class":449},[443,2543,2544],{"class":615}," SettingsNotesTab",[443,2546,1964],{"class":449},[443,2548,2123],{"class":546},[443,2550,2057],{"class":449},[443,2552,2553],{"class":445,"line":813},[443,2554,2555],{"class":449},"  }\n",[443,2557,2558],{"class":445,"line":819},[443,2559,1368],{"class":449},[434,2561,2565],{"className":2562,"code":2563,"language":2564,"meta":439,"style":439},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C!-- notes\u002FSettingsNotesTab.vue -->\n\u003Cscript setup lang=\"ts\">\nimport USwitch from '@nuxt\u002Fui\u002Fcomponents\u002FSwitch.vue'\nimport { SettingsSection } from '@skaile\u002Fforge-editor\u002Fvue'\nimport { ref } from 'vue'\n\nconst shout = ref(false) \u002F\u002F local state; see the settings note below for persisted values\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CSettingsSection title=\"Notizen\">\n    \u003Cdiv class=\"py-3\">\n      \u003CUSwitch v-model=\"shout\" label=\"Hervorheben\" \u002F>\n    \u003C\u002Fdiv>\n  \u003C\u002FSettingsSection>\n\u003C\u002Ftemplate>\n","vue",[422,2566,2567,2572,2596,2612,2631,2650,2654,2676,2685,2689,2698,2720,2742,2776,2785,2794],{"__ignoreMap":439},[443,2568,2569],{"class":445,"line":446},[443,2570,2571],{"class":511},"\u003C!-- notes\u002FSettingsNotesTab.vue -->\n",[443,2573,2574,2576,2579,2582,2585,2587,2590,2592,2594],{"class":445,"line":453},[443,2575,526],{"class":449},[443,2577,2578],{"class":546},"script",[443,2580,2581],{"class":460}," setup",[443,2583,2584],{"class":460}," lang",[443,2586,1857],{"class":449},[443,2588,2589],{"class":449},"\"",[443,2591,438],{"class":474},[443,2593,2589],{"class":449},[443,2595,909],{"class":449},[443,2597,2598,2600,2603,2605,2607,2610],{"class":445,"line":501},[443,2599,1955],{"class":456},[443,2601,2602],{"class":615}," USwitch ",[443,2604,2006],{"class":456},[443,2606,471],{"class":449},[443,2608,2609],{"class":474},"@nuxt\u002Fui\u002Fcomponents\u002FSwitch.vue",[443,2611,498],{"class":449},[443,2613,2614,2616,2618,2621,2623,2625,2627,2629],{"class":445,"line":508},[443,2615,1955],{"class":456},[443,2617,1958],{"class":449},[443,2619,2620],{"class":615}," SettingsSection",[443,2622,1964],{"class":449},[443,2624,1967],{"class":456},[443,2626,471],{"class":449},[443,2628,1994],{"class":474},[443,2630,498],{"class":449},[443,2632,2633,2635,2637,2640,2642,2644,2646,2648],{"class":445,"line":515},[443,2634,1955],{"class":456},[443,2636,1958],{"class":449},[443,2638,2639],{"class":615}," ref",[443,2641,1964],{"class":449},[443,2643,1967],{"class":456},[443,2645,471],{"class":449},[443,2647,2564],{"class":474},[443,2649,498],{"class":449},[443,2651,2652],{"class":445,"line":543},[443,2653,505],{"emptyLinePlaceholder":504},[443,2655,2656,2658,2661,2663,2665,2667,2671,2673],{"class":445,"line":556},[443,2657,1851],{"class":460},[443,2659,2660],{"class":615}," shout ",[443,2662,1857],{"class":449},[443,2664,2639],{"class":1877},[443,2666,2152],{"class":615},[443,2668,2670],{"class":2669},"sfNiH","false",[443,2672,2376],{"class":615},[443,2674,2675],{"class":511},"\u002F\u002F local state; see the settings note below for persisted values\n",[443,2677,2678,2681,2683],{"class":445,"line":562},[443,2679,2680],{"class":449},"\u003C\u002F",[443,2682,2578],{"class":546},[443,2684,909],{"class":449},[443,2686,2687],{"class":445,"line":573},[443,2688,505],{"emptyLinePlaceholder":504},[443,2690,2691,2693,2696],{"class":445,"line":579},[443,2692,526],{"class":449},[443,2694,2695],{"class":546},"template",[443,2697,909],{"class":449},[443,2699,2700,2703,2706,2709,2711,2713,2716,2718],{"class":445,"line":585},[443,2701,2702],{"class":449},"  \u003C",[443,2704,2705],{"class":546},"SettingsSection",[443,2707,2708],{"class":460}," title",[443,2710,1857],{"class":449},[443,2712,2589],{"class":449},[443,2714,2715],{"class":474},"Notizen",[443,2717,2589],{"class":449},[443,2719,909],{"class":449},[443,2721,2722,2725,2728,2731,2733,2735,2738,2740],{"class":445,"line":591},[443,2723,2724],{"class":449},"    \u003C",[443,2726,2727],{"class":546},"div",[443,2729,2730],{"class":460}," class",[443,2732,1857],{"class":449},[443,2734,2589],{"class":449},[443,2736,2737],{"class":474},"py-3",[443,2739,2589],{"class":449},[443,2741,909],{"class":449},[443,2743,2744,2747,2750,2753,2755,2757,2760,2762,2764,2766,2768,2771,2773],{"class":445,"line":597},[443,2745,2746],{"class":449},"      \u003C",[443,2748,2749],{"class":546},"USwitch",[443,2751,2752],{"class":460}," v-model",[443,2754,1857],{"class":449},[443,2756,2589],{"class":449},[443,2758,2759],{"class":615},"shout",[443,2761,2589],{"class":449},[443,2763,2500],{"class":460},[443,2765,1857],{"class":449},[443,2767,2589],{"class":449},[443,2769,2770],{"class":474},"Hervorheben",[443,2772,2589],{"class":449},[443,2774,2775],{"class":449}," \u002F>\n",[443,2777,2778,2781,2783],{"class":445,"line":619},[443,2779,2780],{"class":449},"    \u003C\u002F",[443,2782,2727],{"class":546},[443,2784,909],{"class":449},[443,2786,2787,2790,2792],{"class":445,"line":625},[443,2788,2789],{"class":449},"  \u003C\u002F",[443,2791,2705],{"class":546},[443,2793,909],{"class":449},[443,2795,2796,2798,2800],{"class":445,"line":641},[443,2797,2680],{"class":449},[443,2799,2695],{"class":546},[443,2801,909],{"class":449},[418,2803,2804],{},"Compose it with the advanced list (or any list) and mount it with the same preset the toolbar and settings UI receive:",[434,2806,2808],{"className":436,"code":2807,"language":438,"meta":439,"style":439},"import { defineEditor } from '@skaile\u002Fforge-editor\u002Fcore'\nimport { advancedEditor } from '@skaile\u002Fforge-editor\u002Fvue\u002Fadvanced'\nimport { notesFeature } from '.\u002Fnotes\u002Ffeature'\n\nconst preset = defineEditor({ features: [...advancedEditor().features, notesFeature()] })\n",[422,2809,2810,2829,2849,2868,2872],{"__ignoreMap":439},[443,2811,2812,2814,2816,2819,2821,2823,2825,2827],{"class":445,"line":446},[443,2813,1955],{"class":456},[443,2815,1958],{"class":449},[443,2817,2818],{"class":615}," defineEditor",[443,2820,1964],{"class":449},[443,2822,1967],{"class":456},[443,2824,471],{"class":449},[443,2826,1972],{"class":474},[443,2828,498],{"class":449},[443,2830,2831,2833,2835,2838,2840,2842,2844,2847],{"class":445,"line":453},[443,2832,1955],{"class":456},[443,2834,1958],{"class":449},[443,2836,2837],{"class":615}," advancedEditor",[443,2839,1964],{"class":449},[443,2841,1967],{"class":456},[443,2843,471],{"class":449},[443,2845,2846],{"class":474},"@skaile\u002Fforge-editor\u002Fvue\u002Fadvanced",[443,2848,498],{"class":449},[443,2850,2851,2853,2855,2857,2859,2861,2863,2866],{"class":445,"line":501},[443,2852,1955],{"class":456},[443,2854,1958],{"class":449},[443,2856,2027],{"class":615},[443,2858,1964],{"class":449},[443,2860,1967],{"class":456},[443,2862,471],{"class":449},[443,2864,2865],{"class":474},".\u002Fnotes\u002Ffeature",[443,2867,498],{"class":449},[443,2869,2870],{"class":445,"line":508},[443,2871,505],{"emptyLinePlaceholder":504},[443,2873,2874,2876,2879,2881,2883,2885,2887,2890,2892,2894,2897,2900,2903,2905,2908,2910,2912,2915,2918],{"class":445,"line":515},[443,2875,1851],{"class":460},[443,2877,2878],{"class":615}," preset ",[443,2880,1857],{"class":449},[443,2882,2818],{"class":1877},[443,2884,2152],{"class":615},[443,2886,2096],{"class":449},[443,2888,2889],{"class":546}," features",[443,2891,550],{"class":449},[443,2893,2093],{"class":615},[443,2895,2896],{"class":449},"...",[443,2898,2899],{"class":1877},"advancedEditor",[443,2901,2902],{"class":615},"()",[443,2904,425],{"class":449},[443,2906,2907],{"class":615},"features",[443,2909,1884],{"class":449},[443,2911,2027],{"class":1877},[443,2913,2914],{"class":615},"()] ",[443,2916,2917],{"class":449},"}",[443,2919,1893],{"class":615},[427,2921,2923],{"id":2922},"things-that-bite","Things that bite",[1757,2925,2926,2948,2965,3008,3032],{},[1760,2927,2928,2929,670,2931,1012,2934,2937,2938,670,2941,2944,2945,1810],{},"Items gated by an own ",[422,2930,1086],{},[422,2932,2933],{},"CommandDef.ability",[422,2935,2936],{},"BlockAction.ability",") stay inert until the ability exists at the caret. Grant custom abilities at root through the surface prop: ",[422,2939,2940],{},":abilities=\"{ root: [...ROOT_ABILITIES, MY_ABILITY] }\"",[422,2942,2943],{},"ROOT_ABILITIES"," from ",[422,2946,2947],{},"\u002Fcore\u002Fschema",[1760,2949,2950,2951,2954,2955,670,2958,2944,2961,2964],{},"The hover bar of ",[422,2952,2953],{},"BlockAction","s is right-aligned 8px inside the editor's right edge for every block and is hidden while the editor is read-only. A block that draws its own icons in its top-right corner marks them with ",[422,2956,2957],{},"data-block-corner",[422,2959,2960],{},"BLOCK_CORNER_ATTR",[422,2962,2963],{},"\u002Fblock-ui","): the bar then docks immediately left of them, centred on their row, instead of covering them.",[1760,2966,2967,2968,2971,2972,2975,2976,2979,2980,2983,2984,1012,2987,2991,2992,2995,2996,2999,3000,3003,3004,3007],{},"A feature that adds a ",[1212,2969,2970],{},"node"," must be known to every schema that touches the document. The Nuxt module's collab route builds its schema from ",[422,2973,2974],{},"advancedSchemaExtensions()"," plus the ",[422,2977,2978],{},"schema"," option of ",[422,2981,2982],{},"provideEditorServer({ ports, schema })",", so register the Vue-free node file there (",[422,2985,2986],{},"schema: () => [...advancedSchemaExtensions(), YourNode]",[2988,2989,2990],"a",{"href":71},"tutorial chapter, Backend and collaboration","); a custom Hocuspocus server builds ",[422,2993,2994],{},"getSchema([...advancedSchemaExtensions(), YourNode])"," itself. Standalone editors (JSON ",[422,2997,2998],{},"v-model",") need none of this. ",[422,3001,3002],{},"editorBlock: true"," (via ",[422,3005,3006],{},"NodeFlags",") gives an own node block IDs, also on the server.",[1760,3009,3010,3011,1057,3013,3016,3017,3020,3021,1057,3024,3027,3028,3031],{},"A tab component can bind only to fields that exist in ",[422,3012,1427],{},[422,3014,3015],{},"parseEditorSettings"," drops unknown keys, so new keys are neither stored locally nor sent to the server. The tab component runs inside the app, so it can call ",[422,3018,3019],{},"useEditorSettings()"," (from ",[422,3022,3023],{},"\u002Fvue",[422,3025,3026],{},"{ settings, ready, synced }"," as refs; from ",[422,3029,3030],{},"\u002Freact",": the same names as values).",[1760,3033,3034,3035,1012,3037,1012,3039,3041,3042,1057,3044,1012,3047,1012,3050,1012,3053,1012,3055,1012,3058,1012,3061,1012,3063,1012,3066,1012,3069,3072,3073,3075,3076,3079,3080,3083,3084,3072,3087,3089,3090,3093,3094,3097,3098,3101,3102,3072,3105,3108,3109,3112,3113,670,3116,1012,3119,1012,3121,1012,3124,1012,3127,1012,3130,3133,3134,3136,3137,3140,3141,1028,3143,3145,3146,3148],{},"Factories (",[422,3036,1324],{},[422,3038,1327],{},[422,3040,1330],{},", ...) receive the ",[422,3043,1318],{},[422,3045,3046],{},"app",[422,3048,3049],{},"settings",[422,3051,3052],{},"metadata",[422,3054,2383],{},[422,3056,3057],{},"notify",[422,3059,3060],{},"backend",[422,3062,495],{},[422,3064,3065],{},"documentId",[422,3067,3068],{},"collaboration",[422,3070,3071],{},"getEditor()",". ",[422,3074,3060],{}," is the ",[422,3077,3078],{},"EditorBackend"," of the app (uploads, lookups, themes, AI: ",[422,3081,3082],{},"ctx.backend.assets?.upload(...)","); features never call ",[422,3085,3086],{},"fetch",[422,3088,3049],{}," is a framework-free store: read ",[422,3091,3092],{},"ctx.settings.get()",", change it with ",[422,3095,3096],{},"ctx.settings.update(s => { ... })"," (or ",[422,3099,3100],{},"set","), observe it with ",[422,3103,3104],{},"ctx.settings.subscribe(listener)",[422,3106,3107],{},"ctx.notify({ id?, title, description?, kind?, icon?, duration? })"," shows a user-facing notice (Nuxt UI toast or sonner toast, per surface; features never import a toast library). ",[422,3110,3111],{},"ctx.app"," is the app context that app-level models key on. Menu commands and block-action menus return core ",[422,3114,3115],{},"MenuItem[]",[422,3117,3118],{},"type?: 'label' | 'separator'",[422,3120,1241],{},[422,3122,3123],{},"description",[422,3125,3126],{},"icon",[422,3128,3129],{},"disabled",[422,3131,3132],{},"onSelect","). ",[422,3135,3071],{}," is ",[422,3138,3139],{},"undefined"," while extensions are constructed; use it in event handlers only. Components in ",[422,3142,1120],{},[422,3144,1245],{}," commands receive ",[422,3147,1134],{}," as props.",[418,3150,3151,3152,3155,3156,3164,3165,3167,3168,3170,3171,425],{},"Complete worked example with node, node view, conversions and AI description: the tutorial chapter ",[2988,3153,3154],{"href":66},"The callout as a feature"," and the runnable ",[2988,3157,3161],{"href":3158,"rel":3159},"https:\u002F\u002Fgithub.com\u002Fskaile-ai\u002Fforge-editor\u002Ftree\u002Fmain\u002Fapp\u002Feditor\u002Fcallout",[3160],"nofollow",[422,3162,3163],{},"app\u002Feditor\u002Fcallout\u002F",". Lighter path without a feature (",[422,3166,1324],{}," prop and ",[422,3169,1327],{}," transformer): ",[2988,3172,3173],{"href":61},"The callout through props",[3175,3176,3177],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":439,"searchDepth":453,"depth":453,"links":3179},[3180,3181,3182,3183,3185,3187],{"id":429,"depth":453,"text":432},{"id":1315,"depth":453,"text":1318},{"id":1655,"depth":453,"text":1658},{"id":1744,"depth":453,"text":3184},"What defineEditor validates",{"id":1935,"depth":453,"text":3186},"Example: a notes feature",{"id":2922,"depth":453,"text":2923},"The EditorFeature, FeatureContext and EditorPreset types, what defineEditor validates and how to contribute a custom feature.","md",null,{},{"icon":68},{"title":357,"description":3188},"AhhT5oj_vvG_RAO39Zj2pjZEuqbioy9WiuTOXXON-Kk",[3196,3198],{"title":353,"path":354,"stem":355,"description":3197,"icon":58,"children":-1},"Which features each preset contains, which backend it needs and which modules its bundle must not contain.",{"title":361,"path":362,"stem":363,"description":3199,"icon":107,"children":-1},"Design tokens, stylesheet order, Tailwind sources and the UI kit each surface needs.",1793213909398]