本文转载自我的博客:https://blog.kaciras.com/article/18/add-video-support-to-markdown
都 2020 年了,当初最风行的就是什么直播弹幕短视频,你的博客要是还不反对插视频那可就 OUT 啦!
我的博客目前应用 Markdown 写文,惋惜它原生的语法并不反对视频,于是只能本人来实现这性能了。
视频益处都有啥?
视频是个好货色啊,它要不好当初的直播弹幕短视频怎么火的……咳咳,扯远了,就说写博客,比方写教程啊总会遇到须要动静演示的货色吧,比方我本人的纯 CSS 解决图片加载的布局挪动问题里一结尾的动图(其实是视频啦),要用图片或者文字来阐明文本下移的景象必定没有动静的演示好。
另外玩过 Twitter 的都晓得它外面插入的 GIF 图会转换为视频,GIF 是 1987 年创造的货色,在我看来早是就该进入垃圾堆的技术,因为当年浏览器不反对视频才得以风行。动图这一技术齐全能被视频所代替,视频自身就不是一连串图像的序列吗(当然还包含声音)。
在性能上,H.246 编码的视频体积仅为 GIF 的 13 分之一,尽管 GIF 也有 gifsicle 能压缩一下,但成果仍不如视频。
从我的理论教训来看,技术类文章里大部分动静演示都来源于录屏,录屏软件生成的原本就是视频格式,把它们转 GIF 多此一举。综上所述,视频的反对是一个现代化博客必须的性能。
语法的抉择
Markdown 版本演进曾经有其它的文章写过了 https://juejin.im/post/5baa5b346fb9a05d2d0225cc#heading-6
次要的几个 Markdown 版本原生都不反对视频,我不晓得它的作者是怎么想的,如此重要的性能居然能没有。既然官网没有,那就本人做呗,于是种各样的实现计划就跑了进去,依照自己强迫症的做法当然要比照一番。
间接插 HTML
这是我看到的最多的做法,其劣势就是简略,现有的转换库都反对写 HTML,但我认为这种形式并不好。
- XSS 危险:若是本人用还好说,一旦给评论之类的第三方输出用上,你都猜不到他们会搞些什么进去。
- 扩展性差:一旦写死,当前想改变下输入的 HTML 可就麻烦了,须要把所有文章都扫一遍,本博客就遇到过须要改变渲染后果的状况。
- 可读性差:Markdown 作为轻量级标记语言,扫一眼即可轻松 Parse 是其一大劣势,一旦混入重量级的 HTML 则可读性大打折扣。
这毛病太多,所以我决定还是得用 Markdown 的形式来做。
GitLab Flavored Markdown
GitLab Flavored Markdown(下称 GFM)是 Markdown 的一种修改版,它复用了图片的语法,以扩展名来辨别媒体的类型,比方 ![label](foobar.mp4)
因为链接是 .mp4
结尾所以渲染为视频。
GFM 的反对也很宽泛,实现又简略,还有 GitLab 背书,天然也是个不错的抉择。
但它的毛病也很显著,强制了链接的文件名必须是视频罕用的扩展名,然而并不是所有链接都是如此,Twitter 的视频链接就没有扩展名。另外既然都批改了原始的 Markdown 语义,何不间接另起一个新语法呢?
本人编个语法
对于自定义的语法有很多探讨,我认为比拟好的一种是应用通用指令语法,它的格局是 @< 指令类型 >[...](..){...}
这样的,后面的 @能够换成别的,指令类型用于辨别视频、音频、GIF 视频等,前面三个括号里的内容能够自由发挥。
最终我决定应用这种语法,它跟原生的图片语法一样简洁,又给足了自由发挥的余地。
通常来说,新的语法最好还是跟现有的放弃类似,这里就以语法比拟像的图片为基准。圆括号依然跟图片一样蕴含视频的链接,方括号里填标签(GIF)或者 poster(视频)。
通用指令语法里,花括号用来搁置 key = "val"
这样的键值对,但它们同样能够放在链接 URL 的参数上,而且目前图片就是这么做的,为了保持一致,我抉择不要这个花括号局部。
指令类型蕴含 GIF 视频和一般视频,另外 Markdown 同样不反对插入音频这里也给补上,所以最终的语法为:
@audio[](音频链接)
插入一个音频。@gif[标签](视频链接)
插入视频,并尽可能模拟 GIF 图。@video[视频封面](视频链接)
插入一般视频。
解析器的实现
我的博客应用 markdown-it 来转换 Markdown 为 HTML,markdown-it 的流程分为解析和渲染两局部,所以要给这两个中央编写本人的函数实现。
首先是怎么辨认 @< 指令类型 >[...](..)
这种文本呢,如果不思考本义的话倒是一个正则就能搞定,但问题是如果标签里呈现了方括号,或者链接里有圆括号咋办?当然是要本义了,Markdown 对括号的本义形式有两种:配对计数和斜杠本义,其中配对计数须要一个变量来存储左括号数量挺麻烦,而且斜杠本义齐全能用于所有场景,但反过来配对计数却无奈用于右括号独自呈现的状况(尽管不常见)。
综上所述,我决定不反对计数了,斜杠本义用一个前向环视 (?<!\\)
就能解决,再给指令局部加点限度,最初的正则如下:
- 指令局部:
([a-z][a-z0-9\-_]*)
- 标签局部:
\[(.*?)(?<!\\)]
- 链接局部:
\((.*?)(?<!\\)\)
把它们三个连起来就能够匹配通用指令语法啦。
Markdown 有块 block
和行内 inline
两种构造,原始的图片语法是属于行内的,这能够实现图文混排,但在应用中发现我并没有图文混排的需要,我博客里的图片都是独自一行。所以我决定新的语法作为块构造,这样能够升高解析函数被调用的频率,晋升点性能。
最初要留神一下的是反本义和 XSS 查看,这些函数在 markdown-it 库里已有提供。
解析器代码见 kaciras-blog/web-server/packages/server/lib/markdown-media.ts
不同的渲染指标
Markdown 渲染进去的 HTML 是跟场景相干的,比方在 RSS 里渲染的后果应尽量简略,毕竟阅读器的款式是没法由我来管制的;而在我的博客网站里,会有一些额定的款式和元素来展示更好的成果,比方提前固定宽高比避免布局挪动、居中等。
在我的博客,GIF 视频通过暗藏控制面板、静音、给上面加标签、以及 IntersectionObserver 实现的自动播放 / 暂停,实现了跟 GIF 图片一样的成果。另外因为 RSS 阅读器不会加载我的博客的样式表,也不会运行 JS,所以 RSS 阅读器里的 GIF 视频只能跟一般视频一样。
除了这俩之外,我还筹备让评论零碎也应用 Markdown(暂未实现),这又是一个新的渲染指标,用户评论属于第三方输出,对其的渲染必须退出一些限度以防滥用。
对无法控制的前端,渲染实现跟解析器写在一起,见下面的链接。
我博客的渲染实现见 kaciras-blog/website/blob/master/src/markdown/media.js
最终成果
SegmentFault 不反对插入视频,所以这里展现不了,能够去我的博客里看成果:
https://blog.kaciras.com/article/18/add-video-support-to-markdown# 最终成果