Hexo github页面生成插件
来源:互联网 发布:b2b网站发布软件 编辑:程序博客网 时间:2024/06/07 01:20
痛点
从2013年开始,本人开始活跃于github,以前托管于sourceforge、svn spot和oschina的开源项目,陆续迁移到了github。此前,我一直使用的是wiki系统来维护相关开源项目的文档及下载等。那时,Markdown还没有现在这么流行,在sourceforge等网站,我几乎不放文档。但迁移到github后,将之前的wiki页面渐渐转成了Markdown页面。在迁移到github之后,我比较重视文档,源代码的修改,有可能需要更新文档。此前wiki网站因为访问太慢,空间也不是特别稳定,在今年终于决定放弃维护,转而使用github page功能来托管这些项目文档。
github page是一个静态空间,不支持php等动态语言。虽然如此,不过也有逼格高的玩法。当初曾想过使用jekyll来建站,不过因为工作太忙,没有时间学习。后来无意之中接触了hexo,hexo可以完全兼容github markdown,觉得hexo更适合我一些。于是试用了若干plugin和theme,对其blog功能还是非常满意,但是如果要展现项目文档,还是显得捉襟见肘。我不可能每次更新github后,都手动复制一份相关的文档再更新到博客站点。如何自动抓取github相关的页面等内容成了一个非常大的痛点。
需求
这其实是一个hexo页面与github页面同步的问题。我期望的是,在github项目变更之后,比如README变更了,releases添加了,那么对应的hexo页面可以自动更新,而无需人工同步。
尝试
在尝试若干主题+插件都无法满足我的需求之后,我决定自己开发一个符合我需求的主题。主题的开发还是蛮曲折的,对于项目页这块,我尝试了不少的方案
前端JS实现,在html页面使用ajax请求github api,然后填充内容。本来github访问就慢,多个ajax请求就更慢了,而且github还有limit访问限制,未加token的访问,一天也就60次。访问60次之后,就无法再访问了。这肯定不行。
同步实现,在生成或访问时,使用同步请求将github内容同步输出为html,node.js是异步的,所以特地找了几个同步网络请求请求库,比如ajax同步请求,urllib-sync等。最后,使用urllib-sync终于实现了同步请求,但是它仍然有缺点,一是生成时,仍然会消耗github api limit,二是生成速度太慢,三是不稳定,经常timeout。四是如果生成过程中,有一次同步请求失败,必须重新全部生成。后面我添加了项目页面越来越多,根本就用不下去了。
终级方案
在尝试过多个方案并失败之后,终于痛定思痛,还是要写一个插件,然后仔细研究了hexo源码,发现生成器插件比较适合。它在hexo server
和hexo generate
时,生成器都会被调用,那么我只需写一个生成器,用于抓取github api,然后缓存起来,渲染时,直接从缓存中取github response渲染。
说干就干,在生成器中首先对站点的所有文章查找其是否带gh
front-matter,如果存在,则属于项目页,判断缓存是否存在,存在则跳过生成
pages.forEach(function(item) { if (item.gh) { var path = pathFn.join(cacheDir, item.path); if (!replace && fs.existsSync(path)) { if (github.debug) _self.log.debug(path + " exists skip generate"); return; } _self.log.info("generating github " + path); var dir = pathFn.dirname(path); mkdirsSync(dir);
生成具体规则如下:
var gh = gh_opt.call(_self, item); if (gh.type === 'get_contents') { github.repos.getContent({ user : gh.user, repo : gh.repo, ref : gh.ref ? gh.ref : 'master', path : gh.path ? gh.path : 'README.md' }, function(err, res) { // var url = util.format('repos/%s/%s/contents/%s', user, name, path); if (res && res.content) { var md = new Buffer(res.content, res.encoding).toString(); // var md_func = hs['markdown']; // Why generator can't call helper // function? fs.writeFileSync(path, md); } else { _self.log.w("generate github " + path + " failed"); } }); } else if (gh.type === 'get_releases') { ... } ...
根据不同的gh.type
来调用不同的github api,在这里,使用了node.js github第三方库来简化github操作。比如获取内容,将github上的markdown文件的内容写入到缓存中。所以此种方式,只要缓存存在,则不用重复请求github,不必担心github api limit限制,而且缓存是github原始数据,怎么展示,完全取决于主题。不像某些插件,生成的结果包含html,不好修改。
在主题模板中,使用辅助函数来操作github。比如下面的gh_contents
,将缓存中的markdown内容转化为html。
function gh_contents(options) { var o = options || {} var user = o.hasOwnProperty('user') ? o.user : this.config.github.user; var name = o.hasOwnProperty('repo') ? o.repo : null; var path = o.hasOwnProperty('path') ? o.path : 'README.md'; var ref = o.hasOwnProperty('ref') ? o.ref : 'master'; if (name === undefined) { return ''; } var cache = (this.gh_read_cache(this.page)); if (cache) { return this.markdown(cache.toString()); }
转化后的html可以做为page.content,直接显示。
{%- if gh.type === 'get_contents' %} {% set page.content = gh_contents(gh) %} {{ partial('project/contents', {} )}}
<div class="container-fluid"><div class="row"> <div class="{{theme.layout.p.sidebar}}" role="navigation"> {{ partial('sidebar', {}) }} </div> <div class="{{theme.layout.p.main}}"> {{ partial('../page/article') }} </div> <!-- aside --> <div class="{{theme.layout.p.toc}}"> {%- if page_toc() %} {{ partial('../partial/toc', {style: 'col m4 l3'}) }} {%- endif %} </div></div></div>
如上所示,将github上的文件内容直接输出到hexo页面。
优化
为保证新建一个github相关的页面而不用重新启动hexo server,仍然需要保留github同步请求,当缓存不存在时,则执行同步请求api,并且将结果保存到缓存中。
var url = util.format('repos/%s/%s/contents/%s', user, name, path); console.log("no cache, and try load from : " + url); var repo = gh.reqSync(url, { data : { 'ref' : ref } }); if (repo && repo.content) { var md = new Buffer(repo.content, repo.encoding).toString(); var content = this.markdown(md); this.gh_write_cache(this.gh_cache_dir(this.page, md)); return content; }
为加快生成速度,本插件还提供了控制台命令方式来生成。
$ hexo github [-r --replace]
总结
使用hexo-generator-github可以将github的内容抓取到本地,配合主题来渲染输出。这样就不必手动修改hexo的页面了。比较方便。但是也有不足的地方,比如,为保证github上的markdown在hexo站点正常显示,要求markdown中的链接和图片等外部资源需要使用绝对路径。另外,如果要更新hexo页面,需要将github缓存删除或者通过控制台命令$ hexo github -r
,这样才会重新生成hexo页面。
参考
hexo api: https://hexo.io/zh-cn/api/
hexo-generator-github: http://github.com/Jamling/hexo-generator-github
- Hexo github页面生成插件
- Hexo+GitHub
- Hexo+Github博客css js404导致博客页面空白
- hexo+github教程之四:配置hexo next主题第三方插件
- hexo搭建github博客
- Hexo+GitHub博客
- Github部署Hexo
- hexo + github 个人博客
- hexo+github搭建
- gitHub hexo 个人博客
- MyBlog = Hexo + Github
- hexo+github搭建博客
- Hexo+GitHub创建网站
- github hexo blog
- Github + hexo初涉猎
- Hexo+Github 博客搭建
- Hexo+Github搭建网站
- 搭建CMS,HEXO+Github
- IOC该怎样理解
- PHPCMS 父级ID 查找子类
- Leach protocol installation in ns-2.35 under Ubuntu 14.04
- svn报错can only be performed on a version resource [at this time].
- springmvc的搭建过程
- Hexo github页面生成插件
- $(window).load、$()与window.onload
- hdu 1988-More is better-带权并查集
- Android WebView第三方网站注入在线JS地址
- SVN环境搭建
- 如何在Unity中对程序进行 Android 真机断点调试?
- Sum Two
- leetcode 349. Intersection of Two Arrays
- 5-17 SQLite GreenDAO 笔记 待整理