[{"data":1,"prerenderedAt":463},["ShallowReactive",2],{"msfe-doc:\u002Fextensions\u002Fcode-blocks":3},{"id":4,"title":5,"body":6,"description":451,"extension":452,"keywords":453,"locale":456,"meta":457,"navigation":180,"order":138,"path":458,"section":459,"seo":460,"stem":461,"__hash__":462},"docs\u002Fextensions\u002Fcode-blocks.zh-CN.md","代码块定制",{"type":7,"value":8,"toc":441},"minimark",[9,13,17,21,24,90,104,107,248,263,266,285,292,308,311,328,345,348,353,368,386,389,420,427,430,437],[10,11,12],"h2",{"id":12},"完整代码块工具栏",[14,15,16],"p",{},"示例给代码围栏增加语言选择器。修改语言仅改变 header 的语言字段；代码正文、围栏字符和其他内容保留。切换只读后语言选择器禁用，撤销恢复原语言。",[18,19],"msfe-demo",{"name":20},"code-block\u002Feditor",[10,22,23],{"id":23},"先选择定制层",[25,26,27,40],"table",{},[28,29,30],"thead",{},[31,32,33,37],"tr",{},[34,35,36],"th",{},"需求",[34,38,39],{},"入口",[41,42,43,56,66,77],"tbody",{},[31,44,45,49],{},[46,47,48],"td",{},"改代码字体、背景、间距",[46,50,51,55],{},[52,53,54],"code",{},"EditorView.theme()"," 和语法高亮",[31,57,58,61],{},[46,59,60],{},"增加语言、复制、菜单控件",[46,62,63],{},[52,64,65],{},"CodeBlock.extend({ addNodeView() {} })",[31,67,68,71],{},[46,69,70],{},"支持 TypeScript、JSON 等语法着色",[46,72,73,74],{},"创建选项 ",[52,75,76],{},"codeLanguages",[31,78,79,82],{},[46,80,81],{},"Mermaid、ECharts 或 flow DSL 图形输出",[46,83,84,85],{},"独立语义扩展 + 块级投影，见 ",[86,87,89],"a",{"href":88},"\u002Fextensions\u002Fdiagrams","图表预览",[14,91,92,95,96,99,100,103],{},[52,93,94],{},"CodeBlock"," 的 NodeView 位于围栏前方，属于 ",[52,97,98],{},"placement: 'before'","。它不是整个代码正文的替换入口，也没有 ",[52,101,102],{},"contentDOM"," 供你接管输入。",[10,105,106],{"id":106},"覆盖预设中的一个功能",[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","",[52,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",[14,249,250,251,254,255,258,259,262],{},"不要同时安装 ",[52,252,253],{},"StarterKit"," 和同名 ",[52,256,257],{},"CustomCodeBlock","。如果使用更小的按需预设，也可以禁用预设中的 ",[52,260,261],{},"codeBlock"," 后单独安装一个实现。",[10,264,265],{"id":265},"控件可读写什么",[14,267,268,269,272,273,276,277,280,281,284],{},"组件接收 ",[52,270,271],{},"nodeView: MsfeNodeViewProps\u003CCodeBlockAttributes>","。目前持久属性只有 ",[52,274,275],{},"language","，可调用 ",[52,278,279],{},"nodeView.updateAttributes({ language: 'json' })","。合法语言 token 长度不超过 40，允许字母、数字、下划线及 ",[52,282,283],{},"+ # . -","，不允许换行和任意 header 注入。",[14,286,287,288,291],{},"也可在当前代码块选区使用 ",[52,289,290],{},"editor.commands.setCodeLanguage('typescript')","。它依赖已确认的围栏语法和适用选区；返回 false 时检查结果。语言高亮目录和语言字段校验分别负责不同的事，某个字段合法不代表安装了对应高亮器。",[14,293,294,295,298,299,302,303,307],{},"复制源码属于读取动作：由宿主读取当前已确认的 ",[52,296,297],{},"CodeText"," 范围，保持换行和缩进。NodeView 的 ",[52,300,301],{},"getRange()"," 只提供范围，不承诺给你一份可直接当作代码正文的字符串。跨弹窗动作使用 ",[86,304,306],{"href":305},"\u002Fguide\u002Fselection","锚点","。",[10,309,310],{"id":310},"按需加载语言",[14,312,313,314,317,318,321,322,325,326,307],{},"示例 ",[52,315,316],{},"code-block\u002Flanguages.ts"," 提供 TypeScript、JavaScript 和 JSON，相关依赖为 ",[52,319,320],{},"@quirekit\u002Fcm-lang-javascript"," 与 ",[52,323,324],{},"@quirekit\u002Fcm-lang-json","。创建编辑器时传 ",[52,327,76],{},[14,329,330,321,333,336,337,340,341,344],{},[52,331,332],{},"name",[52,334,335],{},"aliases"," 精确匹配且大小写不敏感。",[52,338,339],{},"load(signal)"," 返回 ",[52,342,343],{},"LanguageSupport","；未知语言保持纯文本，不推测文件名或动态下载任意包。动态导入不能真正中断，宿主资源需要观察信号，过期结果不能覆盖新的编辑器状态。",[10,346,347],{"id":347},"没有正文行的空围栏",[14,349,350,352],{},[52,351,94],{}," 默认给相邻的开闭围栏提供「输入代码」占位行。点击或用 Enter \u002F Space 激活后，\n通过普通编辑命令插入一行，保留引用和列表缩进，并把光标放入代码正文。显示占位、滚动和\n切换模式不改变 Markdown；已有真实空行不重复占位。只读不能激活，插入支持撤销和重做。",[14,354,355,356,359,360,363,364,367],{},"使用 ",[52,357,358],{},"CodeBlock.configure({ emptyLine: false })"," 可关闭；",[52,361,362],{},"emptyLineLabel"," 设置可访问的提示文字。\nMD Editor 通过 ",[52,365,366],{},"features.codeBlock: ProseCodeBlock.configure({ emptyLine: false })"," 配置，默认按界面语言显示提示。\n源码模式始终展示真实围栏和换行，不显示占位。",[14,369,370,371,374,375,377,378,381,382,385],{},"MD Editor 默认提供 ",[52,372,373],{},"mdCodeLanguages","：TypeScript、JavaScript \u002F JSX、TSX、JSON、CSS、HTML、\nPython、Bash 和 Markdown，按需加载；传 ",[52,376,76],{}," 会替换整份目录，传 ",[52,379,380],{},"[]"," 禁用默认目录。\n自定义主题和语法包必须共享同一版本的 ",[52,383,384],{},"@lezer\u002Fhighlight","，否则标记身份不一致会导致已解析却无颜色。",[10,387,388],{"id":388},"样式和源码活动状态",[14,390,391,392,395,396,395,399,395,402,395,405,408,409,412,413,416,417,307],{},"可从 ",[52,393,394],{},".msfe-code-line","、",[52,397,398],{},".msfe-code-start",[52,400,401],{},".msfe-code-body-start",[52,403,404],{},".msfe-code-end",[52,406,407],{},".msfe-code-indented"," 等语义类设置外观，并由 ",[52,410,411],{},"HighlightStyle"," 定义代码 token。语言 token 隐藏与编辑器行布局应由运行时处理；不要隐藏所有 ",[52,414,415],{},".cm-line"," 或把代码正文移到另一个 ",[52,418,419],{},"contenteditable",[14,421,422,423,307],{},"进入围栏源码范围时，活动源码会显露。中文组合输入、跨块拖选、复制和撤销都应继续走原生编辑链路。高度变化使用组件测量入口，详见 ",[86,424,426],{"href":425},"\u002Fextensions\u002Fprojections","投影层",[10,428,429],{"id":429},"验证范围",[14,431,432,433,307],{},"至少测试：切换语言、撤销、空\u002F未知语言、长代码、未闭合围栏、反引号和波浪线围栏、只读、Tab 缩进，以及主题切换后代码仍可编辑。完整选项和组件协议见 ",[86,434,436],{"href":435},"\u002Fapi\u002Frendering","渲染 API",[438,439,440],"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":442},[443,444,445,446,447,448,449,450],{"id":12,"depth":138,"text":12},{"id":23,"depth":138,"text":23},{"id":106,"depth":138,"text":106},{"id":265,"depth":138,"text":265},{"id":310,"depth":138,"text":310},{"id":347,"depth":138,"text":347},{"id":388,"depth":138,"text":388},{"id":429,"depth":138,"text":429},"定制工具栏、语言高亮和样式，理解与整块预览的边界。","md",[94,76,454,455],"setCodeLanguage","syntaxHighlighting","zh-CN",{},"\u002Fextensions\u002Fcode-blocks","扩展开发",{"title":5,"description":451},"extensions\u002Fcode-blocks.zh-CN","3SaALsnAcKiH41HFyoXG51SvqzOqa91uL_mK85R2GeA",1793046311420]