当我们发布一个开源项目的时候,最重要的事情之一就是要创建项目文档。对使用项目的用户来说,文档是非常有必要的,通常我们可以使用下面这些方式来创建文档:
GitHub Wiki:在 Github 上我们可以为每个项目都创建一个 wiki。Wiki 是由一系列的 Markdown 文件组成,所以我们可以用 wiki 来做项目文档。但这种方案也有一些缺点:wiki 的贡献者不会出现在项目贡献者列表中;文档的结构和布局都是有限制的,只能是 Github Wikis 的样式;文档存储在第三方平台上。
README:我们可以为项目创建一个 README.md 文件,它会直接展示在 Github(或 Gitlab、Coding 等 git 仓库)的项目页面。如果文档非常少,这中方案是非常适合的。但如果文档非常多,这个 README.md 文件就会非常大了。而且通常来说,README.md 是用来介绍项目,而不是展示文档。
自建网站:当然,我们也可以创建一个文档网站,然后放在自己的服务器上。这样我们就可以随意编辑文档。但这种方案的缺点是不便于追踪文档的变化、开发网站和文档维护相比前两种方案麻烦非常多、而且还需要自建主机。
Github Pages:Github 也提供了一个托管项目中静态文件的功能。我们可以为项目创建一个
gh-pages
分支,Github 就会将分支中的内容当做静态站点。这种方案好的一方面是文档维护是在一个单独的分支,虽然可能寻找起来比较麻烦。不好的一方面是文档编写是编写成静态文件(html/css/js),修改和维护起来比较麻烦。
以上方案都不完美,所以需要一种综合以上所有优点的方案,简单来说就是:
文档以 MarkDown 文件编写
使用 hexo 将 MarkDown 文件生成成静态文件
将静态文件发布到 github pages
Hexo 简介
Hexo 是一个 Node.js 编写的静态网站生成器。Hexo 主要用来做博客框架,同时 Hexo 也整合了将静态网站部署到 Github 的功能,所以也很适合用来做 Github 项目的文档。
我们可以使用 Hexo,根据写好的 HTML 布局(既 Hexo 的主题),将 MarkDown 文件生成成主题对应的静态 html/css/js 文件。Hexo 提供了将静态文件部署到 Github 分支上的配置。也就是说,我们可以使用 MarkDown 来维护文档,当写好部署配置之后,使用一个命令就可以将文档生成并发布到 Github 的 gh-pages 分支上。
安装 Hexo
Hexo 是通过 Node.js 编译的,所以需要安装 Node.js。Hexo 使用 Git 将文件部署到 Github,所以也需要安装 Git。
安装 Node.js
推荐使用 Node.js 的版本管理器来安装,比如 nvm。当然,也有很多其他的 Node.js 版本管理工具,使用这些工具,我们能很方便地安装 Node.js,以及在不同的 Node.js 的版本中切换。
目前 Node.js 最新的版本是 8.1.3,使用 nvm 来安装:
$ nvm install v8.1.3
安装完 Node.js 的同时也会安装对应的 npm。
安装 Git
我们还需要在系统上安装 Git。如果不确定系统中是否已经安装了 Git,使用下面的命令检查:
$ git --version
如果出现了 Git 的版本号,则不需要再安装了。如果没有,则需要安装 Git。
Windows
Windows 系统直接点此连接 https://git-scm.com/download/win 下载 Git 软件,然后运行即可。
macOS
在 macOS 上安装 Git 有多种不同的方式:
我个人推荐使用 Homebrew 来安装软件。当然如果你更喜欢 MacPorts,也没有任何问题。
Linux – Ubuntu or Debian
在 Ubuntu 或 Debian 上,我们可以使用 apt 来安装软件:
$ sudo apt-get install git-core
Linux – Fedora, Red Hat or CentOS
在 Fedora、Red Hat 或 CentOS 上,我们可以使用 yum 来安装软件:
$ sudo yum install git-core
安装 Hexo CLI
在安装完 Node.js 和 Git 之后,我们最后需要安装 Hexo:
$ npm install -g hexo-cli
通过下面的命令来检查 hexo 是否正确安装上了:
$ hexo --version
如果输出了一系列的版本号,说明所有安装工作都以完成,可以正式使用 hexo 了。
配置
安装好 hexo 之后,现在我们就可以在 Github 的主分支上来创建我们的文档了。根据该文章,你可以:
在一个已存在的项目中创建文档
创建一个新的项目 Create a new repository
简单起见,假设你是新创建了一个名为 hexo-documentation
的项目,当然你也可以用一个已经存在的项目继续下面的操作。
接下来使用下面的名令在本地 clone 项目:
$ git clone https://github.com/USERNAME/REPOSITORY.git
将 USERNAME
替换为你的用户名,REPOSITORY
替换为你的项目名称。例如我执行的命令如下:
$ git clone https://github.com/nodejh/hexo-documentation
然后使用 cd
进入项目目录,并创建一个名为 docs
的目录:
$ cd hexo-documentation
$ mkdir docs
docs 目录将存放我们的文档。使用 hexo 初始化 docs 目录:
$ hexo init docs
上面的命令将生成 hexo 的一些配置并安装相关依赖。安装完成之后,docs 的目录结构如下:
_config.yml
站点配置文件package.json
Node.js 的依赖文化scaffolds
hexo 发布文章的时候使用(本文暂不介绍 hexo 的特性)source
MarkDown 和各种资源文件themes
hexo 的主题
我们可以通过下面的命令来检查网站是否能够正常运行:
$ hexo generate
$ hexo server
第一个命令将根据选用的主题,将 sources 目录中的文件转换成静态网站文件。第二个命令将启动一个 Web 服务器,提供这些静态网站文件,我们可以通过 http://localhost:4000
来访问:
目前我们的网站看起来还是一个博客而不是文档,不过我们将要将其改成文档的样子。
创建一个主题
要改变网站的外观,我们需要创建一个 hexo 的主题。主题确定了 hexo 生成的网站的样式和布局。https://hexo.io/themes/ 这个网站有很多免费的 hexo 主题可以使用。但在这篇文章里,我们要从零开始创建一个 hexo 主题。
Hexo 有一个名为 landscape 的默认主题,在 docs/themes
这个目录里面。你可以在 themes
目录存放多个主题,但每次只能有一个主题被使用。接下来让我们创建自己的主题。在 themes 目录下创建一个名为 documentation
的目录。
Hexo 的主题包含以下文件和目录:
_config.yml
主题配置文件languages
国际化的语言包layout
主题布局,即页面结构等scripts
一些 Hexo 插件脚本source
资源文件夹,里面的文件名以_
开头外的所有文件都会被当作网站的静态资源
我们将创建一个简单的静态主题,所以我们不需要 scripts
目录。然后目前仅以中文展示,所以也不需要 languages
目录。
我们需要做的就是编写网站的布局,以及一些 CSS 代码。在本文中我将使Sass 来生成 CSS,但 hexo 并不能直接处理 Sass,但幸运的是有 hexo-renderer-sass 这个插件来帮助 hexo 处理 Sass。
使用 npm 来安装 hexo-renderer-sass,在 ./docs
(注意不是在 themes 目录里面)运行下面的命令:
$ npm install --save hexo-renderer-sass
然后回到 themes 目录里面,配置 Sass,不然 hexo-renderer-sass 插件不会被加载。在 docs/themes/documentation/_config.yml
文件中加入下面的代码:
node_sass:
outputStyle: nested
precision: 4
sourceComments: false
Sass 的所有可配置在 node-sass
接下来就可以编写 Sass 代码了。不过在本文中我不会详细介绍怎么写 Sass 样式,因为它和本文内容无关,而且范围太大,一时半会儿写不完。你可以在这里 https://github.com/nodejh/hexo-documentation 找到这些文件,然后把他们复制到你的项目中,或者你也可以创建自己的样式。
让我们继续回到布局,开始编写代码之前,还有一个重要的事情就是选择模板引擎,如 swig、ejs 等。Hexo 默认使用的模版引擎是 swig,这也是我们将要使用的。
接下来创建文件 docs/themes/documentation/layout/post.swig
,并写入下面的代码:
<!DOCTYPE html>
<html>
<head>
<meta charSet=‘utf-8‘ />
<title>{{config.title + ‘ - ‘ + page.title}}</title>
<link href=‘https://cdnjs.cloudflare.com/ajax/libs/normalize/4.0.0/normalize.min.css‘ rel=‘stylesheet‘ type=‘text/css‘>
<link href=‘https://fonts.googleapis.com/css?family=Open+Sans:400,600,300,700‘ rel=‘stylesheet‘ type=‘text/css‘>
<link href=‘{{ url_for("css/docs.css") }}‘ rel=‘stylesheet‘>
</head>
<body>
<div class=‘menu‘>
<div class=‘logo‘>
Documentation
</div>
<nav class=‘menu-nav‘>
{% for section in site.data.nav %}
<ul class=‘nav‘>
<span>{{ section.title }}</span>
<ul class=‘nav‘>
{% for item in section.items %}
<li>
<a href=‘{{item.href || url_for(item.id + ".html") }}‘{% if item.id == page.id %} class=‘active‘{% endif %}>{{item.title}}</a>
</li>
{% endfor %}
</ul>
</ul>
{% endfor %}
</nav>
<a class=‘footer‘ href=‘https://github.com/sitepoint-editors/hexo-documentation‘>
Project on github
</a>
</div>
<div class=‘page‘>
<div class=‘page-content‘>
<h1>{{page.title}}</h1>
{{page.content}}
</div>
</div>
<div class=‘switch-page‘>
{% if page.prev %}
<a class=‘previous‘ href=‘{{ url_for(page.prev) }}‘>Previous</a>
{% endif %}
{% if page.next %}
<a class=‘next‘ href=‘{{ url_for(page.next) }}‘>Next</a>
{% endif %}
</div>
</body>
</html>
简单分析一下代码。
<head>
<meta charSet=‘utf-8‘ />
<title>{{config.title + ‘ - ‘ + page.title}}</title>
<link href=‘https://cdnjs.cloudflare.com/ajax/libs/normalize/4.0.0/normalize.min.css‘ rel=‘stylesheet‘ type=‘text/css‘>
<link href=‘https://fonts.googleapis.com/css?family=Open+Sans:400,600,300,700‘ rel=‘stylesheet‘ type=‘text/css‘>
<link href=‘{{ url_for("css/docs.css") }}‘ rel=‘stylesheet‘>
</head>
头部主要包括两部分:
title
Hexo 提供了一些列的变量,我们可以使用其中的config.title
和page.title
来组成我们的 titlelinks
链接里面包括 normalize CSS,使默认的样式保持跨浏览器的一致性;Google Fonts,使文本显示更友好;url_for,这是 Hexo 的一个辅助函数,可以在路径前加上根路径
接下来看 body 部分,大体上还是 HTML。一些重点部分稍后会详细介绍。
<nav class=‘menu-nav‘>
{% for section in site.data.nav %}
<ul class=‘nav‘>
<span>{{ section.title }}</span>
<ul class=‘nav‘>
{% for item in section.items %}
<li>
<a
href=‘{{ item.href || url_for(item.id + ".html") }}‘
{% if item.id == page.id %}
class=‘active‘
{% endif %}
>
{{ item.title }}
</a>
</li>
{% endfor %}
</ul>
</ul>
{% endfor %}
</nav>
上面的代码会生成网站的菜单部分,菜单项来自于 site.data.nav
这个对象,稍后我们会在 docs/source/_data/nav.yml
中创建。source/_data
是 Hexo 的数据文件。site.data.nav
即 _data
目录中的 nav.yml
文件。nav.yml
中是一个包含 title
和 items
对象的数组。
接下来比较重要的是文章内容这部分:
<div class="page-content">
<h1>{{ page.title }}</h1>
{{ page.content }}
</div>
这里面包括了文章标题和内容两部分。文章内容是根据 MarkDown 文件生成的 HTML。
最后还包括 “上一页” 和 “下一页” 按钮:
{% if page.prev %}
<a class=‘previous‘ href="{{ url_for(page.prev) }}">上一页</a>
{% endif %}
{% if page.next %}
<a class=‘next‘ href="{{ url_for(page.next) }}">下一页</a>
{% endif %}
上面的代码中,我们假设每个页面都有 “上一页” 和 “下一页” 按钮。
然后创建一个首页 documentation/layout/index.swig
:
<!DOCTYPE html>
<html>
<head>
<meta charSet=‘utf-8‘ />
<title>{{config.title + ‘ - ‘ + page.title}}</title>
<link href=‘https://cdnjs.cloudflare.com/ajax/libs/normalize/4.0.0/normalize.min.css‘ rel=‘stylesheet‘ type=‘text/css‘>
<link href=‘https://fonts.googleapis.com/css?family=Open+Sans:400,600,300,700‘ rel=‘stylesheet‘ type=‘text/css‘>
<link href=‘{{ url_for("css/docs.css") }}‘ rel=‘stylesheet‘>
</head>
<body>
<div class=‘index‘>
<a href="/what-is-it.html">
Get Start
</a>
</div>
</body>
</html>
现在差不多就完成了!不仅是布局文件完成了,我们的主题也制作好了。最后一件事情就是修改 Hexo 生成静态文件的时候使用的主题。修改 docs/_config.yml
文件中的 theme
属性:
theme: documentation
所有事情都做完了!接下来我们就可以创建文档了。
编写文档
接下来就到了整篇文章最重要的部分了,为我们的项目编写文档。我们将在 docs/source/
目录完成这些事情。这里的文档是网站内容的来源,以及网站的菜单。
首先创建菜单。Hexo 提供了让我们定义一些数据文件,并通过 site.data
来访问。首先在 source
目录里面创建 _data
目录,然后创建名为 nav.yml
的文件:
- title: Introduction
items:
- id: what-is-it
title: What is it?
- id: how-it-works
title: How it works
- title: Usage
items:
- id: installation
title: Installation
- id: using
title: Using It
这样我们就可以通过 site.data.nav
来访问 nav.yml
中的文件。
在上面创建的菜单中,我们创建了两篇文章,每篇文章有两个部分。最后我们就只需要创建页面了。在编写 MarkDown 之前,先创建以下文件,与菜单对应:
what-is-it.md
how-it-works.md
installation.md
using.md
接下来就要往文件中写入内容。文件的开头部分是 Front-matter,里面是页面的一些设置,Front-matter 是包含在两个 ---
之间的 YAML 格式的。
如 what-is-it.md
所示:
---
layout: default
id: what-is-it
title: What is it?
next: how-it-works.html
---
This is our what it is markdown file
- one
- two
- three
在 front-matter 中有下面这些设置:
layout
页面的布局id
页面的唯一标识title
页面标题next
下一页链接
按照类似的方法编写其他几个 MarkDown 文件。当网站创建好之后,这些 MarkDown 内容会被转换为 HTML。
编辑好了之后,就可以生成静态网站了:
$ hexo generate
$ hexo server
然后通过 http://localhost:4000
就可以看到如下页面:
部署到 GitHub Pages
现在我们的文档网站就全部做好了,接下来需要做的就是将其部署到 Github Pages 上。如果我们手动来实现,就需要创建 gh-pages 分支,生成静态网站,复制网站文件到 gp-pages 分支,commit 并且 push 代码到 GitHub。当修改文档之后,又得重复这些工作。
幸运的是,Hexo 提供了一个很方便地将站点部署到 gh-pages 的方法。首先安装 hexo-deployer-git 这个包,在 docs/
目录下运行命令:
$ npm install --save hexo-deployer-git
然后打开 docs/_config.yml
,在文档的最后面,修改部署配置信息,注意将其中的用户名(nodejh)修改为你的用户名:
deploy:
type: git
repo: https://github.com/nodejh/hexo-documentation
branch: gh-pages
message: "Docs updated: {{ now(‘YYYY-MM-DD HH:mm:ss‘) }})"
最后再修改一些其他配置:
# Site
title: Hexo documentation
subtitle: Hexo documentation article
description: Hexo documentation article
author: nodejh
language: zh-cn
timezone: GMT
# URL
url: https://nodejh.github.io/hexo-documentation
root: /hexo-documentation/
OK!现在就只剩下一件事情了,就是将网站部署到 Github 上,在终端上运行:
$ hexo generate
$ hexo deploy
Hexo 将生成静态文件,并将其自动部署到 gh-pages 分支上。部署完成之后,我们就可以通过 https://nodejh.github.io/hexo-documentation 来访问了。
总结
如果你想要的项目被被人使用,文档是非常必要的。在 GitHub 上也有很多创建项目文档的方法。对于中大型项目来说,维护一个文档网站也是很有必要的。Hexo 不仅能生成静态网站,同时也提供了部署网站的方案,非常方便我们使用。