尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
The lunatic is on the grass
The lunatic is on the grass【免费下载链接】milkdown Plugin driven WYSIWYG markdown editor framework.项目地址: https://gitcode.com/GitHub_Trending/mi/milkdownThe lunatic is on the grassThe lunatic is on the grassThe lunatic is on the grass该文件覆盖了 Markdown 最常用的四级标题# 到 ####对应 HTML 的 h1 到 h4并且刻意让每级标题使用**相同的文本内容** The lunatic is on the grass。这种设计并非随意为之它让测试能够在“文本内容完全一致”的前提下专注于验证标题**级别level属性**、**DOM 标签h1/h2/h3/h4**以及**标题 id 去重机制**的行为差异从而精确暴露标题节点独有的处理逻辑。 需要说明的是e2e/tests/data 下的夹具大多由测试用例通过 loadFixture 统一加载见 [e2e/tests/misc/index.ts](https://link.gitcode.com/i/a74c742b469094e0e57409df487c53b9)而 heading.md 同时被输入类、快捷键类测试直接引用是理解 Milkdown 标题节点行为的核心数据源。 ## Markdown 解析阶段标题如何进入编辑器 Milkdown 通过 milkdown/transformer 将 Markdown 文本解析为 ProseMirror 文档。标题的解析入口位于 preset-commonmark 的 heading 节点定义 [packages/plugins/preset-commonmark/src/node/heading.ts](https://link.gitcode.com/i/a12110c4b3c2af7092be5cf5cddc6e64) ts parseMarkdown: { match: ({ type }) type heading, runner: (state, node, type) { const depth node.depth as number state.openNode(type, { level: depth }) state.next(node.children) state.closeNode() }, },解析逻辑非常直白当 Markdown 抽象语法树中出现heading类型节点时直接取其depth即#的个数作为 ProseMirror 节点属性level然后递归处理子节点标题内的行内内容如加粗、斜体、链接等最后关闭节点。对应的序列化方向同样在同一个文件中toMarkdown: { match: (node) node.type.name heading, runner: (state, node) { state.openNode(heading, undefined, { depth: node.attrs.level }) serializeText(state, node) state.closeNode() }, },toMarkdown将编辑器内的 heading 节点重新写回 Markdown以node.attrs.level作为depth再序列化标题的行内文本。这样# The lunatic is on the grass在“Markdown → 编辑器 DOM → Markdown”的往返过程中可以保持语义一致。Heading 节点 Schemalevel 与 id 双属性建模标题节点的 ProseMirror Schema 定义在同一文件 heading.ts其核心结构如下export const headingSchema $nodeSchema(heading, (ctx) { const getId ctx.get(headingIdGenerator.key) return { content: inline*, group: block, defining: true, attrs: { id: { default: , validate: string }, level: { default: 1, validate: number }, }, parseDOM: headingIndex.map((x) ({ tag: h${x}, getAttrs: (node) ({ level: x, id: node.id }), })), toDOM: (node) [ h${node.attrs.level}, { ...ctx.get(headingAttr.key)(node), id: node.attrs.id || getId(node) }, 0, ], } })值得注意的细节content: inline*标题内只允许行内内容文本、强调、代码、链接等不允许嵌套块级节点defining: true声明标题是“定义性”块在块删除/提升等操作中会保留其结构边界level标题级别16对应h1h6id标题锚点 idtoDOM中当id为空时会调用getId(node)自动生成详见下文。parseDOM由headingIndex动态生成Array(6).fill(0).map((_, i) i 1)即同时注册h1h6六个 HTML 标签的解析规则粘贴 HTML 内容时也会被识别为标题节点。标题与段落等节点一起在 composed/schema.ts 中被注册进preset-commonmark的 schema 组合中。标题 id 的生成与去重机制标题 id 是 Milkdown 标题节点的一大特色默认根据文本内容生成 slug 形式的锚点 id。生成器通过$ctx暴露可在初始化编辑器时自定义function defaultHeadingIdGenerator(node: Node) { return node.textContent.toLowerCase().trim().replace(/\s/g, -) } export const headingIdGenerator $ctx( defaultHeadingIdGenerator, headingIdGenerator )默认规则为取标题文本 → 转小写 → 去首尾空白 → 将连续空白替换为-。例如# The lunatic is on the grass会生成the-lunatic-is-on-the-grass。重复 id 的处理由syncHeadingIdPlugin完成它被注册在 composed/plugins.ts 中。其行为在 e2e/tests/input/heading.spec.ts 中有精确断言# Heading1 → id: heading1 # Heading1 → id: heading1-#2 ## Heading1 → id: heading1-#3即当出现同文本的重复标题时后续标题会在基础 id 后追加-#2、-#3等后缀以保证唯一性。这意味着即使标题文本完全相同每个标题仍拥有可稳定引用的锚点 id——这正是 heading.md 夹具让四行标题文本全部相同的原因之一它便于在“文本相同”的前提下单独验证 id 去重逻辑。输入规则输入#即可生成标题wrapInHeadingInputRule提供了 Markdown 风格的快捷输入在行首输入若干#并跟一个空格当前块即被转换为对应级别的标题heading.tstextblockTypeInputRule( /^(?hashes#)\s$/, headingSchema.type(ctx), (match) { const x match.groups?.hashes?.length || 0 const view ctx.get(editorViewCtx) const { $from } view.state.selection const node $from.node() if (node.type.name heading) { let level Number(node.attrs.level) Number(x) if (level 6) level 6 return { level } } return { level: x } } )【免费下载链接】milkdown Plugin driven WYSIWYG markdown editor framework.项目地址: https://gitcode.com/GitHub_Trending/mi/milkdown创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

