🗒

markdown editor 【milkdown】をsvelteで実装してみた

2023/04/04に公開

はじめに

WYSIWYG マークダウンエディタ「milkdown」を svelteで試してみたので、軽くですが紹介できたらと思います。
下記もざっくり説明しております!

  • プラグインの実装
  • 初期値設定
  • 値挿入
  • 取得

mikldownの紹介

milkdownは、WYSIWYGマークダウンエディタの一つで、TypeScriptで書かれたオープンソースのエディタです。
リポジトリ
https://github.com/Milkdown/milkdown
ドキュメント
Milkdown

Milkdown

The plugin based WSIWYG markdown editor framework.

1. 必要なものをインストールする

下記の3つをyarn add してinstallしてください (npm でも可)

$ yarn add @milkdown/core
$ yarn add @milkdown/preset-commonmark
$ yarn add @milkdown/theme-nord

インストールできたらscriptの中でimport

import { Editor, rootCtx } from '@milkdown/core';
import { commonmark } from '@milkdown/preset-commonmark';
import { nord } from '@milkdown/theme-nord';

2. editorを挿入するdomを生成

空のdomを生成して変数に代入しておく
※initializeEditorについては次の工程で説明します

  let editorElement = null;
  
  $: {
    editorElement;
    if (editorElement) {
      initializeEditor(editorElement);
    }
  }

<div bind:this={editorElement}></div>

3. editorインスタンス生成

先ほど生成したdomをsetに渡せば完成です!

 const initializeEditor = (element) => {
    Editor.make()
      .config((ctx) => {
      ctx.set(rootCtx, element);
      })
      .config(nord)
      .use(commonmark)
      .create();
  };

プラグインを追加

ここからは応用になります

必要なプラグインをインストール
不要なものは消してからyarn addしてください!

$ yarn add @milkdown/plugin-emoji @milkdown/plugin-menu @milkdown/plugin-slash @milkdown/plugin-history @milkdown/plugin-prism @milkdown/plugin-tooltip @milkdown/plugin-indent @milkdown/plugin-trailing @milkdown/plugin-upload @milkdown/plugin-cursor @milkdown/plugin-clipboard @milkdown/plugin-listener

プラグインの説明とインポート

現状、知ってるもの && 使えたもの だけ記載しています、ご了承ください🙇

  // 大きな絵文字が使えるようになります
  import { emoji } from '@milkdown/plugin-emoji'
  // 上部にmenuが出ます (※ バージョンが6.5.4までしかサポートしていないので注意)
  import { menu } from '@milkdown/plugin-menu'
   // ⌘ + Z や ⌘ + shift + Z で進む戻るができるようにする
  import { history } from '@milkdown/plugin-history'
  // コードブロックをハイライトできるようになる
  import { prism } from '@milkdown/plugin-prism'
  // コピー/ペーストの操作をサポートするものらしいです
  import { clipboard } from '@milkdown/plugin-clipboard'
  // タブでインデントができるようになります
  import { indent } from '@milkdown/plugin-indent'
  // 画像をドラッグ&ドロップするとbase 64で uploadされます
  import { upload } from '@milkdown/plugin-upload'
  // eventをtriggerできるようになります
  import { listener, listenerCtx } from '@milkdown/plugin-listener'

プラグインを読み込ませる

このような感じでcreate時にuseに渡せば使えるようになります!

  const initializeEditor = async (element) => {
    editor = await Editor.make()
      .config((ctx) => {
        ctx.set(rootCtx, element);
        ctx.set(defaultValueCtx, defaultValue);
      })
      .config(nord)
      .use(commonmark)
      .use(history)
      .use(indent)
      .use(upload)
      .use(cursor)
      .use(clipboard)
      .use(gfm)
      .use(listener)
      .create();
  };

スタイルについて

見た目を綺麗にしたい方向けです!

  1. tailwindcssをインストール
$ yarn add --dev tailwindcss
  1. typography pluginを有効にする
 @tailwindcss/typography plugin
  1. cssをimport
  // tailwindcss用
  import '@milkdown/theme-nord/style.css'
  // テーブル用
  import 'prosemirror-tables/style/tables.css'

初期値の設定方法

  1. デフォルトの値を変数に入れる
  let defaultValue = '# Hello milkdown';
  1. coreからdefaultValueCtxをimport
  import { defaultValueCtx } from '@milkdown/core';
  1. createする時にsetする
    editor = await Editor.make()
      .config((ctx) => {
        ctx.set(defaultValueCtx, defaultValue);
      })
      .create();

テーブルについて

  • |3x3|と入力してenterを押すと生成できます(N x N)
    Image from Gyazo

値の取得

editorの値をmarkdownで取得する関数

  // 値を取得
  const getMarkdown = () => {
    return editor.action((ctx) => {
      const editorView = ctx.get(editorViewCtx);
      const serializer = ctx.get(serializerCtx);
      return serializer(editorView.state.doc);
    });
  };

値の挿入

  • cursorがある箇所に挿入されます
  • 文字選択中の場合、insertしたvalueと置き換わる挙動になります
  • ##などをinsertした場合 h2入力モードになります
  // 値を挿入
  const insertValue = (value) => {
    editor.action(insert(value));
  };

完成

少しスタイルは異なりますが、完成するとこんな感じになります!
Image from Gyazo

装飾コマンドについて

下記画像のような装飾コマンドは解説はこちらの記事で紹介しておりますので、toolbarの実装したい場合はご一読ください
https://zenn.dev/rabee/articles/milkdown-inlinecommands-svelte
Image from Gyazo

最後に

上記は、おおまかなプラグインと生成するところまでですが、プラグインでtooltipやslashコマンドなどもありますので是非調べて追加してみてください!

Discussion