Farseerfc的小窝 - pelican//farseerfc.me/zhs/2016-08-07T16:28:00+09:00启用 GitHub Issue 作为博客留言系统2016-08-07T16:28:00+09:002016-08-07T16:28:00+09:00farseerfctag:farseerfc.me,2016-08-07:/zhs/github-issues-as-comments.html<p>从今天起本博客将启用 GitHub Issue 作为留言系统。
原本使用的 Disqus 将继续保留一段时间,目前没有关闭的计划。</p>
<p>换用 GitHub Issue 是计划了好久的事情了,最初重做这个主题的时候就有考虑过。
这个想法的契机是看到了这篇
<a class="reference external" href="http://ivanzuzak.info/2011/02/18/github-hosted-comments-for-github-hosted-blogs.html">GitHub hosted comments for GitHub hosted blogs</a>
,然后立马觉得这个想法很符合寄宿在 GitHub Pages 上的博客。
一个限制是要求评论者必须有 GitHub
账户,考虑到我的博客的受众这个要求估计不算太过分。
使用 GitHub Issue 的好处么,比如自带的 GFMD
富文本格式,邮件通知,还有订阅和取消订阅通知,邮件回复,
这些方面都不比第三方留言系统逊色。</p>
<p>换用 GitHub Issue 另一方面原因是最近听说 Disqus
被部分墙了,想必以后墙也会越来越高。之前曾经试过在这个博客换上多说,
然而效果我并不喜欢,多说喜欢侵入页面加很多奇怪的东西 …</p><p>从今天起本博客将启用 GitHub Issue 作为留言系统。
原本使用的 Disqus 将继续保留一段时间,目前没有关闭的计划。</p>
<p>换用 GitHub Issue 是计划了好久的事情了,最初重做这个主题的时候就有考虑过。
这个想法的契机是看到了这篇
<a class="reference external" href="http://ivanzuzak.info/2011/02/18/github-hosted-comments-for-github-hosted-blogs.html">GitHub hosted comments for GitHub hosted blogs</a>
,然后立马觉得这个想法很符合寄宿在 GitHub Pages 上的博客。
一个限制是要求评论者必须有 GitHub
账户,考虑到我的博客的受众这个要求估计不算太过分。
使用 GitHub Issue 的好处么,比如自带的 GFMD
富文本格式,邮件通知,还有订阅和取消订阅通知,邮件回复,
这些方面都不比第三方留言系统逊色。</p>
<p>换用 GitHub Issue 另一方面原因是最近听说 Disqus
被部分墙了,想必以后墙也会越来越高。之前曾经试过在这个博客换上多说,
然而效果我并不喜欢,多说喜欢侵入页面加很多奇怪的东西,比如用户的头像通常是
http 的……也试过结合新浪微博的评论,而新浪微博越来越封闭,API 也越来越不靠谱。</p>
<p>使用 GitHub Issue 作为评论的方式比较简单,上面那篇博客里面提到了,代码量不比
加载 Disqus 多多少,而且没有了 iframe 的困扰,唯一麻烦的地方就是要稍微设计一下布局方式让它融入
现有的页面布局。
<a class="reference external" href="https://github.com/farseerfc/pelican-bootstrap3/blob/2ea6c9f3227275fe86ddaa75d8fc6496b3b03d8c/templates/includes/comments.html#L32">我参考上面的实现在这里</a> 。
这个加载代码使用两个变量加载 Issue Comments ,一个是在 pelicanconf.py 里的
<code class="code">
GITHUB_REPO</code>
,可以指向任何 Repo ,我指向 farseerfc/farseerfc.github.io
的这个 GitHub Page repo ,另一个变量是每篇文章里需要加上 <code class="code">
issueid</code>
的元数据,关连文章到每个 Issue 上。</p>
<p>还有一个稍微麻烦的事情是现在每写一篇文章之后都要新建一个 issue 了。
手动操作有点累人,于是我 <a class="reference external" href="https://github.com/farseerfc/farseerfc/blob/master/createissue.py">写了个脚本</a>
自动搜索 pelican 的 content 文件夹里面文章的 slug 并且对没有 issueid 关连的
文章创建 issue 。</p>
<p>好啦新的留言系统的外观样式还在测试中,希望大家多留言帮我测试一下!</p>
<div class="label label-warning">
<strong>2016年8月7日19:30更新</strong></div>
<p>新增了对 GitHub Issue comments 里面
<a class="reference external" href="https://developer.github.com/v3/issues/comments/#reactions-summary">reactions</a>
的支持,套用 font-awesome 的图标(似乎没 GitHub 上的图标好看)。这个还属于 GitHub API
的实验性功能,要加入 <code class="code">
Accept: application/vnd.github.squirrel-girl-preview</code>
HTTP 头才能拿到。</p>
<div class="label label-warning">
<strong>2016年8月7日23:16更新</strong></div>
<p>感谢 @iovxw 的测试让我发现 github 的高亮回复和邮件回复是需要特殊处理的。
高亮回复用上了 <a class="reference external" href="https://github.com/sindresorhus/github-markdown-css">这里的 CSS</a>
邮件引言的展开事件直接用 jQuery 做了:</p>
<div class="highlight"><pre><span class="code-line"><span></span> <span class="nx">$</span><span class="p">(</span><span class="s2">".email-hidden-toggle > a"</span><span class="p">).</span><span class="nx">on</span><span class="p">(</span><span class="s2">"click"</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">){</span></span>
<span class="code-line"> <span class="nx">e</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">();</span></span>
<span class="code-line"> <span class="nx">$</span><span class="p">(</span><span class="s2">".email-hidden-reply"</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">parent</span><span class="p">).</span><span class="nx">toggle</span><span class="p">();</span></span>
<span class="code-line"><span class="p">});</span></span>
</pre></div>
<p>还得注意邮件的回复需要 CSS 里面 <code class="code">
white-space: pre-wrap</code>
。</p>
用 Travis-CI 生成 Github Pages 博客2015-02-20T11:10:00+09:002015-02-20T11:10:00+09:00farseerfctag:farseerfc.me,2015-02-20:/zhs/travis-push-to-github-pages-blog.html
<div class="label label-warning">
<strong>2015年2月21日更新</strong></div>
<p>上次介绍过 <a class="reference external" href="//farseerfc.me/zhs/redesign-pelican-theme.html">这个博客改换了主题</a> ,
本以为这个话题可以告一段落了,没想到还能继续写呢。</p>
<p>寄宿在 Github Pages 上的静态博客通常有两种方案,其一是使用 <a class="reference external" href="http://jekyllrb.com/">Jekyll</a> 方式撰写,这可以利用
Github Pages 原本就有的
<a class="reference external" href="https://help.github.com/articles/using-jekyll-with-pages/">Jekyll支持</a>
生成静态网站。另一种是在 <strong>本地</strong> 也就是自己的电脑上生成好,然后把生成的 HTML 网站 push
到 Github Pages ,这种情况下 Github Pages 就完全只是一个静态页面宿主环境。</p>
<p>我用 <a class="reference external" href="http://getpelican.com/">Pelican</a> 生成博客,当然就只能选择后一种方式了。这带来一些不便,比如本地配置 pelican
还是有一点点复杂的,所以不能随便找台电脑就开始写博客。有的时候只是想修正一两个错别字,
这时候必须打开某台特定的电脑才能编辑博客就显得不太方便了。再比如 pelican 本身虽然是 python
写的所以跨平台,但是具体到博客的配置方面, Windows …</p>
<div class="label label-warning">
<strong>2015年2月21日更新</strong></div>
<p>上次介绍过 <a class="reference external" href="//farseerfc.me/zhs/redesign-pelican-theme.html">这个博客改换了主题</a> ,
本以为这个话题可以告一段落了,没想到还能继续写呢。</p>
<p>寄宿在 Github Pages 上的静态博客通常有两种方案,其一是使用 <a class="reference external" href="http://jekyllrb.com/">Jekyll</a> 方式撰写,这可以利用
Github Pages 原本就有的
<a class="reference external" href="https://help.github.com/articles/using-jekyll-with-pages/">Jekyll支持</a>
生成静态网站。另一种是在 <strong>本地</strong> 也就是自己的电脑上生成好,然后把生成的 HTML 网站 push
到 Github Pages ,这种情况下 Github Pages 就完全只是一个静态页面宿主环境。</p>
<p>我用 <a class="reference external" href="http://getpelican.com/">Pelican</a> 生成博客,当然就只能选择后一种方式了。这带来一些不便,比如本地配置 pelican
还是有一点点复杂的,所以不能随便找台电脑就开始写博客。有的时候只是想修正一两个错别字,
这时候必须打开某台特定的电脑才能编辑博客就显得不太方便了。再比如 pelican 本身虽然是 python
写的所以跨平台,但是具体到博客的配置方面, Windows 环境和 Linux/OSX/Unix-like
环境下还是有
<a class="reference external" href="http://pelican.readthedocs.org/en/latest/settings.html#date-format-and-locale">些许出入</a>
的。还有就是没有像 wordpress 那样的基于 web
的编辑环境,在手机上就不能随便写一篇博客发表出来(不知道有没有勇士尝试过在
Android 的 <a class="reference external" href="https://code.google.com/p/android-scripting/">SL4A</a> 环境下的 python 中跑 pelican ,还要配合一个
<a class="reference external" href="https://play.google.com/store/apps/details?id=com.romanenco.gitt">Android 上的 git 客户端</a> )。</p>
<p>当然并不是因此就束手无策了,感谢 <a class="reference external" href="https://travis-ci.org/">Travis-CI</a> 提供了免费的
<ruby><rb>持续整合</rb><rp>(</rp><rt>Continuous integration</rt><rp>)</rp></ruby> 虚拟机环境,
通过它全自动生成静态博客成为了可能。</p>
<div class="section" id="id4">
<h2><a class="toc-backref" href="#id10">关于 Travis-CI</a></h2>
<p><a class="reference external" href="http://zh.wikipedia.org/wiki/%E6%8C%81%E7%BA%8C%E6%95%B4%E5%90%88">持续整合</a>
原本是 <ruby><rb>敏捷开发</rb><rp>(</rp><rt>Agile Development</rt><rp>)</rp></ruby>
或者 <ruby><rb>极限编程</rb><rp>(</rp><rt>Extreme Programming</rt><rp>)</rp></ruby> 中提到的概念,大意就是说在开发的过程中,
一旦有微小的变更,就全自动地 <strong>持续</strong> 合并到主线中, <strong>整合</strong> 变更的内容到发布版本里。
这里的 <strong>整合</strong> 实际上可以理解为 <strong>全自动测试</strong> 加上 <strong>生成最终产品</strong> 。
可以看到 <strong>持续整合</strong> 实际强调 <strong>全自动</strong> ,于是需要有一个服务器不断地监听主线开发的变更内容,
一旦有任何变更(可以理解为 git commit )就自动调用测试和部署脚本。</p>
<p>于是要用持续整合就需要一个整合服务器,幸而 Travis-CI 对 github 上的公开 repo
提供了免费的整合服务器虚拟机服务,和 github 的整合非常自然。所以我们就可以用它提供的虚拟机
为博客生成静态网站。</p>
</div>
<div class="section" id="id6">
<h2><a class="toc-backref" href="#id11">启用 Travis-CI 自动编译</a></h2>
<p>这一步很简单,访问 <a class="reference external" href="https://travis-ci.org/">https://travis-ci.org/</a> 并用你的 Github 账户登录,
授权它访问你的账户信息就可以了。然后在 <a class="reference external" href="https://travis-ci.org/repositories">https://travis-ci.org/repositories</a> 里开启
需要编译的 repo ,这样 Travis-CI 就会监视对这个 repo 的所有 push 操作,并且对
每个 push 调用测试了。</p>
<div class="figure">
<img alt="在 Travis-CI 中开启对 Github Repo 的持续整合" class="img-responsive" src="//farseerfc.me/zhs/images/travis-repo-enable.png"/>
<p class="caption">在 Travis-CI 中开启对 Github Repo 的持续整合</p>
</div>
<p>然后在 repo 的根目录放一个 <code class="code">
.travis.yml</code>
文件描述编译的步骤。
<strong>暂时</strong> 测试的目的下我写的 <code class="code">
.travis.yml</code>
大概是下面这样。</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="nt">language</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">python</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="nt">python</span><span class="p">:</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="s">"2.7"</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="nt">before_install</span><span class="p">:</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo apt-add-repository ppa:chris-lea/node.js -y</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo apt-get update</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo apt-get install nodejs ditaa doxygen parallel</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="nt">install</span><span class="p">:</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo pip install pelican</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo pip install jinja2</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo pip install babel</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo pip install beautifulsoup4</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo pip install markdown</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo npm install -g less</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">wget "http://downloads.sourceforge.net/project/plantuml/plantuml.jar?r=&ts=1424308684&use_mirror=jaist" -O plantuml.jar</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo mkdir -p /opt/plantuml</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo cp plantuml.jar /opt/plantuml</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">echo "#! /bin/sh" > plantuml</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">echo 'exec java -jar /opt/plantuml/plantuml.jar "$@"' >> plantuml</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo install -m 755 -D plantuml /usr/bin/plantuml</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">wget https://bintray.com/artifact/download/byvoid/opencc/opencc-1.0.2.tar.gz</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">tar xf opencc-1.0.2.tar.gz</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">cd opencc-1.0.2 && make && sudo make install && cd ..</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo locale-gen zh_CN.UTF-8</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo locale-gen zh_HK.UTF-8</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo locale-gen en_US.UTF-8</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">sudo locale-gen ja_JP.UTF-8</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="nt">script</span><span class="p">:</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">git clone --depth 1 https://github.com/farseerfc/pelican-plugins plugins</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">git clone --depth 1 https://github.com/farseerfc/pelican-bootstrap3 theme</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">mkdir output</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">env SITEURL="farseerfc.me" make publish</span></span>
</pre></div>
<p>Travis-CI 提供的虚拟机是比较标准的 Ubuntu 12.04 LTS ,打上了最新的补丁,并且根据你指定的
语言选项会把相应的解释器和编译器升级到最新版(或者指定的版本)。这里用 python 语言的配置,
所以 python 是 2.7 的最新版并且有 pip 可以直接用。
配置中的 before_install 和 install 的区别其实不大,其中任何一个失败的话算作
build errored 而不是 build fail ,而如果在 script 里失败的话算作 build fail 。</p>
<p>为了编译我的模板,还需要比较新的 less.js ,所以添加了 ppa 装了个最新的 nodejs
并用它装上了 less 。
还从源码编译安装上了最新版的 opencc 1.0.2 ,因为 Ubuntu 源里的 opencc 的版本比较老(0.4),
然后 doxygen 作为 opencc 的编译依赖也装上了。
其它安装的东西么,除了 pelican 之外都是插件们需要的。以及我还需要生成 4 个语言的 locale
所以调用了 4 次 locale-gen 。由于是比较标准的 Ubuntu 环境,所以基本上编译的步骤和在本地
Linux 环境中是一样的,同样的这套配置应该可以直接用于本地 Ubuntu 下编译我的博客。</p>
<p>写好 <code class="code">
.travis.yml</code>
之后把它 push 到 github ,然后 travis 这边就会自动 clone
下来开始编译。 travis 上能看到编译的完整过程和输出,一切正常的话编译结束之后
build 的状态就会变成 passing ,比如
<a class="reference external" href="https://travis-ci.org/farseerfc/farseerfc/builds/51344614">我的这次的build</a> 。</p>
</div>
<div class="section" id="travis-ci-github">
<h2><a class="toc-backref" href="#id12">从 Travis-CI 推往 Github</a></h2>
<p>上面的测试编译通过了之后,下一步就是让 travis-ci 编译的结果自动推到 Github Pages
并发布出来。要推往 Github 自然需要设置 Github 用户的身份,在本地设置的时候是把
ssh key 添加到 github 账户就可以了,在编译细节都通过 github repo 公开了的 travis 上
当然不能放推送用的私有 key ,所以我们需要另外一种方案传递密码。</p>
<div class="panel panel-default">
<div class="panel-heading">
Github 上创建 Personal Access Token</div>
<div class="panel-body">
<img alt="Github 上创建 Personal Access Token" class="img-responsive" src="//farseerfc.me/zhs/images/travis-blog-push.png"/>
</div>
</div>
<p>好在 Github 支持通过 <a class="reference external" href="https://github.com/settings/applications">Personal Access Token</a>
的方式验证,这个和 App Token 一样可以随时吊销,同时完全是个人创建的。另一方面 Travis-CI
支持加密一些私密数据,通过环境变量的方式传递给编译脚本,避免公开密码这样的关键数据。</p>
<p>首先创建一个 <a class="reference external" href="https://github.com/settings/applications">Personal Access Token</a>
,这里需要勾选一些给这个 Token 的权限,我只给予了最小的 public_repo 权限,如侧边里的图。
生成之后会得到一长串 Token 的散列码。</p>
<div class="panel panel-default">
<div class="panel-heading">
如果你不能使用 travis 命令</div>
<div class="panel-body">
<div class="label label-warning">
<strong>2015年2月21日更新</strong></div>
<p>使用 <code class="code">
travis encrypt</code>
命令来加密重要数据最方便,不过如果有任何原因,
比如 ruby 版本太低或者安装不方便之类的,那么不用担心,我们直接通过
<a class="reference external" href="http://docs.travis-ci.com/api/#repository-keys">travis api</a>
也能加密数据。</p>
<p>第一步用这个命令得到你的repo的 pubkey :</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="go">curl -H "Accept: application/vnd.travis-ci.2+json" https://api.travis-ci.org/repos/<github-id/repo>/key | python2 -m json.tool | grep key | sed 's/.*"key": "\(.*\)"/\1/' | xargs -0 echo -en | sed 's/ RSA//' > travis.pem</span></span>
</pre></div>
<p>其中的 <github-id/repo> 替换成 github 上的 用户名/repo名, 比如我的是
farseerfc/farseer 。travis api 获得的结果是一个 json ,所以还用 python 的
json 模块处理了一下,然后把其中包含 key 的行用 <code class="code">
grep</code>
提取出来,用
<code class="code">
sed</code>
匹配出 key 的字符串本身,然后 <code class="code">
xargs -0 echo -en</code>
解释掉转义字符,然后删掉其中的 "<空格>RSA" 几个字(否则 openssl 不能读),
最后保存在名为 travis.pem 的文件里。</p>
<p>有了 pubkey 之后用 openssl 加密我们需要加密的东西并用 base64 编码:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="go">echo -n 'GIT_NAME="Jiachen Yang" GIT_EMAIL=farseerfc@gmail.com GH_TOKEN=<Personal Access Token>' | openssl rsautl -encrypt -pubin -inkey travis.pem | base64 -w0</span></span>
</pre></div>
<p>替换了相应的身份信息和token之后,这行得到的结果就是 secure 里要写的加密过的内容。</p>
</div>
</div>
<p>然后我们需要 <code class="code">
travis</code>
命令来加密这个 token , archlinux 用户可以安装
<code class="code">
aur/ruby-travis</code>
,其它用户可以用 gems 安装:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="gp">$</span> gem install travis</span>
</pre></div>
<p>装好之后,在设定了 Travis-CI 的 repo 的目录中执行一下 <code class="code">
travis status</code>
,
命令会指导你登录 Travis-CI 并验证 repo 。正常的话会显示最新的 build 状态。
然后同样在这个 repo 目录下执行:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="gp">$</span> travis encrypt <span class="s1">'GIT_NAME="Jiachen Yang" GIT_EMAIL=farseerfc@gmail.com GH_TOKEN=<Personal Access Token>'</span></span>
</pre></div>
<p>当然上面一行里的相应信息替换为个人的信息,作为这个命令的执行结果会得到另一长串散列码,
把这串散列写入刚才的 <code class="code">
.travis.yml</code>
文件:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="nt">env</span><span class="p">:</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="nt">secure</span><span class="p">:</span> <span class="s">"long</span><span class="nv"> </span><span class="s">secure</span><span class="nv"> </span><span class="s">base64</span><span class="nv"> </span><span class="s">string"</span></span>
</pre></div>
<p>有了这段声明之后, Travis-CI 就会在每次编译之前,设置上面加密的环境变量。
然后在编译脚本中利用这些环境变量来生成博客:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="nt">script</span><span class="p">:</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">git config --global user.email "$GIT_EMAIL"</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">git config --global user.name "$GIT_NAME"</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">git config --global push.default simple</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">git clone --depth 1 https://github.com/farseerfc/pelican-plugins plugins</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">git clone --depth 1 https://github.com/farseerfc/pelican-bootstrap3 theme</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">git clone --depth 1 https://$GH_TOKEN@github.com/farseerfc/farseerfc.github.io output</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">env SITEURL="farseerfc.me" make publish</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="nt">after_success</span><span class="p">:</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">cd output</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">git add -A .</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">git commit -m "update from travis"</span></span>
<span class="code-line"> <span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">git push --quiet</span></span>
</pre></div>
<div class="alert alert-warning compound">
<p>这里要注意最后 <code class="code">
git push</code>
的时候一定要加上 <code class="code">
--quiet</code>
,因为默认不加的时候会把
代入了 <code class="code">
$GH_TOKEN</code>
的 URL 显示出来,从而上面的加密工作就前功尽弃了……</p>
</div>
<p>根据 <a class="reference external" href="http://docs.travis-ci.com/user/build-lifecycle/">travis 的文档</a>
, after_success 里写的步骤只有在 script 里的全都完全无错执行完之后才会执行,这正是我们
push 的条件。目前 after_success 的成功与否不会影响到 build 的状态。
具体我用的配置见
<a class="reference external" href="https://github.com/farseerfc/farseerfc/blob/master/.travis.yml">这里的最新版</a> 。
在我的 <code class="code">
make github</code>
中
<a class="reference external" href="https://github.com/farseerfc/farseerfc/blob/master/Makefile#L102">调用了</a>
<code class="code">
git push</code>
命令,从而执行了 <code class="code">
make github</code>
之后就会自动部署到 github 上。</p>
</div>
<div class="section" id="web">
<h2><a class="toc-backref" href="#id13">用 Web 编辑并发布静态博客</a></h2>
<p>经过以上设置之后,一切正常的话,每次对主 repo 推送更新的同时, Travis-CI 就会自动
拉来更新然后编译并发布了。可以放置这样的图标 <img alt="travisIcon" class="img-responsive no-responsive" src="https://travis-ci.org/farseerfc/farseerfc.svg?branch=master"/> 在项目的 <code class="code">
Readme.md</code>
中显示编译状态。</p>
<p>这样设置之后的另一个好处就在于可以利用 Github 的 Web 界面编辑文章内容。在 Github 里
编辑和保存之后会自动作为一个 commit 提交,所以也会触发 Travis-CI 的自动编译。</p>
<div class="figure">
<img alt="在 Github 的 Web 界面中直接编辑文章内容" class="img-responsive" src="//farseerfc.me/zhs/images/travis-edit-github-web.png"/>
<p class="caption">在 Github 的 Web 界面中直接编辑文章内容</p>
</div>
<p>以及虽然目前还没有好用的 Github 的手机客户端,不过直接用 Android/iPhone 的浏览器登录
github 并编辑文章的可用性也还不错,所以同样的方式也可以直接在手机上发布博文了。</p>
<p>That is all, happy blogging ~</p>
</div>
换到 farseerfc.me 域名2015-01-26T23:32:00+09:002015-01-26T23:32:00+09:00farseerfctag:farseerfc.me,2015-01-26:/zhs/switch-to-farseerfc-dot-me-domain.html<p>上个月就在 <ruby><rb>狗爹</rb><rp>(</rp><rt>godaddy</rt><rp>)</rp></ruby> 上买了个自己的域名 <code class="code">
farseerfc.me</code>
准备用在这个
博客上,当时试着转到过这个域名,发现 <ruby><rb>自定义域名</rb><rp>(</rp><rt>custom domain</rt><rp>)</rp></ruby>
只支持 http 不支持 https ,想着还要买自己的证书,于是就扔在了一旁。不用自定义域名的话,
放在 github.io 上是可以用 HTTPS 的。
今天在 <a class="reference external" href="//webchat.freenode.net/?channels=archlinux-cn">#archlinux-cn</a> 上受大牛 <a class="reference external" href="/links.html#quininer">quininer</a> 和 <a class="reference external" href="/links.html#lilydjwg">lilydjwg</a> 点播,
发现 cloudflare 有提供
<a class="reference external" href="https://blog.cloudflare.com/introducing-universal-ssl/">免费的支持 SSL 的 CDN 服务</a>
赶快去申请了一个,感觉非常赞,于是就换过来了。</p>
<p>设置的方法按照 <a class="reference external" href="https://me.net.nz/blog/github-pages-secure-with-cloudflare/">这篇博文</a>
说的一步步做下来,如它所述,用 CloudFlare …</p><p>上个月就在 <ruby><rb>狗爹</rb><rp>(</rp><rt>godaddy</rt><rp>)</rp></ruby> 上买了个自己的域名 <code class="code">
farseerfc.me</code>
准备用在这个
博客上,当时试着转到过这个域名,发现 <ruby><rb>自定义域名</rb><rp>(</rp><rt>custom domain</rt><rp>)</rp></ruby>
只支持 http 不支持 https ,想着还要买自己的证书,于是就扔在了一旁。不用自定义域名的话,
放在 github.io 上是可以用 HTTPS 的。
今天在 <a class="reference external" href="//webchat.freenode.net/?channels=archlinux-cn">#archlinux-cn</a> 上受大牛 <a class="reference external" href="/links.html#quininer">quininer</a> 和 <a class="reference external" href="/links.html#lilydjwg">lilydjwg</a> 点播,
发现 cloudflare 有提供
<a class="reference external" href="https://blog.cloudflare.com/introducing-universal-ssl/">免费的支持 SSL 的 CDN 服务</a>
赶快去申请了一个,感觉非常赞,于是就换过来了。</p>
<p>设置的方法按照 <a class="reference external" href="https://me.net.nz/blog/github-pages-secure-with-cloudflare/">这篇博文</a>
说的一步步做下来,如它所述,用 CloudFlare 的优点如下:</p>
<ol class="arabic simple">
<li>CDN 加速</li>
<li>SSL (HTTPS) 加密</li>
<li>支持 SPDY 协议</li>
<li>支持 IPv6</li>
</ol>
<div class="label label-warning">
<strong>2015年12月29日更新</strong></div>
<p>现在不光支持 SPDY 而且支持 HTTP/2 了。</p>
<p>然后 <strong>免费账户</strong> 的一些缺点有:</p>
<ol class="arabic simple">
<li>CloudFlare 和 github.io 之间的数据不是加密的,因为 github
<ruby><rb>自定义域名</rb><rp>(</rp><rt>custom domain</rt><rp>)</rp></ruby> 还不支持使用自己的证书。这也是一开始我没用
自定义域名的原因嘛,这没有办法……</li>
<li>CloudFlare 给免费账户签名的 SSL 证书比较新,不支持一些老的设备和浏览器,比如不支持
老的 XP 系统的 IE 或者 2.x 的 Android。这种情况下没办法只能用没有加密的 HTTP 了。</li>
<li>不支持 <a class="reference external" href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security">HSTS 头</a>
,所以不能从服务器这边强制浏览器用 HTTPS。当然可以放个 javascript 跳转,
也可以用 <a class="reference external" href="https://www.eff.org/https-everywhere">HTTPSEverywhere</a> 这种方案。</li>
</ol>
<div class="label label-warning">
<strong>2015年12月29日更新</strong></div>
<p>如评论中 <a class="reference external" href="http://farseerfc.me/switch-to-farseerfc-dot-me-domain.html#comment-2015037231">提到的</a>
现在支持 HSTS 了。</p>
<div class="section" id="id3">
<h2>设置步骤</h2>
<p>基本按照默认的选项下一步就可以了。</p>
<ol class="arabic simple">
<li>和那个博主一样我把 <ruby><rb>安全级别</rb><rp>(</rp><rt>Security profile</rt><rp>)</rp></ruby> 降到了 Low ,即使是可疑流量也
不会要求输入 CAPTCHA 。</li>
<li>把 SSL 方式开在 Flexible SSL,访客到 CloudFlare 是加密的,而 CloudFlare 到
github.io 是不加密的。</li>
<li>把 CDN 开到了 CDT+Full Optimization ,可以对访问加速。由于是完全静态的博客,没有
动态变化的内容,所以应该比较安全。</li>
<li>服务器设置的一步需要将 <ruby><rb>域名解析服务器</rb><rp>(</rp><rt>DNS nameservers</rt><rp>)</rp></ruby> 从狗爹的服务器改到
CloudFlare 的,如下图:</li>
</ol>
<div class="figure">
<img alt="更改狗爹的域名服务器" class="img-responsive" src="//farseerfc.me/zhs/images/godaddy.png"/>
<p class="caption">更改狗爹的域名服务器</p>
</div>
<p>申请好之后就由 CloudFlare 接管域名解析了,接下来在 CloudFlare 的 DNS 设置添加一条
<a class="reference external" href="https://help.github.com/articles/tips-for-configuring-an-a-record-with-your-dns-provider/">A 类规则指向 github pages 的 IP</a> 。</p>
<div class="figure">
<img alt="更改CloudFlare的DNS规则" class="img-responsive" src="//farseerfc.me/zhs/images/cloudflaredns.png"/>
<p class="caption">更改CloudFlare的DNS规则</p>
</div>
<p>等一切都反映到 DNS 服务器上就设置完成了,接下来给
<a class="reference external" href="https://help.github.com/articles/adding-a-cname-file-to-your-repository/">farseerfc.github.io push 一个 CNAME 文件</a>
写上我的域名就可以了。我用 Makefile 配合我的 pelican 配置做这个:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="nf">publish</span><span class="o">:</span> <span class="n">rmdrafts</span> <span class="n">cc</span> <span class="n">clean</span> <span class="n">theme</span></span>
<span class="code-line"> <span class="o">[</span> ! -d <span class="k">$(</span>OUTPUTDIR<span class="k">)</span> <span class="o">]</span> <span class="o">||</span> find <span class="k">$(</span>OUTPUTDIR<span class="k">)</span> -mindepth <span class="m">1</span> -not -wholename <span class="s2">"*/.git*"</span> -delete</span>
<span class="code-line"> rm -rf cache</span>
<span class="code-line"> <span class="nb">echo</span> <span class="k">$(</span>SITEURL<span class="k">)</span> > content/static/CNAME</span>
<span class="code-line"> <span class="k">$(</span>PELICAN<span class="k">)</span> <span class="k">$(</span>INPUTDIR<span class="k">)</span> -o <span class="k">$(</span>OUTPUTDIR<span class="k">)</span> -s <span class="k">$(</span>PUBLISHCONF<span class="k">)</span> <span class="k">$(</span>PELICANOPTS<span class="k">)</span></span>
<span class="code-line"> <span class="k">$(</span>MAKE<span class="k">)</span> rsthtml</span>
<span class="code-line"></span>
<span class="code-line"><span class="nf">github</span><span class="o">:</span></span>
<span class="code-line"> <span class="o">(</span><span class="nb">cd</span> <span class="k">$(</span>OUTPUTDIR<span class="k">)</span> <span class="o">&&</span> git checkout master<span class="o">)</span></span>
<span class="code-line"> env <span class="nv">SITEURL</span><span class="o">=</span><span class="s2">"farseerfc.me"</span> <span class="k">$(</span>MAKE<span class="k">)</span> publish</span>
<span class="code-line"> <span class="o">(</span><span class="nb">cd</span> <span class="k">$(</span>OUTPUTDIR<span class="k">)</span> <span class="o">&&</span> git add . <span class="o">&&</span> git commit -m <span class="s2">"update"</span> <span class="o">&&</span> git push<span class="o">)</span></span>
</pre></div>
<div class="highlight"><pre><span class="code-line"><span></span><span class="n">SITEURL</span> <span class="o">=</span> <span class="s1">'//'</span> <span class="o">+</span> <span class="n">getenv</span><span class="p">(</span><span class="s2">"SITEURL"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s1">'localhost:8000'</span><span class="p">)</span></span>
<span class="code-line"><span class="n">STATIC_PATHS</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'static'</span><span class="p">,</span> <span class="s1">'images'</span><span class="p">,</span> <span class="s1">'uml'</span><span class="p">,</span> <span class="s1">'images/favicon.ico'</span><span class="p">,</span> <span class="s1">'static/CNAME'</span><span class="p">]</span></span>
<span class="code-line"><span class="n">EXTRA_PATH_METADATA</span> <span class="o">=</span> <span class="p">{</span></span>
<span class="code-line"> <span class="s1">'images/favicon.ico'</span><span class="p">:</span> <span class="p">{</span><span class="s1">'path'</span><span class="p">:</span> <span class="s1">'favicon.ico'</span><span class="p">},</span></span>
<span class="code-line"> <span class="s1">'static/CNAME'</span><span class="p">:</span> <span class="p">{</span><span class="s1">'path'</span><span class="p">:</span> <span class="s1">'CNAME'</span><span class="p">}</span></span>
<span class="code-line"><span class="p">}</span></span>
</pre></div>
<p>然后把生成的静态网站 push 到 github 之后可以从项目设置里看到域名的变化:</p>
<div class="figure">
<img alt="Github 配置好自定义域名之后的变化" class="img-responsive" src="//farseerfc.me/zhs/images/githubdomain.png"/>
<p class="caption">Github 配置好自定义域名之后的变化</p>
</div>
<p>最后把Disqus的评论也迁移到新的域名,disqus有方便的迁移向导,一直下一步就可以了。</p>
<p>这样就一切都设置妥当了。</p>
</div>
<div class="section" id="id4">
<h2>致谢</h2>
<p>最后要感谢提供消息的 <a class="reference external" href="/links.html#quininer">quininer</a> 和 <a class="reference external" href="/links.html#lilydjwg">lilydjwg</a> ,感谢撰写设置步骤的
<em>Jonathan J Hunt</em> , 感谢 CloudFlare 提供免费 SSL CDN 服务,感谢 Github 提供
方便免费的 Pages 托管。</p>
</div>
重新设计了 Pelican 的主题与插件2015-01-25T22:45:00+09:002015-01-25T22:45:00+09:00farseerfctag:farseerfc.me,2015-01-25:/zhs/redesign-pelican-theme.html
<!-- PELICAN_BEGIN_SUMMARY -->
<div class="label label-warning">
<strong>2015年2月14日更新</strong></div>
<!-- PELICAN_END_SUMMARY -->
<div class="section" id="id2">
<h2><a class="toc-backref" href="#id38">前言: 新天新地,将一切都更新了 <a class="footnote-reference" href="#id37" id="id1">[1]</a></a></h2>
<!-- PELICAN_BEGIN_SUMMARY -->
<p>不知不觉间放任这边长草很久了,从上次
<a class="reference external" href="//farseerfc.me/zhs/try-pelican.html">折腾主题</a> 到现在都快三年了,
而从上次 <a class="reference external" href="//farseerfc.me/zhs/marry-me.html">写了篇告白信</a> 到现在也有快两年了。
这期间曾经把主题配色从 <a class="reference external" href="http://getbootstrap.com/2.3.2/">Bootstrap 2</a> 默认的
白底黑字改成了让眼睛更舒适的黑底白字,也不过是用 drop-in 的配色方案而已,没有本质上的改进。</p>
<p>洞中一日世上千载,两年里 Bootstrap 已经升上 <a class="reference external" href="http://getbootstrap.com/">v3.3</a> ,
而 Pelican 则已经升到 <a class="reference external" href="https://github.com/getpelican/pelican/releases/tag/3.5.0">3.5</a> 了。
早就眼馋 Bootstrap 和 Pelican 中的诸多新功能新设计,不过无奈于时间有限只能饱饱眼福。</p>
<p>近日想写的东西越积越多,终于下定决心花了前前后后 <strong>两个月</strong> 的时间重新设计了一遍
Pelican 的主题,配合一些我觉得有用的插件。于是本博客就变成你们现在看到的样子了。
(以及本篇博文也用了两个月的时间写完,其间还发了几篇别的短文,算是恢复写博客的尝试吧 …</p></div>
<!-- PELICAN_BEGIN_SUMMARY -->
<div class="label label-warning">
<strong>2015年2月14日更新</strong></div>
<!-- PELICAN_END_SUMMARY -->
<div class="section" id="id2">
<h2><a class="toc-backref" href="#id38">前言: 新天新地,将一切都更新了 <a class="footnote-reference" href="#id37" id="id1">[1]</a></a></h2>
<!-- PELICAN_BEGIN_SUMMARY -->
<p>不知不觉间放任这边长草很久了,从上次
<a class="reference external" href="//farseerfc.me/zhs/try-pelican.html">折腾主题</a> 到现在都快三年了,
而从上次 <a class="reference external" href="//farseerfc.me/zhs/marry-me.html">写了篇告白信</a> 到现在也有快两年了。
这期间曾经把主题配色从 <a class="reference external" href="http://getbootstrap.com/2.3.2/">Bootstrap 2</a> 默认的
白底黑字改成了让眼睛更舒适的黑底白字,也不过是用 drop-in 的配色方案而已,没有本质上的改进。</p>
<p>洞中一日世上千载,两年里 Bootstrap 已经升上 <a class="reference external" href="http://getbootstrap.com/">v3.3</a> ,
而 Pelican 则已经升到 <a class="reference external" href="https://github.com/getpelican/pelican/releases/tag/3.5.0">3.5</a> 了。
早就眼馋 Bootstrap 和 Pelican 中的诸多新功能新设计,不过无奈于时间有限只能饱饱眼福。</p>
<p>近日想写的东西越积越多,终于下定决心花了前前后后 <strong>两个月</strong> 的时间重新设计了一遍
Pelican 的主题,配合一些我觉得有用的插件。于是本博客就变成你们现在看到的样子了。
(以及本篇博文也用了两个月的时间写完,其间还发了几篇别的短文,算是恢复写博客的尝试吧。)</p>
<!-- PELICAN_END_SUMMARY -->
<div class="panel panel-default">
<div class="panel-heading">
在迈阿密参加 <a class="reference external" href="http://icsr2015.ipd.kit.edu/">ICSR 2015</a> 的时候
拍到的街边一家叫 Pelican 的旅馆</div>
<div class="panel-body">
<img alt="Pelican Hotel" class="img-responsive" src="//farseerfc.me/zhs/images/pelican.jpg"/>
</div>
</div>
<div class="section" id="bootstrap-3">
<h3><a class="toc-backref" href="#id39">Bootstrap 3 的新设计</a></h3>
<ul class="simple">
<li>全新的 <ruby><rb>优先移动设备</rb><rp>(</rp><rt>mobile-first</rt><rp>)</rp></ruby> <ruby><rb>响应式</rb><rp>(</rp><rt>responsive</rt><rp>)</rp></ruby> 设计。
原本Bootstrap 2虽然有响应式设计,
不过诸多细节不能符合我的需求,最终还是得手工 hack <code class="code">
@media</code>
查询去微调。
现在的 <ruby><rb>优先移动设备</rb><rp>(</rp><rt>mobile-first</rt><rp>)</rp></ruby> <ruby><rb>响应式</rb><rp>(</rp><rt>responsive</rt><rp>)</rp></ruby>
<ruby><rb>栅格系统</rb><rp>(</rp><rt>grid system</rt><rp>)</rp></ruby> 则相对显得科学很多了,也终于能在手持
设备上看起来舒服一些。诸位可以尝试改变窗口宽度,或者在不同的手持设备上打开这个
blog ,体验一下这个页面在不同显示器大小中的效果。如果仍有问题欢迎
<a class="reference external" href="https://github.com/farseerfc/pelican-bootstrap3/issues">发 Issue 给我</a> 。</li>
<li>科学的 <ruby><rb>导航栏</rb><rp>(</rp><rt>Navbar</rt><rp>)</rp></ruby> 。
比 Bootstrap 2 那个科学很多了。无论是 <ruby><rb>保持</rb><rp>(</rp><rt>sticky</rt><rp>)</rp></ruby> 在上端还是跟着浮动,
或者像这边这样 <a class="reference external" href="http://www.virtuosoft.eu/code/bootstrap-autohidingnavbar/">自动隐藏</a> 都很简单。</li>
</ul>
<p>更多细节参考 <a class="reference external" href="http://getbootstrap.com/">Bootstrap 3 主页</a> 。</p>
</div>
<div class="section" id="pelican-3-5">
<h3><a class="toc-backref" href="#id40">Pelican 3.5 的新功能</a></h3>
<ul class="simple">
<li>Python 2 和 Python 3 统一代码:
再没有恼人的 unicode 相关的问题了。这对 blog 系统来说相当重要啊。
而且还能方便切换 pypy 等不同的解释器。</li>
<li>全新的插件系统:非常多功能强大的 <a class="reference external" href="https://github.com/getpelican/pelican-plugins">插件</a> 等着你。</li>
<li>增强了导入系统:嗯总算可以导入我的中文的 wordpress 博客了。(虽然那边长草更久了……)</li>
<li><a class="reference external" href="http://pelican.readthedocs.org/en/latest/content.html#linking-to-internal-content">站内链接</a>
:不用 <ruby><rb>硬编码</rb><rp>(</rp><rt>hard code</rt><rp>)</rp></ruby> 目标页面的链接了,可以直接写源文件的位置然后让 pelican
处理,这样能简化各种 <ruby><rb>插件</rb><rp>(</rp><rt>plugin</rt><rp>)</rp></ruby> 和 <ruby><rb>主题</rb><rp>(</rp><rt>theme</rt><rp>)</rp></ruby> 的实现。</li>
</ul>
<p>更多细节参考 <a class="reference external" href="http://pelican.readthedocs.org/en/latest/">Pelican 文档</a> 。</p>
</div>
<div class="section" id="id11">
<h3><a class="toc-backref" href="#id41">新的文件夹布局</a></h3>
<div class="panel panel-default">
<div class="panel-heading">
Pelican 的新文件夹布局</div>
<div class="panel-body">
<pre><span class="code-line"></span>
<span class="code-line"><span style="color:blue;font-weight:bold;">.</span></span>
<span class="code-line">├── <span style="color:blue;font-weight:bold;">cache</span> 生成页面的 pickle 缓存</span>
<span class="code-line">├── <span style="color:blue;font-weight:bold;">content</span> 读取的全部内容</span>
<span class="code-line">│ ├── <span style="color:blue;font-weight:bold;"><categories></span> 按分类存放的文章</span>
<span class="code-line">│ ├── <span style="color:blue;font-weight:bold;">pages</span> 像 About 这样的固定页面</span>
<span class="code-line">│ └── <span style="color:blue;font-weight:bold;">static</span> 文章内用到的静态内容</span>
<span class="code-line">├── <span style="color:blue;font-weight:bold;">drafts</span> 文章的草稿箱</span>
<span class="code-line">├── <span style="color:green;font-weight:bold;">Makefile</span> 生成用的 makefile</span>
<span class="code-line">├── <span style="color:green;font-weight:bold;">pelicanconf.py</span> 测试时用的快速 Pelican 配置</span>
<span class="code-line">├── <span style="color:green;font-weight:bold;">publishconf.py</span> 部署时用的耗时 Pelican 配置</span>
<span class="code-line">├── <span style="color:teal;font-weight:bold;">output</span> -> <span style="color:blue;font-weight:bold;">../farseerfc.github.io</span></span>
<span class="code-line">├── <span style="color:teal;font-weight:bold;">plugins</span> -> <span style="color:blue;font-weight:bold;">../pelican-plugins</span></span>
<span class="code-line">└── <span style="color:teal;font-weight:bold;">theme</span> -> <span style="color:blue;font-weight:bold;">../pelican-bootstrap3</span></span>
</pre></div>
</div>
<p><a class="reference external" href="https://github.com/farseerfc/farseerfc.github.com">之前的博客</a> 仍然留在
github 上,其中的内容完全搬过来了。开始写老博客的时候 Pelican 版本较早,没有形成好的
文件夹布局,导致生成的文章、使用的模板和撰写的内容全都混在一起,非常难以管理,
于是趁改版之际用了新的文件夹布局方式,并分为 4 个 git repo 分别管理历史。</p>
<p>首先是存放 <a class="reference external" href="https://github.com/farseerfc/farseerfc">总的博客内容的 repo</a> ,
其布局是如图那样的。这样将生成的静态网站和生成网站用的配置啦内容啦分开之后,顿时清晰了很多。</p>
<p>然后这个内容 repo 中的三个符号链接分别指向三个子 repo(没用 <code class="code">
git submodule</code>
管理纯粹是因为偷懒)。 theme 指向
<a class="reference external" href="https://github.com/farseerfc/pelican-bootstrap3">pelican-bootstrap3</a>
,是我修改过的 pelican 主题。
plugins 指向 <a class="reference external" href="https://github.com/farseerfc/pelican-plugins">pelican-plugins</a>
,由于 plugins 的质量有些参差不齐,其中不少 plugin
都按我的需要做了些许修改,一些是功能改进,另一些则是修bug(比如不少plugin只支持 python 2)。
最后 output 指向
<a class="reference external" href="https://github.com/farseerfc/farseerfc.github.io">farseerfc.github.io</a>
也就是发布的静态网站啦。</p>
<p>接下来从 <strong>主题</strong> 和 <strong>插件</strong> 两个方面介绍一下改版的细节。</p>
</div>
</div>
<div class="section" id="material-design-bootstrap-3">
<h2><a class="toc-backref" href="#id42">主题: Material Design 风格的 Bootstrap 3</a></h2>
<p>上篇 <a class="reference external" href="//farseerfc.me/zhs/summarize-material-design-css-framework.html">博文</a>
就总结了我为了这个博客寻找了一堆 CSS 框架,并且最终决定用
<a class="reference external" href="http://fezvrasta.github.io/bootstrap-material-design/">bootstrap-material-design</a>
, <a class="reference external" href="https://github.com/DandyDev/pelican-bootstrap3">DandyDev/pelican-bootstrap3</a>
和 <a class="reference external" href="http://getbootstrap.com/">Bootstrap 3</a> 这三个项目结合的方式实现这个模板的主题。
这三个项目都或多或少经过了我的修改,修改后的项目以 pelican-bootstrap3 为基础放在
<a class="reference external" href="https://github.com/farseerfc/pelican-bootstrap3">这里</a> ,包括 <a class="reference external" href="https://github.com/farseerfc/pelican-bootstrap3/tree/master/static/bootstrap">Bootstrap3 样式</a>
和 <a class="reference external" href="https://github.com/farseerfc/pelican-bootstrap3/tree/master/static/material">Material 样式</a>。</p>
<div class="section" id="id16">
<h3><a class="toc-backref" href="#id43">对 Bootstrap 3 的定制</a></h3>
<p>由于架构完善,修改 Bootstrap 3 感觉非常简单。另一方面我在 Web 前端技术上的技能点也不多,
所以修改的地方非常有限,只能按我自己的需求定制而已。</p>
<div class="section" id="id17">
<h4><a class="toc-backref" href="#id44">响应式设备的大小</a></h4>
<div class="panel panel-default">
<div class="panel-heading">
修改了 Bootstrap 3 响应式设备的大小</div>
<div class="panel-body">
<div class="highlight"><pre><span class="code-line"><span></span><span class="p">@</span><span class="k">screen-xs</span><span class="o">:</span> <span class="nt">320px</span><span class="p">;</span></span>
<span class="code-line"><span class="p">@</span><span class="k">screen-sm</span><span class="o">:</span> <span class="nt">598px</span><span class="p">;</span> <span class="c">/* 768px; */</span></span>
<span class="code-line"><span class="p">@</span><span class="k">screen-md</span><span class="o">:</span> <span class="nt">952px</span><span class="p">;</span> <span class="c">/* 992px; */</span></span>
<span class="code-line"><span class="p">@</span><span class="k">screen-lg</span><span class="o">:</span> <span class="nt">1350px</span><span class="p">;</span> <span class="c">/* 1200px; */</span></span>
<span class="code-line"><span class="p">@</span><span class="k">screen-xl</span><span class="o">:</span> <span class="nt">2030px</span><span class="p">;</span></span>
<span class="code-line"><span class="p">@</span><span class="k">container-sm</span><span class="o">:</span> <span class="nt">582px</span><span class="p">;</span> <span class="c">/* 750px; */</span></span>
<span class="code-line"><span class="p">@</span><span class="k">container-md</span><span class="o">:</span> <span class="nt">930px</span><span class="p">;</span> <span class="c">/* 970px; */</span></span>
<span class="code-line"><span class="p">@</span><span class="k">container-lg</span><span class="o">:</span> <span class="nt">1320px</span><span class="p">;</span> <span class="c">/* 1170px; */</span></span>
<span class="code-line"><span class="p">@</span><span class="k">container-xl</span><span class="o">:</span> <span class="nt">1990px</span><span class="p">;</span></span>
</pre></div>
</div>
</div>
<p>首先把 Bootstrap 3 默认适配的几个 <a class="reference external" href="http://getbootstrap.com/css/#grid">响应式设备的大小</a>
改成了我需要的大小。 <code class="code">
xs</code>
和 <code class="code">
sm</code>
的大小分别按照我的手机屏幕 <strong>竖屏</strong> 和
<strong>横屏</strong> 时候的浏览器页面宽度来算, <code class="code">
md</code>
是想兼容 Nexus 7 横屏 960 的宽度以及
一个常见上网本 1024 的宽度。 <code class="code">
lg</code>
的大小则按照常见的笔记本 1366 宽的屏幕来适配。</p>
<p>这里 Bootstrap 3 支持的设备大小的一个问题是,它最多考虑到 1200 像素宽的显示器,而更宽的
比如 1600、 2048 甚至 2560 像素宽的显示器现在也并不少见,其结果就是页面中左右两侧
有很大的空间被浪费掉了。作为深受这一问题困扰的用户之一,我用
<a class="reference external" href="http://stackoverflow.com/a/25644266">这里介绍的方法</a>
给 bootstrap 增加了一类「 <ruby><rb>比大更大</rb><rp>(</rp><rt>bigger than bigger</rt><rp>)</rp></ruby> 」的
<code class="code">
xl</code>
响应式设备尺寸,宽度设为支持 2048 像素宽的显示器,具体的修改反映在
<a class="reference external" href="https://github.com/farseerfc/pelican-bootstrap3/blob/master/static/bootstrap/variables.less">variables.less</a>
文件里。</p>
</div>
<div class="section" id="id20">
<h4><a class="toc-backref" href="#id45">根据宽度自动分栏和瀑布式布局</a></h4>
<p>接下来目标是让主页的文章列表像 Google+ 主页那样根据显示器宽度自动调整分栏,使得宽度不同的
显示器上每个分栏的宽度接近。想要达到的效果是,根据上面定义的屏幕宽度尺寸:</p>
<table border="0" class="table docutils borderless">
<colgroup>
<col width="26%"/>
<col width="17%"/>
<col width="18%"/>
<col width="39%"/>
</colgroup>
<tbody valign="top">
<tr><td><code class="code">
xs</code>
用单栏 <ruby><rb>流动</rb><rp>(</rp><rt>fluid</rt><rp>)</rp></ruby> 布局</td>
<td colspan="2"><code class="code">
sm</code>
用上方单栏文章列表、下方双栏 <ruby><rb>侧边栏</rb><rp>(</rp><rt>sidebar</rt><rp>)</rp></ruby> 固定布局</td>
<td><code class="code">
md</code>
用单栏文章列表、单栏 侧边栏 固定布局</td>
</tr>
<tr><td><table border="0" class="table first docutils last borderless">
<colgroup>
<col width="100%"/>
</colgroup>
<tbody valign="top">
<tr><td><ruby><rb>导航栏</rb><rp>(</rp><rt>Navbar</rt><rp>)</rp></ruby></td>
</tr>
<tr><td>文章</td>
</tr>
<tr><td>侧边栏</td>
</tr>
<tr><td>底栏</td>
</tr>
</tbody>
</table>
</td>
<td colspan="2"><table border="0" class="table first docutils last borderless">
<colgroup>
<col width="53%"/>
<col width="47%"/>
</colgroup>
<tbody valign="top">
<tr><td colspan="2">导航栏</td>
</tr>
<tr><td colspan="2">文章</td>
</tr>
<tr><td>侧边栏 1</td>
<td>侧边栏 2</td>
</tr>
<tr><td colspan="2"><ruby><rb>底栏</rb><rp>(</rp><rt>footer</rt><rp>)</rp></ruby></td>
</tr>
</tbody>
</table>
</td>
<td><table border="0" class="table first docutils last borderless">
<colgroup>
<col width="53%"/>
<col width="47%"/>
</colgroup>
<tbody valign="top">
<tr><td colspan="2">导航栏</td>
</tr>
<tr><td>文章 1</td>
<td>侧边栏 1</td>
</tr>
<tr><td>文章 2</td>
<td>侧边栏 2</td>
</tr>
<tr><td colspan="2"><ruby><rb>底栏</rb><rp>(</rp><rt>footer</rt><rp>)</rp></ruby></td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr><td colspan="2"><code class="code">
lg</code>
用双栏文章列表、单栏 侧边栏 固定布局</td>
<td colspan="2"><code class="code">
xl</code>
用三栏文章列表、双栏 侧边栏 固定布局</td>
</tr>
<tr><td colspan="2"><table border="0" class="table first docutils last borderless">
<colgroup>
<col width="35%"/>
<col width="35%"/>
<col width="31%"/>
</colgroup>
<tbody valign="top">
<tr><td colspan="3">导航栏</td>
</tr>
<tr><td>文章 1</td>
<td>文章 3</td>
<td>侧边栏 1</td>
</tr>
<tr><td>文章 2</td>
<td>文章 4</td>
<td>侧边栏 2</td>
</tr>
<tr><td colspan="3"><ruby><rb>底栏</rb><rp>(</rp><rt>footer</rt><rp>)</rp></ruby></td>
</tr>
</tbody>
</table>
</td>
<td colspan="2"><table border="0" class="table first docutils last borderless">
<colgroup>
<col width="26%"/>
<col width="26%"/>
<col width="26%"/>
<col width="23%"/>
</colgroup>
<tbody valign="top">
<tr><td colspan="4">导航栏</td>
</tr>
<tr><td>文章 1</td>
<td>文章 3</td>
<td>文章 5</td>
<td>侧边栏 1</td>
</tr>
<tr><td>文章 2</td>
<td>文章 4</td>
<td>文章 6</td>
<td>侧边栏 2</td>
</tr>
<tr><td colspan="4"><ruby><rb>底栏</rb><rp>(</rp><rt>footer</rt><rp>)</rp></ruby></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>一开始纯粹用 Bootstrap3 的响应式栅格实现这个分栏布局,结果发现效果不太理想,
因为文章列表和侧边栏的高度是变化的,会导致栅格间留下大片空白。后来改用
<a class="reference external" href="http://cssdeck.com/labs/pinterest-like-waterfall-design-purely-css">这里示范的纯CSS瀑布式布局</a>
实现文章和侧边栏的布局,具体的实现代码在
<a class="reference external" href="https://github.com/farseerfc/pelican-bootstrap3/blob/master/static/bootstrap/waterfall.less">waterfall.less</a>
,总算达到了想要的布局了。</p>
</div>
<div class="section" id="id21">
<h4><a class="toc-backref" href="#id46">正文的样式</a></h4>
<p>最最重要的是文章正文的样式。这里我想要达到的效果是,在大屏幕上用更大的字号,让读者
看起来更舒适,同时在小屏幕上用比较小的字号,最终保证基本上「一行」的文字数接近。这个修改
主要针对 <code class="code">
.jumbotron</code>
,
用了 <a class="reference external" href="https://github.com/farseerfc/pelican-bootstrap3/blob/master/static/bootstrap/jumbotron.less">不太科学的方式</a>
代码太长就不贴全了。</p>
</div>
<div class="section" id="id23">
<h4><a class="toc-backref" href="#id47">一些细微的定制</a></h4>
<p>把主题配色改成了现在这样的淡紫色
<code class="code">
@brand-primary: darken(#6B5594, 6.5%);</code>
,配合我的头像风格, 这个修改只需要一行。
接着删掉了 <code class="code">
.btn</code>
的 <code class="code">
white-space: nowrap;</code>
让按钮的文字可以换行,
这也只是一行修改。</p>
<div class="label label-warning">
<strong>2015年1月29日更新</strong></div>
<p>另外我也不太喜欢 Bootstrap 3 默认在手机上的 <ruby><rb>折叠导航栏</rb><rp>(</rp><rt>collapsed navbar</rt><rp>)</rp></ruby> ,
折叠之后的操作不够直观方便而且依赖 javascript 所以有 bug …… 于是我把它关掉了,
具体方式是在 variables.less 把 <code class="code">
@grid-float-breakpoint</code>
和
<code class="code">
@grid-float-breakpoint-max</code>
都设为0就可以了。</p>
</div>
</div>
<div class="section" id="id24">
<h3><a class="toc-backref" href="#id48">对 bootstrap-material-design 的定制</a></h3>
<p>这里定制的地方不多。原样式中一个不太科学的做法是所有 <code class="code">
.btn</code>
都强制加上了阴影
效果,这在已经有阴影的环境里用的话非常碍眼,像是 Win9x 风格的厚重睫毛膏。既然可以单独
给每个样式加阴影,于是就把 <code class="code">
.btn</code>
强制的阴影去掉了,只保留鼠标悬停之后强调的阴影。</p>
<p>其它定制的细节么就是统一配色风格,修补漏洞错误,微调响应式效果而已,这里不细说。</p>
</div>
<div class="section" id="id25">
<h3><a class="toc-backref" href="#id49">将以上两者整合在 pelican-bootstrap3 里</a></h3>
<div class="panel panel-default">
<div class="panel-heading">
Pelican 实现显示源代码按钮</div>
<div class="panel-body">
<p>显示源代码按钮借用了 Pelican 配置中自带的 <code class="code">
OUTPUT_SOURCES</code>
选项将源文件复制到输出文件夹:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="n">OUTPUT_SOURCES</span> <span class="o">=</span> <span class="kc">True</span></span>
<span class="code-line"><span class="n">OUTPUT_SOURCES_EXTENSION</span> <span class="o">=</span> <span class="s1">'.rst'</span></span>
</pre></div>
<p>然后在 Makefile 里用 pygmentize 把所有源代码文件着色:</p>
<div class="highlight"><pre><span class="code-line"><span></span>find -iname <span class="s2">"*.rst"</span> <span class="p">|</span> parallel -I@ pygmentize -f html -o @.html @</span>
</pre></div>
<p>最后在按钮按下的时候用 jQuery 载入源代码:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="p"><</span><span class="nt">a</span> <span class="na">onclick</span><span class="o">=</span><span class="s">"$.get('{{SITEURL}}/{{article.slug}}.rst.html', function(data){$('#source-code').html(data)});$('#article-content').toggle();$('#source-content').toggle();"</span><span class="p">></span></span>
</pre></div>
<p>虽然难看的 hack 比较多,但是能用!</p>
</div>
</div>
<p>虽说 pelican-bootstrap3 是我 fork 出来的,不过由于我修改的地方实在太多,代码看来基本上
接近重写了一份。好在之前有给 pelican 写 bootstrap 2 主题的经验,这次修改算得上驾轻就熟。
可以对比一下 <a class="reference external" href="http://dandydev.net/">上游作者的博客</a> 和这里的样子体会一下感觉。
具体修改过的地方包括:</p>
<ol class="arabic simple">
<li>套用 bootstrap-material-design 的各个元素样式。</li>
<li>在文章列表模板应用上面提到的 Bootstrap 3 的栅格布局和瀑布式布局。</li>
<li>翻译到多个语言,这里在后面的 i18n-subsite 插件里详述。</li>
<li>套用后面会介绍到的各种插件。</li>
<li>统一侧边栏的样式到一个模板里。</li>
<li>添加 Atom 订阅按钮和 breadcrumb 条。</li>
<li>对正文中出现的插图,添加点击放大的功能,通过 Bootstrap 的 <code class="code">
modal</code>
实现。</li>
<li>上面提到的用 <a class="reference external" href="http://www.virtuosoft.eu/code/bootstrap-autohidingnavbar/">这个bootstrap插件</a>
让导航栏自动隐藏。</li>
<li><strong>显示源代码按钮</strong> ,也就是每篇文章信息栏中的
<button class="btn btn-primary"><i class="fa fa-code"></i></button> 按钮。</li>
</ol>
</div>
</div>
<div class="section" id="pelican-restructuredtext">
<h2><a class="toc-backref" href="#id50">插件: 发挥 Pelican 和 reStructuredText 的优势</a></h2>
<p>先列举一下我目前用到的所有插件:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="n">PLUGINS</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"i18n_subsites"</span><span class="p">,</span></span>
<span class="code-line"> <span class="s2">"plantuml"</span><span class="p">,</span></span>
<span class="code-line"> <span class="s2">"youku"</span><span class="p">,</span></span>
<span class="code-line"> <span class="s2">"youtube"</span><span class="p">,</span></span>
<span class="code-line"> <span class="s1">'tipue_search'</span><span class="p">,</span></span>
<span class="code-line"> <span class="s1">'neighbors'</span><span class="p">,</span></span>
<span class="code-line"> <span class="s1">'series'</span><span class="p">,</span></span>
<span class="code-line"> <span class="s1">'bootstrapify'</span><span class="p">,</span></span>
<span class="code-line"> <span class="s1">'twitter_bootstrap_rst_directives'</span><span class="p">,</span></span>
<span class="code-line"> <span class="s2">"render_math"</span><span class="p">,</span></span>
<span class="code-line"> <span class="s1">'extract_toc'</span><span class="p">,</span></span>
<span class="code-line"> <span class="s1">'summary'</span><span class="p">]</span></span>
</pre></div>
<p>嗯其实不算多。接下来逐一介绍一下这些各具特色的插件。</p>
<div class="section" id="i18n-subsites">
<h3><a class="toc-backref" href="#id51">i18n-subsites</a></h3>
<p>这个插件的目的是创建 <ruby><rb>国际化</rb><rp>(</rp><rt>internationalization</rt><rp>)</rp></ruby>
<ruby><rb>子站</rb><rp>(</rp><rt>subsite</rt><rp>)</rp></ruby> 。</p>
<p>之前介绍 Pelican 配置的时候就提到过,
原本的 Pelican 就支持一篇文章用多种语言书写,有 <code class="code">
lang</code>
属性注明这篇文章使用的
语言,以及 <code class="code">
slug</code>
属性注明多语言的翻译之间的关联,换句话说同一篇文章的多个语言
版本应该有相同的 <code class="code">
slug</code>
和不同的 <code class="code">
lang</code>
。然后原本 Pelican 里对多语言的
实现方式是,首先有一个 <strong>主语言</strong> 是模板和大部分文章采用的语言,文章列表中会优先列出
用 <strong>主语言</strong> 撰写的文章,然后从 <strong>主语言</strong> 的文章链接到别的翻译版本。
很多博客系统和CMS对多语言的支持都是这样的,这种处理方式的缺点也显而易见:作为 <strong>主语言</strong>
的语言必须足够通用,才能让进来的人找到合适的翻译版本,所以通常 <strong>主语言</strong> 都是英语。</p>
<p>而这个插件做的事情描述起来很简单:将文章按语言属性分到多个子站,每个子站独立放在各自的文件夹。
比如主站是 <a class="reference external" href="https://farseerfc.github.io/">https://farseerfc.github.io/</a> 的话,那么英语的子站就可以是
<a class="reference external" href="https://farseerfc.github.io/en/">https://farseerfc.github.io/en/</a> 。
然后分别对多个子站生成静态页面。具体的实现方式是对 pelican 的页面生成步骤做了拆分:</p>
<ol class="arabic simple">
<li>pelican 按正常情况读入文章,生成元信息。</li>
<li>i18n-subsites 针对每个语言,覆盖掉 pelican 的一些选项设置比如路径和 URL ,
分别调用 pelican 的页面生成器按模板生成文章。</li>
<li>对共用的静态内容比如模板的 js 和 css 文件,只在主站中生成,子站中的相应链接全部链回主站。</li>
</ol>
<p>虽然描述起来简单,但是这个插件可以说最大化利用了 Pelican 的插件系统,实现细节相对比较
复杂,大概是我用的这些插件里面最复杂的了。不夸张的说 Pelican 3.4 支持的新插件 API 和
站内链接功能基本上就是为了配合这个插件的。至于具体它会覆盖哪些 Pelican 的配置,请参阅它的
<a class="reference external" href="https://github.com/farseerfc/pelican-plugins/blob/master/i18n_subsites/README.rst">README.md文件</a> 。</p>
<p>按内容拆分多语言子站的做法只解决了问题的一半,还留下另一半的问题,也即对模板的翻译。
对这个问题, i18n-subsites 提供了两套方案供选择:</p>
<ol class="arabic simple">
<li>用覆盖配置路径的方式让每个子站套用不同的模板。这配置起来简单,但是对模板维护起来有点困难。</li>
<li>用 jinja2 的 i18n 插件,配合 Python 的 gettext 库实现内容翻译。这个方案
<a class="reference external" href="https://github.com/farseerfc/pelican-plugins/blob/master/i18n_subsites/localizing_using_jinja2.rst">配置起来比较复杂</a> ,但是配置好之后用起来就很方便了。
只是要记得每次修改了模板都要更新翻译,处理 *.po 和 *.mo 文件等等琐碎事宜。</li>
</ol>
<p>这里我用 jinja2 的 i18n 插件的方式实现了模板的翻译,
<a class="reference external" href="https://github.com/farseerfc/pelican-bootstrap3/tree/master/translations">各个语言的翻译在这里</a> ,
然后用 <a class="reference external" href="https://github.com/farseerfc/pelican-bootstrap3/blob/master/SConstruct">这里的 SCons 脚本</a>
根据内容是否变化自动更新 po 和 mo 文件。</p>
<p>配置好这一套方案之后,还要注意在模板和文章中处理好链接。用 Pelican 3.4 之后推荐的
新的文章间链接的写法以及将 <code class="code">
SITEURL</code>
设置为实际 URL 并且关闭 <code class="code">
RELATIVE_URLS</code>
之后,应该就不会出没什么问题了(可能还要考虑使用的模板和插件的兼容性,大部分都是写死了 URL 的问题)。</p>
</div>
<div class="section" id="plantuml">
<h3><a class="toc-backref" href="#id52">plantuml</a></h3>
<div class="panel panel-default">
<div class="panel-heading">
嵌入 PlantUML 的示例</div>
<div class="panel-body">
<img alt="uml diagram" class="uml img-responsive" src="//farseerfc.me/uml/8e4b1ee3.png"/>
</div>
</div>
<p><a class="reference external" href="http://plantuml.sourceforge.net/">PlantUML</a> 是一个Java实现的,
用接近文字描述的语言绘制 UML 图或者 GUI 界面图的工具,非常适合嵌入在
Markdown、 reStructuredText、 AsciiDoc 等这种轻量级标记语言里。
然后么这个 plantuml 插件就是定义了一个新的 reStructuredText
<ruby><rb>指示符</rb><rp>(</rp><rt>directive</rt><rp>)</rp></ruby> <code class="code">
.. uml::</code>
,把嵌入的内容提取出来调用 plantuml 命令处理
成图像然后再插入到文章中。</p>
<p>比如示例里的这个 UML 图就是用这样一段简单的文字描述生成的:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="p">..</span> <span class="ow">uml</span><span class="p">::</span></span>
<span class="code-line"></span>
<span class="code-line"> Object <|-- ArrayList</span>
<span class="code-line"></span>
<span class="code-line"> Object : equals()</span>
<span class="code-line"> ArrayList : Object[] elementData</span>
<span class="code-line"> ArrayList : size()</span>
</pre></div>
<p>实际用起来这个插件实现上稍微有点小问题:首先它只支持 python2,所以我把它改写成了 python
2 和 3 都通用的语法;其次它原本输出的文件夹似乎会被 pelican 删掉,所以把它改了个位置;
然后它输出的 URL 也和 i18n-subsites 插件间有不兼容的问题,也顺带修掉了。
<a class="reference external" href="https://github.com/farseerfc/pelican-plugins/tree/master/plantuml">修改之后的代码在这里</a> 。</p>
<div class="label label-warning">
<strong>2015年1月30日更新</strong></div>
<div class="panel panel-default">
<div class="panel-heading">
嵌入 Ditaa 的示例</div>
<div class="panel-body">
<img alt="ditaa diagram" class="ditaa img-responsive" src="//farseerfc.me/uml/973a8424.png"/>
</div>
</div>
<p>plantuml 是绘制UML的,除此之外还有一个类似的工具是绘制一般的 <ruby><rb>流程图</rb><rp>(</rp><rt>diagram</rt><rp>)</rp></ruby>
的,叫 <a class="reference external" href="http://ditaa.sourceforge.net/">ditaa</a> ,和 plantuml 非常像,也比较像
reStructuredText 的表格。
于是我也照猫画虎实现了一个 ditaa 的 <ruby><rb>指示符</rb><rp>(</rp><rt>directive</rt><rp>)</rp></ruby> ,用起来类似这样:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="p">..</span> <span class="ow">ditaa</span><span class="p">::</span></span>
<span class="code-line"></span>
<span class="code-line"> +-------------+</span>
<span class="code-line"> <span class="o">|</span> ditaa |-------+</span>
<span class="code-line"> <span class="o">|</span> Diagram | |</span>
<span class="code-line"> +-------------+ | PNG out</span>
<span class="code-line"> ^ |</span>
<span class="code-line"> <span class="o">|</span> ditaa in |</span>
<span class="code-line"> <span class="o">|</span> v</span>
<span class="code-line"> +--------+ +--------+----+ /----------------\</span>
<span class="code-line"> <span class="o">|</span> | --+ Pelican +--> | |</span>
<span class="code-line"> <span class="o">|</span> Text | +-------------+ | Beautiful Blog |</span>
<span class="code-line"> |Document| | !magic! | | |</span>
<span class="code-line"> <span class="o">|</span> {d}| | | | |</span>
<span class="code-line"> +---+----+ +-------------+ \----------------/</span>
<span class="code-line"> : ^</span>
<span class="code-line"> <span class="o">|</span> Lots of work |</span>
<span class="code-line"> +-----------------------------------+</span>
</pre></div>
</div>
<div class="section" id="render-math">
<h3><a class="toc-backref" href="#id53">render-math</a></h3>
<div class="panel panel-default">
<div class="panel-heading">
嵌入公式的示例</div>
<div class="panel-body">
<p>示范行内公式 <span class="math">\(A_\text{c} = (\pi/4) d^2\)</span>.</p>
<p>整行公式</p>
<div class="math">
\begin{equation*}
\alpha{}_t(i) = P(O_1, O_2, \ldots O_t, q_t = S_i \lambda{})
\end{equation*}
</div>
</div>
</div>
<p>这个插件提供在 reStructuredText 中用 LaTeX 语法插入数学公式的能力,定义了
<code class="code">
:math:</code>
<ruby><rb>行内角色</rb><rp>(</rp><rt>role</rt><rp>)</rp></ruby> 和 <code class="code">
.. math::</code>
<ruby><rb>指示符</rb><rp>(</rp><rt>directive</rt><rp>)</rp></ruby> 。
实际工作的渲染库当然是大名鼎鼎的 <a class="reference external" href="http://www.mathjax.org/">MathJax</a> ,这个插件
会用 MathJax 的 CDN 载入,所以也没有额外的依赖文件。(只是不知道是否会被国内墙掉,
如果公式显示不正常请 <strong>务必</strong> 告诉我。)</p>
</div>
<div class="section" id="youtube-youku">
<h3><a class="toc-backref" href="#id54">youtube 和 youku</a></h3>
<p>顾名思义,这两个插件分别实现嵌入 youtube 和 youku 视频。其中 youtube 是原本就有的插件,
youku 是我照猫画虎抄的。
之前写了一篇
<a class="reference external" href="//farseerfc.me/zhs/jumping-kde5-plasma-activities-button.html">KDE5 Plasma 之跳动卖萌的活动按钮</a>
用到了这两个插件。</p>
</div>
<div class="section" id="tipue-search">
<h3><a class="toc-backref" href="#id55">tipue_search</a></h3>
<p><a class="reference external" href="http://www.tipue.com/search/">Tipue search</a> 是一个非常有意思也很强大的搜索工具,
通过 jQuery 实现静态博客的站内搜索功能。实现方式是,它需要你写一个 json 文件,包含
整个网站的 <strong>全部</strong> 文章的标题和文字内容,然后在搜索的时候读入这个 json 做搜索(是不是有点耍赖)。
虽然听起来会有性能问题,但是应用在小型的静态博客上效果意外很不错,比如本站的所有文章内容
放在一起的 json 也只有 300KiB 左右。</p>
<p>这个插件就是自动在 pelican 输出完全部静态网页之后,调用 beautifulsoup4 从所有网页中抽取出
纯文本,产生这个 json 给 Tipue 用。</p>
</div>
<div class="section" id="neighbors-series">
<h3><a class="toc-backref" href="#id56">neighbors 和 series</a></h3>
<p>这两个插件比较类似也都比较简单, neighbors 提供一篇文章的前后文章信息,
在主题模板里可以用来制作 <strong>上一篇</strong> 和 <strong>下一篇</strong> 按钮。
series 提供将多篇文章归类为一个 <strong>系列</strong> 的支持,当然也需要在
主题模板中定义显示「文章系列」的列表。这两个插件的效果都能在本文末尾,评论区上方的部分看到。</p>
</div>
<div class="section" id="bootstrapify-twitter-bootstrap-rst-directives">
<h3><a class="toc-backref" href="#id57">bootstrapify 和 twitter_bootstrap_rst_directives</a></h3>
<p>这两个插件让文章的 <strong>正文</strong> 套用上 Bootstrap 的样式。</p>
<p>bootstrapify 这个插件实现得比较简单,用 beautifulsoup4 在静态网页的结果里面过滤元素,
对 <code class="code">
table</code>
, <code class="code">
img</code>
, <code class="code">
embed</code>
, <code class="code">
iframe</code>
,
<code class="code">
video</code>
, <code class="code">
object</code>
这几个标签套用上
<a class="reference external" href="http://getbootstrap.com/components/#responsive-embed">响应式嵌入对象的类</a>
让他们更美观。</p>
<p>twitter_bootstrap_rst_directives 这个插件则是增加了几个 reStructuredText 的
<ruby><rb>行内角色</rb><rp>(</rp><rt>role</rt><rp>)</rp></ruby> 和 <ruby><rb>指示符</rb><rp>(</rp><rt>directive</rt><rp>)</rp></ruby> 。
它实现的 <ruby><rb>行内角色</rb><rp>(</rp><rt>role</rt><rp>)</rp></ruby> 包括:
用 <code class="code">
:kbd:</code>
实现如 <kbd class="kbd">
Ctrl+C</kbd>
这样的键盘快捷键,
用 <code class="code">
:code:</code>
嵌入代码片段,用 <code class="code">
:glyph:</code>
嵌入字符图标。
它实现的 <ruby><rb>指示符</rb><rp>(</rp><rt>directive</rt><rp>)</rp></ruby> 包括:
<a class="reference external" href="http://getbootstrap.com/components/#labels">labels 行内标签</a> ,
<a class="reference external" href="http://getbootstrap.com/components/#alerts">alerts 提示段落</a> ,
<a class="reference external" href="http://getbootstrap.com/components/#panels">panels 嵌入面板</a> ,
以及还有一个 <a class="reference external" href="http://getbootstrap.com/components/#media">media 混排图标</a> 。</p>
<p>对其中的 <code class="code">
panel</code>
我改写了它在文章正文中的样式,在 <code class="code">
lg</code>
或者 <code class="code">
xl</code>
的屏幕宽度下,分别用 <span class="math">\(\frac{1}{2}\)</span> 和 <span class="math">\(\frac{1}{3}\)</span> 大小的嵌入面板,
简单实现和正文文字的图文混排。</p>
<p>除此以外我还在 twitter_bootstrap_rst_directives 这个插件里套用它的框架实现了两个额外
的 <ruby><rb>行内角色</rb><rp>(</rp><rt>role</rt><rp>)</rp></ruby> , 分别是 <code class="code">
:ruby:</code>
:通过 html5 的 <code class="code">
<ruby></code>
标签实现文字上方的注音(firefox下
<a class="reference external" href="https://bugzilla.mozilla.org/show_bug.cgi?id=33339">不支持</a>
,会使用文字后的括号显示), 以及 <code class="code">
:html:</code>
:在
行内插入 <ruby><rb>裸</rb><rp>(</rp><rt>raw</rt><rp>)</rp></ruby> html 标签(这属于 Markdown 的基本功能,在 reStructuredText
这边由于要考虑多种输出格式于是就比较麻烦了)。这两个 <ruby><rb>行内角色</rb><rp>(</rp><rt>role</rt><rp>)</rp></ruby> 的
<a class="reference external" href="https://github.com/farseerfc/pelican-plugins/blob/master/twitter_bootstrap_rst_directives/bootstrap_rst_directives.py#L140">实现代码在这里</a> 。</p>
<div class="label label-warning">
<strong>2015年2月3日更新</strong></div>
<p>今天又在 twitter_bootstrap_rst_directives 里增加了两个 <ruby><rb>行内角色</rb><rp>(</rp><rt>role</rt><rp>)</rp></ruby> 。
一个是 <code class="code">
:twi:</code>
用来写 twitter 用户的链接,比如 <a class="reference external" href="//twitter.com/farseerfc">@farseerfc</a> ,另一个是
<code class="code">
:irc:</code>
用来指向 freenode 的 channel ,比如 <a class="reference external" href="//webchat.freenode.net/?channels=yssyd3">#yssyd3</a> 。</p>
<div class="label label-warning">
<strong>2015年2月14日更新</strong></div>
<p>今天增加了 <code class="code">
.. friend::</code>
用来写好友链接,以及 <code class="code">
fref</code>
用来引用好友,
比如 <a class="reference external" href="/links.html#lqymgt">LQYMGT</a> 这样。</p>
</div>
<div class="section" id="extract-toc-summary">
<h3><a class="toc-backref" href="#id58">extract_toc 和 summary</a></h3>
<p>最后是这两个有点「名不副实」的插件。</p>
<p>reStructuredText 原本就有自动生成
<ruby><rb>目录</rb><rp>(</rp><rt>toc</rt><rp>)</rp></ruby> 的功能,用起来也非常简单,只需要在想要插入目录的地方写一行
<code class="code">
.. contents::</code>
,剩下的都由 docutils 自动生成了。
只是当然这样生成的目录肯定会插入在文章的正文里,而 extract_toc 这个插件的作用就是简单地
把这个目录抽取出来,让模板能在别的地方放置这个目录。比如我这里就把目录放在了一个
<code class="code">
panel</code>
里。</p>
<p>然后 Pelican 也原本就有从文章中抽取 <ruby><rb>总结</rb><rp>(</rp><rt>summary</rt><rp>)</rp></ruby> 显示在文章列表的功能。
Pelican 原始的实现似乎是按照文字数抽取前半段,不总是适合作为总结。 于是这个 summary
插件的作用其实是允许在正文中以特殊的注释的方式标注哪些部分应该被抽出来作为总结。
summary 这个插件原本的实现只允许抽取一段文字,我又对它的实现做了少许扩充,允许标注多段
文字合并起来作为总结。</p>
<div class="label label-warning">
<strong>2015年1月29日更新</strong></div>
<p>今天在 extract_toc 插件的帮助下,在侧边栏里放了一个 Bootstrap affix 的目录,
它保持在页面的右侧位置不变,方便导航到文章的各个地方。具体实现方法除了 Bootstrap 3 的
<a class="reference external" href="http://getbootstrap.com/javascript/#affix">Affix 文档</a> ,还参考了
<a class="reference external" href="http://tutsme-webdesign.info/bootstrap-3-affix/">这篇更详细的说明</a> 。</p>
</div>
</div>
<div class="section" id="id36">
<h2><a class="toc-backref" href="#id59">结语</a></h2>
<p>这个博客的配置都可以在
<a class="reference external" href="https://github.com/farseerfc/farseerfc/blob/master/pelicanconf.py">github 上找到</a>
,包括用来
<a class="reference external" href="https://github.com/farseerfc/farseerfc/blob/master/Makefile">自动生成整个博客的 Makefile</a>
,由于比较长,这里就不再贴了。</p>
<p>折腾这个主题前后历时两个月,期间学会了不少东西,也算是不错的收获吧。
现在既然基础打好了,接下来就要开始多写博客了。(希望拖延症不会再犯……)</p>
<p>最近发现除了我的博客之外还有一个网站
<a class="reference external" href="http://www.kansaslinuxfest.us/">Kansas Linux Fest</a> fork
了我的主题,不过他们用了我修改的早期版本,还是原本的 Bootstrap 3 和
bootstrap-material-design 样式。自己草草修改的东西被别人用到果然还是有点小激动呢,
以及接下来不能马马虎虎地写 commit 消息了。</p>
<table border="0" class="docutils table footnote" frame="void" id="id37" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>赛65:17「看哪!我造新天新地」启21:5「我将一切都更新了。」</td></tr>
</tbody>
</table>
</div>
<script type='text/javascript'>if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {
var align = "center",
indent = "0em",
linebreak = "false";
if (false) {
align = (screen.width < 768) ? "left" : align;
indent = (screen.width < 768) ? "0em" : indent;
linebreak = (screen.width < 768) ? 'true' : linebreak;
}
var mathjaxscript = document.createElement('script');
var location_protocol = (false) ? 'https' : document.location.protocol;
if (location_protocol !== 'http' && location_protocol !== 'https') location_protocol = 'https:';
mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
mathjaxscript.type = 'text/javascript';
mathjaxscript.src = location_protocol + '//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML';
mathjaxscript[(window.opera ? "innerHTML" : "text")] =
"MathJax.Hub.Config({" +
" config: ['MMLorHTML.js']," +
" TeX: { extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: { autoNumber: 'AMS' } }," +
" jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
" extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
" displayAlign: '"+ align +"'," +
" displayIndent: '"+ indent +"'," +
" showMathMenu: true," +
" messageStyle: 'normal'," +
" tex2jax: { " +
" inlineMath: [ ['\\\\(','\\\\)'] ], " +
" displayMath: [ ['$$','$$'] ]," +
" processEscapes: true," +
" preview: 'TeX'," +
" }, " +
" 'HTML-CSS': { " +
" styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: 'inherit ! important'} }," +
" linebreaks: { automatic: "+ linebreak +", width: '90% container' }," +
" }, " +
"}); " +
"if ('default' !== 'default') {" +
"MathJax.Hub.Register.StartupHook('HTML-CSS Jax Ready',function () {" +
"var VARIANT = MathJax.OutputJax['HTML-CSS'].FONTDATA.VARIANT;" +
"VARIANT['normal'].fonts.unshift('MathJax_default');" +
"VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
"VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
"VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
"});" +
"MathJax.Hub.Register.StartupHook('SVG Jax Ready',function () {" +
"var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;" +
"VARIANT['normal'].fonts.unshift('MathJax_default');" +
"VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
"VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
"VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
"});" +
"}";
(document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
}
</script>尝试一下 Pelican2012-02-24T17:33:00+09:002012-02-24T17:33:00+09:00farseerfctag:farseerfc.me,2012-02-24:/zhs/try-pelican.html<p>似乎一夜之间所有的
<a class="reference external" href="http://blog.yxwang.me/2011/11/migrated-to-octopress/">极客们</a>
<a class="reference external" href="http://xoyo.name/2012/02/migrate-to-octopress/">都</a>
<a class="reference external" href="http://blog.xdite.net/posts/2011/10/07/what-is-octopress/">有了</a>
<a class="reference external" href="http://www.yangzhiping.com/tech/octopress.html">自己</a>
的 <a class="reference external" href="http://pages.github.com/#user__organization_pages">Github主页</a>
和 <a class="reference external" href="http://octopress.org/">Octopress</a> 博客。就像所有人在他们的博客中指出的,静态博客的确比传统的WordPress方式具有更多优势。 自从看到这些
我就一直在想着自己搭一个 <a class="reference external" href="http://octopress.org/">Octopress</a> 。</p>
<div class="section" id="id6">
<h2>但是似乎 <a class="reference external" href="http://octopress.org/">Octopress</a> 不适合我</h2>
<p>一上手就被 <a class="reference external" href="http://octopress.org/docs/setup/">Octopress的搭建步骤</a> 烦到了。 <a class="reference external" href="http://beginrescueend.com/">RVM</a> 是什么? <a class="reference external" href="https://github.com/sstephenson/rbenv">rbenv</a> 又是什么?
看来 Ruby 社区的快节奏发展已经超过了我的想象,他们似乎需要一套发行版管理器来调和不同版本之间的 Ruby 的兼容性问题。
虽然同样的兼容性问题在 Python 社区也有 <a class="footnote-reference" href="#id10" id="id8">[1]</a> ,不过总觉得 Python 至少还没到需要一个发行版管理器的程度 <a class="footnote-reference" href="#id11" id="id9">[2]</a> 。</p>
<p>真正的问题是我手上还没有一个可以让我随便玩的 Linux 环境(真的想要……)。 而无论是 <a class="reference external" href="http://beginrescueend.com/">RVM</a> 还是 <a class="reference external" href="https://github.com/sstephenson/rbenv">rbenv</a> 似乎都只支持 Unix/Linux …</p></div><p>似乎一夜之间所有的
<a class="reference external" href="http://blog.yxwang.me/2011/11/migrated-to-octopress/">极客们</a>
<a class="reference external" href="http://xoyo.name/2012/02/migrate-to-octopress/">都</a>
<a class="reference external" href="http://blog.xdite.net/posts/2011/10/07/what-is-octopress/">有了</a>
<a class="reference external" href="http://www.yangzhiping.com/tech/octopress.html">自己</a>
的 <a class="reference external" href="http://pages.github.com/#user__organization_pages">Github主页</a>
和 <a class="reference external" href="http://octopress.org/">Octopress</a> 博客。就像所有人在他们的博客中指出的,静态博客的确比传统的WordPress方式具有更多优势。 自从看到这些
我就一直在想着自己搭一个 <a class="reference external" href="http://octopress.org/">Octopress</a> 。</p>
<div class="section" id="id6">
<h2>但是似乎 <a class="reference external" href="http://octopress.org/">Octopress</a> 不适合我</h2>
<p>一上手就被 <a class="reference external" href="http://octopress.org/docs/setup/">Octopress的搭建步骤</a> 烦到了。 <a class="reference external" href="http://beginrescueend.com/">RVM</a> 是什么? <a class="reference external" href="https://github.com/sstephenson/rbenv">rbenv</a> 又是什么?
看来 Ruby 社区的快节奏发展已经超过了我的想象,他们似乎需要一套发行版管理器来调和不同版本之间的 Ruby 的兼容性问题。
虽然同样的兼容性问题在 Python 社区也有 <a class="footnote-reference" href="#id10" id="id8">[1]</a> ,不过总觉得 Python 至少还没到需要一个发行版管理器的程度 <a class="footnote-reference" href="#id11" id="id9">[2]</a> 。</p>
<p>真正的问题是我手上还没有一个可以让我随便玩的 Linux 环境(真的想要……)。 而无论是 <a class="reference external" href="http://beginrescueend.com/">RVM</a> 还是 <a class="reference external" href="https://github.com/sstephenson/rbenv">rbenv</a> 似乎都只支持 Unix/Linux/MacOSX 。 身为极客就注定不能用 Windows 么?(或许是的……)。</p>
<p>剩下的问题就是 Ruby 和 Python 两大阵营的对立问题了。我不熟悉 <a class="reference external" href="http://daringfireball.net/projects/markdown/">Markdown</a> , 相对来说比较喜欢 <a class="reference external" href="http://docutils.sourceforge.net/rst.html">ReST</a> 。 似乎无论哪边都要
依赖 <a class="reference external" href="http://pygments.org/">Pygments</a> 作为代码着色器,那么其实 Rubyist 也至少需要安装 Python 。 我倾向于不依赖任何 Ruby 组件,最好没有 C 扩展
的纯 Python 实现。</p>
<p>于是我开始在 Github 上找 Python 的静态博客引擎。 <a class="reference external" href="http://flask.pocoo.org/">Flask</a> 的作者 <a class="reference external" href="https://github.com/mitsuhiko">mitsuhiko</a> 写的 <a class="reference external" href="https://github.com/mitsuhiko/rstblog">rstblog</a> 看起来不错,不过似乎没有多少人在用。 <a class="reference external" href="http://ringce.com/hyde">Hyde</a> 似乎很完善,不过默认的标记语言是 MarkDown , 又依赖于几个 Ruby 组建,而且官方网站的设计实在太前卫。 最终我看到了 <a class="reference external" href="http://pelican.notmyidea.org/en/latest/">Pelican</a> 。</p>
<table border="0" class="docutils table footnote" frame="void" id="id10" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id8">[1]</a></td><td>比如 Python 2.x 与 3.x 之间看似难以跨越的鸿沟,以及 <a class="reference external" href="http://pypy.org/">PyPy</a> 、 <a class="reference external" href="http://python.org/">CPython</a> 、 <a class="reference external" href="http://www.stackless.com/">Stackless</a> 、 <a class="reference external" href="http://cython.org/">Cython</a> 等各个实现之间的微妙差别。</td></tr>
</tbody>
</table>
<table border="0" class="docutils table footnote" frame="void" id="id11" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id9">[2]</a></td><td>是的,我们有 <a class="reference external" href="http://packages.python.org/distribute/easy_install.html">easy_install</a> ,我们有 <a class="reference external" href="http://www.pip-installer.org/en/latest/index.html">pip</a> , 不过这些都是包管理器,都是装好特定的Python实现之后的事情。 Python实现本身还不需要包管理器来管理。 Python 的版本问题基本上也只需要 <a class="reference external" href="http://docs.python.org/release/3.0.1/library/2to3.html">2to3.py</a> 和 <a class="reference external" href="http://www.startcodon.com/wordpress/?cat=8">3to2.py</a> 这样的轻量级转换器就可以了,你不需要为了安装多个软件而在硬盘里留下多个不同版本的 Python 。 如果为了引用的稳定性,你可以用 <a class="reference external" href="http://pypi.python.org/pypi/virtualenv">virtualenv</a> ,不过这又是另一回事情了。</td></tr>
</tbody>
</table>
</div>
<div class="section" id="id12">
<h2>那么就 <a class="reference external" href="http://pelican.notmyidea.org/en/latest/">Pelican</a> 吧</h2>
<p>对我而言, <a class="reference external" href="http://pelican.notmyidea.org/en/latest/">Pelican</a> 相比于 <a class="reference external" href="http://octopress.org/">Octopress</a> 有几个好处:</p>
<blockquote>
<ol class="arabic simple">
<li>纯 Python 实现。 这意味着我可以换用任何 Python 解释器而不必担心兼容性问题。比如我就换成了 <a class="reference external" href="http://pypy.org/">PyPy</a>。</li>
<li>多语言支持。因为 <a class="reference external" href="http://pelican.notmyidea.org/en/latest/">Pelican</a> 的作者似乎是个法国人。不过这个似乎大部分人不需要…… 我是想尽量把一篇博客写成三种语言作为锻炼吧。</li>
<li><a class="reference external" href="http://docutils.sourceforge.net/rst.html">ReST</a> 。这样我就可以用 <a class="reference external" href="http://webpages.charter.net/edreamleo/front.html">Leo</a> 的 @auto-rst 直接写 ReST了。简单方便快捷有效。</li>
</ol>
</blockquote>
<p>不过似乎 <a class="reference external" href="http://pelican.notmyidea.org/en/latest/">Pelican</a> 的关注度不如 <a class="reference external" href="http://octopress.org/">Octopress</a> 那么高,现在一些部分还有细微的问题:</p>
<blockquote>
<ol class="arabic simple">
<li>pelican-import 从 WordPress 导入的时候对中文、日文的支持似乎很成问题。</li>
<li>日期格式、时区、字符集、和多语言功能的结合度还不够。 <strong>我在尝试改善它。</strong></li>
<li>模板还不够丰富。</li>
<li>插件也不够多……</li>
</ol>
</blockquote>
<p>希望这么优秀的工具能够受到更多关注,以上这些问题都是增加关注度之后很快就能解决的问题。</p>
</div>
<div class="section" id="settings-py">
<h2>我的设置 settings.py</h2>
<p>安装 <a class="reference external" href="http://pelican.notmyidea.org/en/latest/">Pelican</a> 很容易,一句话就够了:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="gp">$</span> pip install pelican</span>
</pre></div>
<p>然后把文章写成ReST的格式,放在`pages`文件夹里面。(重新)生成只要:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="gp">$</span> pelican -s settings.py</span>
</pre></div>
<p>上传到 Github:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="gp">$</span> git commit -am <span class="s2">"Commit message"</span></span>
<span class="code-line"><span class="gp">$</span> git push</span>
</pre></div>
<p>就这么简单。附上我的配置文件:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="c1"># -*- coding: utf-8 -*-</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="n">TIMEZONE</span> <span class="o">=</span> <span class="s1">'Asia/Tokyo'</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="n">DATE_FORMATS</span> <span class="o">=</span> <span class="p">{</span></span>
<span class="code-line"> <span class="s1">'en'</span><span class="p">:(</span><span class="s1">'usa'</span><span class="p">,</span><span class="s1">'</span><span class="si">%a</span><span class="s1">, </span><span class="si">%d</span><span class="s1"> %b %Y'</span><span class="p">),</span></span>
<span class="code-line"> <span class="s1">'zh'</span><span class="p">:(</span><span class="s1">'chs'</span><span class="p">,</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1">, </span><span class="si">%a</span><span class="s1">'</span><span class="p">),</span></span>
<span class="code-line"> <span class="s1">'jp'</span><span class="p">:(</span><span class="s1">'jpn'</span><span class="p">,</span><span class="s1">'%Y/%m/</span><span class="si">%d</span><span class="s1"> (</span><span class="si">%a</span><span class="s1">)'</span><span class="p">),</span></span>
<span class="code-line"><span class="p">}</span></span>
<span class="code-line"><span class="c1"># windows locale: http://msdn.microsoft.com/en-us/library/cdax410z%28VS.71%29.aspx</span></span>
<span class="code-line"><span class="n">LOCALE</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'usa'</span><span class="p">,</span> <span class="s1">'chs'</span><span class="p">,</span> <span class="s1">'jpn'</span><span class="p">,</span> <span class="c1"># windows</span></span>
<span class="code-line"> <span class="s1">'en_US'</span><span class="p">,</span> <span class="s1">'zh_CN'</span><span class="p">,</span> <span class="s1">'ja_JP'</span><span class="p">]</span> <span class="c1"># Unix/Linux</span></span>
<span class="code-line"><span class="n">DEFAULT_LANG</span> <span class="o">=</span> <span class="s1">'zh'</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="n">SITENAME</span> <span class="o">=</span> <span class="s1">'Farseerfc Blog'</span></span>
<span class="code-line"><span class="n">AUTHOR</span> <span class="o">=</span> <span class="s1">'Jiachen Yang'</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="n">DISQUS_SITENAME</span> <span class="o">=</span> <span class="s1">'farseerfcgithub'</span></span>
<span class="code-line"><span class="n">GITHUB_URL</span> <span class="o">=</span> <span class="s1">'https://github.com/farseerfc'</span></span>
<span class="code-line"><span class="n">SITEURL</span> <span class="o">=</span> <span class="s1">'http://farseerfc.github.com'</span></span>
<span class="code-line"><span class="n">TAG_FEED</span> <span class="o">=</span> <span class="s1">'feeds/</span><span class="si">%s</span><span class="s1">.atom.xml'</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="n">SOCIAL</span> <span class="o">=</span> <span class="p">((</span><span class="s1">'twitter'</span><span class="p">,</span> <span class="s1">'http://twitter.com/farseerfc'</span><span class="p">),</span></span>
<span class="code-line"> <span class="p">(</span><span class="s1">'github'</span><span class="p">,</span> <span class="s1">'https://github.com/farseerfc'</span><span class="p">),</span></span>
<span class="code-line"> <span class="p">(</span><span class="s1">'facebook'</span><span class="p">,</span> <span class="s1">'http://www.facebook.com/farseerfc'</span><span class="p">),</span></span>
<span class="code-line"> <span class="p">(</span><span class="s1">'weibo'</span><span class="p">,</span> <span class="s1">'http://weibo.com/farseerfc'</span><span class="p">),</span></span>
<span class="code-line"> <span class="p">(</span><span class="s1">'renren'</span><span class="p">,</span> <span class="s1">'http://www.renren.com/farseer'</span><span class="p">),</span></span>
<span class="code-line"> <span class="p">)</span></span>
<span class="code-line"></span>
<span class="code-line"></span>
<span class="code-line"><span class="n">TWITTER_USERNAME</span> <span class="o">=</span> <span class="s1">'farseerfc'</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="n">THEME</span><span class="o">=</span><span class="s1">'notmyidea'</span></span>
<span class="code-line"><span class="n">CSS_FILE</span> <span class="o">=</span> <span class="s2">"wide.css"</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="n">DEFAULT_CATEGORY</span> <span class="o">=</span><span class="s1">'Others'</span></span>
<span class="code-line"><span class="n">OUTPUT_PATH</span> <span class="o">=</span> <span class="s1">'.'</span></span>
<span class="code-line"><span class="n">PATH</span> <span class="o">=</span> <span class="s1">'posts'</span></span>
</pre></div>
</div>