[{"data":1,"prerenderedAt":449},["ShallowReactive",2],{"msfe-doc:\u002Fen\u002Fextensions\u002Fcode-blocks":3},{"id":4,"title":5,"body":6,"description":437,"extension":438,"keywords":439,"locale":442,"meta":443,"navigation":180,"order":138,"path":444,"section":445,"seo":446,"stem":447,"__hash__":448},"docs\u002Fextensions\u002Fcode-blocks.en.md","Custom code blocks",{"type":7,"value":8,"toc":427},"minimark",[9,14,18,22,26,92,103,107,248,251,255,274,281,297,301,318,329,333,339,354,372,376,404,411,415,423],[10,11,13],"h2",{"id":12},"complete-toolbar-example","Complete toolbar example",[15,16,17],"p",{},"The example adds a language selector to a fence. Changing language edits only its header field, preserving the body and fence spelling. Locked mode disables the selector; undo restores the previous language.",[19,20],"msfe-demo",{"name":21},"code-block\u002Feditor",[10,23,25],{"id":24},"choose-the-customization-layer","Choose the customization layer",[27,28,29,42],"table",{},[30,31,32],"thead",{},[33,34,35,39],"tr",{},[36,37,38],"th",{},"Goal",[36,40,41],{},"Entry point",[43,44,45,58,68,79],"tbody",{},[33,46,47,51],{},[48,49,50],"td",{},"Fonts, surfaces and spacing",[48,52,53,57],{},[54,55,56],"code",{},"EditorView.theme()"," and syntax highlighting",[33,59,60,63],{},[48,61,62],{},"Language, copy or menu controls",[48,64,65],{},[54,66,67],{},"CodeBlock.extend({ addNodeView() {} })",[33,69,70,73],{},[48,71,72],{},"TypeScript, JSON and other grammars",[48,74,75,78],{},[54,76,77],{},"codeLanguages"," creation option",[33,80,81,84],{},[48,82,83],{},"Mermaid, ECharts or flow DSL output",[48,85,86,87],{},"Semantic extension plus block projection; see ",[88,89,91],"a",{"href":90},"\u002Fen\u002Fextensions\u002Fdiagrams","Diagrams",[15,93,94,95,98,99,102],{},"The CodeBlock NodeView sits before the fence with ",[54,96,97],{},"placement: 'before'",". It does not replace the complete code body and provides no editable ",[54,100,101],{},"contentDOM",".",[10,104,106],{"id":105},"replace-one-preset-feature","Replace one preset feature",[108,109,114],"pre",{"className":110,"code":111,"language":112,"meta":113,"style":113},"language-ts shiki shiki-themes github-light github-light github-dark","import { StarterKit } from '@quirekit\u002Fmsfe-starter-kit'\nimport { CodeBlock } from '@quirekit\u002Fmsfe-code-block'\nimport { VueNodeViewRenderer } from '@quirekit\u002Fmsfe-vue'\nimport Toolbar from '.\u002Ftoolbar.vue'\n\nconst CustomCodeBlock = CodeBlock.extend({\n  addNodeView() { return VueNodeViewRenderer(Toolbar) },\n})\nconst extensions = [StarterKit.configure({ codeBlock: CustomCodeBlock })]\n","ts","",[54,115,116,136,149,162,175,182,205,223,229],{"__ignoreMap":113},[117,118,121,125,129,132],"span",{"class":119,"line":120},"line",1,[117,122,124],{"class":123},"sDD9d","import",[117,126,128],{"class":127},"sVPnS"," { StarterKit } ",[117,130,131],{"class":123},"from",[117,133,135],{"class":134},"s-HEn"," '@quirekit\u002Fmsfe-starter-kit'\n",[117,137,139,141,144,146],{"class":119,"line":138},2,[117,140,124],{"class":123},[117,142,143],{"class":127}," { CodeBlock } ",[117,145,131],{"class":123},[117,147,148],{"class":134}," '@quirekit\u002Fmsfe-code-block'\n",[117,150,152,154,157,159],{"class":119,"line":151},3,[117,153,124],{"class":123},[117,155,156],{"class":127}," { VueNodeViewRenderer } ",[117,158,131],{"class":123},[117,160,161],{"class":134}," '@quirekit\u002Fmsfe-vue'\n",[117,163,165,167,170,172],{"class":119,"line":164},4,[117,166,124],{"class":123},[117,168,169],{"class":127}," Toolbar ",[117,171,131],{"class":123},[117,173,174],{"class":134}," '.\u002Ftoolbar.vue'\n",[117,176,178],{"class":119,"line":177},5,[117,179,181],{"emptyLinePlaceholder":180},true,"\n",[117,183,185,188,192,195,198,202],{"class":119,"line":184},6,[117,186,187],{"class":123},"const",[117,189,191],{"class":190},"sUNQB"," CustomCodeBlock",[117,193,194],{"class":123}," =",[117,196,197],{"class":127}," CodeBlock.",[117,199,201],{"class":200},"sgQzM","extend",[117,203,204],{"class":127},"({\n",[117,206,208,211,214,217,220],{"class":119,"line":207},7,[117,209,210],{"class":200},"  addNodeView",[117,212,213],{"class":127},"() { ",[117,215,216],{"class":123},"return",[117,218,219],{"class":200}," VueNodeViewRenderer",[117,221,222],{"class":127},"(Toolbar) },\n",[117,224,226],{"class":119,"line":225},8,[117,227,228],{"class":127},"})\n",[117,230,232,234,237,239,242,245],{"class":119,"line":231},9,[117,233,187],{"class":123},[117,235,236],{"class":190}," extensions",[117,238,194],{"class":123},[117,240,241],{"class":127}," [StarterKit.",[117,243,244],{"class":200},"configure",[117,246,247],{"class":127},"({ codeBlock: CustomCodeBlock })]\n",[15,249,250],{},"Do not install both StarterKit's original owner and a derived owner with the same name. Alternatively disable the preset entry and install exactly one replacement.",[10,252,254],{"id":253},"available-fields-and-actions","Available fields and actions",[15,256,257,258,261,262,265,266,269,270,273],{},"The component receives ",[54,259,260],{},"nodeView: MsfeNodeViewProps\u003CCodeBlockAttributes>",". The persisted field is currently ",[54,263,264],{},"language",". Call ",[54,267,268],{},"nodeView.updateAttributes({ language: 'json' })",". Admitted language tokens contain at most 40 letters, digits, underscores or ",[54,271,272],{},"+ # . -","; newlines and arbitrary header injection are rejected.",[15,275,276,277,280],{},"With an applicable selection, ",[54,278,279],{},"editor.commands.setCodeLanguage('typescript')"," updates a confirmed fence. Check failure results. Field validity does not imply that a matching highlighter was installed.",[15,282,283,284,287,288,291,292,296],{},"Copying is a read action: the host should read confirmed ",[54,285,286],{},"CodeText"," ranges while preserving indentation and line breaks. NodeView ",[54,289,290],{},"getRange()"," supplies coordinates, not an already-extracted code body. Use ",[88,293,295],{"href":294},"\u002Fen\u002Fguide\u002Fselection","anchors"," for actions spanning a dialog.",[10,298,300],{"id":299},"lazy-language-loading","Lazy language loading",[15,302,303,306,307,310,311,314,315,317],{},[54,304,305],{},"code-block\u002Flanguages.ts"," supplies TypeScript, JavaScript and JSON through ",[54,308,309],{},"@quirekit\u002Fcm-lang-javascript"," and ",[54,312,313],{},"@quirekit\u002Fcm-lang-json",". Pass the registry as ",[54,316,77],{}," when creating the editor.",[15,319,320,321,324,325,328],{},"Names and aliases match exactly, case-insensitively. ",[54,322,323],{},"load(signal)"," returns ",[54,326,327],{},"LanguageSupport",". Unknown languages remain plain text; no package path is guessed or downloaded. Dynamic imports cannot truly abort, so host resources must respect cancellation and discard obsolete results.",[10,330,332],{"id":331},"closed-fences-without-a-body-line","Closed fences without a body line",[15,334,335,338],{},[54,336,337],{},"CodeBlock"," shows an input placeholder when the opening and closing fence are on adjacent lines.\nClicking it or activating it with Enter \u002F Space inserts one real line through a normal editor command,\npreserves quote\u002Flist prefixes, and moves the caret into the body. Rendering, scrolling and mode changes\ndo not modify Markdown. Existing empty body lines need no placeholder. Read-only mode disables activation;\nmaterializing the line supports undo and redo.",[15,340,341,342,345,346,349,350,353],{},"Set ",[54,343,344],{},"CodeBlock.configure({ emptyLine: false })"," to disable it; ",[54,347,348],{},"emptyLineLabel"," supplies the accessible hint.\nMD Editor accepts ",[54,351,352],{},"features.codeBlock: ProseCodeBlock.configure({ emptyLine: false })"," and localizes the default hint.\nSource mode shows the actual fences and newlines without an input placeholder.",[15,355,356,357,360,361,363,364,367,368,371],{},"MD Editor provides the lazy ",[54,358,359],{},"mdCodeLanguages"," catalog by default: TypeScript, JavaScript \u002F JSX, TSX, JSON,\nCSS, HTML, Python, Bash and Markdown. Supplying ",[54,362,77],{}," replaces the catalog; ",[54,365,366],{},"[]"," disables it.\nCustom themes and grammar packages must share the same ",[54,369,370],{},"@lezer\u002Fhighlight"," version: different tag identities\ncan leave parsed tokens without colors.",[10,373,375],{"id":374},"styling-and-active-source","Styling and active source",[15,377,378,379,382,383,382,386,382,389,310,392,395,396,399,400,403],{},"Style semantic classes such as ",[54,380,381],{},".msfe-code-line",", ",[54,384,385],{},".msfe-code-start",[54,387,388],{},".msfe-code-body-start",[54,390,391],{},".msfe-code-end",[54,393,394],{},".msfe-code-indented","; use ",[54,397,398],{},"HighlightStyle"," for code tokens. Let the runtime handle source-token reveal and line layout. Do not hide arbitrary ",[54,401,402],{},".cm-line"," elements or move the body into another editable region.",[15,405,406,407,102],{},"Selecting a fence reveals active source. Composition, cross-block drag selection, copying and history remain native. Report geometry changes through the component measurement entry; see ",[88,408,410],{"href":409},"\u002Fen\u002Fextensions\u002Fprojections","Projection layers",[10,412,414],{"id":413},"verification","Verification",[15,416,417,418,422],{},"Cover language changes and undo, empty\u002Funknown languages, long code, unclosed fences, both fence characters, readonly mode, Tab indentation and theme changes. See ",[88,419,421],{"href":420},"\u002Fen\u002Fapi\u002Frendering","Rendering API"," for exact language and component contracts.",[424,425,426],"style",{},"html pre.shiki code .sDD9d, html code.shiki .sDD9d{--shiki-default:#D73A49;--shiki-light:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVPnS, html code.shiki .sVPnS{--shiki-default:#24292E;--shiki-light:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s-HEn, html code.shiki .s-HEn{--shiki-default:#032F62;--shiki-light:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sUNQB, html code.shiki .sUNQB{--shiki-default:#005CC5;--shiki-light:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sgQzM, html code.shiki .sgQzM{--shiki-default:#6F42C1;--shiki-light:#6F42C1;--shiki-dark:#B392F0}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 .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 .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":113,"searchDepth":138,"depth":138,"links":428},[429,430,431,432,433,434,435,436],{"id":12,"depth":138,"text":13},{"id":24,"depth":138,"text":25},{"id":105,"depth":138,"text":106},{"id":253,"depth":138,"text":254},{"id":299,"depth":138,"text":300},{"id":331,"depth":138,"text":332},{"id":374,"depth":138,"text":375},{"id":413,"depth":138,"text":414},"Customize toolbars, language loading and styles while retaining native code editing.","md",[337,77,440,441],"setCodeLanguage","syntaxHighlighting","en",{},"\u002Fen\u002Fextensions\u002Fcode-blocks","Extensions",{"title":5,"description":437},"extensions\u002Fcode-blocks.en","2rfhc3IQIADeXh4mIHjSJNWBv5UtOLqxQTB4mayNpwo",1793046312518]