
众所周知,随着 Github Pages 这样的服务越来越流行,现在像 Hexo、Hugo、Pelican 这样的静态博客越来越多, 像我以前就是用Pelican的,但因为Pelican的依赖比较多(其实是想自己造轮子), 自从见过Nim就一直很想自己写一个静态博客,但总是觉得比较麻烦,
直到看到 Writing a small static site generator , 才发现原来写一个静态博客竟如此简单。
废话不多说,那我们就开始动手做吧!
apt install nim即可nimble install markdown nimble install nwt 静态博客大多是使用 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 因为不像 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 kun
感谢 Thea,在我想用 Nim 编写自己的静态博客时, 看到了 Writing a small static site generator , 惊叹竟然可以如此简洁,所以此篇文章基本也是和她一样的思路,只是实现的语言换成了 Nim
1 mingyuexin 2019-08-13 12:46:38 +08:00 不错 |
2 Wyane 2019-08-13 13:10:11 +08:00 技术收藏一下 |
4 zagfai 2019-08-14 11:56:33 +08:00 关注了 Nim 语言好久了 一直没实践过:) |