12个版本

0.3.1 2024年1月25日
0.3.0 2024年1月24日
0.2.7 2023年12月31日
0.2.5 2023年7月15日
0.1.1 2022年9月10日

#449 in 模板引擎


用于 stuart

MIT 许可证

135KB
2.5K SLoC

Stuart

一款闪电般的快速静态网站生成器。
立即下载 »







Stuart是一款非常快速且灵活的静态网站生成器,每页构建时间低至0.1毫秒。它使用Rust编写,旨在比其他SSGs更易于使用,同时在基准测试中击败它们。Stuart简单而强大的模板系统允许您定义站点复杂的逻辑,从Markdown和JSON文件以及模板文件中获取数据,然后再将其渲染为静态HTML。对于更复杂的项目,您可以使用任何语言的定制构建脚本来增强Stuart,这些脚本与核心构建系统集成,以及使用Rust或JavaScript的定制插件。

注意: Stuart是一个非常新的项目,因此功能和文档仍在添加中。目前,文档仅限于本README。

目录

入门

安装

Stuart提供Windows和Linux的预构建二进制文件。您可以从发布页面下载最新版本。或者,您可以使用Rust的包管理器Cargo从头开始构建代码。为此,克隆仓库并运行cargo build --release。默认情况下禁用了JavaScript插件的支持,要启用它,请启用js功能。

Stuart需要安装Git才能使许多功能正常工作。

创建项目

您可以通过运行以下命令创建一个项目:stuart new <项目-名称>。这将创建一个具有指定名称的新目录,并用基本的项目模板填充它。默认情况下,Stuart 还会在项目目录中初始化一个 Git 仓库,因此为了避免这种行为,您可以使用 --no-git 标志。

构建项目

您可以通过在项目目录中运行 stuart build 命令来构建项目。这将把项目构建到 dist 目录中。

要启动开发服务器,当文件发生变化时,它会自动重新构建项目并在您的浏览器中重新加载,请运行 stuart dev。这将启动服务器在 https://127.0.0.1:6904

配置

stuart.toml 文件中,您可以在 [settings] 节中设置项目的配置选项。以下是一些可用的选项:

名称 描述 默认值
strip_extensions 是否通过创建包含 index.html 文件的文件夹来删除 HTML 文件扩展名 true
save_data_files 是否将 JSON 数据文件保存到输出目录 false
save_metadata 是否输出有关构建的元数据,用于与构建脚本集成 false

您可以在 [dependencies] 节中使用类似于 Cargo 的语法声明插件依赖项,例如

[dependencies]
my_plugin = "/path/to/plugin.so"
my_other_plugin = "/path/to/cargo/project/"
my_git_plugin = "https://github.com/username/plugin"
my_remote_plugin = "https://example.com/plugin.so"

Stuart 将自动检测插件是否需要从 Git 仓库克隆,以及是否需要编译。如果插件需要编译,Stuart 需要安装 Rust 工具链。

您可以使用分号分隔插件源来指定回退,例如

my_plugin = "/lib/plugin.so;https://example.com/plugin.so"

项目结构

一个 Stuart 项目包含多个文件夹,每个文件夹都有特定的用途。此外,一些文件名也有特殊的意义。所有内容都应该放在 content 目录中,因为这是唯一一个会被构建系统处理的目录。

根模板

根模板是一个 HTML 模板文件,称为 root.html,它为其目录和子目录中的所有其他页面提供基础。将使用与正在渲染的页面最具体的根模板。

它是一个普通的 HTML 文件,可以包含模板标签(我们将在后面讨论),但必须至少包含非常重要的 insert 函数。该函数接受一个参数,即节的名字。节是 Stuart 知道在哪里将内容插入根模板的方式。这可以通过一个例子来说明。

root.html:

<html>
  <head>
    {{ insert("head") }}
  </head>

  <body>
    {{ insert("body") }}
  </body>
</html>

在这个虚构的例子中,网站的每一页都将渲染到这个模板中。每个页面的 head 部分(通过我们稍后将要看到的 beginend 函数标记)将插入到页面的头部,而 body 将插入到主体中。这允许您为网站定义一个共同的布局,或者为网站的一部分定义布局,并将内容插入其中。

需要注意的是,节是必需的:在根模板中定义的每个节都必须出现在使用它渲染的每个页面上。

可以渲染到这个模板的页面如下

index.html:

{{ begin("head") }}
<title>Stuart</title>
{{ end("head") }}

{{ begin("body") }}
<h1>Stuart</h1>
<p>A blazingly-fast static site generator.</p>
{{ end("body") }}

HTML和Markdown页面

HTML 页面是普通的 HTML 文件,可以包含模板标签。它们定义了要渲染到根模板中的节。

Markdown页面是Markdown文件,以包含文件元数据的frontmatter开头,然后是页面内容。这些文件被转换成HTML,通过md.html模板通过$self变量渲染,然后将这些内容渲染到根模板中。用例子说明会更清晰。

my_page.md:

---
title: "My Page"
author: "William Henderson"
---

# My Page
Markdown content...

md.html:

{{ begin("head") }}
<title>{{ $self.title }}</title>
{{ end("head") }}

{{ begin("body") }}
<h1>{{ $self.title }}</h1>
<p>By {{ $self.author }}</p>

{{ $self.content }}
{{ end("body") }}

root.html 如上。

JSON数据

JSON数据文件也可以作为Stuart网站的源数据使用,通过在HTML页面中使用import模板函数,将JSON文件作为变量导入。

