🐭喂汁,用Python寫個專屬Markdown轉換工具

  • 慚愧,兩個多月沒更文,掘金域名都從juejin.im遷移到juejin.cn了;
  • 近況,孺子牛依舊,寫Android基礎業務寫到有些麻木了,技術不進反退;
  • 忙裏偷閒,偶爾公號詐屍更新一兩篇Python爬蟲教程,有個困擾許久的問題 → 文章排版

0x一、需求分析

一直使用 Markdown 語法編寫文章,而後用Markdown轉換工具轉換下,經常使用的工具備:css

轉換後的文章樣式(以Md2All爲例):html

還行,簡潔夠用。但,人老是很難知足於現狀,三個誘因讓我有了改變的念頭:git

  • 工具畢竟不是開源的,你用別人也用,樣式爛大街,都是改改顏色,替換圖片、審美疲勞;
  • 老弟給我安利的公號編輯插件,如新媒體管家(已涼),壹伴助手,秀米,13五、小螞蟻等;

做爲漆黑中的螢火蟲,怎甘平平無奇,因而花了點時間,來定製本身的文章排版~github

在參(chao)考(xi)完多個公號後,整理了本身的公號排版規範,有須要的能夠參考一波~微信

# 字號:正文(1四、15),註釋-標註來源-超連接-代碼(12)
# 字間距:(一、1.5)
# 行間距:(1.五、1.7五、2)
# 頁邊距:即雙端縮進、兩端對齊,頁面左右留白,建議縮進尺寸爲1.0

# 字體顏色:標題 #000000;正文 #4C4C4C;標註 #888888;其餘 #B2B2B2
# 正文也能夠嘗試:#545454;#3f3f3f;#7f7f7f;#2f2f2f
# 備註性文字:#a5a5a5

# Tips:除去字體顏色,公號排版顏色不宜超過三種,顏色一旦多起來,風格就很難定,2-3種尤佳;
# 好比個人三種顏色:蕾姆藍#5A78EA;拉姆粉#FF4081;艾米莉亞:#C65BDA

# 符號系統:創建本身的符號系統,用做內容分割,好比用//////////做爲正文大段落的分隔,- 做爲段落小結的分隔,有時還可使用一些表情符號來增長趣味性:http://cn.piliapp.com/symbol/

# 無論怎麼排,要有本身固定的設置,如:段落和圖片間空2行、圖片大小控制在一屏版面的1/3面積內、一個段落不超過3行字、每當一屏版面文字太滿時,拆解段落作分段或作一些highlight製造空間感等。

# 總而言之,儘可能利用 簡單的基礎設置 去優化閱讀體驗,讓總體排版看起來簡潔但有序、不密集、不沉重、不壓抑。

# 採用固定格式的公號封面圖!!! 
# 固定版式造成強烈的我的特點,製做新的封面圖只需置換文字和圖片,好看又方便。
複製代碼

具體效果能夠看下:mp.weixin.qq.com/s/why-ikTbb…markdown

大概的樣式,其實就下面這幾種:app

而每次寫完文章,想發佈到公號,我須要這樣:編輯器

複製文章內容()
無格式粘貼到公號文章編輯處()
for(其中一行:全部內容) {
    when(其中一行) {
        is 一級標題 → 應用一級標題樣式
        is 二級標題 → 應用一級標題樣式
        is 正文 → 應用正文樣式
        ...
    }
}
複製代碼

機器重複,費事費力費神,特別是表格複製粘貼,使人絕望,文章內容多的時候,得花上半把小時,熱情也被消磨殆盡... 迫切需一種工具,幫我跳出這樣的困境,不能全自動,也要儘量減小我花在排版上的時間。函數

0x二、工具設計

轉換工具的核心:→ 解析Markdown文件對特定類型元素進行渲染生成HTML文件工具

這裏的渲染,其實沒那麼高深,以 Md2All工具爲例,輸入:# 一級標題

點擊複製,而後隨便貼到一個IDE,保存爲.html後綴,格式化一下:

由於微信公衆號文章不支持CSS和JS(不過支持SVG),因此只能在HTML標籤裏寫內聯樣式。 因此,這裏的渲染其實只是:當解析到特定類型元素時,替換成對應的帶內聯樣式的HTML代碼

