news 2026/9/16 14:29:12

Nuemark 语法完全参考:Nue 内容优先标记语言详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Nuemark 语法完全参考:Nue 内容优先标记语言详解

Nuemark 语法完全参考:Nue 内容优先标记语言详解

【免费下载链接】nueFastest way to build modern websites项目地址: https://gitcode.com/GitHub_Trending/nu/nue

Nuemark 是 Nue 项目中面向内容创作者的 Markdown 扩展格式,它保留了标准 Markdown 的全部能力,同时新增了区块(sections)、块(blocks)、标签(tags)、脚注与自定义组件等面向现代网页开发的语法结构。本文以仓库 packages/www/docs/nuemark-syntax.md 为骨架,结合 packages/nuemark 包的真实源码与测试用例,系统讲解 Nuemark 的每一种语法形态、其底层解析逻辑与最终 HTML 输出,帮助你直接用 Markdown 写出结构清晰、组件化、可交互的内容页面。

一、Nuemark 在项目中的位置

Nuemark 是独立的核心包之一,入口在 packages/nuemark/index.js。它对外暴露三个主要 API:

  • nuemark(content, opts):把一段 Markdown 字符串直接渲染成 HTML;
  • parseNuemark(content):把文档解析为结构化的 AST(blocksmetaheadingscodeblocks等),供程序化查询;
  • parseSize/renderIcon等工具函数。

解析过程分为两段:先由parseBlocks/parseDocument把文本拆成块级与行内 token,再由renderBlocks/renderInline输出 HTML。整条管线不依赖任何运行时框架,既可以在构建期渲染成静态页面,也可以作为服务端 API 使用。如果你想先了解整体设计理念,可阅读 Nuemark 介绍 与 项目 README。

二、文件结构与 Front Matter

Nuemark 文件使用.md扩展名,文件头部可以携带可选的 YAML front matter,用于注入页面元数据:

--- title: My Page date: 2024-01-15 tags: [web, design] --- # Page content starts here

front matter 的元数据可以被布局、组件和构建系统读取。从源码实现看,front matter 的提取与解析发生在 src/parse-document.js 的stripMeta函数中:它扫描文件前几行,找到成对的---定界符,把中间内容拼接后交给nueyaml包的parseYAML解析,因此所有标准 YAML 类型(字符串、数字、布尔、数组、嵌套对象)都受支持

stripMeta之后,parseDocument还会自动做两件补充:

  • 自动标题:如果 front matter 没有title,会从正文第一个h1(或标签块内的标题)提取标题;
  • 自动描述:如果 front matter 没有description,会取第一个内容块的第一行作为描述。

也就是说,即使不写 front matter,文档对象依然可以拿到meta.titlemeta.description,这对 SEO 和内容聚合非常友好。

三、标准 Markdown 支持

Nuemark 完整支持标准 Markdown 语法,包括各级标题、段落、加粗/斜体/行内代码、无序/有序列表(含嵌套)、多行引用、链接、图片等:

# Heading 1 ## Heading 2 ### Heading 3 This is a paragraph with **bold** and *italic* text, plus `inline code`. - Unordered list item - Another item - Nested item 1. Ordered list 2. Second item > Blockquote with multiple lines > continues here [Link text](https://example.com) Alt text

在块级解析(src/parse-blocks.js)中,行首字符决定了块的类型:#开头识别为标题、-/*/数字.开头识别为列表项、>开头识别为引用、|...|识别为表格、```识别为围栏代码块,其余非空行按连续段落合并。引用与列表支持嵌套递归解析,例如测试 test/block.test.js 验证了- item内再缩进- nested会生成多层<ul><li>结构。

另外,代码解析器会跳过以<开头的行和//开头的注释行,这些内容不会进入输出。

代码块与语法高亮

围栏代码块通过语言标注启用高亮:

