如何自己写一个静态站点生成器
微wx笑 2019-09-06【网页网站】 28 0关键字: 生成器 generator
一直很想自己写一个静态博客,但总是觉得比较麻烦。直到看到 Writing a small static site generator ,才发现原来写一个静态博客竟如此简单。
为什么要自己动手写一个静态博客?
众所周知,随着Github Pages这样的服务越来越流行,现在像Hexo、Hugo、Pelican这样的静态博客越来越多, 像我以前就是用Pelican
的,但因为Pelican
的依赖比较多(其实是想自己造轮子), 自从见过Nim
就一直很想自己写一个静态博客,但总是觉得比较麻烦,
直到看到 Writing a small static site generator , 才发现原来写一个静态博客竟如此简单。
废话不多说,那我们就开始动手做吧!
准备工作
安装好Nim编译器,如果你用Debian GNU/Linux,
apt install nim
即可安装依赖
nimble install markdown nimble install nwt
收集markdown列表
静态博客大多是使用markdown这样的源格式来编写文章,然后输出成HTML,
因为最近几年写markdown比较多,这里就只支持markdown。
这段代码比较简单,遍历srcs
目录中的*.md
文件,然后交给md_processor
去解析
proc write_posts(): seq[JsonNode] = var post: JsonNode for file in walkDirRec "./srcs/": if file.endsWith ".md": echo file post = md_processor(file) write_post(post) result.add post
解析markdown源
因为不像Python里有好用的frontmatter
,所以我们这里用pegs
来解析markdown中的元信息(如Title、Tags等)。
这里的markdown
解析是用nim-markdown ,这在准备工作中已经安装好了
proc md_processor(file_path: string): JsonNode = var file_meta = splitFile(file_path) head = true post = initTable[string, string]() matches: array[0..1, string] src = "" for line in file_path.open().lines: if head and line.match(peg"\s* {\w+} \s* ':' \s* {.+}", matches): post[matches[0]] = matches[1] elif head and line.strip.len == 0: discard else: head = false if head == false: src.add line & "\n" if not post.contains"Slug": post["Slug"] = file_meta.name if "Category" in post: if "Tags" in post: post["Tags"].add "," & post["Category"] else: post["Tags"] = post["Category"] post["content"] = markdown(src) result = %* post
生成博客文章
现在我们已经完成了对markdown的解析,接着我们把它输出到HTML中供浏览器查看,
在这里,我选择了类似jinja2
的nwt
模板引擎,得以兼容Thea模板的大部分内容。
这是一个简化后的模板样例:
{% block title %}{{title}}{% endblock %} {% block content %}<article> <aside> <time>{{Date}}</time> Tags: {{tag_links}} · <a href="/">view all posts</a> </aside> <h1>{{title}}</h1> <content> {{content}} </content></article>{% endblock %}
接着,我们在Nim中根据这个模板去输出HTML,我把HTML输出到./public
这个目录:
proc write_post(post: JsonNode)= var p: string new_post = initTable[string, string]() new_post["Tags"] = "" for k, v in post: new_post[k] = v.getStr new_post["tag_links"] = "" if "Tags" in post: for tag in post["Tags"].getStr.split(","): p = """ <a href="/tags/$1.html"> $1 </a> """ % tag.strip() new_post["tag_links"].add p var json_post = %* new_post var content = templates.renderTemplate("post.html", json_post) writeFile("public/" & post["Slug"].getStr & ".html", content)
生成博客首页索引
现在我们已经完成了对博客文章的解析和生成,接下来我们去更新一下首页吧!
首页的模板如下:
{% block content %}<nav> <h1>My blog posts</h1> <dl class="posts-list"> {{content}} </dl></nav>{% endblock %}
在Nim中去生成index.html
(因为nwt不支持for
循环,所以只好在Nim中去循环了):
proc write_index(posts: seq[JsonNode]) = var seq_post : seq[string] tags = initCountTable[string]() p, summary, tag_cloud: string for key, post in posts: if "Summary" in post: summary = post["Summary"].getStr else: summary = "" p = """ <a href="/$1.html"> <dt>$2</dt> <dd> <time>$3</time> </dd> </a> <div class="summary"> $4 </div> """ % [ post["Slug"].getStr, post["Title"].getStr, post["Date"].getStr, summary, ] seq_post.add p if "Tags" in post: for tag in post["Tags"].getStr.split(","): tags.inc tag.strip() for tag, count in tags: p = """ <a href="/tags/$1.html"> $1 </a> """ % tag tag_cloud.add p seq_post.add tag_cloud var index_post = %* { "content": seq_post.join("\n") } var content = templates.renderTemplate("index.html", index_post) writeFile("public/" & "index.html", content)
最后的工作,写个main
函数
proc main()= var posts = write_posts() posts = sort_posts(posts) write_index(posts)
开始编译吧!
nim c -r build.nim
完整代码
感谢
感谢 Thea ,在我想用Nim编写自己的静态博客时, 看到了 Writing a small static site generator , 惊叹竟然可以如此简洁,所以此篇文章基本也是和她一样的思路,只是实现的语言换成了Nim
本文转自:http://muxueqz.top/a-small-static-site-generator.html
本文为转载文章,版权归原作者所有,不代表本站立场和观点。