/ Site 模式 / 开始

本节将带你从零编写一份最简单的构建脚本,把源目录中的 Markdown 文件渲染为 HTML。

Site 模式下,项目的入口是一份 MoonBit 源文件(文件名可以自定义,只要在运行时正确指定即可)。需要在项目中引入核心库作为依赖。

假设项目结构如下:

├── site.mbt
└── src
    └── hello.markdown

在入口文件中写入:

///|
async fn main {
  @core.mopress([
    @core.Glob(
      "*.markdown",
      @core.Text(raw => raw
        |> @core.render_markdown_and_frontmatter
        |> @core.set_extension(".html")
        |> @core.unify),
    ),
  ])
}

这份代码声明了一条规则:匹配源目录下所有以 .markdown 结尾的文件,将其内容作为文本读入,依次经过“渲染 Markdown 与元数据”和 修改目标扩展名为.html”两个 step,最后调用 unify 转换为最终可写入磁盘的格式。

moon run site.mbt build

构建完成后,源目录中的 hello.markdown 会被渲染为输出目录中的 hello.html(默认的源目录与输出目录,可以通过 Options 自定义,参见下方说明)。

默认情况下,构建函数使用默认的 Options 提供的源目录与输出目录。如果需要自定义,可以显式传入:

///|
async fn main {
  let options :  @core.Options = { src: "content", dest: "public" }
  @core.mopress(
    [
      @core.Glob(
        "*.markdown",
        @core.Text(raw => raw
          |> @core.render_markdown_and_frontmatter
          |> @core.set_extension(".html")
          |> @core.unify),
      ),
    ],
    options~,
  )
}

上面的示例只是把 Markdown 渲染为一段 HTML 片段,并没有套上完整的页面结构。可以在管线中加入套用模板的 step:

///|
async fn main {
  @core.mopress([
    @core.Glob(
      "*.markdown",
      @core.Text(raw => raw
        |> @core.render_markdown_and_frontmatter
        |> @core.set_extension(".html")
        |> x => x.load_and_apply_template("templates/default.html")
        |> @core.unify),
    ),
  ])
}

当需要声明一系列所有规则共用的值时可使用 @core.mopress_with 函数:

pub async fn[E] mopress_with(
  options? : Options = Options::default(),
  init : (Options) -> E,
  rules : (Options, E) -> Rules,
) -> Unit

在传入的 init 函数中自定义返回的类型 E,并将其作为 rules 函数的第二个参数,所有的规则都将能访问到 E 值:

///|
async fn main {
  @core.mopress_with(
    (options) => {
      let shared = {
        "title": "My Site",
        "footer": "© 2023 My Company",
      }
      shared
    },
    (options, shared) => [
      // ...
    ],
  )
}

Tip

关于模板语法本身、以及模板变量是如何对应起来的,请参见 [组合 Steps](./composing-steps.md) 与 [模板引擎](../custom/template.md) 相关说明。