或许我就是一个文艺青年,连个吐槽帖子的标题都要想半天然后模仿一下 The Unbearable Lightness of Being,或者至少不是文艺青年也是个可怜的完美主义者:所以才会写出这篇文章来呀。 完美主义者很可怜的原因是世间万物都本是不完美的,于是完美主义者就会在永远地最求完美的过程中不断受到打击和挫折。这基本上就是我这段世间尝试各种 static blog generator 的感想了吧!
开始尝试 static blog generator 的理由理所当然地是:原来的 Wordpress 平台的 blog 系统并不是完美的。要数可以数出很多来,最不方便的就是写日志了,由于我的 blog 是放在 dreamhost 上的,从国内连接速度不是很快,而像我这种写一段就喜欢刷新看一下效果(特别是在文章中很多公式的时候)的人来说,基本上大部分时间都花在等待浏览器刷新上了。同样的原因插入图片什么之类的附件也很不方便。此外自己需要的一些扩展功能不太好实现,例如在这篇关于 PAC Learnability 的文章中出现的定义那个 block ,还有类似的定理呀、证明呀之类的,我在书写的时候都要写比较复杂的 HTML 代码,如果要自动化的话似乎又得用 PHP 写 Wordpress 插件,又兴师动众了。等等等等,如此这般,反正欲加之罪,何患无辞,于是我就开始尝试 static blog generator 了。
实际上要说静态网页生成的话,我很早就开始尝试了,最开始是为了给自己搞一个主页,出国申请用。当时找到了一个叫做 bonsai 的 Ruby 的简易网页生成工具,现在看来确实很简易,不过那个时候我要求很低,也没见过世面,就用上了。用的过程中发现了一个小 bug :他文档中说子页面的顺序会按照文件名顺序来排,但是实际在代码中根本没有排序,于是我直接改了代码,在某个地方加了一句:
.sort_by{|p| p.disk_path }
(偷偷说其实我在测试新 blog 的代码高亮功能)然后顺便去报告了 bug
:首先感谢了作者提供这么好用的工具,然后委婉地说那个地方好像和文档中说的有点不符合,修正如下。作者很快回复说欢迎提交
patch (with a test) 。我黑线了一下…… -_-!!!
后来作者又说他发现是和文档不太符合,这里应该是返回文件系统默认的顺序,所以我们这里需要把文档修正一下,如果你有时间的话,欢迎提交
patch 来修正文档。此时此刻我心理只想着逃命要紧了! ^_^bb
虽然这个作者宁愿修改文档都不修改代码让我觉得有点汗,但是他抓人的行为实在是很有既视感:有时候有人问起你的某个
N 久没有更新或维护过的开源项目的时候,你就会巴不得他把一切都搞好比如在
github 上提交个 pull request ,你只要点一下 accept
就好了,或者甚至希望他能直接 take over 项目将来的维护……哈哈!
第一次 static site generator 之旅就这样结束了,bonsai 果然还只是小工具,虽然能生成网站,但是开发起来不能方便地预览。后来过了很久我有空了,又把自己的主页重新做了一下,主要的改动是使用 twitter-bootstrap 来作为基础 css 让页面更好看一点。顺便呢,把那个 bonsai 给替换掉。
经过一番调研我最后选择了 Hyde
这个用 Python 写的工具。看起来很 promising ,似乎也有不少好评。也确实比
bonsai 要强大许多,比如可以直接启动一个 web server
在本地预览呀之类的。不足的地方就是好像没有文档……
=.=,不过最后我也不知道怎么 figure out
了,把主页改造了一番,还用上了一些比较 fancy 的 twitter-bootstrap
里的效果。
Hyde 的 template 是用的 Jinja ,似乎是很受推崇的。发现 Python 派系的 template 和 Ruby 派系有一个比较明显的区别就是:比如 Jinja2 里,在不同的 template 间共享代码的方式是通过继承。例如,你定义一个基本的框架(一个非常简化的例子):
- <!DOCTYPE html>
- <html lang="en">
- <head>
- {% block head %}
- <meta charset="utf-8">
- {% endblock head %}
- </head>
- <body>
- {% block body %}
- {% endblock body %}
- </body>
- </html>
然后在更具体的 template 中,你可以继承这个 template ,并重载其中的某些 block ,例如在 head block 中加入 favicon :
- {% extends "base.j2" %}
- {% block head %}
- {{ super() }}
- <link rel="shortcut icon" href="/favicon.png">
- {% endblock head %}
就如同 OOP 中的继承一样,还可以调用 super 。不过在 Ruby 社区似乎主要是用另一种方式:他们会把每个不同的功能组件分割开成为一些 “partial”,例如 head 、sidebar、navbar 之类的,然后在需要的页面,通过 include 这些 partial 的方式来组装成一个完整的页面 template 。
不过后来开始考虑 blog 也用 static site generator 来搞的时候,我又尝试了 Ruby 派系的,毕竟写网站似乎从 Rails 开始就是用 Ruby 的工具链显得”洒脱”一些。特别是 jekyll 似乎是非常有人气的。不过由于 jekyll 虽然号称是 “blog-aware” 的 static site generator,但是本身还是一个比较底层的工具,要从头搭建一个 blog 的话,还是比较麻烦的,由于之前对 twitter-boostrap 的好感,自然就找到了 jekyll-bootstrap,而且 jekyll 本身的文档也非常不友好,只有一些零星的 wiki page,虽然作为已经熟悉了系统之后的 reference manual 来用还是挺不错的,但是连一个 introductor 或者 tutorial 都没有的话,对于外行就很不友好了,不过还好 jekyll-bootstrap 那里提供了一个很不错的 jekyll 的 tutorial。
这里可以简单讲一下 jekyll 之类的 blog generator 的工作方式。一个 blog 中的页面通常由两种组成:page 和 post 。page 是比较固定的页面,比如主页呀、About 页面之类的,而 post 则是正常的 blog 了。page 页一般可以比较简单,就将 template 展开成 HTML 即可;而 post 则有一些额外的套路:
- post 通常都是统一 layout 的,因此通常被分为 layout 和 content 两个部分,layout 是普通的 template,里面指定了一个地方放置 content,每一篇或者至少每一类 blog 都是相同的;而 content 则是 blog post 的具体内容,一般用 markdown 或者 textile 之类的标记语言写成。
- post 有一些 meta data,包括发布日期、tags 和 category 等。系统在处理的时候会把这些信息收集起来,比如发布日期会用来对 post 进行排序,tag 和 category 会生成反向映射(例如用于找出某个 tag 对应了哪些 post 等等)。
将 post 生成为 HTML 页面的时候粗略地来讲可以分为以下几个步骤:
- 收集 payload:包括整个 site 的信息例如有哪些 tag 、有哪些 post 之类的;和 post 自己的信息,例如标题、发布日期等。这些 payload 信息可以在 template 中访问到。
- 渲染内容:jekyll 的 post 内容是标记语言和模版语言混合的。这样做的好处是添加了灵活性,因为像 markdown 和 textile 之类的标记语言毕竟语法是固定的,如果想要添加什么扩展功能的话,还是添加 template 来得方便一些,例如要添加语法高亮功能,或者是嵌入 video 之类的。
- 展开模版:最后 post 对应的 layout 模版会被展开,上一步中生成出来的内容会被插入到模版所指定的位置上。
内容渲染的时候 jekyll 中是先用 Liquid
模版展开,然后把得到的结果传给标记语言的转换器进行转换。具体使用什么转换器依赖于
post 那个文件的扩展名,内置了 markdown 和 textile
等的转换器。这样一来添加的扩展功能就可以抢先被处理,当然由于生成出来的内容会经过(比如)markdown,所以又需要注意不要让你生成出来的内容被
markdown 破坏掉了。markdown 是不会去动 block HTML
里面的内容的,所以如果你生成出来是一个 block HTML
的话,一般没有什么问题,但是如果是嵌入在段落文本中的话就有些麻烦了,标准的
markdown 语法并没有什么有效的 escape 功能,不过如果使用 kramdown 来进行
markdown 转换的话,可以将对应的内容包装在 {::nomakrdown} 和
{:/nomarkdown} 之间。
实际上我最急需的扩展就是书写数学公式——更确切地说:方便地书写数学公式,我希望可以写
$e^{i\pi}$ 就可以得到 eiπ,而不需要繁杂的
Liquid tag 语法。所以这个功能不能在 Liquid template
那里添加,不过由于渲染用的 converter 是可以定制的,所以我们可以定制一个
markdown converter,在传入真正的 markdown
渲染之前就把这些公式全部处理好——如果用 MathJax
在网页里动态解析的话,其实只有保持文本原样就可以了,因此这里主要就是将它保护起来,需要保护的原因是公式里的许多标记如上标、下标之类的都是和
markdown 冲突的。
不过后来我发现还有一个东西叫做 textile 之后,就立即放弃 markdown
了,主要原因是 textile 标准就包含了一个保护用的
<notextile> 语法。当然 textile 和 markdown
相比也更加强大,或者说目标不同吧:
- markdown 的目标是写出来的文档直接看它原来的纯文本格式也是结构清晰的,顺便还可以方便地转化为 HTML 之类的格式。
- textile 生来就是为了写可以转化为 HTML 的文档的,因此它功能更加强大一些,甚至可以直接控制生成出来的 HTML 元素的各种 property 。
于是我果断放弃 markdown 换了 textile,并做了这样的定制 converter 。不过最后我用的不是 jekyll-bootstrap,而是同一个作者新搞的一个工具叫做 ruhoh 。这个东西比较新一点,据说是作者在开发 jekyll-bootstrap 的过程中总计经验的全新力作,当然是完全重写的,不过野心也比较大,是要做一个 universal static blogging platform,有一套 API,说是要做成 language agnostic 的,目前提供了 Ruby 的版本,好像后面要开发 Python 、PHP 和 node.js 等的版本。当然我对是否 language agnostic 不感兴趣,不过总得来说 ruhoh 还是很不错的。
先说缺点吧,第一就是由于它这个 language agnostic,所以用了一个 language agnostic 的 template 叫做 Mustache,这货语法巨简单,功能有点弱(当然功能弱并不是说它干不了有些事,只是干起来比较麻烦,夸张一点来说就像汇编语言和 Ruby 比较一样),什么 for 啊、if 之类的统统都没有,倒是有一个简单的 loop,可以重复一个列表里的元素进行展开,但是也不支持上下文判断是否是列表第一个、偶数个等功能。比如最简单的我有一个 tags 列表,想要让每个 tag 是到对应 tag 页面的链接然后把这些链接用逗号连接起来,就是除了最后一个 tag 之外其他每个后面都加一个逗号。这个在 Liquid 或者 Jinja2 之类的 template 语言里是很好写的,但是在 Mustache 里就变得非常痛苦。
另外一个缺点就是 ruhoh 还比较新,就在我弄好自己的
blog,并且认认真真写了一篇文章,表示很满意,准备 deploy 的时候,ruhoh
发布了新版本,在 announce blog 中第一句话是 “I Just Broke Everything” ……
-.-bbb
这些个缺点促使我还尝试了其他的一些工具,包括自己从裸的 jekyll 开始搭建,以及使用非常受欢迎的基于 jekyll 的 octopress 。总的来说令我非常崩溃……
先说 jekyll,和 ruhoh 比起来,实在是比较原始。它虽然有一个 auto
re-generation
功能,就是启动起来之后监视本地文件,如果改动了就自动重新生成,这样可以使得本地写
blog
预览更加方便一些,但是我从输出来看它似乎每次都把整个网站重新生成一遍,虽然我的
blog
目前就一篇文章和两三张图片,但是对于一个完美主义者来说这简直是不可忍受的。万一我以后写了数千万篇的文章了呢?并且它似乎把本地预览和
deploy
的时候所生成的文件混在一起用的,原本我在模版里区分了生成的时候的环境是
development 还是 production,如果是前者就载入本地另外用 lighttpd host 的
MathJaX,如果是后者则载入 MathJaX 官方的 CDN 的版本(MathJaX
发布的那个包里的文件实在是太乱了,完美主义者表示不愿意把那个包整个丢到自己的
blog 目录里去)。结果在用 jekyll
的时候就混乱了。其他的什么缺点一时也想不起来了,因为我已经一怒之下把自己折腾半天的那个目录给删掉了。
相比起来,ruhoh 的开发模式就友好得多,本地预览和 deploy 是分开的,并且本地预览是用 rack,我发现这个东西也挺好玩的。最开始是希望能找到一个功能是我在写 blog 的时候,文本编辑器这边一保存,浏览器那边自动就刷新。因为我现在在家里有双显示器,所以这个功能非常实用。Linux 下可以用 inotify 来跟踪文件的改变,可是发现变更之后怎么让浏览器刷新呢?找半天发现 Firefox、Chrome 之类的浏览器都不支持通过命令行发送刷新命令。可能的解决方案有:
- 使用浏览器 REPL,例如 mozrepl,给浏览器添加一个脚本解释器的 server,然后通过 netcat 等工具发送脚本指令到浏览器里去执行。这样子有点感觉略杀鸡用牛刀。而且我随便尝试了一下没有成功,也没有深究了……
- 使用专用浏览器插件,例如 Firefox 的 Auto Reload 插件,就可以跟踪本地文件,在改变的时候自动刷新,看起来刚好就是为这个任务设计的,不过不知道为什么我就是不喜欢,-.-bb 大概是因为要跑到浏览器里去配置该归本地 blog 目录管的内容吧。而且似乎底下的评论有说新版本不 work 了,于是我就没有尝试。
- 使用 xdotool,人肉发送
<F5>给浏览器。这个方案多少有些迂回,而且需要先把焦点切换到 Firefox,然后再切换回编辑器,反正用起来差强人意。
但是后来我发现一个叫做 rack-livereload
的东西,这货是工作在 server 端的,用法很简单,在 ruhoh 生成的 rack
用的配置 config.ru 里加一行变成这样
- require 'rack'
- require 'rack-livereload'
- require 'ruhoh'
- use Rack::LiveReload
- run Ruhoh::Program.preview
然后写一个 Guardfile,里面写想要 watch 的文件(guard
还可以做很多其他事情,更多例子可以参考它的 readme)
- guard 'livereload' do
- watch(%r{posts/.+\.textile})
- end
之后就可以了,运行 guard 把文件 watch 起来,然后运行
rackup 把本地预览用的 web server 启动起来,然后你修改被
watch
到的文件的时候,浏览器里对应的页面就会自动刷新,神奇吧?它的工作原理其实也不神秘,就是通过一个
rack 的中间件,在最终发送给浏览器的 HTML 页里做了点手脚,插入了一个
livereload.js,这个脚本负责监听服务端的 reload 指令,而 web 服务端那里从
guard
服务器得知文件变动之后就会通知该脚本刷新。用起来很透明也很方便!^_^
但是如果用 jekyll
的话大概就没法用这个功能了,至少我不知道怎么把它们黏合起来。
不过折腾的结果是对 jekyll 的内部有了更多的了解,于是也能看得懂它那些散布的文档了,顺便在看 octopress 的时候也明白了,其实它就是在 jekyll 的基础上加了一堆 plugin 。所以我也顺便尝试了一下 octopress 。总的来说完成度相当高了,基本直接就可以用,不过由于是基于 jekyll,所以 jekyll 有的缺点它都有。另外它默认的那个主题实在是让人又爱又恨,爱的是看起来确实挺 pp 的,恨的是看起来确实挺 pp 以至于网上已经有无数个基于 octopress 的 blog 直接用了默认主题,最多改了个颜色。
此外 Octopress 虽然默认添加了 SASS 支持,但是它那个 style
文件看起来好像很复杂的样子,不知道是它自己从零写出来的还是基于某个 css
框架搞出来的,要做一些扩展的时候又觉得无从下手了。由于我尝试 Octopress
的直接原因是出于对 ruhoh 的 Mustache 模版的不满,所以自然对 jekyll 的
Liquid
模版满心期待,但是最后也是让我很崩溃,反正我看文档(基本没有这部分的文档)加看代码加运行时调试,最后都没太搞明白在
Liquid 中定义的一个 block
tag,它传进来的那些个参数到底是啥……我定义了一个生成定理的
block,老是出错,后来我找到原因是因为 Octopress 的 RSS
生成插件那里用了非常规的处理方法,由于要将内容嵌入到 XML 中,它将每个
post 的原始内容拿过来直接做了些处理(比如不管三七二十一用 markdown
转换一下 =.=bb),然后做了 XML 的
escape,最后再模版自己本身展开的时候有些自定义的 tag
已经被搞得面目全非了,自然就解析出错了。
各种崩溃的最后我还是选择了崩溃点最少的 ruhoh,并更新到最新版。然后做了一些自己的定制和改动,比如可以用页内生成定理、公式编号和引用功能,实在是非常好用呀(比如参见关于 L1 sparsity 的那篇文章)。当然 static blog generator 也有它的许多缺点:
- 搜索:静态网页是没法提供搜索功能的,最多是基于 javascript 的那种,感觉那种对于文档类的网站有特定的类名呀、函数名之类的需要检索的还有用一些,对于通用的 blog 就不太好用了。要么就只能用 google custom search 了,不过那样也得先等到 blog rank 足够高被 google 给好好索引了之后才会好用。但是其实我是几乎没有用过像 wordpress 之类的平台自己提供的搜索功能的,我想大家要搜索的时候也都是直接去 google 整个 Internet 搜吧,所以这一条不是特别 critical 。
- 评论:静态网页没法支持评论,现在比较流行的解决办法就是使用 disqus 或者 intensedebate 之类的外部评论系统。关于外部评论系统的优缺点网上已经有很多分析讨论了,甚至还有针对这些系统开不开源的争执。不过我还是主要关心的是 anti-spam 的问题,用这些外部评论工具的话,可以有的控制就少了许多,我目前在 Wordpress 上用的 anti-spam 是要求评论中必须有中文字符出现,实践证明是非常有效好用的手段,但是如果用 disqus 的话就不成了,不知道到时候体验会如何呢?
- 写作系统:表面上看 static blog generator 写 blog 似乎变简单了,用一个文本工具就可以了,实际上却变复杂了许多,因为需要有一整套的软件装好了才能生成内容。由于我最近主要是在用 Linux,所以安装配置相关的工具都很轻松(顺便吐槽一下 Linux 下的各种中文输入法都好难用),但要是哪天我想在 windows 或者其他别人的电脑上写个 blog 的话,就痛苦了,相比之下,像 Wordpress 之类的平台就很清爽,只要有一个浏览器和 Internet access 就可以了。
总的来说其实就是一句话:世间没有完美的软件。真是个残酷的事实。唯一的生存之道就是把自己从一个完美主义者强制转换成一个将就主意者。否则走了极端就是大把大把的青春浪费到各种无意义的折腾上了=.=。总之现在的系统先用用看吧。
最后讲一下 rake-pipeline 吧。各种 blog generator 会自动处理 post 的内容转换和渲染,但是有时候我们还有除了 post 之外的其他内容需要转换,例如可能用 SASS 写成的 styles 需要转换为 CSS,而我自己也有一个需求就是有时候画的图(比如用 asymptote )需要从源码格式编译为图片格式等等。blog generator 一般没有处理这些东西的功能,一方面是因为已经有额外的程序可以比较好地处理这些了。当然用 Make 或者 Rake 手写也是可以的,不过这里我们可以用 rake-pipeline 会更方便一些。
rake-pipeline 的使用方法很简单,写一个 Assetfile (其实是一个 ruby
文件),在里面写规则,然后运行 rakep build
即可。例如下面是我用的 Assetfile,包含了编译 asy 文件的规则,由于 2D 的
asy 文件我希望编译为 svg 格式,而 3D 的编译成 png 格式比较好,所以我在
asy 源文件里用注释的方式加 meta 信息来表明输出格式:
- # vim: filetype=ruby
- output "compiled/files"
- class AsyFilter < Rake::Pipeline::Filter
- attr_accessor :config
- def initialize
- @output_name_generator = proc { |fn, wrap|
- @config = {'ext' => 'png', 'opt' => ''}
- /^---$(.*?)^---$/m.match(wrap.read) do
- require 'yaml'
- config.merge!(YAML::load($1))
- end
- ext = config['ext']
- fn.sub(/\.[^.]+$/, '.' + ext)
- }
- end
- def generate_output(inputs, output)
- system("asy #{config['opt']} -f #{config['ext']} -o " +
- File.join(output.root,output.path) + " " +
- File.join(inputs[0].root, inputs[0].path))
- end
- end
- input "files" do
- match '**/*.asy' do
- filter AsyFilter
- end
- filter Rake::Pipeline::ConcatFilter
- end
不过我这里由于决定输出文件的文件名的时候需要读取输入文件的内容,所以需要至少
0.6.0 版的 rake-pipeline 才好用(低版本的
output_name_generator 那个 lambda
的参数只有输入文件名,没有第二个 wrap
那个参数,当然在这种情况下要人肉把文件名和目录名合并起来找到原来的文件读取内容也不是不行的)。
为了避免每次都要人肉运行 rakep,我们可以写一个 compiler
task plugin 来自动调用它。ruhoh 里的 compiler task plugin 就是每次生成
site
的时候都会被运行,里面基本上可以做任意的事情。这里我们很简单地直接调用命令即可,把这个文件放到
plugins 目录下就可以了。
- class Ruhoh
- module Compiler
- module Assets
- def self.run(target, page)
- Ruhoh::Friend.say { green "building files" }
- system("rakep build")
- end
- end
- end
- end
当然 jekyll 里也有 compiler task plugin,那里被称作 generator plugin
。不过我当时也算吃了点苦头,因为好像文件老是没法生成。最后我发现原来文件其实是生成了,只是
jekyll 管理比较严格,在生成 site
之后做了一些清理工作,把目标目录里未注册的文件全给删了。所以我们还得多做一点事情,在生成文件之后给它们发放假户口。由于我所以生成的文件都放到
files
目录下,所以我就简单地为该目录下的每个文件都注册了一下:
- module Jekyll
- class FakeStaticFile < StaticFile
- def initialize(site, base, dir, name)
- super
- end
- def write(dest)
- end
- end
- class AssetsGenerator < Generator
- safe true
- def generate(site)
- system("rakep build")
- # register generated files to prevent them from being deleted
- Dir.chdir(site.dest) do
- Dir['files/**/*'].each { |f|
- site.static_files <<
- FakeStaticFile.new(site, site.source, *File.split(f))
- }
- end
- end
- end
- end
让每个文件都成为一个伪装的 StaticFile,然后重写
write 方法,让他什么都不干,就可以蒙混过关了,嘿嘿!
Comments
标题漏了个a
每次都忘记disqus密码……
google openid 绝对忘不了阿
悲剧……改了标题还要花大半天来 migrate comment thread ,又一个外部 comment system 的不方便的地方呀。
不知为何,就是比较排斥Ruby/Perl/Python
这……排斥 Ruby/Perl/Python 却喜欢 Javascript 吗?
Javascript也仅仅是能用而已了,其实更喜欢Lua的语法,不过Lua的实现实在太渣了,周边功能太少。
看来你是喜欢语法越简单越好啊…… =.=b 语法糖多一点的话写起来更方便些么~
行距和段间距也许可以再设大一些,文字多的时候读起来会更舒服。:)
嗯,不过我一般都把 blog 写得老长,如果行距设置得太大的话,就更长更长了……回头再调一调。
貌似每更新一次,都会在RSS里面重新出现一下,于是Google Reader出现了几个版本……
会不会是因为这篇 post 的标题(和 url )改过了的原因?看来还得好好研究一下是不是 rss generator 的 timestamp 还要仔细设置一下……
仔细看了下,是url改过了,原来是unberable(typo?),现在改成了unbearable,应该不是timestamp的问题
由于选择太多,带来的纠结比只有一个选择更加严重。我正在用 liquidluck , 是 @lepture 使用 Python 编写的。
是啊,我现在也暂时折腾够了,打算这几天赶紧多写几篇文章,到时候就算是想再折腾,看到有不少文章要移植太麻烦的话也就放弃了……
这个折腾起来的确要人命啊...我大概就是折腾到那个jekyllboostrap就停下了..那plusjade的后续ruhoh就没再折腾 放在自己的空间还是玩法多一些,比如用dropbox来同步,这样发布文章就不会有很大的局限,我就丢在github上..
嗯,Dropbox 太透明了,这种东西还是比较喜欢用 git 来管理。
这个,
ruhoh 好像还不错,不过作者能够给个 github 的 repo 地址嘛?我搞不清那个 repo 的名字是否可以随意起的以及如何绑定域名呃。以及我已经找了作者的 github 帐号,见不到相应的 repo 似乎 = =//
你可以用他的 hosting ,也可以自己 hosting ,这个很随意的,github 的 repo 是: https://github.com/ruhoh/ru...
上周也在折腾jekyllboostrap,也看到ruhoh和octopress,比较了下,觉得jekyll简单些。在开始觉得还不错,文章能在线更新,直接预览结果,挺方便的,可是结束还是各种郁闷。。后来换了下主题,文章不更新了,删除_site后,就直接没法生成和更新了。然后发现折腾了头天blog,一篇post也没写。。。折腾不起呀
PS:很喜欢lz的新blog主题,公式编号也很酷呀!
嘿嘿,谢谢!
嗯,折腾这些东西很花时间,其实很多东西凑合一下就好了……
没生成是语法有错误……jekyll这东西也不搞个提醒
啊,对,好像确实是这么一回事,它应该在命令行给个提示或者生成一个空文档都要好些……
原来这样呀。。。
好详细,如果从markdown转到textile,以前的文档要全从新改么,还是有什么好方法?……不怎么想折腾了,但各个markdown实现实在有些奇怪,有时都想直接用html写……
有个工具叫做 pandoc ,可以在各种不同的格式之间转换,你可以试一试。
到头来还是pandoc……
我说怎么回事……不用转了,最近太nc了,本地没有装RedCloth……
另外发现,对图片的处理很好啊。
文章很詳細很好,已收藏。
但看完之後覺得,嘛,這麼麻煩,說不定自己純手工 Html 還省事兒些呢……
話說為什麼你的 CSS 和 js 鏈接後面沒有尾巴?
fcitx用起来还可以
最近Ruhoh又更新了,而且变动好大。kid有打算更新吗?:smiley
其实我现在在用的是后来自己山寨的一个 generator ……
嗯,看得出来。不过ruhoh的2.1版本将pages,posts,themes等所有资源都模块化,统一用collection来表示,而且可以很方便的新建collections,图片等其他资源也统一放在media这个collection里,看起来很系统的样子。不过因为改动太多,原来的widget和plugin都不能用了,得再修改一番,又需要折腾了。而且官网的文档还停留在2.0。
PS: kid你的博客似乎没有对手机端作优化,我为了回复你用手机换了三个浏览器。Google和QQ浏览器直接卡死了,Opera mini又不能很好支持disqus,最后只好跑到disqus dashboard回复。针对手机端定制一下,另外选择性关闭掉没有公式的文章的MathJax应该会快些。
恩,确实一开始设计的时候就没有考虑到手机用户,然后版面设计尽量是使得 web 端和 PDF 渲染结果差不多,所以结构变得比较复杂,然后也就不太容易在手机端上很好地 reflow 了,特别是有侧边插图的时候。长远来看这个是个需要解决的问题,但是短期内暂时没有很好的解决办法。然后由于整个 blog 是 static html files,所以也没有针对不同的 UA 返回不同的渲染结果的机制。
嗯。另外请教下textile的公式输出问题。我是使用PandocRuby写了一个converter,可以解析markdown、rst和textile,但前面两个都可以顺利和MathJax结合产生公式,而textile就不行。不知道是什么原因?看了pandoc的说明好像是用 <span class="math"></math>包起来,不过好像没效果。另外,如果用pandoc,为了加快公式加载速度,同样也可以用本地预览,编译后CDN的方案,但应该怎么实现呢?
我不知道 textile,因为最后用 pandoc 之后就直接用的它提供的改进过的 markdown,公式就自动能转换了。至于 MathJaX,那个需要你的 generator 支持,生成 HTML 的时候如果是 dev 状态就链接到本地的 MathJaX,如果是 production mode 就链接到 CDN。
嗯,想起来ruhoh的确是有development和production好几种mode的。pandoc markdown的确比较强大,但这个flavor比较“重量级”,如果以后又不想用ruhoh了迁移到一个只能用类github flavorred的就悲催了。textile还好一些,因为只有RedCloth的定义,我想支持它的站点底层肯定会用RedCloth作为解析器,所以不会存在兼容性问题,而且github现在也支持textile了。可惜emacs的textile-mode太简单,只支持语法高亮。还不如markdown-mode和rst-mode。其实最想pandoc实现org-mode作为input,毕竟和emacs相结合所向披靡。现在github都支持org-mode了,pandoc对它的双向支持应该不远了吧。
最近发现有个不错的面向程序员的主机 koding:https://koding.com/R/wzpan ,提供了一个完善的 Web UI ,可以用类似 ssh 的 web 终端在线管理主机里的文件,包括调用 emacs 编辑源文件。基本实现无需配置可以在多台机之间写静态博客了。
那个终端不支持中文。
ssh 进去之后就可以用本地的输入法输入中文了呀。如果使用 fbterm 也许可以解决中文问题?
恩,我是说它提供的那个 web 终端。
Web 终端的确不行。感觉那个 Web 终端只适合用来执行一些命令。要编辑文件还是用它的 web 编辑器,或者 SSH 进去。而且 web 终端下使用远程的 Emacs 很蛋疼,很多快捷键和 Chrome 冲突,例如 “C-n” 。
pandoc能把latex转化成markdown么?怎么好像对中文支持不是很好啊
这个倒是没有尝试过。
只是想在这里留个名……博主好厉害,加油