因此,想寫這樣的工具,要點就是:

  • ① 解析Markdown,能對不一樣類型的元素作區分;
  • ② 各類帶有樣式的HTML代碼;

先是解析Markdown的問題,秉着有輪子就不本身造的精神,直接搜關鍵字Python MarkDown解析,在衆多的庫中選擇了mistune

而樣式HTML的獲取,就簡單多了,善用Chrome開發者工具的Elements便可,好比:

看上的樣式,直接偷,勸那種用爛大街轉換工具的年輕人 耗子喂汁~

固然,獲取到的樣式可能還須要微調下,接着到工具開發環節~

0x三、我啪的就站起來了,很快嗷

上面也說了,使用渾元功法(mistune),來解析Markdown,簡要介紹下此庫:

直接用pip命令安裝一波:

pip install mistune==2.0.0a4
複製代碼

用法也很簡單,寫個簡單的Demo體驗體驗:

默認渲染樣式顯然不能知足咱們的需求,須要自定義渲染器,定義一個渲染器 mistune.HTMLRenderer 的子類,重寫相應的函數便可。一樣寫個簡單例子,以#、##的解析爲例:

運行輸出結果以下:

接着塞到文章編輯器裏驗證下,微信不支持粘貼源碼,藉助開發者工具,定位到正文元素,右鍵選中:

粘貼一波:

回到編輯器看下效果:

能夠,跟預期一致,大概玩法就這樣,接着就是具體邏輯的細化及優化了。更多渲染器中可供重寫的函數能夠參見下述連接: mistune.readthedocs.io/en/latest/a…

0x四、松果彈抖閃電鞭

接着是記錄開發此工具的細節,有興趣想自定義的能夠借鑑一波,不感興趣的直接跳過用成品亦可,後續會慢慢更新一些主題,也歡迎投稿~

① 一鞭 → 樣式採集示例

由於用的壹伴助手插件,複製元素的時候帶了點沒用的東西:

有些潔癖,寫個正則清洗一下:

清洗完:

強迫症做祟,格式化下代碼,這裏用的lxml,你也能夠用BeautifulSoup或者其餘:

看下效果:

能夠,溫馨感up↑,後續採集到的樣式,先放這個池子裏清洗一下,再用,也可添加新的過濾規則。

樣式搞到手了,接着就該想一想怎麼存了,總不能像Demo那裏同樣,複製一堆字符串吧。繁冗不說,複用性也差,這裏引入模板的概念,將每一個樣式保存成單個html,用到傳參渲染,此處使用jinja2模板庫

pip命令安裝一波:

pip install Jinja2
複製代碼

接着把文本部分,替換成一個變量text:

再接着使用jinja2獲取模板並渲染:

輸出結果以下:

能夠,很強,關於Jinja2的具體用法可參見:

建立模板,使用模板渲染的流程就這樣,接下來演示下每種樣式的具體獲取過程。

② 兩鞭 → 標題、粗體、段落

h3和h2相似,都是直接將樣式文本替換爲{{text}}

h4稍微麻煩一點,由於前面還傳多一個順序參數:

接着重寫heading函數,根據不一樣的level進行渲染:

接着傳入下述mardown字符串:

運行,把渲染後的HTML貼到微信編輯器校驗下:

能夠,效果是針不戳,爾後是粗體及段落樣式:

運行後,把生成的樣式貼到公號編輯器康康效果:

擦,換行全沒了,緣由是:微信會自動濾除文本結點中的\n換行符。 一個簡單的解決方法就是:在渲染段落文本時,將\n替換爲<br>

修改下渲染處邏輯:

校驗下效果:

③ 三鞭 → 表格、列表

表格的話直接用的微信編輯器自帶的表格,樣式以下:

對應代碼以下:

mistune需啓用plugin_table工具,才能解析表格,提供了下述可供覆蓋的函數:

寫個簡單的demo試試康:

能夠看到table_head中獲取到了表頭的文本結構,其餘幾個函數一樣可得到不一樣部位的表結構。

可是,我最後仍是選擇了重寫table()函數,由於表格的渲染是連貫的,若是每一個函數單獨渲染,最後塞到一個<table>裏很是麻煩。