```js function hello() { return "Hello world" }
支持的常见语言包括 JavaScript、TypeScript、Python、HTML、CSS 等,高亮由内置的 [Nueglow](https://link.gitcode.com/i/38444fd5df71280332ce4708b0a09eaf) 语法高亮引擎完成。从 [src/render-blocks.js](https://link.gitcode.com/i/dd3ada8164366ce38498805a0f122000) 的 `renderCode` 可以看到:语言名会被存入 tag 的 `name`,代码正文交给 `glow(code, { language, numbered })` 处理,因此你还可以: - 通过 `numbered` 数据项开启行号; - 通过 `caption` 或 `_` 提供代码标题,此时输出会包一层 `<figure>` + `<figcaption>`; - 为代码块指定 class,用于定制样式。 ## 四、增强的格式化语法 在标准 Markdown 之外,Nuemark 提供了一套紧凑的格式化标记,其映射关系定义在 [src/parse-inline.js](https://link.gitcode.com/i/0501a45875e04569828684970540600a) 的 `FORMATTING` 表中: ```md **bold** or __bold__ → <strong>bold</strong> *italic* or _italic_ → <em>italic</em> `code` → <code>code</code> ~strikethrough~ → <s>strikethrough</s> "quoted text" → <q>quoted text</q> \|highlighted| → <mark>highlighted</mark>

特殊字符(bullet)提供非语义的加粗

•bold text• → <b>bold text</b>

格式化解析器有一些值得注意的细节(均有测试覆盖):***___会生成<em><strong>嵌套;格式化标记内部不允许首尾空白;如果闭合标记后紧跟单词字符则不视为格式化(避免误伤**x-bold**之类的英文连写);反引号包裹的代码会转义<>后再输出,防止注入。

五、标题与属性

Nuemark 允许在标题末尾用花括号语法附加 id 和 class,用于样式与锚点链接:

# Nuemark: Content-first web development { .heroic } ## Nuemark Introduction { #intro } ## How to use Nuemark { #howto.heroic }

生成结果:

<h1 class="heroic">Nuemark: Content-first web development</h1> <h2 id="intro">Nuemark Introduction</h2> <h2 id="howto" class="heroic">How to use Nuemark</h2>