静态文件

静态文件应放置在static目录中,该目录将在构建结束时与构建内容合并。文件名冲突将导致构建失败。

构建脚本

构建脚本应放置在scripts目录中。目前,Stuart支持的唯一脚本有onPreBuildonPostBuild。在Windows上,它们应该有.bat扩展名,在Linux上,它们应该有.sh扩展名或没有扩展名。这些脚本分别在构建前后运行。

onPostBuild脚本可以访问metadata.json文件中关于构建的元数据,如果项目配置中启用了save_metadata

如果预构建脚本想在输出目录中创建文件,它应该在temp目录中这样做,Stuart将在构建结束时将其合并到输出目录中。这是为了避免与构建系统的冲突,因为直接写入输出目录可能会导致意外的行为。

为构建脚本设置了某些环境变量,以提供有关构建的信息。这些是

名称 描述
STUART_MANIFEST_PATH stuart.toml清单文件的完整路径。
STUART_MANIFEST_DIR 包含stuart.toml清单文件的目录的完整路径。
STUART_TEMP_DIR 在预构建脚本执行期间应放置文件的temp目录的完整路径。
STUART_OUT_DIR 输出目录的完整路径。
STUART_ENV Stuart运行的环境。这将要么是productiondevelopment,要么是benchmark

模板语言

Stuart模板语言由两个主要部分组成:变量和函数。变量用于将数据插入模板,函数允许更复杂的行为,如迭代和选择。

所有模板标签都包含在双大括号中。变量以美元符号为前缀。

变量

基本变量可以按以下方式插入到模板中

{{ $variable }}

所有变量都是JSON值,因此可以使用点符号访问对象值

{{ $variable.property }}

可以在模板中使用$env变量访问环境变量,例如,要获取STUART_ENV环境变量的值,您将使用{{ $env.STUART_ENV }}

函数

使用以下语法调用函数

{{ function_name(arg1, arg2, positional_arg="value", ...) }}

Stuart目前支持以下函数

名称 描述 示例
begin 开始一个部分。 begin("section_name")
end 结束一个部分或另一个函数。 end("section_name"), end(function_name)
插入 将一个部分插入到模板中,仅在 root.html 中使用。 插入("section_name")
导入 将 JSON 文件作为变量导入。 导入($data, "data.json")
for 遍历 JSON 数组或 markdown 文件夹。循环通过 end(for) 结束。 for($tag, "tags.json"), for($post, "posts/", skip=3, limit=3, order="desc", sortby="date"), for($item, $array)
dateformat 使用 chrono 格式字符串格式化日期。日期输入可以是任何类型的格式化日期或时间戳。 dateformat($date, "%Y-%m-%d")
if[eq,ne,gt,ge,lt,le] 执行两个值之间的比较。块通过 end(if[eq,ne,...]) 结束。 ifeq($a, $b), ifge($age, 18)
ifdefined 检查一个变量是否已定义。块通过 end(ifdefined) 结束。 ifdefined($variable), ifdefined($variable.property)
else 为条件语句开始 else 块。 else()
摘录 从字符串创建摘录。 摘录($post.内容, 100)
timetoread 计算阅读字符串所需的时间(以分钟为单位)。 timetoread($post.内容)

插件

Stuart 支持动态加载的插件,这些插件是提供额外功能的 Rust 库。插件依赖项在前面描述的 stuart.toml 文件中指定。可以通过在函数名称前加上插件名称来在模板内部调用插件函数,例如

{{ my_plugin::my_function() }}

如果函数名称不与另一个函数冲突,则可以省略插件名称。如果冲突,则内置函数优先于插件函数,但插件函数的顺序是未定义的。因此,请避免这样做。

原生插件API

原生插件使用核心crate中的define_plugin!宏定义。它们可以向Stuart添加函数,这些函数的实现方式与内置函数完全相同,还可以添加新文件类型的解析器。请参考内置函数以获取函数实现的示例,并参考图像优化插件源代码以了解如何使用新文件类型的解析器。调用宏的示例如下

declare_plugin! {
    name: "my_plugin",
    version: "1.0.0",
    functions: [
        SomeFunctionParser,
        AnotherFunctionParser
    ],
    parsers: [
        MyParser
    ]
}

您必须将Cargo项目配置为编译为cdylib库,如下所示(在Cargo.toml中)

[lib]
crate-type = ["cdylib"]

项目还必须将stuart_core作为依赖项,以便使用define_plugin!宏和Stuart插件类型。您可以禁用默认功能以避免编译不必要的依赖项,如下所示

[dependencies]
stuart_core = { version = "*", default-features = false }

JavaScript插件API

当使用js功能编译时,Stuart还可以使用V8加载用JavaScript编写的插件。这些插件只能向Stuart添加函数。插件只是一个导出包含插件元数据的默认对象的JavaScript模块,类似于Rust中的declare_plugin!

export default {
  name: "my_plugin",
  version: "1.0.0",
  functions: [
    {
      name: "add",
      fn: (a, b) => a + b
    }
  ]
}

当作为参数传递时,Stuart变量将自动转换为JavaScript对象,但对其的更改不会自动传播回Rust端。为此,您可以使用STUART全局对象来访问插件API。

const self = STUART.get("self");
STUART.set("my_var", `Title: ${self.title}`);

有关更复杂JavaScript插件的示例,请参阅stuart-math,它使用MathJax来渲染LaTeX。

依赖项

~0.8–1.8MB
~35K SLoC