另外,公號大多時候是在手機上閱讀,屏幕寬就那麼點,通常建議兩列的表格,這裏我另外定義一個類Cell:

先來編寫模板吧,預期是傳入 表頭列表表內容列表,而後遍歷渲染:

模板弄完,接着就是數據處理了,提取表頭及表內容,塞到列表中,打印下text:

嘔吼,直接用lxml提取一波:

丟個測試markdown進來:

複製生成樣式至編輯器,檢驗下效果:

能夠,舒服,而後是無序列表,也是使用編輯器自帶樣式:

摳出模板:

重寫函數渲染模板:

傳參校驗:

Tips:把渲染後的HTML貼到編輯器處,空白處按下回車,無序列表才能正確縮進!

④ 四鞭 → 圖片、連接

這裏有個坑要注意下,筆者再這裏卡了好一段時間,手滑按了tab縮進:

渲染後的代碼:

這裏是被當成代碼塊處理了,改成沒縮進,或一兩個空格縮進就能夠了。 一樣,摳出樣式模板:

重寫函數渲染模板:

這裏也有個坑,mistune中會把每一行都當作段落,而後把在這個上面又套一層樣式,因此還須要修改下段落渲染函數:

傳參校驗:

效果以下:

⑤ 五鞭 → 代碼高亮、引用、行內代碼

代碼塊的渲染亦稱代碼高亮,看了網上大部分轉換工具,使用的都是使用 highlight.js,樣式多多: highlightjs.org/

這裏是Python,直接調js渲染有些麻煩,這裏使用 pygments代碼高亮庫 來替換,樣式及預覽可到下述連接挑選: pygments.org/demo/

pip命令安裝一波庫:

pip install Pygaments
複製代碼

使用方式也很簡單:

參數簡述:

  • noclasses=True:設置不生成css文件,即便用HTML內聯樣式;
  • style='perldoc':設置主題;
  • wrapcode=True:使用<code>包裹渲染後的代碼;

複製到編輯器看下效果:

這裏坑可多着呢,羅列下:

  • ① 代碼超過屏幕,沒有顯示橫向滾動條,需添加 overflow-x: auto;
  • ② 字體大了,設置12px爲佳,要爲每一個span標籤的style屬性添加 font-size: 12px;
  • ③ 以下圖,代碼中的部分字符串沒有用span包裹,大小不一,需外層套一個span包裹;

此處使用lxml操做節點元素增刪及屬性修改,具體代碼以下:

傳參校驗:

字體大小和滾動條都出來了,看似沒啥問題了,但若是你點擊手機上預覽:

臥槽,全亂了,有些代碼擠在一行上了,歸根到底仍是換行符\n被微信吃了唄,看了下其餘工具的作法:

添加 → white-space:nowrap,指定文本不換行,直到遇到<br>爲止。

因此咱們須要在合適的地方插入<br>標籤,就在lxml解析前加吧:

看下手機上的效果:

換行卻是換行了,就是前面的縮進沒了,看了下別的工具的作法:

前面加上縮進對應數量的&nbsp;

因此,還須要統計每行前面的空格,補上對應數量的&nbsp;

看下手機上的效果:

好傢伙,能夠了,也算是把代碼塊的坑都踩完了!

而後把引用的樣式也補上吧:

傳參校驗:

最後,把行內代碼的樣式也補上

傳參校驗:

經常使用結點的解析渲染就講解到這裏,而後就是全文渲染的微調了,換行,各類解析衝突處理啊,限於篇幅,就不一一講解了,能夠參考倉庫中的最新代碼。

0x五、傳統功夫以點到爲止

正文的渲染就這樣,另一般公號喜歡每一篇都加上一個特定的頭部和尾部,這個簡單,直接偷兩個樣式保存成html模板,正文渲染完後,拼接便可,寫下簡單示例吧:

點擊預覽,手機看下效果:

效果仍是很讚的,踩N多坑+寫文,總耗時三天,終於把這個工具的雛形作出來了;
儘管它還不完整,不是很人性化,目前只有一個主題,還有各類未知的BUG,雞動,久違的成就感;
歡迎各位大佬試用,提建議,提issues,丟主題公號,慢慢完善這個小的 生產力工具,謝謝~

倉庫地址github.com/coder-pig/h…

相關文章
相關標籤/搜索