於Markdown文件highlight程式語言

整合 markdown-it + highlight.js + react-markdown-editor-lite with React。補充:加入 markdown-it-checkbox 以增加呈現Checkbox的能力。

參考

為何要用Markdown

Markdown是一個新的文件呈現或展示的一套表示語法。可以參考維基百科-Markdown介紹。總之,相對直接用HTML編寫文件,Markdown就是簡單又易用且CP值超高。不過若要寫高精度又高客製化的文件那Markdown不適合;若要快速寫出段落明確內容清析的靜態文件那Markdown是現在為止個人認為最好的選擇。

開發Markdown Editor/Viewer

因為Markdownd文件是唯讀的,所以在它的編輯設計一般都是分割成雙畫面,一邊是原始本文一邊是預覽。現在的Markdown的基礎元件已相當的完整只要引進來即可。本人選取了三個元件如下:

markdown-it 為此應用的核心元件,用來解析Markdown的原始本文並產生相應的Html代碼以呈現在UI上。

highlight.js 輔助用途。因markdown-it本身沒有highlight能力,所以要額外加裝此模組。一般應用於highlight程式語言段落。

react-markdown-editor-lite 為Markdown本文編輯器的外殼介面,所以要再鑲入Markdown模組才能作用。當然也有其它版本,只是現階段還不錯用。

markdown-it-checkbox 為Markdown加入checkbox 呈現能力。

markdown-it-link-attributes 為Markdown的Link強化設定屬性能力。如:target="_blank" rel="noopener"等。

整合 markdown-it + highlight.js

各項目如何使用,請參考各自的基本使用說明。把markdown-ithighlight.js整合起來的文件,前前後後不同時期不同版本(好煩吶)。總之,關鍵程式碼如下:

Syntax highlighting

var hljs = require('highlight.js') // https://highlightjs.org/

// Actual default values
var md = require('markdown-it')({
  highlight: function (str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return '<pre class="hljs"><code>' +
               hljs.highlight(lang, str, true).value +
               '</code></pre>';
      } catch (__) {}
    }

    return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>';
  }
});

整合 markdown-it + highlight.js + react-markdown-editor-lite with React

import React from 'react'
import MarkdownIt from 'markdown-it'
import hljs from 'highlight.js'
import 'highlight.js/styles/xcode.css'
import MdEditor from 'react-markdown-editor-lite'
import 'react-markdown-editor-lite/lib/index.css'

// Initialize Markdown parser
const mdParser = new MarkdownIt()
// Checkbox plugin
mdParser.use(require('markdown-it-checkbox'), {
    divWrap: true,
    divClass: 'cb',
    idPrefix: 'cbx_'
})
// link attributes
mdParser.use(require('markdown-it-link-attributes'), {
    attrs: {
        target: '_blank',
        rel: 'noopener'
    }
})
// Syntax highlighting
mdParser.options.highlight = (str, lang) => {
    if (lang && hljs.getLanguage(lang)) {
        try {
            return '<pre class="hljs"><code>' +
                hljs.highlight(lang, str, true).value +
                '</code></pre>'
        } catch (__) { }
    }

    return '<pre class="hljs"><code>' + mdParser.utils.escapeHtml(str) + '</code></pre>';
}

// Markdown UI
export default function MarkdownEditor ({ text, onTextChange }) {
    function handleEditorChange({ html, text }) {
        onTextChange(text)
    }

    return (
        <MdEditor
            value={text}
            style={{ height: "500px", marginTop: 8, marginBottom: 4 }}
            renderHTML={(text) => mdParser.render(text)}
            onChange={handleEditorChange}
        />
    )
}

較完整的程式碼在此

Last updated