读Ghost博客源码与自定义Ghost博客主题
我使用的Ghost
博客一直使用者默认的Casper
主题。我向来没怎么打理过自己博客,一方面认为自己不够专业,很难写出质量比较高的文字;另一方面认为博客太耗时间,很容易影响正常的工作内容。最近公司即将搬迁,我的开发工作也告一段落,因此抽点时间自定义一个自己的博客主页。
备注:上图来自GhostChina官网,与本文内容无关。
Ghost与Ghost主题
Ghost
自称是专业的内容发布平台,实际上跟WordPress
相比它只能算一个相对比较年轻的博客系统,在功能上完全无法与成熟的WordPress
相比。
我之所以选择Ghost
作为博客系统除了它简单方便,更因为它是基于Node.js
且开源。毕竟基本的功能有了,如果有其他需求的话自己改代码就可以实现。Ghost
提供HTTP
服务用的是Express
框架。这是一种对我这类半路接触js
的人都可以轻易掌握的框架。
Ghost主题存放在安装路径的content/themes
目录中。安装包自带了Casper
和Roon
两个主题,其中前者为默认主题。
Ghost
支持HandleBars
模板语言,自带的两个主题也是基于此语言编写的,因此,定制Ghost
主题最简单的方法是复制一份Casper
的代码,基于它进行自定义。我就是这么做的。
关于自定义主题的详细介绍不在这里展开,若有需要请参考该链接:http://docs.ghostchina.com/zh/themes/。
自定义主页
Ghost
只定义了几个主要页面,分别是文章列表页(包含主页)、文章内容页、某标签的文章列表、某作者的文章列表,以及一些rss或sitemap相关的页面。
这么一说你就发现了,博客的主页和文章列表页面是同一个页面。主页对应的路径为/
,列表对应的路径为/page/:page
,其中:page为占位符,表示某个页码值,如1、2、3等。这两个路径实际上渲染的都是同一个模板文件index.hbs
。默认地,Ghost
接收到请求时/page/1
的GET请求时,返回301重定向到/
,再结合一些样式变化,从而让你以为主页和列表页是分离开的。
我要做的就是让主页和列表页面不一样。
解决方法1
首先我想到的就是在index.hbs文件中通过变量渲染不一样的内容。参考pagination.hbs我发现确实存在这两个可用的变量:prev
表示是否有前一页,以及page
表示当前为第几页。
如果能拿到这两个变量中的一个,我就可以区别对待主页和列表。遗憾的是不行。
分页相关的变量是模板驱动的,也就是说只能在固定的pagination.hbs这个文件中才能获取对应的值。该结论尚未在代码上得到验证
若在这个问题继续下去是可以实现我的需求的,但考虑到偏离Ghost
原来的设计太远可能埋下更多坑,因此放弃该解决方法。
解决方法2
既然无法在模板上解决问题,那就让路径/
渲染原来的index.hbs,让路径/page/:page
渲染另一个HandleBars
文件(我设定为list)。
实现这个方法只要两个步骤:
- 去除针对
/page/1
的重定向; - 为
/page/:page
指定新的渲染文件list.hbs。
需要改动ghost安装目录下的core/server/routes/frontend.js
文件。下面是改动后的结果:
其中,handleIndexPageParam
是参考handlePageParam
后新增加的一个函数,内容如下:
function handleIndexPageParam(req, res, next, page) {
var rssRegex = new RegExp('/rss/(.*)?/'); page = parseInt(page, 10); if (page === 1 && rssRegex.test(req.url)) {
// Page 1 is an alias, do a permanent 301 redirect
return redirect301(res, req.originalUrl.replace(rssRegex, '/rss/'));
} else if (page < 1 || isNaN(page)) {
// Nothing less than 1 is a valid page number, go straight to a 404
return next(new errors.NotFoundError());
} else {
// Set req.params.page to the already parsed number, and continue
req.params.page = page;
return next();
}
}
另外/page/:page
路径对应的渲染对象frontend.list
在core/server/controllers/frontend/index.js
中定义。改后的内容如下图所示:
描述list节点的配置在core/server/controllers/frontend/channel-config.js
中定义,在defaults中增加一个节点:
...
list: {
name: 'list',
route: '/',
frontPageTemplate: 'home'
},
...
尽管需求实现了,但是这种解决方法产生了新的问题:以后无法直接使用第三方提供的主题,若要使用,需要复制index.hbs
到新的文件list.hbs
。
解决方法3
实际上方法2的解决方案增加list
相关的代码是多余的,我在Ghost官网的文档里面查到,原来可以让路径/
独立渲染home.hbs
文档,而路径/page/2+
依旧渲染index.hbs
。
因此结合方法2,应该可以有一种更轻巧的自定义主页的方式。
读Ghost博客源码与自定义Ghost博客主题的更多相关文章
- SpringMVC+Spring+MyBatis个人技术博客源码
项目描述 Hi,大家好,又到了源码分享时间啦,今天我们分享的源码一个<个人技术博客>,该博客是基于SSM实现的一个个人博客系统,适合初学SSM和个人博客制作的同学学习.有了这个源码,直接买 ...
- java个人博客源码
初入博客园,请各位多关照,来而不往非礼也. 如需要源码以及学习内容,qq:1397617269,我看到就回你们资源. 直接给链接: 链接:https://pan.baidu.com/s/1S_awtg ...
- 如何读懂Framework源码?如何从应用深入到Framework?
如何读懂Framework源码? 首先,我也是一个应用层开发者,我想大部分有"如何读懂Framework源码?"这个疑问的,应该大都是应用层开发. 那对于我们来讲,读源码最大的问题 ...
- 修改VCL源码实现自定义输入对话框
来自:https://yq.aliyun.com/wenji/88428 通过修改VCL源码实现自定义输入对话框 在BCB中有两个函数可以实现输入对话框:InputBox和InputQuery,其实I ...
- Android菜鸟的成长笔记(6)——剖析源码学自定义主题Theme
原文:Android菜鸟的成长笔记(6)--剖析源码学自定义主题Theme 还记得在Android菜鸟的成长笔记(3)中我们曾经遇到了一个问题吗?"这个界面和真真的QQ界面还有点不同的就是上 ...
- css控制div显示/隐藏方法及2种方法比较原码 - czf164的专栏 - 博客频道 - CSDN.NET
body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...
- Java并发指南10:Java 读写锁 ReentrantReadWriteLock 源码分析
Java 读写锁 ReentrantReadWriteLock 源码分析 转自:https://www.javadoop.com/post/reentrant-read-write-lock#toc5 ...
- 读源码【读mybatis的源码的思路】
✿ 需要掌握的编译器知识 ★ 编译器为eclipse为例子 调试准备工作(步骤:Window -> Show View ->...): □ 打开调试断点Breakpoint: □ 打开变量 ...
- 从无到有开发自己的Wordpress博客主题---代码环境准备
注意这里说的是代码环境准备哦,而不是L(M)AMP运行环境哦,运行环境会在后述文章中在写. 一.在本地初始化git环境并且链接上gitee 1.在gitee上创建一个项目托管你的代码 这个不在赘述,按 ...
随机推荐
- 模板类-bitset
stl提供了std::bitset模板类,定义:bitset <32> bitvec;尖括号中的为长度,这条语句把bitvec定义为含有32个的bitset对象.和容器一样,按位置来访问他 ...
- ubuntu配置服务器apache
在配置apache之前我们需要先配置好ubuntu中的网络,如果不太懂的话可以看看这我的这篇文章:配置ubuntu网络,里面详细的介绍了怎么配置ubuntu的网络. 1.安装apache服务器 sud ...
- Spring的IOC分析(一)
我们学习Spring之前需要对23种java的设计模式的9种有一定的理解,设计模式为了解耦,Spring也是在解耦的方向上设计的,所以设计模式要理解一下,它当中用到了很多. 单例模式(写法很多钟,7种 ...
- python基础2 day3
一.上节回顾 1,while else2,格式化输出name = input('>>>')s1 = '我叫%s,今年%d岁'%(name,18)dic1name = input('& ...
- python动态类型
在python中,省去了变量声明的过程,在引用变量时,往往一个简单的赋值语句就同时完成了,声明变量类型,变量定义和关联的过程,那么python的变量到底是怎样完成定义的呢? 动态类型 python使用 ...
- node学习笔记2 —— npm包管理
全局模式安装包 将包安装为全局可用的可执行命令, 并非可以从任意地方require 将 package.json中bin定义的文件软链到统一的目录下, 该目录可以通过如下方式推算出来: path.re ...
- 通过JiaThis API接口自定义分享功能按钮实现分享功能本地化
http://www.mdaima.com/jingyan/20.html 最早李雷博客采用的是百度分享插件,为此还发过博文讲解如何在一个页面调用多个按钮分享不同的文章,感兴趣的朋友可以在本站搜索一下 ...
- Eclipse配置maven环境
一.什么是maven? Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个 ...
- P2P视频模块
P2P视频模块数据手册 公 司 : 深圳市万秀电子有限公司 网 站 : http://www.wanxiucx.com 总 机 : 0755-23215689 联系人: 张先生 手 机 : 1 ...
- xmind2013激活
参考链接:http://blog.163.com/m15999573195_1/blog/static/248705063201542622112823/