基于Flask的Markdown編輯器實踐

Markdown編輯器——Editor.MD于Flask:

能預(yù)覽的Markdown編輯器中, 讀狗書時用的Flask-Pagedown比較不錯, 在逛知乎的時候?qū)W習greyli大神的flask富文本編輯器實現(xiàn)退腥,實踐中遇到 Editor.md很合胃口, 類似簡書或者 Remarkable的左右分欄預(yù)覽方式非常喜歡软舌,見坑就跳吧灿渴。

最終效果大概是這樣的:

11?22?18_7.png

Editor.md是個國人維護的開源項目, 四年沒更新不過還是很好用的譬嚣。相關(guān)Issues比較多庭再,基本上小問題翻翻即可解決,

首先進入Editor.md官網(wǎng)下載zip,或者點擊Github download下載

解壓重命名為editormd际起,并置入static文件夾

表單類里使用Flask-WTF設(shè)置<textarea>標簽存放文章內(nèi)容, 定義TextAreaField字段, 對Body字段進行修改:

forms.py:

from wtforms import TextAreaField
#...

class PostForm(FlaskForm):
    #...
    body = TextAreaField('Body', [DataRequired()])
    #...

此時編輯模板的js腳本, 用于拾取id=editormd的 textarea 渲染的

這真的是一個坑大的決定悍缠,相關(guān)探究并無太多參考,Editor.MD已經(jīng)荒廢四年姑荷,相關(guān)文檔都未必打得開盒延,基本都是Java做后端,F(xiàn)lask上幾乎沒人用鼠冕。相關(guān)討論比較雜亂添寺,甚至有的錯漏百出⌒阜眩基本只能靠踩坑和閱讀源碼來運作计露。目前還在艱苦奮斗階段,有能力后會編寫相關(guān)拓展憎乙。

為便于支持更多的MarkDown格式甚至emoji代碼高亮表格解析等問題票罐。而不是一點點自定義,這次我們利用更強大的Editor.MD編輯自帶的Markdown2HTML渲染方式泞边。

new_post.html:

<link rel="stylesheet" href="{{ url_for('static',filename='editormd/css/editormd.css') }}"/>

這里我將Editor.MD置于static靜態(tài)文件目錄并重命名為editormd该押,個人根據(jù)目錄自行更改即可。


使用saveHTMLToTextarea : true字段開啟自動轉(zhuǎn)換HTML為后臺直接提取html文檔提供接口繁堡。其中js代碼處注意寬度設(shè)置與Bootstrap4的body相沖突沈善,這里我們注釋掉width字段,否則將無法直接提取html椭蹄。如果是繼承模板闻牡,引入js較多時,可以在js的順序上優(yōu)先保證editor.MD绳矩,上下文在最后繼承

new_post.html:

<script src="{{ url_for('static',filename='editormd/examples/js/jquery.min.js') }}"></script>
<script src="{{ url_for('static',filename='editormd/editormd.min.js') }}"></script>
<script type="text/javascript">
    $(function () {
        editormd("fancy-editormd", {
            // width: "100%", 請不要添加
            height: 640,
            syncScrolling: "single"罩润,
            path: "{{ url_for('static',filename='editormd/lib/') }}",
            saveHTMLToTextarea : true
        });
    });
</script>
 {{ super() }}

結(jié)尾scripts段加載JS:順序為jQuery在前, editormd.min.js在后.

相關(guān)的textarea部分 new_post.html:

<div id="fancy-editormd" class="editormd">
{{ form.body(style="display:none;") }}
</div>

在編輯文章的部分也照做即可。
其中的"fancy-editormd"字段是自定義的翼馆,用于拾取textarea
這里有個坑割以,如果使用WTForms渲染表單的話name屬性是無法更改的金度,而editormd理論上是通過name=“fancy-editormd-markdown-doc"屬性來渲染我們編輯markdown文件的地方
這里不用擔心太多,如果沒有多個textarea的話严沥,其實我們只需要照常渲染formbody即可猜极,再次渲染時可見Editor.MD會自動找到第一個textarea并渲染為markdown編輯器,并自動為我們生成了一個textareaname=”fancy-editormd-html-code"里面內(nèi)容即是Editor.MD的HTML文件消玄。

11?22?18_1.png

這里我們將其保存下來跟伏,以便歸檔查看以及預(yù)覽方便節(jié)省資源。如果正文渲染的話還是建議用markdown即時轉(zhuǎn)換這樣表格和特殊內(nèi)容更加直觀翩瓜,當然如果服務(wù)器并發(fā)訪問過多的話并不建議這么做受扳。

首先在Forms中我們自定義一個body_html用于保存撰寫文檔時Editor.MD留下的HTML格式文檔:
forms.py:

class PostForm(FlaskForm):
  #...
  body_html = HiddenField()

添加一個實例化數(shù)據(jù)庫模型字段的Column類在文章模型中,注意如果使用Flask-Whooshee全文搜索的話建立索引字段改為我們的html格式文檔兔跌,還好注意而后使用reindex()方法重建索引勘高。(目前文檔較少做了搜索也沒用,而后會單獨列出文章做詳細討論):

models.py:

@whooshee.register_model('title', 'body_html')
class Post(db.Model):
    #...
    body_html = db.Column(db.Text)

在文章管理藍本中直接使用request來獲取數(shù)據(jù)坟桅,不使用WTForms

admin.py:

from flask import request
# ...
@admin_bp.route('/post/new', methods=['GET', 'POST'])
@login_required
def new_post():
    if form.validate_on_submit():
        # ...
        body_html = request.form['fancy-editormd-html-code']
            post = Post(..., body_html = body_html)
            #...

同樣在編輯文章的藍本中也要做相應(yīng)的修改:

@admin_bp.route('/post/<int:post_id>/edit', methods=['GET', 'POST'])
@login_required
def edit_post(post_id):
# ...
if form.validate_on_submit():
        # ...
        post.body_html = request.form['fancy-editormd-html-code']
        # ...
    # ...
form.body_html.data = post.body_html
# ...

此時我們要編輯的都編輯完了华望,在文檔正部直接調(diào)用轉(zhuǎn)換好的html即可,加個safe過濾器即可
{{ post.body_html| safe }}
當然代碼高亮以及表格支持這些等等桦卒,想要顯示出編輯時右邊的預(yù)覽的效果立美,還是需要調(diào)用Editor.MD的渲染,在文章正文的模板里做相應(yīng)的修改:
引入靜態(tài)文件方灾,

    <link href="{{ url_for('static', filename='editormd/css/editormd.preview.min.css') }}" rel="stylesheet" />  
    <link href="{{ url_for('static', filename='editormd/css/editormd.css') }}" rel="stylesheet" /> 
    <!--以下是js部分 -->
    <script type="text/javascript" src="{{ url_for('static', filename='editormd/lib/marked.min.js') }}"></script>
    <script type="text/javascript" src="{{ url_for('static', filename='editormd/lib/prettify.min.js') }}"></script>
    <script type="text/javascript" src="{{ url_for('static', filename='editormd/editormd.min.js') }}"></script>
    <script type="text/javascript">
        editormd.markdownToHTML("fancy-content");
    </script>

在文檔中定義我們自定義的fancy-content

<div class="content" id="fancy-content">
            {{ post.body_html| safe }}
</div>

這里無需使用post原文建蹄,無需定義textarea,直接用flask-WTF的定義表單即可裕偿,直接使用html文件即可洞慎。

沒有引入Editor.MD的渲染表單:

11?22?18_2.png

渲染后:


11?22?18_3.png

再對比編輯欄效果:

11?22?18.png

在文章預(yù)覽處我們做相應(yīng)的修改,
_post.html :

<h3 class=`text-primary`><a href=`{{ url_for('.show_post', post_id=post.id) }}`>{{ post.title }}</a></h3>
    <p>
        <div class=`post-body`>
            {% if post.body_html %}
                {{ post.body_html |safe|striptags|truncate }}
            {% else %}
                {{ post.body }}
            {% endif %}
        </div>
        <small><a href=`{{ url_for('.show_post', post_id=post.id) }}`>Read More</a></small>
    </p>

先調(diào)用safe轉(zhuǎn)義過濾器, 再調(diào)用striptags清除html渲染后的格式, 最后調(diào)用truncate過濾器只保留開頭255個字符,而后慣例一個Read More鏈接.

如果使用了Flask-Migrate的Alembic話,創(chuàng)建遷移環(huán)境生成遷移腳本更新數(shù)據(jù)庫三部曲即可嘿棘。由于數(shù)據(jù)庫已經(jīng)從SQlite遷移到了MySQL劲腿, 一切都沒什么。生產(chǎn)環(huán)境還是先備份以下


目前來說Markdown于Flask的實現(xiàn)應(yīng)該是打好了基礎(chǔ). Editor.md的界面比較討喜, 相比其他富文本編輯器更加受青睞. 關(guān)于Editor.md的進階功能還有許多, 日后需要還會繼續(xù)添加.至此鸟妙,Editor.MD的回調(diào)已經(jīng)完成了焦人。在下篇里我會談一下圖片上傳的問題。

個人是新入門的求職學生重父,歡迎大家指教

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末花椭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子房午,更是在濱河造成了極大的恐慌矿辽,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異袋倔,居然都是意外死亡雕蔽,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門宾娜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來批狐,“玉大人,你說我怎么就攤上這事前塔〖窒荩” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵嘱根,是天一觀的道長。 經(jīng)常有香客問我巷懈,道長该抒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任顶燕,我火速辦了婚禮凑保,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涌攻。我一直安慰自己欧引,他們只是感情好,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布恳谎。 她就那樣靜靜地躺著芝此,像睡著了一般。 火紅的嫁衣襯著肌膚如雪因痛。 梳的紋絲不亂的頭發(fā)上婚苹,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機與錄音鸵膏,去河邊找鬼膊升。 笑死,一個胖子當著我的面吹牛谭企,可吹牛的內(nèi)容都是我干的廓译。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼债查,長吁一口氣:“原來是場噩夢啊……” “哼非区!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起攀操,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤院仿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體歹垫,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡剥汤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了排惨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吭敢。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖暮芭,靈堂內(nèi)的尸體忽然破棺而出鹿驼,到底是詐尸還是另有隱情,我是刑警寧澤辕宏,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布畜晰,位于F島的核電站,受9級特大地震影響瑞筐,放射性物質(zhì)發(fā)生泄漏凄鼻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一聚假、第九天 我趴在偏房一處隱蔽的房頂上張望块蚌。 院中可真熱鬧,春花似錦膘格、人聲如沸峭范。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纱控。三九已至,卻和暖如春菜秦,著一層夾襖步出監(jiān)牢的瞬間其徙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工喷户, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留唾那,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓褪尝,卻偏偏與公主長得像闹获,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子河哑,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容