升級 Jekyll 3 之前你一定要注意的一件事情
Jekyll 在不久之前發布了 3.0 ,讀完整個 release notes后,我并未發現任何潛在的風險,于是我果斷跑到我的服務器上(沒錯,我自己托管了 Jekyll 服務而不是使用 GitHub Page,為了逼格,為了https)升級了 Jekyll。
接著慘絕人寰的悲劇發生了
升級后,我訪問了我的博客,首頁一切完美如初。然后我試著打開某篇我自認為寫的還不錯的文章,拉到頁面底端,打算再次回味一下粉絲們的評論。wat,怎么評論都沒了!!!辛辛苦苦寫軟文騙來的粉絲和眼球,就這么消失了!!!
我第一時間看了下瀏覽器地址欄,holly f**k,我的精心設計的大小寫交錯的 url 已經全部變成了小寫。我迅速滾回了2.5.3,坐和放寬了一會會兒,小站又恢復了平靜。
變成小寫究竟意味著什么
首先,即使你不是處女座,你的內心也會因為這樣一個不小的變化感到內心煎熬,不是嗎?為什么要改變我的 url 呢。
然后是正經的,我們曾經發布的博客的 url,已經出現在各種 RSS、推ter、Google 的索引等等之中,一旦 url 發生改變,之前的所有鏈接都失效了。我不確定谷歌的索引是否大小寫敏感,但是我確定是,feedly 中我的文章的性感度(hot!)已經被清零了,推ter上 ifttt 自動發布的更新消息也無法成功的打開。
也就是說,這是一個 breaking change ,然而這并沒有出現在 Jekyll 3.0 的 release notes 中。
那個第五分鐘出現的紅裙子小妹妹就是兇手!
為了找出問題的真兇,我立刻到 GitHub 上查看 Jekyll 的源碼。經過一段時間的比對,root cause 出現了。在 2.x 中,Jekyll 使用post.rb來處理文章,同時存在一個document.rb來應對別的類型的文件。下面摘錄一小段代碼
#post.rb :title => slug,def process(name) m, cats, date, slug, ext = *name.match(MATCHER) self.date = Utils.parse_date(date, "Post '#{relative_path}' does not have a valid date in the filename.") self.slug = slug self.ext = ext end
document.rb
title: Utils.slugify(data['slug']) || Utils.slugify(basename_without_ext)</pre>
簡單來說,post 中的 title,就是你文件中的名字,比如2015-11-16-IAmAwesome.md的 title 就是IAmAwesome。但是在document.rb中,Jekyll 額外進行了一步處理Utils.slugify,我們看看這個函數會做什么:
SLUGIFY_RAW_REGEXP = Regexp.new('\s+').freeze SLUGIFY_DEFAULT_REGEXP = Regexp.new('[^[:alnum:]]+').freeze SLUGIFY_PRETTYREGEXP = Regexp.new("[^[:alnum:].~!$&'()+,;=@]+").freezedef slugify(string, mode=nil) mode ||= 'default' return nil if string.nil? return string.downcase unless SLUGIFY_MODES.include?(mode)
Replace each character sequence with a hyphen
re = case mode when 'raw' SLUGIFY_RAW_REGEXP when 'default' SLUGIFY_DEFAULT_REGEXP when 'pretty'
# "._~!$&'()+,;=@" is human readable (not URI-escaped) in URL # and is allowed in both extN and NTFS. SLUGIFY_PRETTY_REGEXP
end
string.
# Strip according to the mode gsub(re, '-'). # Remove leading/trailing hyphen gsub(/^\-|\-$/i, ''). # Downcase downcase
end</pre>
Jekyll 把它認為不正常的字符都替換成-,并且把字符都換成小寫的。
為了修復我博客的小問題,我立刻發了個 Pull request ,然而這個 pr 是有私心的,我當時只考慮了大小寫的問題。后來有哥們 表示 他寫在文件名里的_都被換成了-,不開心。
可以想見,以后會不斷有人跑過來說,把我的什么什么符號還給我…
終極解決方案
我的 pr 之后只會保留大小寫和-、_,其他的符號依然會被替換掉,這不是一個一勞永逸的修復。再加上 Jekyll 目測進入了 maintain mode,feature change 和 bug fix 現在都需要多人 review 才能進入主分支。我的 pr 寫了兩周了,一個 maintainer 表示可以 merge,但要等別人再 review。結果我這一等就是兩周,這期間我給 Jekyll 提了四個 issue,三個 pr,通通 pending。所以,要想等 Jekyll 發布新的版本,可能不是一個明智的做法。
為此,我寫了一個插件,叫做 jekyll-post-unslugify ,大家可以參考 文檔 進行安裝,安裝配置完畢后,你的文章的 title 就會像 Jekyll 2.x 里面一樣隨心所欲。只有 title 回到了過去,你依然可以享受 Jekyll 3.0 的新功能。
最后,May the title be with you.