PlainSite:A Simple but Powerful Static Site Generator

PlainSite是我用Ruby语言写的一个简单的静态站点生成工具。它的工作方式非常简单,只是将指定目录下的Markdown或HTML格式的文件重新组织成一个个Web页面。 你只需要使用Markdown或HTML格式编写文章,用目录来分类,PlainSite就能为此生成一个静态站点。当然它能做的并不仅仅是这些,事实上它是一个用于生成静态站点的Framework,它包含一个简单的URL Router、一个基于ERB的Template系统、还有优雅的Data Access DSL,借助PlainSite的API,可以做到对输出页面的完全控制。

起因

生成静态站点的工具很多,GitHub Pages内置支持JekyllOctopress则基于Jekyll,扩展了很多功能,并提供一套美观的UI。为什么又要自己动手呢?Jekyll虽然功能很丰富,但却不能对输出页面进行灵活的控制。PlainSite完全是按照传统Web开发的MVC模式设计的,Simple与Powerful兼具,事实它起源于我早期的另一个想法:一个动态Blog程序+一个站点下载器。原本我打算用GoClojure什么的写一个类似 WordPress 那样Blog程序,但是这样的程序有一个缺陷就是服务器环境被限定死了,试想除了 Google AppEngine 还有哪家云服务商提供Golang环境支持的?一个博客真正需要动态程序支持的功能只不过是其管理后台,前端页面其实都可以静态化。静态站点的好处就是可以自由迁移到任何一个Web服务器。回想到以前用 Python 写过一个整站下载工具,我便想到其实可以这样做:博客程序运行在本地,每次发布时,用整站下载工具去把 Localhost 站点下载下来,再把下载下来的纯静态页面作为站点发布。这样不就一举两得了吗?你可以随便选择一个Blog程序,只运行在本地,发布的全是静态网页,这样就可以直接使用 GitHub Pages 托管了。高!实在是高!——不过为什么要这么折腾呢?直接让Blog程序自己直接输出所有静态页面就行了嘛,干嘛还要再写个爬虫去下载呢? 于是顺着 Static Site Generator 的思路,便有了PlainSite中的routes.rb

$site.route(
  url_pattern: "/essays/{slug}.html",
  data: $site.data / :essays / '*' ,
  template: 'post.html'
)

这只是一段Ruby代码,用于指定哪些数据用哪个模板渲染输出,输出的URL路径是什么,通过这样一个配置文件,程序就可以知道总共要输出哪些页面。这和普通的MVC框架中的URL映射配置是非常类似的,如 Python Django Framework中的urls.py配置文件。你已经看到了URL与Template配置,但 Model、Controller在哪里呢?注意它只是一段Ruby代码,所以你可以随心所欲地控制输出的数据,它就是 Controller:

$site.route(
  url_pattern: "/today-top-news.html",
  data: ($site.data / :news / '*' ).select {|post|
    post.top && post.date==Date.today
  },
  template: 'news-list.html'
)

不过等等,那个$site.data / :news / '*'是什么意思?这就是对应于Model啦。 这段代码的意思就是读取news目录下的所有Post,相当于SQL:SELECT * FROM news。PlainSite也选择了使用文件与目录作为组织数据的方案。一篇文章作为一个文件,相当于数据库中一条记录;目录分类,则相当于数据库中的Table;你可以把它看成一个文档型数据库。虽然文件系统不支持SQL语句,但借助于Ruby的DSL表现力,上面一段Ruby代码相当于SQL:

SELECT * FROM news WHERE top=true AND date=CURDATE()

特性

事实上,有了这个基础架构,理论上可以自定义输出任意复杂的页面,所以说它是一个 Simple but Powerful Tool。不过除此之外,PlainSite还有其它几个小的功能亮点:

PlainSite具体怎么安装使用,请直接参阅项目的README及RDOC文档。

Github:https://github.com/JexCheng/plain_site