行内解析器对{ #id.class }这种形态会生成is_attrtoken,交给parseAttr提取 id 与 class(见 src/parse-tag.js)。如果渲染时传入heading_ids选项,renderHeading还会为没有显式 id 的标题自动生成锚点 id(规则见createHeadingId:取前 32 个字符、去撇号、非单词字符转连字符、统一小写),并包一个<a href="#id">锚点链接。parseDocument返回的headings数组也会为每个标题补全id,方便程序化生成目录(TOC)。

六、变量插值

用花括号嵌入动态值:

Current version: { version } Page title: { title } Author: { author }

变量可以访问渲染上下文提供的数据(opts.data),以及 front matter 中定义的元数据。底层实现在 src/render-inline.js 的renderVariable:它对表达式执行new Function('data', 'return data.' + expr),因此支持点号访问嵌套属性,例如{ site.author.name };取值失败时静默返回空字符串,不会中断渲染。

需要说明的是:花括号同时承担了“标题属性”语法({ #id.class }),解析器会根据花括号内首字符是#/.还是普通变量名来区分两者。

七、区块(Sections)与包装

自动分节

开启sections: true后,Nuemark 会根据标题层级自动把内容包进语义化的<section>

--- sections: true --- # Introduction First section content... ## Features Second section content... ## Technical Details Third section content...

生成:

<article> <section> <h1>Introduction</h1> <p>First section content...</p> </section> <section> <h2>Features</h2> <p>Second section content...</p> </section> <section> <h2>Technical Details</h2> <p>Third section content...</p> </section> </article>

分节算法在 src/parse-document.js 的sectionize中:它寻找第一个h1h3之间的标题或---分隔符作为切分依据;若首个标题是h3,则以每个h3为一节,否则以h1/h2级别切分。完全没有标题或分隔符的文档不会产生 section。

区块类名

用数组形式为每个 section 依次指定 class:

--- sections: [hero, features, details] ---

渲染时第 i 个 section 会带上classList[i],因此你可以对不同区块应用不同的背景、字号或网格样式。

手动分节

如果你希望完全控制切分点,可以用三连短横线---显式分隔:

First section content... --- Second section content... --- Third section content...

---在块级解析中被识别为is_separator(注意它同时是水平线***/___等主题分隔符中的一种),sectionize遇到分隔符必然开新节。

区块包装

通过section_wrapper可以给每个 section 内部再包一层容器,便于控制内容的最大宽度:

--- section_wrapper: wrap ---

生成:

<section> <div class="wrap"> <!-- content here --> </div> </section>

这对“通栏背景 + 居中内容”的版式非常实用:<section>负责背景铺满,.wrap通过max-width约束内容宽度,从而实现更精细的设计控制。在源码中该选项名为content_wrapper(见parseDocumentrenderSections)。

八、块(Blocks)语法

块语法用[.类名]把一段内容包进带指定 class 的<div>,类名完全由你的设计系统决定:

[.note] ### Important Note This content is wrapped in a div with class "note"

生成:

<div class="note"> <h3>Important Note</h3> <p>This content is wrapped in a div with class "note"</p> </div>

任何类名都可以使用:

[.warning] → <div class="warning">...</div> [.testimonial] → <div class="testimonial">...</div> [.pricing-tier] → <div class="pricing-tier">...</div> [.photo-gallery] → <div class="photo-gallery">...</div>

实现上,[.name]被解析为名为block的内置标签(见 src/render-tag.js),缩进的内容递归解析为子块;attr.popover存在时甚至会输出<dialog>元素。

自动嵌套 div

块内部会根据第一个出现的标题级别自动分组生成嵌套 div。下面的例子中首个标题是h3,所以每个h3都会开启一个新的嵌套 div:

[.features] ### Feature One First feature description ### Feature Two Second feature description
<div class="features"> <div> <h3>Feature One</h3> <p>First feature description</p> </div> <div> <h3>Feature Two</h3> <p>Second feature description</p> </div> </div>

也可以使用三连短横线---显式创建嵌套 div:

[.testimonials] "Great product!" - Sarah Chen --- "Changed our workflow" - Michael Park
<div class="testimonials"> <div> <p>"Great product!"</p> <p>- Sarah Chen</p> </div> <div> <p>"Changed our workflow"</p> <p>- Michael Park</p> </div> </div>

这正是sectionize在块级内容上的复用:block标签渲染时对子块调用sectionize,有多个分组时每组包一个<div>(实现见 src/render-tag.js 的block())。

常见模式

类名随设计系统而定,以下是两个常用模式:

网格布局——响应式多列:

[.grid] ### Feature One First feature description ### Feature Two Second feature description ### Feature Three Third feature description

堆叠布局——纵向排列、间距一致:

[.stack] ### Design Focus on systematic design ### Engineering Built for performance ### Content Pure content structure

这些模式之所以成立,是因为你的 CSS 定义了.grid.stack的行为;Nuemark 只负责结构,表现层完全交给设计系统,内容里不会出现任何 div 堆叠或内联样式。

嵌套块

块可以无限嵌套,自由组合:

[.feature] ## Main Feature Feature description [.grid] ### Sub-feature A Description A ### Sub-feature B Description B

九、标签(Tag)语法

标签(tag)用方括号扩展出富组件能力,是 Nuemark 组件化的核心:

[tagname options]

选项格式

命名属性:

[image src="photo.jpg" alt="Description" loading="eager"]

纯值(作为默认参数):

[image photo.jpg]

**嵌套 YAML:**把标签体作为 YAML 数据块解析(源码中isYAML会识别key: value或列表形态):

[image] src: photo.jpg alt: Description caption: Photo caption

ID 与类名:

[image#hero.responsive photo.jpg]

解析逻辑在 src/parse-tag.js 的parseTag中,值得注意的规则:

  • 属性值支持单引号/双引号(valueGetter会把带空格的字符串保护起来);
  • idclasshiddendisabledpopover等白名单属性(ATTR)以及data-*前缀的键会写入 HTML 属性,其余键进入data(组件数据);
  • 纯值会存入_键,即“默认参数”;
  • 布尔值:loopmuted这类无值的键等价于true;字符串"true"/"false"/数字会自动转换类型(parseValue);
  • :开头的键(如:rows="pricing")会被解析为数据绑定,渲染时从全局数据中取值(extractData)。

嵌套内容

标签可以携带嵌套内容,其中依然可以使用 Markdown:

[note] This is nested content that becomes part of the component. Markdown **works** here.

嵌套内容与嵌套 YAML 的区别在于:标签体若整体是合法的key: valueYAML 则作为数据;否则作为 Markdown 内容递归解析(见 src/parse-blocks.js 的processNestedBlocks)。测试 test/block.test.js 对这两种形态都有断言。

十、内置标签

图片

基本用法:

[image photo.jpg]

带说明文字(支持 Markdown):

[image photo.jpg] This is the image caption with **markdown** support

响应式图片(small/large分别用于移动端与桌面端):

[image] small: mobile.jpg large: desktop.jpg alt: Responsive image

图片链接:

[image photo.jpg] href: /gallery/ caption: Click to view gallery

从源码(src/render-tag.js 的image())可以看到实现细节:

  • loading默认lazy
  • 提供了small时,会输出<picture>+ 两个<source>,分别带max-width/min-width媒体查询,断点默认750px(可用offset覆盖),并补<img>兜底;
  • href时整张图包进<a>
  • caption或嵌套内容时补<figcaption>,最终始终包在<figure>中;
  • size="400x300"之类的尺寸会被parseSize解析为width/height属性,帮助浏览器预留布局空间、避免 CLS。

视频

基本用法:

[video intro.mp4]

带选项:

[video] src: intro.mp4 poster: thumbnail.jpg autoplay: true muted: true loop: true

video()会依据文件扩展名推断 MIME 类型(mp4/webm/mov 等映射表见MIME常量),并透传autoplay controls loop muted poster preload src width这些原生属性;嵌套内容可作为<video>的 fallback 文本。

表格

增强表格语法:

[table] Name | Email | Role Alice | alice@example.com | Developer Bob | bob@example.com | Designer

带标题、表头与表尾:

[table caption="Team Members"] Name | Email | Role ------ Alice | alice@example.com | Developer Bob | bob@example.com | Designer ------ Total: 2 team members

renderTable会自动识别------分隔出的表头(thead)与表尾(tfoot),并处理单元格合并(列数不足时自动colspan);caption输出<caption>;单元格内支持行内 Markdown。配合数据绑定,你还可以用[table :rows="users"]直接渲染站点数据里的表格。

内联 SVG

把 SVG 图标内联进句子:

Continue reading [svg /icons/arrow-right.svg]

svg()通过readIcon读取.svg文件(路径省略扩展名时会自动补.svg),并把根元素加上class="icon"后内联输出,因此图标可以直接被 CSS 着色与缩放。另一个icon标签则支持 symbol 引用方式(输出<svg class="icon icon-xxx"><use href="#xxx"/></svg>)。

十一、手风琴(Accordions)

手风琴非常适合 FAQ 或任何需要渐进式披露的内容:

[accordion] ## First Question Answer to the first question ## Second Question Answer to the second question ## Third Question Answer to the third question

它生成使用原生<details>/<summary>的语义化 HTML,无需任何 JavaScript:

<div> <details> <summary>First Question</summary> <p>Answer to the first question</p> </details> <details> <summary>Second Question</summary> <p>Answer to the second question</p> </details> <details> <summary>Third Question</summary> <p>Answer to the third question</p> </details> </div>

与块语法相同,手风琴按遇到的第一个标题级别或---分隔符分组(内部同样复用sectionize)。

手风琴选项

name—— 给一组手风琴命名,使同一时刻只展开一个:

[accordion name="faq"]

共享相同name的手风琴会自动联动:打开一个会关闭组内其他项(name会原样输出到<details>的 name 属性上)。

open—— 设置初始展开状态:

[accordion open] # First item open by default [accordion open="2"] # Second item open by default

源码中open === true && i == 0 || i === open决定了第几项默认展开,其中i是从 0 开始的序号。

十二、脚注

标准脚注语法:

This needs clarification[^1]. [^1]: This is the footnote content.

命名脚注:

[Separation of Concerns][^soc] is fundamental. [^soc]: Keeping HTML, CSS, and JavaScript separate.

脚注引用会渲染为带role="doc-noteref"的上标序号,文档末尾自动生成带role="doc-endnotes"<ol>列表(实现见 src/parse-document.js 的renderFootnotes),语义化与无障碍标准保持一致。

你还可以用[define]标签配合带 id 的标题来定义术语,生成<dl>描述列表,并自动把这些 id 注册为可被[^term1]引用的脚注锚点:

[define] ## Term One { #term1 } Definition of term one ## Term Two { #term2 } Definition of term two

十三、自定义组件

Nuemark 的扩展性体现在:开发者可以在 HTML 文件中定义自定义标签,内容作者只需用自然语法调用。组件文件以<!doctype html lib>开头:

<!doctype html lib> <!-- Button component --> <a :is="button" class="button { class }" href="{ href }"> { label || _ } </a> <!-- Card component --> <div :is="card" class="card { type }"> <h3>{ title }</h3> <slot/> <footer :if="footer">{ footer }</footer> </div>

在 Markdown 中使用:

[button "Get Started" href="/docs/"] [card type="feature"] title: Key Feature footer: Learn more This is the card content with full **Markdown** support.

组件属性

组件(标签)在渲染时接收以下数据来源:

  • 命名属性[card type="feature"]中的type
  • 未命名属性:通过_访问,例如[button "Get Started"]中的文本"Get Started"
  • 嵌套 Markdown 作为 HTML:通过<slot/>标签注入,内容保持完整的 Markdown 渲染;
  • 页面元数据:来自 front matter;
  • 站点数据:通过 .yaml 文件提供(可配合:key="data.path"语法绑定全局数据)。

当某个标签没有对应的内置/自定义渲染函数时,Nuemark 不会报错,而是输出“客户端存根”(见 src/render-tag.js 的renderIsland):生成<tagname nue="tagname">元素并内联一段application/json数据脚本,交由客户端组件挂载,从而实现 SSR 与交互组件(islands)的平滑过渡。

十四、参考文件索引

  • 语法文档原文:packages/www/docs/nuemark-syntax.md
  • Nuemark 包入口与 API:packages/nuemark/index.js
  • 块级解析:packages/nuemark/src/parse-blocks.js
  • 文档级解析(front matter、分节、脚注):packages/nuemark/src/parse-document.js
  • 行内解析(格式化、变量、链接、行内标签):packages/nuemark/src/parse-inline.js
  • 块级渲染:packages/nuemark/src/render-blocks.js
  • 内置标签渲染(image/video/table/svg/accordion 等):packages/nuemark/src/render-tag.js
  • 标签解析(选项格式、数据绑定):packages/nuemark/src/parse-tag.js
  • 测试用例:packages/nuemark/test/block.test.js、packages/nuemark/test/tag.test.js、packages/nuemark/test/inline.test.js
  • 相关文档:Nuemark 介绍、Nueglow 语法高亮、HTML 文件类型

【免费下载链接】nueFastest way to build modern websites项目地址: https://gitcode.com/GitHub_Trending/nu/nue

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 14:28:41

SpringBoot考研咨询网站源码解析:数据脚本、查询与部署

简介&#xff1a;面向Java毕业设计与课程设计的考研咨询网站系统完整交付包&#xff0c;基于SpringBoot与MySQL开发&#xff0c;覆盖学生前台、管理员后台、学生后台三大端口&#xff0c;适合需要整体方案与可运行源码的开发者参考。压缩包共1806个文件&#xff0c;约94.26MB&a…

作者头像 李华
网站建设 2026/9/16 14:28:24

燃烧污染物控制技术与仿真优化方法详解

1. 燃烧污染物控制技术概述燃烧过程产生的污染物排放一直是能源利用和工业生产中的关键环保难题。作为一名在燃烧仿真领域工作多年的工程师&#xff0c;我见证了从早期简单排放控制到如今复杂污染物协同治理的技术演进历程。燃烧污染物控制技术&#xff08;Combustion Pollutio…

作者头像 李华
网站建设 2026/9/16 14:25:46

基于反步法的船舶直线路径跟踪控制:Matlab仿真与控制器设计解析

简介&#xff1a;基于反步法的船舶直线路径跟踪控制MATLAB程序包&#xff0c;面向船舶控制、自动化、计算机等专业的学生与研究人员&#xff0c;旨在解决船舶自动循迹控制中的建模与仿真问题&#xff0c;适用于课程设计、期末大作业与毕业设计等环节。包内共8个文件&#xff0c…

作者头像 李华
网站建设 2026/9/16 14:25:37

C#药店管理系统毕业设计:数据模型、事务与报表实战

简介&#xff1a;基于C#的药店管理系统完整源码包&#xff0c;面向计算机相关专业学生的毕业设计或期末作业场景&#xff0c;也适合希望掌握WinForms与数据库开发的中级开发者参考学习。压缩包共912个文件&#xff0c;主要包括C#源代码、窗体资源、项目工程、报表及DLL库等&…

作者头像 李华