Notist
On this page
  1. Cook Book
  2. 构建与扩展
  3. 基础 Markup 语法
  4. 内容树与属性标注
  5. 类型系统
  6. 内容函数
  7. Notist Markdown
  8. 按前端处理源码

Cook Book

构建与扩展

需要从清单或源文件自动生成页面时,可阅读 从 Cargo examples 生成站点。该教程给出完整的 Notist.toml、Python stdio 扩展和模板,用正常 CLI 构建站点,不逐项维护生成的文档和数据文件。

配置与协议见 文档扩展 和 SSG 站点扩展。

基础 Markup 语法

下列示例使用 .not;完整规则见 Syntax 与 Builtin。

= 标题,加粗,强调(斜体),删除线

独占一行的分隔线:


  • 无序列表

  • 无序列表

    • 无序列表

      1. 有序列表

      2. 有序列表

管道表格:

名称

数量

苹果

3

.not 表格按逻辑行解析,只有最外层换行结束表格行,最外层管道符分隔单元格。完整公式、字符串与调用内部可以自然换行,块级公式也可以留空行;raw / math 内部的管道符和反斜杠保持原样。普通文字里的管道符使用 \|。多行 raw 字符串使用 r#"""..."""#,开引号后立即换行。需要多个段落或列表时,用 #node[ ... ] 包裹单元格内容,两端内侧留白:

名称

内容

图形源码

stateDiagram-v2
    [*] --> s1
    s1 --> [*]

多行公式

多段内容

第一段,可以直接写字面管道符 a | b。

第二段。

  • 列表项一

  • 列表项二

公式采用本 Vault 默认的 Typst 数学方言:反斜杠表示排版换行,& 标记对齐点,普通源码换行只是空白。数学引擎由 Notist.toml 的 extensions 选择,切换引擎不会转换公式方言,见 本地模块。

闭公式后的换行已在最外层,因此表格行末的管道符要与闭美元符号写在同一行,例如 $ |。Markdown 表格仍按 GFM 的物理行规则解析,不能使用这个多行表格写法。

行内代码块 code,以及多行代码块:

fn main() {
    println!("Hello World");
}

数学公式使用 $x$ 写行内内容;两端内侧留白的 $ x $ 写块级内容,对应同一个 math 函数的 BlockContent 实例:

也可以显式调用:

#math<BlockContent>("x^2 + y^2 = z^2")

原生 .not 的块级公式可以在一对 $ 内跨行并留空行;行内公式只能跨软换行。Markdown 的两种公式都限于同一 Markdown 块,允许段落内的软换行,空行会结束该段落。源码中的换行能否形成排版换行,由公式引擎决定。

内容树与属性标注

在 Notist 中,所有的内容都是节点,使用属性标注语法可以将一个字典字面量标注在节点上:

  • @(dict):标注在紧接着的节点上。

  • @!(dict):标注在根节点上,写在文档开头。

比如下面这篇文档:

@!(draft: true)

@(id: "example")
= Example

== Hello World

Let's say *Hello* _World_!

对应下面这颗内容树:

- Doc @(draft: true)
  - Section @(id: "example")
    - Heading(level: 1)
      - Text("Example")
    - Section
      - Heading(level: 2)
        - Text("Hello World")
      - Paragraph
        - Text("Let's say ")
        - Strong
          - Text("Hello")
        - Text(" ")
        - Emph
          - Text("World")
        - Text("!")

标题开启一个 Section,标题前的块注解挂在该 Section 上,见 section 规则。

类型系统

见 Types & Literals。

内容函数

所有 Markup 下的元素都有对应的 内容函数,比如:

  • #raw("code"):code

  • #strong[加粗]:加粗

  • #strike[删除线]:删除线

  • #divider():与独占一行的 --- 相同

  • #embed("assets/example.png", description: "示例", title: "说明"):嵌入资源;与 Markdown 的 ![示例](assets/example.png "说明") 对应,具体呈现由渲染器决定

  • #table(align: ("left", "right"))[#row[#cell[苹果] #cell[3]]]:表格;使用 row(header: true) 表示表头,cell 可以挂载段落等内容

  • #list(ordered: true, start: 3)[#item[准备] #item[执行]]:从 3 开始编号;item 可包含多个段落与子列表

Callout 没有专用 Markup 语法,直接调用:

这里可以放段落、列表等块级内容。

Notist Markdown

.notmd 与 .nmd 使用 Markdown 标题、强调、列表等语法,并支持 Notist 注解与内容函数;.md / .markdown 也使用同一前端。调用的参数及属性使用相同字面量,正文使用 Markdown。

@!(title: "示例", tags: ("markdown", "notist"))
@(id: "intro")
# 入门

普通 Markdown,包含 @(role: "highlight")**粗体** 和 #emph[行内调用]。

@(id: "tip")
#callout(kind: "note")[
## 提示

- 正文继续按 **Markdown** 解析
- 也可以调用 #math("x^2") 或导入模块的内容函数
]

#emph[行内调用] 使用 Markdown 行内正文;#callout[ ... ] 两端内侧留有换行,使用块级正文。换成 .not 时,调用名称与参数相同,正文改用 .not 语法。

按前端处理源码

默认 Pipeline 按扩展名选择前端,并执行共用后端:

let pipeline = notist::Pipeline::default();
let context = notist::Context::default();
let document = pipeline.analyze(
    "example.nmd",
    "@(id: \"intro\")\n# Title\n\n#strong[**Markdown**]",
    &context,
)?;

只安装原生前端时使用 Pipeline.new().with_frontend(notist.NotistFrontend);只安装 Markdown 时使用 Pipeline.new().with_frontend(notist.MarkdownFrontend)。自定义前端实现 Frontend 与 ContentLowering,注册后按同一规则参与选择;接口见 文档前端。

使用 pipeline.inspect(path, source, &context) 查看解析树和中间 IR。Context.default 提供内置函数;项目模块与扩展由宿主加载,见 文档管线。