26
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

超簡単にMarkdownエディタをWebページに実装可能な"SimpleMDE"

Posted at

もう平成も終わろうとしているのに未だ神Excel依存な弊社で、せめて所属部署、所属課だけでも良いのでMarkdownを使ってくれ...と思い、色々考えてました。

まず「Markdownは難しくない」と感じてもらう為に、エディタ/ビューアを用意しなければなりません。
しかし、いきなりVSCodeだのStackblitzだの言っても確実にコケると直感しました。

この手のは、とっつきで「難しそう」と感じられてしまったら確実に失敗するんですよね。

イントラにアクセスするだけで誰でも使える、Webページ埋込タイプのエディタが無いか探してたら、丁度良い物があるではないですか。

SimpleMDE

JavaScript/CSSの2ファイルをロードするだけで使える、お手軽Markdownエディタです。

つかいかた

SimpleMDE.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/simplemde@latest/dist/simplemde.min.css">
        <script src="https://cdn.jsdelivr.net/npm/simplemde@latest/dist/simplemde.min.js"></script>
    </head>
    <body>
        <textarea id="mde"></textarea>
    </body>
    <script>
        const mde = new SimpleMDE({
            element: document.getElementById("mde")
        });
    </script>
</html>

たったこれだけで立派なMarkdownエディタが実装出来ます。
ちょうど公式サイトの一番上のデモと同じ感じになります。

機能の追加/削除

素の状態でも十分使えるスグレモノですが .md ファイルの読込/保存やDataURLで軽量バイナリ埋込など、痒い所に手を届かせる自作の機能も追加可能です。

インスタンス生成時にオプション指定可能です。

new SimpleMDE({
    element: document.getElementById("mde"),
    toolbar: [
    ...,
    {
        name: "save", // 機能名
        action: saveHandler, // アクションハンドラ
        className: "fa fa-download", // アイコン
        title: "Save Markdown" // 説明
    }]
});

function saveHandler(editor){ // コンテキスト
    saveAs(new Blob([editor.value()]), "markdown.md");
    editor.codemirror.focus();
}

"ツールバー" が機能の実体なので、MixInを使って toolbar オプションに新しい機能を宣言することで追加可能です。
なお、MixInを使用しないと上書きになるので、BoldやItalicなどの基本的な機能も再宣言しなければなりません。

アイコンは FontAwesome の物が使えます。
ハンドラにはエディタのコンテキストが引数として渡されます。

エディタとプレビューのフォントを変えたい場合は、既存のCSSを上書きする事で可能です。

/* エディタ領域 */
.CodeMirror {
    font-family: "MigMix 1M";
}
/* プレビュー領域 */
.editor-preview,
.editor-preview-side {
    font-family: "M PLUS 1p";
}

/* プレビュー領域内コード */
.editor-preview code,
.editor-preview-side code {
    font-family: "Kosugi";
}

NotoSansやHiraginoなど、お好きなフォントを使ってください。
あ、僕はMigMixが好きです。

Tips: D&D(ドラッグアンドドロップ)対応

放り込みたくなりますよね。

// ウィンドウ全域でD&D禁止
addEventListener("dragover", (event)=>{
    event.preventDefault();
    event.dataTransfer.dropEffect = "none";
});
addEventListener("drop", (event)=>{
    event.preventDefault();
});

const dnd = document.getElementsByClassName("CodeMirror-scroll")[0];
// エディタ領域のみD&D許可
dnd.addEventListener("dragover", (event)=>{
    event.preventDefault();
    event.dataTransfer.dropEffect = "move";
});
dnd.addEventListener("drop", async(event)=>{
    event.preventDefault();
    mde.value(await fileReader(event.dataTransfer.files[0]));
    mde.codemirror.focus();
});

// ここら辺はお好みで
function fileReader(blob){
    return new Promise((res, rej)=>{
        const fr = new FileReader();
        fr.addEventListener("load", () => res(fr.result));
        fr.addEventListener("error", () => rej(fr.error));
        fr.readAsText(blob);
    });
}

これでエディタ領域のみD&Dが可能となります。

Tips: ファイルピッカー呼出

ツールバーにファイル入力を設けたいとき。
もはやHTML初心者講座になってる気がしないでもないですが、とりあえず書いときます。

// Toolbar アクションハンドラ
async function loadHandler(editor){
    editor.value(await filePicker().then(b => fileReader(b)));
    editor.codemirror.focus();
}

function filePicker(){
    return new Promise((res)=>{
        const input = document.createElement("input");
        input.type = "file";
        input.id = "file";
        input.style.display = "none";
        document.body.appendChild(input);

        const file = document.getElementById("file");

        file.addEventListener("change", function fn(event){
            input.removeEventListener("change", fn);
            document.body.removeChild(file);

            res(event.target.files[0]);
        });

        file.click();
    });
}

本当は once: true オプションを使いたいのですが、神Excelが横行してるような職場のブラウザシェアを考えるとね...

26
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?