MetaMask Extension 如何用 Mock Segment API 调试 MetaMetrics 事件?

MetaMask Extension 如何用 Mock Segment API 调试 MetaMetrics 事件?

MetaMask Extension 如何用 Mock Segment API 调试 MetaMetrics 事件? 【免费下载链接】metamask-extension :globe_with_meridians: :electric_plug: The MetaMask browser extension enables browsing Ethereum blockchain enabled websites 项目地址: https://…

📅 2026/9/15 11:09:49
pyannote.audio 官方 FAQ 全解读:内存音频、离线使用 gated 模型、流式说话人日志与性能提升

pyannote.audio 官方 FAQ 全解读:内存音频、离线使用 gated 模型、流式说话人日志与性能提升

pyannote.audio 官方 FAQ 全解读:内存音频、离线使用 gated 模型、流式说话人日志与性能提升 【免费下载链接】pyannote-audio Neural building blocks for speaker diarization: speech activity detection, speaker change detection, overlapped speech detectio…

📅 2026/9/15 11:09:49
如何 5 分钟跑通 SillyTavern:免费 AI 角色扮演聊天室的完整上手指南

如何 5 分钟跑通 SillyTavern:免费 AI 角色扮演聊天室的完整上手指南

如何 5 分钟跑通 SillyTavern:免费 AI 角色扮演聊天室的完整上手指南 【免费下载链接】SillyTavern LLM Frontend for Power Users. 项目地址: https://gitcode.com/GitHub_Trending/si/SillyTavern 晚上想找个角色聊聊天,翻遍各种 API 页面却只有…

📅 2026/9/15 11:09:49
MORE NEWS

更多资讯

📰

Thrift module: DocTest

Thrift module: DocTest 【免费下载链接】thrift Apache Thrift 项目地址: https://gitcode.com/GitHub_Trending/thr/thrift **随后**是模块级文档注释(对应 namespace * markdown_test 上方的注释,本例中该注释为空,因此未出现&#…

📰

Claude Code技术栈解析:LLM驱动的智能编程助手

1. 项目概述:Claude Code技术栈解析Claude Code是基于大型语言模型(LLM)的智能编码代理框架,它通过将Claude模型的自然语言理解能力与代码生成功能相结合,为开发者提供智能化的编程辅助工具。这个框架本质上构建了一个"思考-行动"循…

📰

Mealie 批量 URL 导入实战指南:用 Bash、Python 脚本与内置批量导入器批量抓取菜谱

Mealie 批量 URL 导入实战指南:用 Bash、Python 脚本与内置批量导入器批量抓取菜谱 【免费下载链接】mealie Mealie is a self hosted recipe manager and meal planner with a RestAPI backend and a reactive frontend application built in Vue for a pleasant u…

📰

零拷贝技术详解:从原理到实战,掌握mmap与sendfile

1. 先聊聊零拷贝到底是什么前两天团队里一个小伙子跑来问我:“Kafka 天天吹自己用了零拷贝,到底零在哪?我看源码里也就是调了 transferTo,凭什么就能比我们现在的方案快那么多?”这个问题问得挺好的。很多人一说零拷贝…

📰

香港科技大学北京校友会2026年会亮点解析

1. 活动背景与核心价值解析香港科技大学北京校友会2026年会以"携手同心 向光而行"为主题,这场年度盛事不仅是校友联络感情的纽带,更是跨行业、跨届别校友资源整合的重要平台。作为在华北地区规模最大的港科大人聚会,今年特别选在北…

📰

LongProc 长程过程生成基准评测任务:在 lm-evaluation-harness 中使用与指标解析

LongProc 长程过程生成基准评测任务:在 lm-evaluation-harness 中使用与指标解析 【免费下载链接】lm-evaluation-harness A framework for few-shot evaluation of language models. 项目地址: https://gitcode.com/GitHub_Trending/lm/lm-evaluation-harness …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