只需五步,用 Nim 语言自己动手写一个静态博客 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
muxueqz
V2EX    分享创造

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

  •  1
     
  •   muxueqz
    muxueqz 2019-08-13 12:25:42 +08:00 3333 次点击
    这是一个创建于 2283 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    众所周知,随着 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 中供浏览器查看,

    在这里,我选择了类似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

    5 条回复    2019-08-14 12:07:53 +08:00
    mingyuexin
        1
    mingyuexin  
       2019-08-13 12:46:38 +08:00
    不错
    Wyane
        2
    Wyane  
       2019-08-13 13:10:11 +08:00
    技术收藏一下
    muxueqz
        3
    muxueqz  
    OP
       2019-08-14 08:34:20 +08:00
    @Wyane 谢谢 ^_^
    zagfai
        4
    zagfai  
       2019-08-14 11:56:33 +08:00
    关注了 Nim 语言好久了 一直没实践过:)
    muxueqz
        5
    muxueqz  
    OP
       2019-08-14 12:07:53 +08:00
    @zagfai Nim 蛮好玩的,我最近用 Nim 写了不少工具呢,写起来蛮爽的,我都不想写 Go 了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2991 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 12:31 PVG 20:31 LAX 04:31 JFK 07:31
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86