[{"data":1,"prerenderedAt":1337},["ShallowReactive",2],{"navigation_docs":3,"-guides-render":412,"-guides-render-surround":1332},[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":214,"body":414,"description":1325,"extension":1326,"links":1327,"meta":1328,"navigation":1329,"path":215,"seo":1330,"stem":216,"__hash__":1331},"docs\u002F3.guides\u002F33.render.md",{"type":415,"value":416,"toc":1317},"minimark",[417,435,541,552,557,636,1069,1083,1090,1106,1110,1119,1199,1241,1245,1273,1277,1283,1310,1313],[418,419,420,421,425,426,430,431,434],"p",{},"A ",[422,423,424],"strong",{},"render target"," turns one Typed block, or a whole Document, into a file: Markdown, a PDF, a slide deck, a spoken recording. The editor ships one target, ",[427,428,429],"code",{},"markdown",". A host or an add-on contributes the others. The ",[427,432,433],{},"render"," capability connects the pieces:",[436,437,438,454],"table",{},[439,440,441],"thead",{},[442,443,444,448,451],"tr",{},[445,446,447],"th",{},"Piece",[445,449,450],{},"What it does",[445,452,453],{},"Port (capability)",[455,456,457,472,486,504,523],"tbody",{},[442,458,459,465,468],{},[460,461,462],"td",{},[427,463,464],{},"Renderer",[460,466,467],{},"lists the targets a user may use and renders one input to one target",[460,469,470],{},[427,471,433],{},[442,473,474,479,482],{},[460,475,476],{},[427,477,478],{},"GET \u002Fapi\u002Feditor\u002Frender\u002Ftargets",[460,480,481],{},"the targets with the Block types each accepts and its MIME type",[460,483,484],{},[427,485,433],{},[442,487,488,493,496],{},[460,489,490],{},[427,491,492],{},"POST \u002Fapi\u002Feditor\u002Frender",[460,494,495],{},"one render, streamed as server-sent events; the result is stored as an asset of the Document",[460,497,498,500,501],{},[427,499,433],{}," and ",[427,502,503],{},"assets",[442,505,506,511,519],{},[460,507,508],{},[427,509,510],{},"EditorBackend['render']",[460,512,513,500,516],{},[427,514,515],{},"targets()",[427,517,518],{},"render(target, input, { onProgress })",[460,520,521],{},[427,522,433],{},[442,524,525,534,537],{},[460,526,527,528,530,531],{},"Block action ",[427,529,433],{}," and command ",[427,532,533],{},"render-document",[460,535,536],{},"menus of the targets that take the Block type, or the whole Document",[460,538,539],{},[427,540,433],{},[418,542,543,544,547,548,551],{},"A render lives as long as its request. There is no job store: the server streams progress while the target runs, stores the file, and ends the stream. A client that disconnects aborts the target through the ",[427,545,546],{},"AbortSignal"," that ",[427,549,550],{},"Renderer.render"," receives.",[553,554,556],"h2",{"id":555},"add-a-target","Add a target",[418,558,559,560,563,564,567,568,571,572,563,575,563,578,563,581,584,585,588,589,591,592,595,596,598,599,563,602,563,605,563,608,611,612,615,616,618,619,588,622,625,626,628,629,632,633,635],{},"A target (",[427,561,562],{},"RenderTarget",", ",[427,565,566],{},"@skaile\u002Fforge-editor\u002Fadapters\u002Frender",") is a ",[427,569,570],{},"RenderTargetInfo"," (",[427,573,574],{},"id",[427,576,577],{},"label",[427,579,580],{},"accepts",[427,582,583],{},"mime",") plus ",[427,586,587],{},"run",". ",[427,590,580],{}," lists Block type ids, and ",[427,593,594],{},"'document'"," for a whole Document. ",[427,597,587],{}," receives the input (",[427,600,601],{},"documentId",[427,603,604],{},"blockId?",[427,606,607],{},"content",[427,609,610],{},"options?","), a ",[427,613,614],{},"progress"," reporter and an ",[427,617,546],{},", and returns ",[427,620,621],{},"{ data, mime, fileName }",[427,623,624],{},"createRenderer(targets)"," makes the ",[427,627,464],{}," of the host's ",[427,630,631],{},"ports.render",". A target whose ",[427,634,574],{}," repeats an earlier one is dropped, so a host can list its own before the defaults.",[637,638,644],"pre",{"className":639,"code":640,"filename":641,"language":642,"meta":643,"style":643},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { createRenderer, markdownTarget, type RenderTarget } from '@skaile\u002Fforge-editor\u002Fadapters\u002Frender'\nimport type { EditorPorts } from '@skaile\u002Fforge-editor\u002Fserver'\n\n\u002F\u002F A render target names the Block types (or 'document') it accepts and the MIME type it produces. `run` reports its\n\u002F\u002F steps through `progress` and returns the file; a thrown error reaches the client as the `error` event.\nconst plainText: RenderTarget = {\n  id: 'plain-text',\n  label: 'Text (.txt)',\n  accepts: ['document'],\n  mime: 'text\u002Fplain',\n  async run({ content }, progress) {\n    progress({ phase: 'collect', percent: 50 })\n    const text = JSON.stringify(content)\n    return { data: new TextEncoder().encode(text), mime: 'text\u002Fplain', fileName: 'document.txt' }\n  },\n}\n\n\u002F\u002F The renderer is one port: the host passes its targets, the built-in `markdown` among them.\nexport const render: NonNullable\u003CEditorPorts['render']> = createRenderer([markdownTarget(), plainText])\n","docs\u002Fsnippets\u002Frender-target.ts","ts","",[427,645,646,692,715,722,729,735,757,777,794,817,834,861,902,928,992,998,1004,1009,1015],{"__ignoreMap":643},[647,648,651,655,659,663,666,669,671,674,677,680,683,686,689],"span",{"class":649,"line":650},"line",1,[647,652,654],{"class":653},"s7zQu","import",[647,656,658],{"class":657},"sMK4o"," {",[647,660,662],{"class":661},"sTEyZ"," createRenderer",[647,664,665],{"class":657},",",[647,667,668],{"class":661}," markdownTarget",[647,670,665],{"class":657},[647,672,673],{"class":653}," type",[647,675,676],{"class":661}," RenderTarget",[647,678,679],{"class":657}," }",[647,681,682],{"class":653}," from",[647,684,685],{"class":657}," '",[647,687,566],{"class":688},"sfazB",[647,690,691],{"class":657},"'\n",[647,693,695,697,699,701,704,706,708,710,713],{"class":649,"line":694},2,[647,696,654],{"class":653},[647,698,673],{"class":653},[647,700,658],{"class":657},[647,702,703],{"class":661}," EditorPorts",[647,705,679],{"class":657},[647,707,682],{"class":653},[647,709,685],{"class":657},[647,711,712],{"class":688},"@skaile\u002Fforge-editor\u002Fserver",[647,714,691],{"class":657},[647,716,718],{"class":649,"line":717},3,[647,719,721],{"emptyLinePlaceholder":720},true,"\n",[647,723,725],{"class":649,"line":724},4,[647,726,728],{"class":727},"sHwdD","\u002F\u002F A render target names the Block types (or 'document') it accepts and the MIME type it produces. `run` reports its\n",[647,730,732],{"class":649,"line":731},5,[647,733,734],{"class":727},"\u002F\u002F steps through `progress` and returns the file; a thrown error reaches the client as the `error` event.\n",[647,736,738,742,745,748,751,754],{"class":649,"line":737},6,[647,739,741],{"class":740},"spNyl","const",[647,743,744],{"class":661}," plainText",[647,746,747],{"class":657},":",[647,749,676],{"class":750},"sBMFI",[647,752,753],{"class":657}," =",[647,755,756],{"class":657}," {\n",[647,758,760,764,766,768,771,774],{"class":649,"line":759},7,[647,761,763],{"class":762},"swJcz","  id",[647,765,747],{"class":657},[647,767,685],{"class":657},[647,769,770],{"class":688},"plain-text",[647,772,773],{"class":657},"'",[647,775,776],{"class":657},",\n",[647,778,780,783,785,787,790,792],{"class":649,"line":779},8,[647,781,782],{"class":762},"  label",[647,784,747],{"class":657},[647,786,685],{"class":657},[647,788,789],{"class":688},"Text (.txt)",[647,791,773],{"class":657},[647,793,776],{"class":657},[647,795,797,800,802,805,807,810,812,815],{"class":649,"line":796},9,[647,798,799],{"class":762},"  accepts",[647,801,747],{"class":657},[647,803,804],{"class":661}," [",[647,806,773],{"class":657},[647,808,809],{"class":688},"document",[647,811,773],{"class":657},[647,813,814],{"class":661},"]",[647,816,776],{"class":657},[647,818,820,823,825,827,830,832],{"class":649,"line":819},10,[647,821,822],{"class":762},"  mime",[647,824,747],{"class":657},[647,826,685],{"class":657},[647,828,829],{"class":688},"text\u002Fplain",[647,831,773],{"class":657},[647,833,776],{"class":657},[647,835,837,840,843,846,850,853,856,859],{"class":649,"line":836},11,[647,838,839],{"class":740},"  async",[647,841,842],{"class":762}," run",[647,844,845],{"class":657},"({",[647,847,849],{"class":848},"sHdIc"," content",[647,851,852],{"class":657}," },",[647,854,855],{"class":848}," progress",[647,857,858],{"class":657},")",[647,860,756],{"class":657},[647,862,864,868,871,874,877,879,881,884,886,888,891,893,897,899],{"class":649,"line":863},12,[647,865,867],{"class":866},"s2Zo4","    progress",[647,869,870],{"class":762},"(",[647,872,873],{"class":657},"{",[647,875,876],{"class":762}," phase",[647,878,747],{"class":657},[647,880,685],{"class":657},[647,882,883],{"class":688},"collect",[647,885,773],{"class":657},[647,887,665],{"class":657},[647,889,890],{"class":762}," percent",[647,892,747],{"class":657},[647,894,896],{"class":895},"sbssI"," 50",[647,898,679],{"class":657},[647,900,901],{"class":762},")\n",[647,903,905,908,911,913,916,919,922,924,926],{"class":649,"line":904},13,[647,906,907],{"class":740},"    const",[647,909,910],{"class":661}," text",[647,912,753],{"class":657},[647,914,915],{"class":661}," JSON",[647,917,918],{"class":657},".",[647,920,921],{"class":866},"stringify",[647,923,870],{"class":762},[647,925,607],{"class":661},[647,927,901],{"class":762},[647,929,931,934,936,939,941,944,947,950,952,955,957,960,962,964,967,969,971,973,975,977,980,982,984,987,989],{"class":649,"line":930},14,[647,932,933],{"class":653},"    return",[647,935,658],{"class":657},[647,937,938],{"class":762}," data",[647,940,747],{"class":657},[647,942,943],{"class":657}," new",[647,945,946],{"class":866}," TextEncoder",[647,948,949],{"class":762},"()",[647,951,918],{"class":657},[647,953,954],{"class":866},"encode",[647,956,870],{"class":762},[647,958,959],{"class":661},"text",[647,961,858],{"class":762},[647,963,665],{"class":657},[647,965,966],{"class":762}," mime",[647,968,747],{"class":657},[647,970,685],{"class":657},[647,972,829],{"class":688},[647,974,773],{"class":657},[647,976,665],{"class":657},[647,978,979],{"class":762}," fileName",[647,981,747],{"class":657},[647,983,685],{"class":657},[647,985,986],{"class":688},"document.txt",[647,988,773],{"class":657},[647,990,991],{"class":657}," }\n",[647,993,995],{"class":649,"line":994},15,[647,996,997],{"class":657},"  },\n",[647,999,1001],{"class":649,"line":1000},16,[647,1002,1003],{"class":657},"}\n",[647,1005,1007],{"class":649,"line":1006},17,[647,1008,721],{"emptyLinePlaceholder":720},[647,1010,1012],{"class":649,"line":1011},18,[647,1013,1014],{"class":727},"\u002F\u002F The renderer is one port: the host passes its targets, the built-in `markdown` among them.\n",[647,1016,1018,1021,1024,1027,1029,1032,1035,1038,1041,1043,1045,1047,1049,1052,1054,1056,1059,1062,1064,1066],{"class":649,"line":1017},19,[647,1019,1020],{"class":653},"export",[647,1022,1023],{"class":740}," const",[647,1025,1026],{"class":661}," render",[647,1028,747],{"class":657},[647,1030,1031],{"class":750}," NonNullable",[647,1033,1034],{"class":657},"\u003C",[647,1036,1037],{"class":750},"EditorPorts",[647,1039,1040],{"class":661},"[",[647,1042,773],{"class":657},[647,1044,433],{"class":688},[647,1046,773],{"class":657},[647,1048,814],{"class":661},[647,1050,1051],{"class":657},">",[647,1053,753],{"class":657},[647,1055,662],{"class":866},[647,1057,1058],{"class":661},"([",[647,1060,1061],{"class":866},"markdownTarget",[647,1063,949],{"class":661},[647,1065,665],{"class":657},[647,1067,1068],{"class":661}," plainText])\n",[418,1070,1071,1072,1074,1075,1078,1079,918],{},"A host that needs its own target logic, for example a per-user list, implements the ",[427,1073,464],{}," interface directly instead of calling ",[427,1076,1077],{},"createRenderer",". See the ",[1080,1081,1082],"a",{"href":346},"Renderer port reference",[553,1084,1086,1087,1089],{"id":1085},"the-built-in-markdown-target","The built-in ",[427,1088,429],{}," target",[418,1091,1092,1095,1096,1098,1099,500,1102,1105],{},[427,1093,1094],{},"markdownTarget(options?)"," renders a Typed block or a whole Document as Markdown, the same text the block action \"Als Markdown exportieren\" downloads: every Typed block becomes a heading with its description, tags and body beneath it. It accepts ",[427,1097,594],{}," and every Block type, takes ",[427,1100,1101],{},"schema",[427,1103,1104],{},"blockTypes"," options for a host with its own Block types, and needs no editor, only the schema.",[553,1107,1109],{"id":1108},"the-route","The route",[418,1111,1112,1114,1115,1118],{},[427,1113,492],{}," takes ",[427,1116,1117],{},"{ target, input }",". The server checks the request before the stream starts:",[436,1120,1121,1131],{},[439,1122,1123],{},[442,1124,1125,1128],{},[445,1126,1127],{},"Status",[445,1129,1130],{},"Cause",[455,1132,1133,1143,1153,1163,1173,1183],{},[442,1134,1135,1140],{},[460,1136,1137],{},[427,1138,1139],{},"400",[460,1141,1142],{},"malformed body or a Document ID that is not valid",[442,1144,1145,1150],{},[460,1146,1147],{},[427,1148,1149],{},"401",[460,1151,1152],{},"no user",[442,1154,1155,1160],{},[460,1156,1157],{},[427,1158,1159],{},"403",[460,1161,1162],{},"the user may not read the Document",[442,1164,1165,1170],{},[460,1166,1167],{},[427,1168,1169],{},"404",[460,1171,1172],{},"unknown target",[442,1174,1175,1180],{},[460,1176,1177],{},[427,1178,1179],{},"422",[460,1181,1182],{},"the target does not accept this Block type, or a whole Document",[442,1184,1185,1190],{},[460,1186,1187],{},[427,1188,1189],{},"501",[460,1191,1192,1193,1195,1196,1198],{},"the host has no ",[427,1194,433],{}," or no ",[427,1197,503],{}," port",[418,1200,1201,1202,1205,1206,571,1208,1211,1212,571,1215,1218,1219,571,1222,1225,1226,1229,1230,588,1233,1236,1237,1240],{},"After that the answer is a ",[427,1203,1204],{},"text\u002Fevent-stream"," with the events ",[427,1207,614],{},[427,1209,1210],{},"{ phase, percent? }","), then ",[427,1213,1214],{},"done",[427,1216,1217],{},"{ asset, fileName, mime }",") or ",[427,1220,1221],{},"error",[427,1223,1224],{},"{ message }","). The result is stored through ",[427,1227,1228],{},"ports.assets.storeAsset"," as an asset of ",[427,1231,1232],{},"input.documentId",[427,1234,1235],{},"asset"," is the asset name: read it with the asset route (",[427,1238,1239],{},"GET \u002Fapi\u002Feditor\u002Fassets\u002F:documentId\u002F:asset","), like any upload.",[553,1242,1244],{"id":1243},"the-client","The client",[418,1246,1247,1250,1251,1253,1254,1257,1258,1261,1262,571,1265,1268,1269,1272],{},[427,1248,1249],{},"backend.render"," is present when the server serves the ",[427,1252,433],{}," capability. ",[427,1255,1256],{},"backend.render.render(target, input, { onProgress, signal })"," resolves with ",[427,1259,1260],{},"{ asset, fileName, mime, url }"," and rejects with the server's message when the render fails. The loop over the stream is ",[427,1263,1264],{},"postSse",[427,1266,1267],{},"core\u002Fsse.ts","), the same helper the AI streams use (",[427,1270,1271],{},"postAiSse"," calls it), so there is one parser for server-sent events in the client.",[553,1274,1276],{"id":1275},"in-the-editor","In the editor",[418,1278,1279,1280,1282],{},"The composites feature adds both entries when the backend serves ",[427,1281,433],{},", and hides them otherwise:",[1284,1285,1286,1299],"ul",{},[1287,1288,1289,1290,571,1293,1295,1296,1298],"li",{},"the block action ",[422,1291,1292],{},"„Erzeugen als …“",[427,1294,433],{},") on a Typed block, a menu of the targets whose ",[427,1297,580],{}," names the Block type;",[1287,1300,1301,1302,571,1305,1307,1308,918],{},"the command ",[422,1303,1304],{},"„Dokument erzeugen als …“",[427,1306,533],{},", ⌘K palette), a menu of the targets that accept ",[427,1309,594],{},[418,1311,1312],{},"A notice reports the phase and percent of the running render, then the end. The finished file downloads at once.",[1314,1315,1316],"style",{},"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 .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}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 .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 .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}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 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 .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);}",{"title":643,"searchDepth":694,"depth":694,"links":1318},[1319,1320,1322,1323,1324],{"id":555,"depth":694,"text":556},{"id":1085,"depth":694,"text":1321},"The built-in markdown target",{"id":1108,"depth":694,"text":1109},{"id":1243,"depth":694,"text":1244},{"id":1275,"depth":694,"text":1276},"The Renderer port with its render targets, the SSE route that streams progress and stores the result as an asset, the client call, and the block action and command that offer it.","md",null,{},{"icon":217},{"title":214,"description":1325},"HYClmCfjIBxGIoFovD6-0TDh9ZlTQTBcAGfeO4WzQxc",[1333,1335],{"title":210,"path":211,"stem":212,"description":1334,"icon":193,"children":-1},"What is connected to a Block: the Blocks that point at it, the Blocks related to it, and the chain of Derivations behind it. The explore Feature, the panel, the related route and derivationTrailOf.",{"title":219,"path":220,"stem":221,"description":1336,"icon":222,"children":-1},"The importer registry of the feature contract: Importer and ImportPlan, planImport, the Markdown, subtitle and BibTeX importers of the media feature, and how composite-media wraps the plan.",1793178234743]