都2020年了,現(xiàn)在最流行的就是什么直播彈幕短視頻,你的博客要是還不支持插視頻那可就OUT啦!
我的博客目前使用Markdown寫文,可惜它原生的語法并不支持視頻,于是只能自己來實(shí)現(xiàn)這功能了。
視頻是個(gè)好東西啊,它要不好現(xiàn)在的直播彈幕短視頻怎么火的……咳咳,扯遠(yuǎn)了,就說寫博客,比如寫教程啊總會(huì)遇到需要?jiǎng)討B(tài)演示的東西吧,比如我自己的純CSS解決圖片加載的布局移動(dòng)問題里一開頭的動(dòng)圖(其實(shí)是視頻啦),要用圖片或者文字來說明文本下移的現(xiàn)象肯定沒有動(dòng)態(tài)的演示好。
另外玩過Twitter的都知道它里面插入的GIF圖會(huì)轉(zhuǎn)換為視頻,GIF是1987年發(fā)明的東西,在我看來早是就該進(jìn)入垃圾堆的技術(shù),因?yàn)楫?dāng)年瀏覽器不支持視頻才得以流行。動(dòng)圖這一技術(shù)完全能被視頻所替代,視頻本身就不是一連串圖像的序列嗎(當(dāng)然還包括聲音)。
在性能上,H.246編碼的視頻體積僅為GIF的13分之一,雖然GIF也有g(shù)ifsicle能壓縮一下,但效果仍不如視頻。
從我的實(shí)際經(jīng)驗(yàn)來看,技術(shù)類文章里大部分動(dòng)態(tài)演示都來源于錄屏,錄屏軟件生成的本來就是視頻格式,把它們轉(zhuǎn)GIF多此一舉。綜上所述,視頻的支持是一個(gè)現(xiàn)代化博客必需的功能。
Markdown版本演進(jìn)已經(jīng)有其它的文章寫過了https://juejin.im/post/5baa5b346fb9a05d2d0225cc#heading-6
主要的幾個(gè)Markdown版本原生都不支持視頻,我不知道它的作者是怎么想的,如此重要的功能竟然能沒有。既然官方?jīng)]有,那就自己做唄,于是種各樣的實(shí)現(xiàn)方案就跑了出來,按照本人強(qiáng)迫癥的做法當(dāng)然要對比一番。
這是我看到的最多的做法,其優(yōu)勢就是簡單,現(xiàn)有的轉(zhuǎn)換庫都支持寫HTML,但我認(rèn)為這種方式并不好。
這缺點(diǎn)太多,所以我決定還是得用Markdown的方式來做。
GitLab Flavored Markdown(下稱GFM)是Markdown的一種修改版,它復(fù)用了圖片的語法,以擴(kuò)展名來區(qū)分媒體的類型,比如![label](foobar.mp4)
因?yàn)殒溄邮?code style="box-sizing: border-box; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 14px; color: rgb(232, 62, 140); overflow-wrap: break-word;">.mp4結(jié)尾所以渲染為視頻。
GFM的支持也很廣泛,實(shí)現(xiàn)又簡單,還有GitLab背書,自然也是個(gè)不錯(cuò)的選擇。
但它的缺點(diǎn)也很明顯,強(qiáng)制了鏈接的文件名必須是視頻常用的擴(kuò)展名,然而并不是所有鏈接都是如此,Twitter的視頻鏈接就沒有擴(kuò)展名。另外既然都修改了原始的Markdown語義,何不直接另起一個(gè)新語法呢?
關(guān)于自定義的語法有很多討論,我認(rèn)為比較好的一種是使用通用指令語法,它的格式是@<指令類型>[...](..){...}
這樣的,前面的@可以換成別的,指令類型用于區(qū)分視頻、音頻、GIF視頻等,后面三個(gè)括號(hào)里的內(nèi)容可以自由發(fā)揮。
最終我決定使用這種語法,它跟原生的圖片語法一樣簡潔,又給足了自由發(fā)揮的余地。
通常來說,新的語法最好還是跟現(xiàn)有的保持相似,這里就以語法比較像的圖片為基準(zhǔn)。圓括號(hào)仍然跟圖片一樣包含視頻的鏈接,方括號(hào)里填標(biāo)簽(GIF)或者poster(視頻)。
通用指令語法里,花括號(hào)用來放置key = "val"
這樣的鍵值對,但它們同樣可以放在鏈接URL的參數(shù)上,而且目前圖片就是這么做的,為了保持一致,我選擇不要這個(gè)花括號(hào)部分。
指令類型包含GIF視頻和普通視頻,另外Markdown同樣不支持插入音頻這里也給補(bǔ)上,所以最終的語法為:
@audio[](音頻鏈接)
插入一個(gè)音頻。@gif[標(biāo)簽](視頻鏈接)
插入視頻,并盡可能模仿GIF圖。@video[視頻封面](視頻鏈接)
插入普通視頻。我的博客使用markdown-it來轉(zhuǎn)換Markdown為HTML,markdown-it 的流程分為解析和渲染兩部分,所以要給這兩個(gè)地方編寫自己的函數(shù)實(shí)現(xiàn)。
首先是怎么識(shí)別@<指令類型>[...](..)
這種文本呢,如果不考慮轉(zhuǎn)義的話倒是一個(gè)正則就能搞定,但問題是如果標(biāo)簽里出現(xiàn)了方括號(hào),或者鏈接里有圓括號(hào)咋辦?當(dāng)然是要轉(zhuǎn)義了,Markdown對括號(hào)的轉(zhuǎn)義方式有兩種:配對計(jì)數(shù)和斜杠轉(zhuǎn)義,其中配對計(jì)數(shù)需要一個(gè)變量來存儲(chǔ)左括號(hào)數(shù)量挺麻煩,而且斜杠轉(zhuǎn)義完全能用于所有場景,但反過來配對計(jì)數(shù)卻無法用于右括號(hào)單獨(dú)出現(xiàn)的情況(雖然不常見)。
綜上所述,我決定不支持計(jì)數(shù)了,斜杠轉(zhuǎn)義用一個(gè)前向環(huán)視(?<!\\)
就能解決,再給指令部分加點(diǎn)限制,最后的正則如下:
([a-z][a-z0-9\-_]*)
\[(.*?)(?<!\\)]
\((.*?)(?<!\\)\)
把它們?nèi)齻€(gè)連起來就可以匹配通用指令語法啦。
Markdown有塊block
和行內(nèi)inline
兩種結(jié)構(gòu),原始的圖片語法是屬于行內(nèi)的,這可以實(shí)現(xiàn)圖文混排,但在使用中發(fā)現(xiàn)我并沒有圖文混排的需求,我博客里的圖片都是單獨(dú)一行。所以我決定新的語法作為塊結(jié)構(gòu),這樣可以降低解析函數(shù)被調(diào)用的頻率,提升點(diǎn)性能。
最后要注意一下的是反轉(zhuǎn)義和XSS檢查,這些函數(shù)在markdown-it庫里已有提供。
解析器代碼見kaciras-blog/web-server/packages/server/lib/markdown-media.ts
Markdown渲染出來的HTML是跟場景相關(guān)的,比如在RSS里渲染的結(jié)果應(yīng)盡量簡單,畢竟閱讀器的樣式是沒法由我來控制的;而在我的博客網(wǎng)站里,會(huì)有一些額外的樣式和元素來展現(xiàn)更好的效果,比如提前固定寬高比防止布局移動(dòng)、居中等。
在我的博客,GIF視頻通過隱藏控制面板、靜音、給下面加標(biāo)簽、以及IntersectionObserver實(shí)現(xiàn)的自動(dòng)播放/暫停,實(shí)現(xiàn)了跟GIF圖片一樣的效果。另外由于RSS閱讀器不會(huì)加載我的博客的樣式表,也不會(huì)運(yùn)行JS,所以RSS閱讀器里的GIF視頻只能跟普通視頻一樣。
除了這倆之外,我還準(zhǔn)備讓評(píng)論系統(tǒng)也使用Markdown(暫未實(shí)現(xiàn)),這又是一個(gè)新的渲染目標(biāo),用戶評(píng)論屬于第三方輸入,對其的渲染必須加入一些限制以防濫用。
對無法控制的前端,渲染實(shí)現(xiàn)跟解析器寫在一起,見上面的鏈接。
我博客的渲染實(shí)現(xiàn)見kaciras-blog/website/blob/master/src/markdown/media.js
聯(lián)系客服