只需五步,用 Nim 语言自己动手写一个静态博客

2019-08-13 12:25:42 +08:00
 muxueqz

自己动手写一个静态博客?

众所周知,随着 Github Pages 这样的服务越来越流行,现在像 Hexo、Hugo、Pelican 这样的静态博客越来越多, 像我以前就是用Pelican的,但因为Pelican的依赖比较多(其实是想自己造轮子), 自从见过Nim就一直很想自己写一个静态博客,但总是觉得比较麻烦,

直到看到 Writing a small static site generator , 才发现原来写一个静态博客竟如此简单。

废话不多说,那我们就开始动手做吧!

准备工作

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 中供浏览器查看,

在这里,我选择了类似jinja2nwt模板引擎,得以兼容 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

原文:http://muxueqz.top/a-small-static-site-generator.html

2907 次点击
所在节点    分享创造
5 条回复
mingyuexin
2019-08-13 12:46:38 +08:00
不错
Wyane
2019-08-13 13:10:11 +08:00
技术收藏一下
muxueqz
2019-08-14 08:34:20 +08:00
@Wyane 谢谢 ^_^
zagfai
2019-08-14 11:56:33 +08:00
关注了 Nim 语言好久了 一直没实践过:)
muxueqz
2019-08-14 12:07:53 +08:00
@zagfai Nim 蛮好玩的,我最近用 Nim 写了不少工具呢,写起来蛮爽的,我都不想写 Go 了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/591456

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX