在Ghost中使用分类

有不少刚接触Ghost博客的朋友都会问:Ghost如何做分类?如何按分类来浏览博客?其实Ghost没有分类这个概念,不像其它的博客系统,在发表文章时要选择分类,Ghost只有标签(Tag)。而我们正是要利用这个标签来变相地实现分类浏览。
  首先说下Ghost添加标签的地方,还是有些人是不知道的。在如图位置输入标签,标签和标签之间以英文逗号隔开,会自动提示之前的标签:Ghost tag
  Ghost中的标签是没有限制的,给了我们很多自由,但如果要做分类,我们还是需要遵守一定规则为好,比如之前有篇文章有个标签test,那么你下一篇文章如果还要使用这个标签,在标签输入处输入t,Ghost会自动提示出之前的test分类,选择即可。这样我们就有2篇文章有相同的标签test了,这时候我们可以通过http://your.blog.site/tag/test来访问这个分类下的所有文章。
  OK,现在我们已经完成了一半了,还有个问题是如何在我们的首页中显示分类信息呢?这里有几种方法,我们一一介绍。
  1. 第一种也是最简单最粗暴的方法,修改首页模板,在需要的位置添加一个到刚才的标签链接的a标签即可,该方法不做过多介绍,会网页基础的应该都会。
  2.使用Ghost新的helpernavigation,这个需要你现在后台的设置里面加入相应的标签的链接即可。如图Ghost navigation之后在模板中使用navigation来显示导航,关于该helper的使用,可以参考我翻译的文档。我们的GhostChina网站的导航就是使用了该方法,只不过它的导航链接都不是标签的,这里只是举例说明。
  3.使用中文版中特有的标签tag_cloud,关于该标签的使用请查看。另外GhostChina网站也使用了该标签云。Ghost china
  这里简单地介绍了如何在Ghost中添加分类浏览,那么有人要问了,Ghost可以按日期来浏览文章么?其实Ghost可以在发表文章时选择在文章的链接上加上日期的,Ghost title date但是要实现按日期浏览文章暂时是没有的,起码我没有看到过,不过这个可以通过添加标签的方式来实现,期待高手出现。

分享到

在Ghost中使用附件

有不少人问过ghost能不能上传附件的问题,当然大家可能都知道Ghost可以上传图片,使用![]()可以插入一个图片。然后有人就尝试在选择图片时上传一个普通文件,可惜这样系统会报错。
Ghost image format error
  这是因为ghost后台做了限制,当然,你可以改代码去掉这个限制,不过上传后的图片在image目录里,这与设计之初的本意不符。Ghost本就是一个极简的,专注于写作的博客系统,使用的是markdown来写作,因此也没有做上传附件这个功能。不过如果真的要在文章中使用附件怎么办呢?
  其实很简单,附件也不过只是个网络资源,你只需要将资源的url引用下就可以了。一种是自己用apache建一个静态文件服务器,比如我这个我的简单媒体工具。一种是使用云存储,然后获得文件的下载地址,比如使用七牛云存储
  这里以使用七牛为例,首先建一个静态目录的空间
Ghost image format error,关于空间的设置不做介绍,点击“空间管理”再点击“上传”,建议添加一个前缀,完成附件的上传。七牛上传这时候在列表页面点击刚上传的文件,在右侧就可以获取到文件的外链。Qiniu link
  通过上面2种方法得到了文件的外链后,只需要在博客中需要插入附件的地方插入[your title](刚获取到的外链地址)或者使用a标签<a href="刚获取到的外链地址" target="_blank">链接显示的文字</a>插入。a标签与markdown的语法相比,可以实现打开的页面是一个新的标签而不是覆盖当前的页面。最后,如果觉得默认的附件样式很丑,可以通过css来完善一下。下面附上我使用的附件。
自己服务器上的
七牛云存储的

分享到

在OpenShift上安装Ghost

使用OpenShift(以下简称OS)搭建Ghost环境的好处就是简单、免费,速度还不错。如果只是希望使用Ghost的用户不妨试试吧。

###注册OS并登录
这一步不做介绍,很简单。

###创建Ghost
1.在OS的控制台中切换到Applications页面,点击Add Application
2.在搜索输入框中输入ghost并回车,在搜索结果页面中点击Ghost 0.5.10(目前版本)。
3.在Public URL中输入一个唯一的二级域名,这里输入的内容不重要,后面可以使用自己的域名,其它默认就可以了,点击Create Application
4.完成后的页面可以无视,重新点击Applications就可以看到已经创建好的Ghost博客了,点击进去可以看到系统给你分配的二级域名,点击此链接即可访问博客。

###使用自定义的域名
1.在上面第4步的二级域名旁有一个change链接,点击之。
2.在新页面的Domain name里输入你想要绑定的域名,下面的ssl本文不做介绍,接着点击下面的Save按钮。
3.最后在你的域名的dns解析的地方加一条cname解析,cname的指向是之前系统给你分配的二级域名。配置好了以后等待一段时间,你就可以用你自定义的域名来访问Ghost博客了。

###Ghost汉化与升级

#####汉化
汉化我采用的是GhostChina提供的汉化版本。
1.首先去下载页面下载最新的版本。
2.然后再OS的控制台的应用界面里面找到Source Code
Source Code
复制此地址。
3.使用git拷贝项目

1
2
#xxxxxx是刚复制的地址
git clone ssh://xxxxxx

4.将第1步下载的中文版的/content/themes/casper-zh目录下的所有文件拷贝到第3步clone的项目下的/content/themes/casper目录下并覆盖原文件。将中文版的/core目录下的所有文件拷贝到第3步clone的项目下的/core目录下并覆盖原文件。
5.在第3步clone的项目的根目录下执行

1
2
3
git add ./ --all
git commit-m "hanhua"
git push

在执行push前请在OS中添加自己电脑的ssh公钥,生成公钥的方法可参考Git SSH Key 生成步骤,OS添加公钥的方法就是点击Settings–>Add a new key,在Key name中输入一个名字,在Paste the contents of your public key file中输入你的公钥并保存。

push完成后系统会自动重启,无需担心重启的问题,完成后再次访问你的域名吧。

#####升级
升级请参照更新 Ghost

分享到

使用Swiftype完成Ghost搜索功能

不知道出于什么目的,Ghost并没有给出搜索功能,但是我们可以使用第三方服务来完成站内搜索,本文推荐使用Swiftype来实现这一功能(不仅仅说Ghost可以使用该服务,所有需要站内搜索的都可以,可以查看本站blog.erguotou.me体验)。

#####注册
OK,这一步不做过多介绍,应该都会,记得激活账号,激活后进入控制台主界面。

#####创建一个搜索引擎

选择左侧的“Create a search engine(standard web crawler)”,然后输入你的Ghost博客地址。接着系统会验证你输入的网址,验证成功后在弹出框中输入引擎名称。

#####安装搜索引擎
1.在控制面板中切换至“install”,点击”Start Installation”。在”Appearance”中选择搜索引擎到外貌,这里我选择默认设置一直Next下去,最后点击”Save&Preview”。
2.然后点击“Install Code”,将代码复制到你的Ghost中去(可以在default.hbs的body标签后面添加),完成后点击Next。
3.在“Search Field”中根据自己的情况(一般Ghost博客没有搜索输入框)选择,这里我选择第二个“ No, my site needs an input field”,接着选择“Use the Swiftype search tab”,下面会有一个预览样式,然后点击Next。
4.最后点击页面最下方的“Active Swiftype”就可以为你的Ghost博客提供一个样式不错的搜索引擎啦~

分享到

GIT分支管理策略(非Git workflow)

参照 http://www.ruanyifeng.com/blog/2012/07/git.html

##主分支Master
主分支有且只有一个,所有提供给用户使用的正式版本都在这个分支上发布。

##开发分支Develop
日常的开发工作应该都在这个分支上进行。

1
git checkout -b develop

如果需要从develop对外发布版本

1
2
git checkout master
git merge --no-ff development

注:这里的参数--no-ff是不进行快速合并(快速合并只是改变指针)的意思。

##临时分支
前面介绍的是两条主要分支,一般正常情况下仓库中只存在这2个分支,但有时需要一些临时性的分支用于特定目的,这些分支在使用完成后应该删除掉,删除的命令为

1
git branch -d temp-branch

如果删除过程中出现错误需要强制删除的话可以执行

1
git branch -D temp-branch

注:临时分支不要提交到远程,在本地提交就可以了。

###功能分支(feature)
比如突然需要开发某个新的功能,但不是必需的,或者实现起来可能有些困难而直接放弃,或者是BOSS临时的想法,但不确定是否要加入到产品中,此时可以使用功能分支。

1
git checkout -b feature-xxx develop

开发完成后需要合并到develop分支的话

1
2
git checkout develop
git merge --no-ff feature-xxx

然后删除

###预发布分支(release)
当我们需要在正式发布版本前做一个测试的时候就需要预发布分支。使用过程和功能分支稍有差别,第一步创建

1
git checkout -b release-xxx develop

然后可能要执行一些操作,比如我会在这时执行grunt构建命令,完成开发代码到发布代码的构建。
当测试完成且没有问题的时候就开始合并代码

1
2
3
4
git checkout master
git merge --no-ff release-xxx
# 对合并后产生的新节点做一个标签(一般为版本号)
git tag -a xxx

接着根据情况考虑是否需要合并到开发分支(比如我grunt构建后的代码就不需要),最后说删除此分支。

###修复bug分支
项目正式发布后难免会有bug出现,此时就需要这样的分支,命名为fixbug-xxxxxx一般是项目的bug管理中对应的bug编号。

1
git checkout -b fixbug-xxx master

修改完成后合并到master分支

1
2
3
4
5
6
git checkout master
git merge --no-ff fixbug-xxx
# 遵循版本升级原则
# 一般bug修复后的版本号在上个版本的最后一位上面加1
# 比如上个版本为0.1.0,那么bug修复后的版本就是0.1.1
git tag -a xxx

再合并到develop分支

1
2
git checkout develop
git merge --no-ff fixbug-xxx

最后删除此分支

分享到

Ghost开发之API

Ghost API 接口

当前版本为0.5.8,后续更新的API不在其中。 本文写作时用的是英文版,下面所有涉及languageen_US的对应的中文版为zh_CN
下面所有的链接都是以http://your.blog.site:port开头,请注意。
你可以使用Chrome的Postman工具进行调试

登录认证

POST /ghost/api/v0.1/authentication/token
ACCEPT json
DATA

1
2
3
4
grant_type:password
username:your.email@email.com(请替换为你的邮箱)
password:your_password(请替换为你的登录密码)
client_id:ghost-admin

RESULT

1
2
3
4
5
6
7
{
access_token: 'xxx',
expires_in: 3600,
refresh_token: 'xxx',
token_type: "Bearer"
}
注意保存返回的结果

如果登录错误,会返回错误结果

1
2
status: 404
errors[0]: {message: 'xxx', type: 'xxxError'}

错误主要分为不存在的邮箱、错误的密码、密码输入错误次数过多几种
注意:以下所有请求涉及用户权限的,都需要在HTTP请求的头中加入access_token的信息,请求格式为

1
2
Request Headers中添加
Authorization: Bearer your_access_token

如果验证信息过期,会提示错误,如果没有加Authorization的头信息也会返回类似的错误信息

获取登录者信息

GET /ghost/api/v0.1/users/me/?status=all&include=roles
ACCEPT json
Authorization 见上说明
RESULT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
accessibility: null
bio: null
cover: null
created_at: "2015-02-08T12:11:34.683Z"
created_by: 1
email: "your.email@email.com"
id: 1
image: null
language: "en_US"
last_login: "2015-03-18T08:55:30.330Z"
location: null
meta_description: null
meta_title: null
name: "你的名字"
roles: [{id: 4, uuid: "9227adb4-a836-4f6c-ba41-7d5dd307968a", name: "Owner", description: "Blog Owner",…}]
slug: "your-slug"
status: "active"
updated_at: "2015-03-18T08:55:30.331Z"
updated_by: 1
uuid: "xxxx-uuid"
website: null
}

每个字段对应的意思从单词应该可以看出来,具体不做说明,注意保存返回结果

下面列出的所有api路径都是由/ghost/api/v0.1开头,在调用时请自行追加

配置相关

系统级的配置信息的json格式

1
2
3
4
{
"key": "fileStorage",
"value": true
}

  • GET /configuration 获取博客配置信息
  • GET /configuration/:key 根据指定ID获取配置信息

文章相关

新增文章的业务流程应该是(2,3步骤在Ghost中是监测输入间隔,然后发送请求)

  1. 获取标签等信息/tags/?limit=all
  2. 输入title后调用/slugs/post/:inputed-title会返回一个新的slug
  3. 输入正文时保存/posts/?include=tags,其中发送的数据格式为
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    {
    posts: [
    {
    title: 'xxx',
    slug: 'xxx', // 上一步获取到的slug
    markdown: 'xxx', // 输入的markdown内容
    image: 'xxx', // 文章的封面
    featured: false, // 是否推荐
    page: false, //是否单独页
    status: "draft", // 状态为草稿或者发布published
    language: "en_US", // 语言
    meta_title: null, // 设置里面的meta信息,下同
    meta_description: null,
    author: "1", // 作者id
    published_by: null, // 发布者
    tags:[ // 标签数组
    {
    description: null
    hidden: false
    image: null
    meta_description: null
    meta_title: null
    name: "tag1"
    post_count: null
    slug: null // 这个是新增的tag,没有uuid和slug
    uuid: null
    }
    ]
    }
    ]
    }

此请求返回的数据里面有一个id,保存id,下次在保存文章时的地址就是/posts/:id?include=tags

文章的json结构体如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
slug: "welcome-to-ghost", // 类似文章的链接
status: "published", // 文章的状态 草稿 已发布等
id: 1, // 文章ID
uuid: "xxxx-xxxx", // 文章的UUID
title: "Welcome to Ghost", // 文章标题
markdown: xxx // 文章的markdown内容
html: xxx // 文章的html内容
image: null, // 图片
featured: false, // 推荐
page: false, // 单独页
language: "en_US", // 语言
meta_title: null, // meta里面的title
meta_description: null, // meta里面的description,下面的很好理解,不做解释
created_at: "2015-02-08T12:11:20.645Z",
created_by: 1,
updated_at: "2015-02-08T12:11:20.645Z",
updated_by: 1,
published_at: "2015-02-08T12:11:20.684Z",
published_by: 1,
author: 1,
url: "/welcome-to-ghost/"
}

  • GET /posts 获取所有文章,返回的数据里面还包含分页信息
  • POST /posts 新增文章
  • GET /posts/:id 根据ID获取文章
  • GET /posts/slug/:slug 根据文章链接获取文章
  • PUT /posts/:id 编辑文章
  • DEL /posts/:id 根据ID删除文章

设置相关

博客的设置数据的json格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
"settings": [
{
"id": 5,
"uuid": "xxxx-xxxx",
"key": "title",
"value": "My blog",
"type": "blog",
"created_at": "2015-02-08T12:11:35.040Z",
"created_by": 1,
"updated_at": "2015-03-18T09:47:42.464Z",
"updated_by": 1
},
...
{
"key": "availableThemes", // 可用的主题
"value": [
{
"name": "casper",
"package": {
"name": "Casper",
"version": "1.1.5"
},
"active": true
}
],
"type": "theme"
},
{
"key": "availableApps", // 可用的app,当前版本暂时还不支持app的调用?
"value": [],
"type": "app"
}
],
"meta": {}
}

  • GET /settings 获取所有设置
  • GET /settings/:key 根据指定key获取设置
  • PUT /settings 修改设置

用户相关

用户数据的json格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
email: "your.email@email.com",
id: 1,
uuid: "xxxx-xxxx",
name: "你的名字",
slug: "exxx", // slug,个人信息页面链接为http://your.blog.site/author/:slug
image: null, // 头像
cover: null, // 封面
bio: null, // 简介
website: null,
location: null,
accessibility: null, // 这是虾米?
status: "active",
language: "en_US",
meta_title: null,
meta_description: null,
last_login: "2015-03-18T10:11:18.753Z",
created_at: "2015-02-08T12:11:34.683Z",
created_by: 1,
updated_at: "2015-03-18T10:11:18.753Z",
updated_by: 1
}

  • GET /users 获取所有用户
  • GET /users/:id 根据指定Id获取用户
  • GET /users/slug/:slug 根据用户的slug获取用户
  • GET /users/email/:email 根据邮箱获取用户
  • PUT /users/password 修改用户登录密码
  • PUT /users/owner 修改用户的所有者(不懂,没测试过)
  • PUT /users/:id 根据用户id来修改用户信息
  • POST /users 添加用户
  • del /users/:id 删除用户

标签相关

标签数据的json格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"id": 1,
"uuid": "xxxx-xxxx",
"name": "Getting Started",
"slug": "getting-started",
"description": null,
"image": null,
"hidden": false,
"meta_title": null,
"meta_description": null,
"created_at": "2015-02-08T12:11:20.685Z",
"created_by": 1,
"updated_at": "2015-02-08T12:11:20.685Z",
"updated_by": 1,
"parent": null
}

  • GET /tags 获取所有表情
  • GET /tags/:id 根据Id获取标签
  • POST /tags 添加标签
  • PUT /tags/:id 根据ID修改标签
  • del /tags/:id 根据ID删除标签

角色相关

角色数据的json格式

1
2
3
4
5
6
7
8
9
10
{
"id": 1,
"uuid": "1b925c9f-92f2-45b3-9828-9244adbaaddc",
"name": "Administrator",
"description": "Administrators",
"created_at": "2015-02-08T12:11:20.687Z",
"created_by": 1,
"updated_at": "2015-02-08T12:11:20.687Z",
"updated_by": 1
}

  • GET /roles/ 获取所有的角色

Slugs

  • GET /slugs/:type/:name 未研究,不做解释

主题

主题数据的json格式

1
2
3
4
5
6
{
"uuid": "casper",
"name": "Casper",
"version": "1.1.5",
"active": true
}

  • GET /themes 获取所有主题
  • PUT /themes/:name 修改当前的主题

通知相关

通知信息的json结构

1
2
3
4
5
6
7
8
9
10
{
notifications: [
{
dismissible: true,
location: 'bottom',
type': 'info', // 错误等级'error', 'success', 'warn' and 'info'
message: 'message'
}
]
}

  • GET /notifications
  • POST /notifications
  • del /notifications/:id

DB数据库

能获得数据里的各种数据,建议不要直接操作,使用其它方法单独操作

  • GET /db
  • POST /db
  • del /db

邮件

未测试

  • POST /mail 发送邮件
  • POST /mail/test 发送测试邮件

用户认证

未测试。。

  • POST /authentication/passwordreset
  • PUT /authentication/passwordreset
  • POST /authentication/invitation
  • GET /authentication/invitation
  • POST /authentication/setup
  • GET /authentication/setup
  • POST /authentication/token
  • POST /authentication/revoke

上传文件

  • POST /uploads
    uploadimage file数据,上传时的图片文件
分享到

一些备忘

  • 登录到ssh

    1
    ssh git@127.0.0.1
  • 查看版本和远程url

    1
    git remote -v
  • git迁移
    1.clone一份或者直接在原本地工程上开始
    2.git remote set-url origin <url> url为目标迁移的git地址
    3.git push origin master 将本地资源push到远程

  • bing每日背景请求地址

分享到

在搬瓦工上安装Ghost

1.前面的内容不做介绍,SSH连接上(本文以CentOS 6 64位系统做说明)
2.安装需要的环境,中间有确认的过程,直接输入y回车

1
yum install libtool automake autoconf gcc-c++ openssl-devel

3.在/home目录下新建一个目录(名字随意,主要用于存放我们的文件,本例使用的是latazu)latazu,并下载我们需要的文件nodejs、ghost

1
2
3
4
5
cd /home
mkdir latazu
cd latazu
wget http://nodejs.org/dist/v0.10.36/node-v0.10.36.tar.gz
wget http://cdn.diancloud.com/ghost/releases/Ghost-0.5.8-zh.zip

4.编译安装nodejs(make的过程有点长,耐心等待)

1
2
3
4
tar zxvf node-v0.10.36.tar.gz
cd node-v0.10.36
./configure
make && make install

5.解压ghost文件,并配置ghost配置文件config.js

1
2
3
4
5
cd ../
unzip Ghost-0.5.8-zh.zip -d ghost
cd ghost
cp config.example.js config.js
vi config.js

配置完成后保存(具体配置不做详细说明)
6.安装依赖文件(只安装生产环境需要的文件)

1
npm install --production

如果npm过程中出现glibc版本过低的问题,请参考“libc.so.6: version `GLIBC_2.14’ not found”系统的glibc版本太低升级glibc版本

7.设置环境变量并启动Ghost(这里使用的是forever守护进程)

1
2
3
export NODE_ENV=production
npm install -g forever
forever start index.js

8.安装Nginx

1
2
rpm -Uvh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
yum install nginx

配置nginx(新建一个配置文件ghost.conf,下面有一个样例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mkdir /etc/nginx/logs
vi /etc/nginx/conf.d/ghost.conf

server {
listen 80;
server_name www.renshiwo.me renshiwo.me;
charset utf-8;
access_log logs/ghost.log;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;

proxy_pass http://127.0.0.1:2368;
proxy_redirect off;
}
}

9.启动nginx,并设置开机自启动

1
2
service start nginx
chkconfig nginx on

OK!可以了,现在访问你的域名看看吧!哦~对了,不要忘记设置域名解析!

其它后续操作
1.安装FTP vsftpd的安装配置
2.安装ShandowSocks(翻墙必备) CentOS下shadowsocks一键安装脚本

分享到

Ghost源码解读系列(一)目录结构

本系列文章以Ghost0.5.8安装版本为基础,后续版本升级时可能会做升级记录日志
由于个人水平和理解有限,可能部分地方没有给出分析或者解读有误,欢迎指正

#1. Ghost目录结构
├content: 内容
 ├apps: 以后Ghost开发的app会放在这个目录下,期待吧!
 ├data: 数据文件夹,请勿修改此文件下任何内容,默认sqlite数据文件会存放与此
 ├images: 图片文件夹,默认使用本地存储时,上传的图片会存于此处
 ├themes: 主题文件夹,所有的主题文件夹存放于此,下面以默认的casper主题为例
  ├casper: 默认主题
   ├assets: 资源目录,不做更多介绍
   ├partials:
   author.hbs: 作者页面
   default.hbs:
   index.hbs: 首页
   page.hbs:
   post.hbs:
   tag.hbs:
├core: 核心模块
 ├built: 用Grunt合并压缩后的js代码,不做展开介绍
 ├client: 客户端代码,主要是js css font image等内容,后续详细介绍
 ├server: 服务端代码,后续详细介绍
 ├shared: 共享文件
 index.js: 服务器启动入口文件
.bower.json: bower文件配置
.config.example.js: 示例的配置文件
Gruntfile.js: grunt配置
index.js: 主入口函数,启动函数位置
LICENSE: LICENSE
package.json: 项目配置
PRIVACY.md: 隐私控制,可用的第三方功能说明,可以在config.js中修改
README.md: 项目说明文档

分享到

群友博文大合集

分享到