博客开始支持标签
标签:blog,openresty,javascript
文章越来越多了,需要给每篇文章打上标签,方便分类
由于博客是静态的,我也不打算把标签保存在数据库,页面加载时发出异步请求,获取标签数据.
sidebar tags
博客的所有页面都是通过gulp-template-html生成的,因此只要在模板页面加上标签侧边栏就行了
- markdown文件添加标签,占位符和title,content类似
<!-- build:tags -->my-tag<!-- /build:tags -->
- 编写gulp插件收集标签数据
function tags() {
function process (file, enc, cb) {
...
if (file.isBuffer()) {
var title_reg=/build:title.+>(.*?)</,
tag_reg=/build:tags.+>(.*?)</,
path_reg=/markdown\/(.+)\./,
content=file.contents.toString(enc),
title_result=title_reg.exec(content),
tag_result=tag_reg.exec(content),
path_result=path_reg.exec(file.history[0]);
var tags,title,path
if(title_result!=null){
title=title_result[1]
}
if(path_result!=null){
path=path_result[1]
}
if(tag_result!=null){
var item={title:title,path:path}
tags=tag_result[1].split(';')
for(var i=0;i<tags.length;i++){
var posts=all_tags[tags[i]]
if(posts==undefined){
all_tags[tags[i]]=[item]
}else{
all_tags[tags[i]].push(item)
}
}
}
file.contents = new Buffer(file.contents, enc);
}
cb(null, file);
}
...
}
module.exports = tags;
标签数据存在all_tags变量
,格式如
{
"nginx":[
{"title":"openresty定制prometheus metrics监控nginx(1)","path":"monitor-nginx-with-openresty-and-prometheus-1"},
{"title":"openresty定制prometheus metrics监控nginx(2)","path":"monitor-nginx-with-openresty-and-prometheus-2"},
...
],
"tmux":[{"title":"我的tmux配置","path":"tmux_conf"}],
...
}
- 模板页面添加标签列表html
上面的stream注册end事件
,收集完所有markdown文件的标签后,生成标签列表的html
return through.obj(process).on('end',function(){
co(gen_tags_html,Object.keys(all_tags));
...
});
var through = require('through2'),
PluginError = require('plugin-error'),
fs = require('fs'),
path = require('path'),
thunkify = require('thunkify'),
writeFileThunk=thunkify(fs.writeFile)
readFileThunk = thunkify(fs.readFile),
co = require('co');
var root_path=path.resolve(__dirname),
all_tags={};
function* gen_tags_html(tag_list){
var template_path=root_path+'/src/template.html',
content=yield readFileThunk(template_path),
html='<ul>\n';
for(var i=0;i<tag_list.length;i++){
html+="<li><a href='../tag/"+tag_list[i]+"'/>"+tag_list[i]+"</a></li>\n"
}
html+='</ul>\n'
content=content.toString().replace('{{tag_list}}',html)
yield writeFileThunk(template_path,content)
}
这里使用ES6的Generator函数
,避免异步函数的回调金字塔,使用tj大神的co执行Generator函数
- gulp配置添加tags task
gulp.task('tags',function(){
return gulp.src([root_path+'/src/markdown/!(index)*'])
.pipe(tags())
.pipe(gulp.dest(root_path+'/src/markdown'))
});
gulp.task('markdown',['css','js','tags'],function(){
var manifest = gulp.src(root_path+'/build/*');
return gulp.src(root_path+'/src/markdown/*.md')
.pipe(markdown())
.pipe(template(root_path+'/src/template.html'))
.pipe(rename({extname: ".html"}))
.pipe(revRewrite({ manifest }))
.pipe(gulp.dest(root_path+dist_dir+'/html'))
});
tags details
还需要标签详情页,就是点击侧边栏标签跳转到的页面,页面内容是该标签下的所有文章
- 生成标签json文件
var through = require('through2'),
PluginError = require('plugin-error'),
fs = require('fs'),
path = require('path'),
thunkify = require('thunkify'),
writeFileThunk=thunkify(fs.writeFile)
readFileThunk = thunkify(fs.readFile),
co = require('co');
...
return through.obj(process).on('end',function(){
co(gen_tags_html,Object.keys(all_tags));
co(gen_tags_json,all_tags);
});
function* gen_tags_json(all_tags){
yield writeFileThunk(root_path+'/tags.json',JSON.stringify(all_tags))
}
- nginx加载标签json文件
当然要先配置gitlab CI,将json文件添加到docker镜像
.gitlab-ci.yml
build:
stage: build
...
script:
- docker pull $CACHE_IMAGE_URL || true
- - tar -cf source.tar nginx.conf lua src gulpfile
+ - tar -cf source.tar nginx.conf lua src gulpfile tags*
- docker build --cache-from $CACHE_IMAGE_URL -f ./dockerfile/build -t $BUILD_IMAGE_URL -t $CACHE_IMAGE_URL .
...
nginx.conf
init_by_lua_file /root/lua/init.lua;
init.lua
local json = require("cjson")
local tags_json=""
file = io.open("/root/blog/tags.json", "r")
for line in file:lines() do
tags_json=tags_json..line
end
file:close()
tags = json.decode(tags_json)
- 根据请求,使用lua-resty-template渲染标签详情页面
location ^~ /tag {
root /root/blog;
content_by_lua_file /root/lua/tags.lua;
add_header content-type text/html;
...
}
tags.lua
--请求是/tag/nginx,提取后为nginx
local key=string.sub(ngx.var.request_uri,6)
local template = require "resty.template"
template.render("tags.html", { tag_list =tags[key] })
通过tags[key],由上面的标签json,得到该tag下所有文章
模板tags.html
<!-- build:content -->
{% for _, tag in ipairs(tag_list) do %}
<li><a href="../{{tag.path}}.html">{{tag.title}}</a></li>
{% end %}
<!-- /build:content -->