Ghost主题的临时Pjax化解决方案

由于Ghost目前不支持插件, 很多功能的实现都依赖于修改程序源码, 这在日后的升级维护上会带来很多麻烦, 但如果不这么做, 功能又实现不了, 甚是蛋疼. 比如我们通常而言需要后端程序配合才能实现的Pjax, 在这以Handlebars.js作为模板引擎的Ghost里就显得有些强人所难.

不过群众的脑洞是可怕的, 有个叫做MoOx/pjax的JavaScript模块, 通过直接解析XHR得来的源文件, 强行脱离后端实现了Pjax加载(这会比常规的Pjax实现多一些网络资源占用). 今天尝试把这个模块强行加进Casper主题里, 最终实现了Casper主题的Pjax化效果.

具体的实现步骤如下:

一、把MoOx/pjax的pjax.js作为静态资源加入你的Ghost主题, 我将它放在了

/assets/plugins/pjax/pjax.js

二、在partials目录里新建一个名为pjax.hbs的Handlebars.js模板文件, 输入以下内容后保存:

<script src="{{asset "plugins/pjax/pjax.js"}}"></script>  
<script>  
(function() {
    if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
        return
    }

    $(document).on('pjax:success', function() {
        var a = document.createElement('a')
        a.href = document.URL
        var pathname = a.pathname
            .split('/')
            .filter(function(value){return !!value})
            .shift()
        switch(pathname) {
            case 'author':
            case 'tag':
            case 'page':
            case undefined:
                $('body').removeClass('post-template')
                $('body').addClass('home-template')
                break
            default:
                $('body').removeClass('home-template')
                $('body').addClass('post-template')
        }
        $.getScript('{{asset"js/index.js"}}')
    })

    new Pjax({
        elements: 'a[href]:not([href^="#"])',
        selectors: [
            'title',
            '.site-wrapper',
            '.menu-button, .nav-cover, .nav-close'
        ]
    })
})()
</script>  

其中有一些是依赖jQuery实现的, 现在的Ghost版本已经脱离了jQuery库, 如果你不需要jQuery, 请自行修改上面的代码, 我个人已经很久没有碰ES5的VanillaJS和jQuery了, 这里图方便进行了混写, 代码质量比较差, 让大家见笑了.

这个文件的JavaScript部分做了三件微小的工作, 第一件是确立了移动设备不得使用Pjax技术, 因为是强行实现的Pjax, 在模板的各部分逻辑分离上还存在硬伤, 在移动设备上效果不好, 所以干脆就停用了; 第二件是当Pjax成功时, 将Casper主题的一部分HTML差异还原, 并且重新载入index.js脚本, 保证菜单导航的正常使用; 第三件就是在当前页面上应用Pjax, 没什么好说的.

三、编辑default.hbs, 在的前一行添加:

{{> pjax}}

这样pjax.hbs就会被引入每个页面里, 从而实现全站Pjax化.

至此, pjax化就完成了. 完整的实现见BlackGlory/Casper

如果有使用动态评论框之类的需求, 可以参考本站目前在用的主题BlackGlory/Casper-Mine, 也是基于MoOx/pjax实现的.