Farseerfc的小窩 - python//farseerfc.me/2016-07-31T03:52:00+09:00PacVis: 可視化 pacman 本地數據庫2016-07-31T03:52:00+09:002016-07-31T03:52:00+09:00farseerfctag:farseerfc.me,2016-07-31:/pacvis.html
<div class="panel panel-default">
<div class="panel-heading">
PacVis</div>
<div class="panel-body">
<img alt="Demo of PacVis" class="img-responsive" src="//farseerfc.me/images/pacvis-first.png"/>
</div>
</div>
<div class="section" id="pacvis">
<h2><a class="toc-backref" href="#id11">我爲什麼要做 PacVis</a></h2>
<p>我喜歡 Arch Linux ,大概是因爲唯有 Arch Linux 能給我對整個系統「瞭如指掌」的感覺。
在 Arch Linux 裏我能清楚地知道我安裝的每一個包,能知道系統裏任何一個文件是來自哪個包,
以及我爲什麼要裝它。或許對 Debian/Fedora/openSUSE 足夠熟悉了之後也能做到這兩點,
不過他們的細緻打包的結果通常是包的數量比 Arch 要多個 3 到 10 倍,並且打包的細節也比 Arch
Linux 簡單的 PKGBUILD 要複雜一個數量級。</p>
<p>每一個裝過 Arch Linux 的人大概都知道,裝了 Arch Linux 之後得到的系統非常樸素,按照
ArchWiki 上的流程一路走下來的話,最關鍵的一條命令就是 <code class="code">
pacstrap /mnt …</code></p></div>
<div class="panel panel-default">
<div class="panel-heading">
PacVis</div>
<div class="panel-body">
<img alt="Demo of PacVis" class="img-responsive" src="//farseerfc.me/images/pacvis-first.png"/>
</div>
</div>
<div class="section" id="pacvis">
<h2><a class="toc-backref" href="#id11">我爲什麼要做 PacVis</a></h2>
<p>我喜歡 Arch Linux ,大概是因爲唯有 Arch Linux 能給我對整個系統「瞭如指掌」的感覺。
在 Arch Linux 裏我能清楚地知道我安裝的每一個包,能知道系統裏任何一個文件是來自哪個包,
以及我爲什麼要裝它。或許對 Debian/Fedora/openSUSE 足夠熟悉了之後也能做到這兩點,
不過他們的細緻打包的結果通常是包的數量比 Arch 要多個 3 到 10 倍,並且打包的細節也比 Arch
Linux 簡單的 PKGBUILD 要複雜一個數量級。</p>
<p>每一個裝過 Arch Linux 的人大概都知道,裝了 Arch Linux 之後得到的系統非常樸素,按照
ArchWiki 上的流程一路走下來的話,最關鍵的一條命令就是 <code class="code">
pacstrap /mnt base</code>
,
它在 <code class="code">
/mnt</code>
裏作爲根調用 <code class="code">
pacman -S base</code>
裝上了整個 base 組,
然後就沒有然後了。這個系統一開始空無一物,你需要的任何東西都是後來一點點用
<code class="code">
pacman</code>
手動裝出來的,沒有累贅,按你所需。</p>
<p>然而時間長了,系統中難免會有一些包,是你裝過用過然後忘記了,
然後這些包就堆在系統的角落裏,就像家裏陳年的老傢俱,佔着地,落着灰。雖然
<code class="code">
pacman -Qtd</code>
能方便地幫你找出所有
<strong>曾經作爲依賴被裝進來,而現在不被任何包依賴</strong> 的包,但是對於那些你手動指定的包,
它就無能爲力了。</p>
<p>於是我就一直在找一個工具能幫我梳理系統中包的關係,方便我:</p>
<ol class="arabic simple">
<li>找出那些曾經用過而現在不需要的包</li>
<li>找出那些體積大而且佔地方的包</li>
<li>釐清系統中安裝了的包之間的關係</li>
</ol>
<div class="figure">
<img alt="Android System Architecture" class="img-responsive" src="//farseerfc.me/images/Android-System-Architecture.jpg"/>
<p class="caption"><a class="reference external" href="https://en.wikipedia.org/wiki/Android_(operating_system)">Android 系統架構</a></p>
</div>
<p>關於最後一點「釐清包的關係」,我曾經看到過
<a class="reference external" href="https://en.wikipedia.org/wiki/Architecture_of_OS_X">macOS 系統架構圖</a>
和 Android 的系統架構圖,對其中的層次化架構印象深刻,之後就一直在想,是否能畫出現代
Linux 桌面系統上類似的架構圖呢?又或者 Linux 桌面系統是否會展現完全不同的樣貌?
從維基百科或者別的渠道能找到 Linux 內核、或者 Linux 圖形棧,
或者某個桌面環境的架構,但是沒有找到覆蓋一整個發行版的樣貌的。
於是我便想,能不能從包的依賴關係中自動生成這樣一張圖呢。</p>
</div>
<div class="section" id="id1">
<h2><a class="toc-backref" href="#id12">PacVis的老前輩們</a></h2>
<p>在開始寫 PacVis 之前,我試過一些類似的工具,他們都或多或少能解決一部分我的需要,
又在某些方面有所不足。這些工具成爲了 PacVis 的雛形,啓發了 PacVis
應該做成什麼樣子。</p>
<div class="section" id="pactree">
<h3><a class="toc-backref" href="#id13">pactree</a></h3>
<p>pactree 曾經是一個
<a class="reference external" href="https://bbs.archlinux.org/viewtopic.php?id=51795">獨立的項目</a> ,現在則是
<a class="reference external" href="https://www.archlinux.org/pacman/pactree.8.html">pacman 的一部分</a> 了。
從手冊頁可以看出, pactree 的輸出是由某個包開始的依賴樹。
加上 <code class="code">
--graph</code>
參數之後 pactree 還能輸出
<a class="reference external" href="http://www.graphviz.org/">dot</a> 格式的矢量圖描述,然後可以用 dot 畫出依賴圖:</p>
<div class="panel panel-default">
<div class="panel-heading">
<code class="code">
pactree pacvis-git -d3 --graph | dot -Tpng >pacvis-pactree.png</code>
</div>
<div class="panel-body">
<img alt="pactree --graph" class="img-responsive" src="//farseerfc.me/images/pacvis-pactree.png"/>
</div>
</div>
<div class="highlight"><pre><span class="code-line"><span></span><span class="gp">$</span> pactree pacvis-git -d3</span>
<span class="code-line"><span class="go">pacvis-git</span></span>
<span class="code-line"><span class="go">├─python-tornado</span></span>
<span class="code-line"><span class="go">│ └─python</span></span>
<span class="code-line"><span class="go">│ ├─expat</span></span>
<span class="code-line"><span class="go">│ ├─bzip2</span></span>
<span class="code-line"><span class="go">│ ├─gdbm</span></span>
<span class="code-line"><span class="go">│ ├─openssl</span></span>
<span class="code-line"><span class="go">│ ├─libffi</span></span>
<span class="code-line"><span class="go">│ └─zlib</span></span>
<span class="code-line"><span class="go">├─pyalpm</span></span>
<span class="code-line"><span class="go">│ ├─python</span></span>
<span class="code-line"><span class="go">│ └─pacman</span></span>
<span class="code-line"><span class="go">│ ├─bash</span></span>
<span class="code-line"><span class="go">│ ├─glibc</span></span>
<span class="code-line"><span class="go">│ ├─libarchive</span></span>
<span class="code-line"><span class="go">│ ├─curl</span></span>
<span class="code-line"><span class="go">│ ├─gpgme</span></span>
<span class="code-line"><span class="go">│ ├─pacman-mirrorlist</span></span>
<span class="code-line"><span class="go">│ └─archlinux-keyring</span></span>
<span class="code-line"><span class="go">└─python-setuptools</span></span>
<span class="code-line"><span class="go"> └─python-packaging</span></span>
<span class="code-line"><span class="go"> ├─python-pyparsing</span></span>
<span class="code-line"><span class="go"> └─python-six</span></span>
<span class="code-line"><span class="gp"> $</span> pactree pacvis-git -d3 --graph <span class="p">|</span> dot -Tpng >pacvis-pactree.png</span>
</pre></div>
<p>從畫出的圖可以看出,因爲有共用的依賴,所以從一個包開始的依賴關係已經不再是一棵
<a class="reference external" href="https://zh.wikipedia.org/wiki/%E6%A8%B9%E7%8B%80%E7%B5%90%E6%A7%8B">圖論意義上的樹(Tree)</a>
了。最初嘗試做 PacVis 的早期實現的時候,就是試圖用 bash/python 腳本解析 pactree 和
pacman 的輸出,在 pactree 的基礎上把整個系統中所有安裝的包全都包含到一張圖裏。
當然後來畫出的結果並不那麼理想,首先由於圖非常巨大,導致 dot
的自動佈局要耗費數小時,最後畫出的圖也過於巨大基本上沒法看。</p>
<p>然而不得不說沒有 pactree 就不會有 PacVis ,甚至 pacman 被分離出 alpm
庫也和 pactree 用 C 重寫的過程有很大關係,而 PacVis 用來查詢 pacman 數據庫的庫
pyalpm 正是 alpm 的 Python 綁定。因爲 pactree 的需要而增加出的 alpm 庫奠定了 PacVis
實現的基石。</p>
</div>
<div class="section" id="pacgraph">
<h3><a class="toc-backref" href="#id14">pacgraph</a></h3>
<div class="panel panel-default">
<div class="panel-heading">
pacgraph 的輸出</div>
<div class="panel-body">
<img alt="pacgraph" class="img-responsive" src="//farseerfc.me/images/pacvis-pacgraph.png"/>
</div>
</div>
<p><a class="reference external" href="http://kmkeen.com/pacgraph/index.html">pacgraph</a> 是一位 Arch Linux 的
Trusted User <a class="reference external" href="http://kmkeen.com/">keenerd</a> 寫的程序,和
PacVis 一樣也是用 Python 實現的。
比起 pactree , pacgraph 明顯更接近我的需求,它默認繪製整個系統的所有安裝包,
並且用聰明的佈局算法解決了 dot 佈局的性能問題。</p>
<p>pacgraph 的輸出是一個富有藝術感的依賴圖,圖中用不同的字體大小表示出了每個包佔用
的磁盤空間。通過觀察 pacgraph 的輸出,我們可以清楚地把握系統全局的樣貌,
比如一眼看出這是個桌面系統還是個服務器系統,並且可以很容易地發現那些佔用磁盤空間
巨大的包,考慮清理這些包以節約空間。</p>
<p>更棒的是 pacgraph 還提供了一個交互性的 GUI 叫做 pacgraph-tk ,顯然通過 tk 實現。
用這個 GUI 可以縮放觀察整幅圖的細節,或者選中某個包觀察它和別的包的依賴關係。</p>
<p>pacgraph 還支持通過參數指定只繪製個別包的依賴關係,就像 pactree 那樣。</p>
<p>不過 pacgraph 也不是完全滿足我的需要。如我前面說過,我希望繪製出的圖能反應
<strong>這個發行版的架構面貌</strong> ,而 pacgraph 似乎並不區別「該包依賴的包」和「依賴該包的包」
這兩種截然相反的依賴關係。換句話說 pacgraph 畫出的是一張無向圖,
而我更想要一張有向圖,或者說是 <strong>有層次結構的依賴關係圖</strong> 。</p>
</div>
</div>
<div class="section" id="id4">
<h2><a class="toc-backref" href="#id15">於是就有了 PacVis</a></h2>
<div class="panel panel-default">
<div class="panel-heading">
PacVis 剛打開的樣子</div>
<div class="panel-body">
<img alt="PacVis on startup" class="img-responsive" src="//farseerfc.me/images/pacvis-second.png"/>
</div>
</div>
<p>總結了老前輩們的優勢與不足,我便開始利用空餘時間做我心目中的 PacVis 。
前後斷斷續續寫了兩個月,又分爲兩個階段,第一階段做了基本的功能和雛形,
第二階段套用上 <a class="reference external" href="https://getmdl.io/">https://getmdl.io/</a> 的模板,總算有了能拿得出手給別人看的樣子。</p>
<p>於是乎前兩天在 AUR 上給 pacvis 打了個
<a class="reference external" href="https://aur.archlinux.org/packages/pacvis-git/">pacvis-git</a>
包,現在想在本地跑 pacvis 應該很方便了,用任何你熟悉的 aurhelper
就可以安裝,也可以直接從 aur 下載 PKGBUILD 打包:</p>
<div class="highlight"><pre><span class="code-line"><span></span><span class="go">~$ git clone aur@aur.archlinux.org:pacvis-git.git</span></span>
<span class="code-line"><span class="go">~$ cd pacvis-git</span></span>
<span class="code-line"><span class="go">~/pacvis-git$ makepkg -si</span></span>
<span class="code-line"><span class="go">~/pacvis-git$ pacvis</span></span>
<span class="code-line"><span class="go">Start PacVis at http://localhost:8888/</span></span>
</pre></div>
<p>按照提示說的,接下來打開瀏覽器訪問 <a class="reference external" href="http://localhost:8888/">http://localhost:8888/</a> 就能看到 PacVis
的樣子了。僅僅作爲嘗試也可以直接打開跑在我的服務器上的 demo:
<a class="reference external" href="https://pacvis.farseerfc.me/">https://pacvis.farseerfc.me/</a> ,這個作爲最小安裝的服務器載入速度大概比普通的桌面系統快一點。</p>
<div class="panel panel-default">
<div class="panel-heading">
在 Windows msys2 跑 PacVis</div>
<div class="panel-body">
<img alt="PacVis on Windows msys2" class="img-responsive" src="//farseerfc.me/images/pacvis-msys2.png"/>
</div>
</div>
<p>另外補充一下,因爲 PacVis 只依賴 pyalpm 和 tornado ,所以在別的基於 pacman
的系統上跑它應該也沒有任何問題,包括
<a class="reference external" href="https://msys2.github.io/">Windows 上的 msys2</a> 裏(儘管在 msys2 上編譯
tornado 的包可能要花些功夫)。</p>
</div>
<div class="section" id="id5">
<h2><a class="toc-backref" href="#id16">PacVis 的圖例和用法</a></h2>
<p>操作上 PacVis 仿照地圖程序比如 Google Maps 的用法,可以用滾輪或者觸摸屏的手勢
縮放、拖拽,右上角有個側邊欄,不需要的話可以點叉隱藏掉,右下角有縮放的按鈕和
回到全局視圖的按鈕,用起來應該還算直觀。</p>
<div class="figure">
<img alt="PacVis showing pacvis-git" class="img-responsive" src="//farseerfc.me/images/pacvis-pacvis-git.png"/>
<p class="caption">pacvis-git 包的依賴</p>
</div>
<p>先解釋圖形本身,整張圖由很多小圓圈的節點,以及節點之間的箭頭組成。
一個圓圈就代表一個軟件包,而一條箭頭代表一個依賴關係。縮放到細節的話,
能看到每個小圓圈的下方標註了這個軟件包的名字,鼠標懸浮在圓圈上也會顯示相應信息。
還可以點開軟件包,在右側的邊欄裏會有更詳細的信息。</p>
<p>比如圖例中顯示了 pacvis-git 自己的依賴,它依賴 pyalpm, python-tornado 和
python-setuptools ,其中 pyalpm 又依賴 pacman 。圖中用
<span class="label label-primary">紫色</span> 表示手動安裝的包,
<span class="label label-warning">橙色</span> 表示被作爲依賴安裝的包,
箭頭的顏色也隨着包的顏色改變。</p>
<p>值得注意的是圖中大多數箭頭都是由下往上指的,這是因爲 PacVis 按照包的依賴關係做
了拓撲排序,並且給每個包賦予了一個拓撲層級。比如 pacvis-git 位於 39
層,那麼它依賴的 pyalpm 就位於 38 層,而 pyalpm 依賴的 pacman 就位於 37
層。根據層級關係排列包是 PacVis 於 pacgraph 之間最大的不同之處。</p>
<p>除了手動縮放, PacVis 還提供了搜索框,根據包名快速定位你感興趣的包。
以及在右側邊欄中的 Dep 和 Req-By 等頁中,包的依賴關係也是做成了按鈕的形式,
可以由此探索包和包之間的關聯。</p>
<p>最後稍微解釋一下兩個和實現相關的參數:</p>
<div class="label label-info">
Max Level</div>
<p>這是限制 PacVis 載入的最大拓撲層。系統包非常多的時候 PacVis
的佈局算法會顯得很慢,限制層數有助於加快載入,特別是在調試 PacVis 的時候比較有用。</p>
<div class="label label-info">
Max Required-By</div>
<p>這是限制 PacVis 繪製的最大被依賴關係。稍微把玩一下 PacVis 就會發現系統內絕大多數
的包都直接依賴了 glibc 或者 gcc-libs 等個別的幾個包,而要繪製這些依賴的話會導致
渲染出的圖中有大量長直的依賴線,不便觀察。於是可以通過限制這個值,使得 PacVis
不繪製被依賴太多的包的依賴關係,有助於讓渲染出的圖更易觀察。</p>
</div>
<div class="section" id="id6">
<h2><a class="toc-backref" href="#id17">從 PacVis 能瞭解到的一些事實</a></h2>
<div class="panel panel-default">
<div class="panel-heading">
一個 KDE 桌面的 PacVis 結果全圖, <a class="reference external" href="//farseerfc.me/images/pacvis-16384.png">放大(17M)</a></div>
<div class="panel-body">
<img alt="A normal KDE desktop in PacVis" class="img-responsive" src="//farseerfc.me/images/pacvis-4096-anno.png"/>
</div>
</div>
<p>稍微玩一下 PacVis 就能發現不少有趣現象,上述「絕大多數包依賴 glibc 」就是一例。
除此之外還有不少值得玩味的地方。</p>
<div class="section" id="id7">
<h3><a class="toc-backref" href="#id18">依賴層次</a></h3>
<p>系統中安裝的包被明顯地分成了這樣幾個層次:</p>
<ul class="simple">
<li>glibc 等 C 庫</li>
<li>Bash/Perl/Python 等腳本語言</li>
<li>coreutils/gcc/binutils 等核心工具</li>
<li>pacman / systemd 等較大的系統工具</li>
<li>gtk{2,3}/qt{4,5} 等 GUI toolkit</li>
<li>chromium 等 GUI 應用</li>
<li>Plasma/Gnome 等桌面環境</li>
</ul>
<p>大體上符合直觀的感受,不過細節上有很多有意思的地方,比如 zsh 因爲 gdbm
間接依賴了 bash,這也說明我們不可能在系統中用 zsh 完全替代掉 bash。
再比如 python (在 Arch Linux 中是 python3)和 python2 和 pypy
幾乎在同一個拓撲層級。</p>
<div class="figure">
<img alt="zsh depends on bash because of gdbm" class="img-responsive" src="//farseerfc.me/images/pacvis-zsh-bash.png" style="width: 45%;"/>
<p class="caption">zsh 因爲 gdbm 間接依賴了 bash</p>
</div>
<p>不過偶爾顯示的依賴層級不太符合直觀,比如 qt5-base < qt4 < gtk2 < gtk3 。
qt5 因爲被拆成了數個包所以比 qt4 更低級這可以理解,而 gtk 系比 qt
系更高級這一點是很多人(包括我)沒有預料到的吧。</p>
</div>
<div class="section" id="id8">
<h3><a class="toc-backref" href="#id19">循環依賴</a></h3>
<p>有些包的依賴關係形成了循環依賴,一個例子是 freetype2 和 harfbuzz,freetype2
是繪製字體的庫,harfbuzz 是解析 OpenType 字形的庫,兩者對對方互相依賴。
另一個例子是 KDE 的 kio 和 kinit,前者提供類似 FUSE 的資源訪問抽象層,
後者初始化 KDE 桌面環境。</p>
<div class="figure">
<img alt="freetype2 harfbuzz" class="img-responsive" src="//farseerfc.me/images/pacvis-freetype2-harfbuzz.png" style="width: 45%;"/>
<p class="caption">freetype2 和 harfbuzz 之間的循環依賴</p>
</div>
<p>因爲這些循環依賴的存在,使得 PacVis 在實現時不能直接拓撲排序,我採用環探測
算法找出有向圖中所有的環,並且打破這些環,然後再使用拓撲排序。
因此我在圖中用紅色的箭頭表示這些會導致環的依賴關係。</p>
</div>
<div class="section" id="id9">
<h3><a class="toc-backref" href="#id20">有些包沒有依賴關係</a></h3>
<div class="figure">
<img alt="PacVis Level 0" class="img-responsive" src="//farseerfc.me/images/pacvis-level0.png" style="width: 45%;"/>
<p class="caption">man-pages 和 licenses 沒有依賴關係</p>
</div>
<p>有些包既不被別的包依賴,也不依賴別的包,而是孤立在整張圖中,比如
man-pages 和 licenses 。這些包在圖中位於最頂端,拓撲層級是 0 ,我用
<span class="label label-info">藍色</span> 正方形特別繪製它們。</p>
</div>
<div class="section" id="linux">
<h3><a class="toc-backref" href="#id21">只看依賴關係的話 Linux 內核完全不重要</a></h3>
<p>所有用戶空間的程序都依賴着 glibc ,而 glibc 則從定義良好的 syscall 調用內核。
因此理所當然地,如果只看用戶空間的話, glibc 和別的 GNU 組件是整個 GNU/Linux
發行版的中心,而 Linux 則是位於依賴層次中很深的位置,甚至在我的 demo 服務器上
Linux 位於整個圖中的最底端,因爲它的安裝腳本依賴 mkinitcpio
而後者依賴了系統中的衆多組件。</p>
</div>
<div class="section" id="pacman-qtd">
<h3><a class="toc-backref" href="#id22">pacman -Qtd 不能找到帶有循環依賴的孤兒包</a></h3>
<div class="figure">
<img alt="pacman -Qtd cannot find packages with circle dependency" class="img-responsive" src="//farseerfc.me/images/pacvis-circledeps-Qtd.png" style="width: 45%;"/>
<p class="caption">msys2 中帶有循環依賴的孤兒包</p>
</div>
<p>這是我在 msys2 上測試 PacVis 的時候發現的,我看到在渲染的圖中有一片羣島,
沒有連上任何手動安裝的包。這種情況很不正常,因爲我一直在我的所有系統中跑
<code class="code">
pacman -Qtd</code>
找出孤兒包並刪掉他們。放大之後我發現這些包中有一條循環依賴,
這說明 <code class="code">
pacman -Qtd</code>
不能像語言的垃圾回收機制那樣找出有循環依賴的孤兒包。</p>
</div>
</div>
<div class="section" id="id10">
<h2><a class="toc-backref" href="#id23">PacVis 的未來</a></h2>
<p>目前的 PacVis 基本上是我最初開始做的時候設想的樣子,隨着開發逐漸又增加了不少功能。
一些是迫於佈局算法的性能而增加的(比如限制層數)。</p>
<p>今後準備再加入以下這些特性:</p>
<ol class="arabic simple">
<li>更合理的 optdeps 處理。目前只是把 optdeps 關係在圖上畫出來了。</li>
<li>更合理的 <strong>依賴關係抉擇</strong> 。有時候包的依賴關係並不是直接根據包名,而是
<code class="code">
provides</code>
由一個包提供另一個包的依賴。目前 PacVis 用 alpm
提供的方式抉擇這種依賴,於是這種關係並沒有記錄在圖上。</li>
<li>目前的層級關係沒有考慮包所在的倉庫 (core/extra/community/...) 或者包所屬的組。
加入這些關係能更清晰地表達依賴層次。</li>
<li>目前沒有辦法只顯示一部分包的關係。以後準備加入像 pactree/pacgraph 一樣顯示部分包。</li>
</ol>
<p>如果你希望 PacVis 出現某些有趣的用法和功能,也
<a class="reference external" href="https://github.com/farseerfc/pacvis/issues">請給我提 issue</a> 。</p>
</div>
重新設計了 Pelican 的主題與插件2015-01-25T22:45:00+09:002015-01-25T22:45:00+09:00farseerfctag:farseerfc.me,2015-01-25:/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/try-pelican.html">折騰主題</a> 到現在都快三年了,
而從上次 <a class="reference external" href="//farseerfc.me/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/try-pelican.html">折騰主題</a> 到現在都快三年了,
而從上次 <a class="reference external" href="//farseerfc.me/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/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/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/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>Pyssy 項目2012-04-02T12:42:00+09:002012-04-02T12:42:00+09:00farseerfctag:farseerfc.me,2012-04-02:/pyssy.html<div class="section" id="id1">
<h2>簡介</h2>
<p>Pyssy 是用於 <a class="reference external" href="https://bbs.sjtu.edu.cn">上海交通大學 飲水思源站</a> 的一系列 Python 腳本和工具。</p>
<p>Pyssy 被有意設計爲既可以託管寄宿在 SAE <a class="footnote-reference" href="#sae" id="id3">[1]</a> 上,也可以在單機上獨立使用。</p>
<p>項目地址: <a class="reference external" href="http://pyssy.sinaapp.com/">http://pyssy.sinaapp.com/</a></p>
<p>Github上的源代碼地址: <a class="reference external" href="https://github.com/yssy-d3/pyssy">https://github.com/yssy-d3/pyssy</a></p>
<table border="0" class="docutils table footnote" frame="void" id="sae" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id3">[1]</a></td><td><a class="reference external" href="http://sae.sina.com.cn/">Sina App Engine</a> ,新浪雲平臺,類似 <a class="reference external" href="https://appengine.google.com/">Google App Engine</a> 的東西。</td></tr>
</tbody>
</table>
</div>
<div class="section" id="id4">
<h2>依賴關係</h2>
<p>Pyssy 使用 <a class="reference external" href="http://flask.pocoo.org/">Flask</a> 作爲網頁服務器,
並且使用 Memcached 或者 Redis 作爲抓取 <em>水源Web</em> 的緩存。</p>
<p>SAE Python 環境下請開啓 …</p></div><div class="section" id="id1">
<h2>簡介</h2>
<p>Pyssy 是用於 <a class="reference external" href="https://bbs.sjtu.edu.cn">上海交通大學 飲水思源站</a> 的一系列 Python 腳本和工具。</p>
<p>Pyssy 被有意設計爲既可以託管寄宿在 SAE <a class="footnote-reference" href="#sae" id="id3">[1]</a> 上,也可以在單機上獨立使用。</p>
<p>項目地址: <a class="reference external" href="http://pyssy.sinaapp.com/">http://pyssy.sinaapp.com/</a></p>
<p>Github上的源代碼地址: <a class="reference external" href="https://github.com/yssy-d3/pyssy">https://github.com/yssy-d3/pyssy</a></p>
<table border="0" class="docutils table footnote" frame="void" id="sae" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id3">[1]</a></td><td><a class="reference external" href="http://sae.sina.com.cn/">Sina App Engine</a> ,新浪雲平臺,類似 <a class="reference external" href="https://appengine.google.com/">Google App Engine</a> 的東西。</td></tr>
</tbody>
</table>
</div>
<div class="section" id="id4">
<h2>依賴關係</h2>
<p>Pyssy 使用 <a class="reference external" href="http://flask.pocoo.org/">Flask</a> 作爲網頁服務器,
並且使用 Memcached 或者 Redis 作爲抓取 <em>水源Web</em> 的緩存。</p>
<p>SAE Python 環境下請開啓 Memcached 支持。</p>
<p>本地環境下請安裝 Redis-py 並運行 redis-server 服務器程序。</p>
</div>
PyRuby2012-03-02T23:09:00+09:002012-03-02T23:09:00+09:00farseerfctag:farseerfc.me,2012-03-02:/mix-ruby.html<p>今天在GitHub上閒逛的時候看到一個叫做 <a class="reference external" href="https://github.com/danielfm/pyruby">PyRuby</a> 的項目。項目的Readme說得很好:</p>
<pre class="literal-block">
PyRuby - Some Ruby for your Python!
PyRuby is a simple way to leverage the power of Ruby to make your Python code more readable and beautiful.
Usage
All you have to do is import the ruby module:
import ruby
From now on you should be able …</pre><p>今天在GitHub上閒逛的時候看到一個叫做 <a class="reference external" href="https://github.com/danielfm/pyruby">PyRuby</a> 的項目。項目的Readme說得很好:</p>
<pre class="literal-block">
PyRuby - Some Ruby for your Python!
PyRuby is a simple way to leverage the power of Ruby to make your Python code more readable and beautiful.
Usage
All you have to do is import the ruby module:
import ruby
From now on you should be able to write Ruby code within a regular Python module. An example:
1.upto(10) { |n| puts n }
</pre>
<p>甚至 <a class="reference external" href="http://pypi.python.org/pypi/pyruby/1.0.0">PyPI</a> 上還有這個項目的包。</p>
<p>一開始我還以爲這又是一個野心勃勃的基於PyPy的Ruby實現,或者某種trick在Python裏面直接調用Ruby解釋器。</p>
<div class="section" id="id2">
<h2>然後我想看看這個的源代碼</h2>
<p>只有一個ruby.py文件,內容是:</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="nb">print</span><span class="p">(</span><span class="s2">"""</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="s2"> `.-:/+ossyhhddmmmmNNNNNNNmmmmmdddddhhhyyyyhhhyo:`</span></span>
<span class="code-line"><span class="s2"> .:+sydNNNmmdhhysso++/+++++++////::::::-.```......--/oymms.</span></span>
<span class="code-line"><span class="s2"> `:ohmdys+//::/::--::::////:-.```......`````.://:-` `/dNs.</span></span>
<span class="code-line"><span class="s2"> .+hNds:`-:-:///::------::///++///:--....--::///::-`.///. `oMm/</span></span>
<span class="code-line"><span class="s2"> /hNmo.` `` `....``````````` ...------:::-:/+/-.:/:` /NMs</span></span>
<span class="code-line"><span class="s2"> oMd/` `::::--.---://+` //` `````-:::::+/-`::.` :NM+</span></span>
<span class="code-line"><span class="s2"> yN` -+.` `/` o. ``::.-:. `` :NN:</span></span>
<span class="code-line"><span class="s2"> :Nm - ./ : `.-://///:-. `-` `` :NN-</span></span>
<span class="code-line"><span class="s2"> /NM/ .-:::-.` `/ `:sdmdhyMMMMMMNNmy/` :mNo`</span></span>
<span class="code-line"><span class="s2"> :hMd: /dmddddNNmdy+-. `smmy/-```hMMMMMMMhydm/ `-.`` `...:mMm+.</span></span>
<span class="code-line"><span class="s2"> -hNd/-/o/-..-::`.ydmmmmNMMMMMMNh:/+- dMN-`-+hmmmmdhhhhdddmMN-`-/o: .-::::/oydms-</span></span>
<span class="code-line"><span class="s2"> oNMo:+/::. ``...--:/+ohNMNhs- :hNmmdyo:..``yo-```.--. `-`-+shdddhs+-` `.//yms.</span></span>
<span class="code-line"><span class="s2"> .MMo:/`o:.:+sso+:-` sM+ ./-` /mNh+-....-/ymNNdo::--/shd+` -`:mm:</span></span>
<span class="code-line"><span class="s2"> /MM-o ./ ohhsooohNmy::sh. `yM/ `:oyyyyyyhys+:.` hy `/Nh` : -NN.</span></span>
<span class="code-line"><span class="s2"> -MM// -: `` y: odddhh+ -omNh- `--.` `` ```` .:ohMMs. +Ms / yMo</span></span>
<span class="code-line"><span class="s2"> hMoo .+. :Mh ```` `/hNd/.` ohdddy::...`..` `-/sdmdyo+NMNh+- :Mh / sMs</span></span>
<span class="code-line"><span class="s2"> .mmh:..:. :NMm `-/dMNM+ ./+++/:`.hM:`.````.` `-/shmNmh+-` /Mmooso.hM/ .: `mM/</span></span>
<span class="code-line"><span class="s2"> .mNs://: .NMNMs- -:-.`/+-sms. ` `shyyyhy`sNd` `.:+sdmmmdMM-. .oNM+ :m/ `s``yMh</span></span>
<span class="code-line"><span class="s2"> -mMo . sMNdMNNh+-. .ydyoyy` ``+o::+shdddhs+:-.:MM.`.-+hNMMh- `.`-/::dNs`</span></span>
<span class="code-line"><span class="s2"> -NM- mMMMh:MMdNmhs+:-..```-ohs-`...-:/+syhddmMMs:-.` `/mMMdmmddNMm+` ..-/hNh-</span></span>
<span class="code-line"><span class="s2"> sMy NMMM`:Mh`-/mMmmmdddddddddhhhdNNdhyo+:--.yMs `..:+ymMMMMd+--yNh. `+hNh:</span></span>
<span class="code-line"><span class="s2"> -Mm NMMM/yMh -NM-`..--:NMo:--.`+My :MNoydmNMMNmhdMh` -dNs` `yMd:</span></span>
<span class="code-line"><span class="s2"> `MN mMMMMMMMyshMN+:---.-MN-.....+My...-:/oyhdMMMMNmdy+-` +Mh:sNm/ yMy`</span></span>
<span class="code-line"><span class="s2"> MN yMMMMMMMMMMMMMMMMMNMMMMNNNNNMMMNNNMMMMMNmhMM/-. `yMMNs. /My</span></span>
<span class="code-line"><span class="s2"> `MN :MMmMMMMMMMMMMMMMMMMMMMMMMMMMMMMNmmdy+:-``NM- ./hNNy- /Nd`</span></span>
<span class="code-line"><span class="s2"> -Mh dMydMmsNMNdNNMMmmmNMMMdddhys+yMo`` /Nm: `:yNNdo. .sNd.</span></span>
<span class="code-line"><span class="s2"> +Ms .mMsMN::NN:.:MN: `.+NM. +Mo +Mm+ymNdo- .omm+`</span></span>
<span class="code-line"><span class="s2"> yM: .hNMd+:sMN. oMm. oMo +Mh ```.:+shMNmy+-``.-:-..-//-`:yNmo`</span></span>
<span class="code-line"><span class="s2"> mM. :ohmNNMMdhyMMdo//+Mm//////sMNhyhhdmNNmhs/-``./+/:--+so/-:smNy/`</span></span>
<span class="code-line"><span class="s2"> .Mm `` .-:/+osyyhhddddddddddhhyysoo+/:-. `./+//--+oo/--+ymmy/.</span></span>
<span class="code-line"><span class="s2"> :Mh .: `+:` `.------------` ```-////:/++/:../ydNdo:`</span></span>
<span class="code-line"><span class="s2"> +Ms `/` :+o+:-``` ``..-::///++///:-.`-+ydNdo:`</span></span>
<span class="code-line"><span class="s2"> oMs :/:.`` `..---.``` ````````..-:/:::---.` `-ohmmh+:`</span></span>
<span class="code-line"><span class="s2"> /Mh .://///:::-----.-----.......` `-+hmmy+-</span></span>
<span class="code-line"><span class="s2"> sMy` ``````-+ydmy+-</span></span>
<span class="code-line"><span class="s2"> /mNs-` `./ohmNMNNNmy+-</span></span>
<span class="code-line"><span class="s2"> /yNmho/:.``````````.-:/+syhdNmdyso+/-.`</span></span>
<span class="code-line"><span class="s2"> `:+ydmNMNNNNNNNNNmdhys+/:.`</span></span>
<span class="code-line"><span class="s2"> ``.....`</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="s2"> LOL U MAD?</span></span>
<span class="code-line"><span class="s2">"""</span><span class="p">)</span></span>
<span class="code-line"></span>
<span class="code-line"><span class="kn">import</span> <span class="nn">sys</span></span>
<span class="code-line"><span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span></span>
</pre></div>
<p>是的……的確……這種嘗試把Python和Ruby放在一起的想法絕對是瘋了……</p>
</div>
嘗試一下 Pelican2012-02-24T17:33:00+09:002012-02-24T17:33:00+09:00farseerfctag:farseerfc.me,2012-02-24:/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>