Rust项目Zola的源码分析
更新日期:
Zola是一个快速的静态站点生成工具,使用Rust语言实现。阅读源代码是很好的学习Rust的方式,今天将探索下Zola项目的源代码。
zola命令行只有4个命令,代码分析也将从命令行开始。
init
创建site目录结构build
构建site内容,生成目标位于public目录下serve
构建site并启动本地访问的服务器,服务地址默认为`127.0.0.1:1111`check
构建site但并不生成文件,同时会检查markdown文件中的外部链接
zola 源码
Zola的github源码,2个重要的目录是src
与components
, src
下是主要是命令行参数解析,components
才是站点内容的核心逻辑。
先来大概看下Cargo.toml
中的依赖关系,其内容如下。clap
、clap_complete
是用于命令行参数解析与bash脚本自动完成; hyper
、tokio
用于构建serve
命令使用的本地web服务器; 使用相对路径方式依赖于components
目录下的site
、errors
、console
、utils
、libs
, components/site
将会是分析的重点。
1 | [[bin]] |
命令行参数解析
src
目录的内容如下, src/main.rs
是程序运行的起点,src/cmd/
下的文件是实现各个子命令。
1 | $ tree src |
如下是简化的main.rs
, 删除了一些参数检查逻辑与判断。先使用Cli::parse()
解析命令行参数,将解析结果cli.command
使用match匹配枚举类型Command
,匹配时再执行模块cmd
下的命令。
子命令为Build
时,执行的方法为cmd::build()
。命令行参数解析逻辑,使用库clap
来实现。
1 | use cli::{Cli, Command}; |
构建命令build的实现
构建命令cmd::build()
的实现方法在src/cmd/build.rs
文件中。主要逻辑是: 先创建Site
对象,然后调用其方法site.load()
, site.build()
。
1 | use std::path::Path; |
Site::new()
方法
Site
结构体及其实现的方法在src/components
目录下。先看下components目录下的内容,每一个子目录都是一个Rust项目目录。site
负责整个构建过程,config
管理配置,content
管理内容如下, markdown
负责markdown内容解析与转换,templates
加载模板文件。模块的功能划分还是比较明确的。
1 | $ tree -L 1 components |
接下来看下结构体Site
的实现,位于文件src/components/site/src/lib.rs
中。创建Site
时有2个参数,一个是站点site的根目录,另一个是配置文件名,Site::new()
方法中通过config::get_config
解析配置文件config.toml
,templates::load_tera()
加载模板文件,由init
命令创建的目录结构会转成完整路径后传给Site
。
1 | use config::{get_config, Config, IndexFormat}; |
Site::load()
方法
Site::load()
读取目录content
下所有文件,创建pages与sections实例。 这里只列出重要的代码行。主要逻辑是: 遍历content
文件夹进行循环处理,是子目录且有_index.md
时新增section, 普通文件新增page, 加载时会将md转换成html文件。
1 | pub fn load(&mut self) -> Result<()> { |
Site::build()
方法
Site::build()
将生成的内容写入public
目录,主体就是调用各种render方法生成文件。 其中生成内容在render_sections()
方法中,一个section会包含多个page,所以是由render_section
方法调用render_page
方法。
render_sections()
是生成section列表,循环调用render_section()
方法;render_section()
中又对section.page
循环调用render_page()
render_section()
与render_page()
方法将分别调用两个结构体Section
与Page
的render_html()
方法。
1 | pub fn build(&self) -> Result<()> { |
参考: