まるでWordpress? Editor.jsを試してみる インラインツール作成編

こんにちは コバヤシです。
今回は以前ブログで記事にしたEditor.jsでインラインツールを作成してみました。

tech.arms-soft.co.jp

インラインツールとは

インラインツールとは、テキストのブロックで文字を選択した時に出るツールのことです。
標準で太字にしたり斜体にしたり、リンクを設定できたり出来ます。
これらのツールにオリジナルのツールを追加していきます。

インラインツールを作成する

今回はツールボタンを押したら、選択した部分の文字を削除する簡単なツールを作りたいと思います。 まずプラグインのベースとなるファイルを作成します。

test.js

export default class Test {
    static get isInline() {
    }

    render() {
    }

    surround(range) {
    }


    checkState(selection) {
    }
}

isInline、render、surround、checkStateのメソッドが最低限あればOKです。

isInline

プラグインがインラインツールかどうかの判定に使用します。
インラインツールの場合はtrueを返却するようにします。

render

ツールに表示するボタンを返却します。

surround

範囲選択された状態で、ツールボタンがクリックされた時の処理を記述します。

checkState

状態の判定に使用します。 trueを返却するとツールがONの状態で、falseであればOFFの状態です。 今回はステータスでの制御は行わないのでcheckStateはとりあえずtrueを返却しておきます。

それでは、処理を記述していきます。

まずはボタンを表示します。

export default class Test {

    constructor({api}) {
        this.api = api
    }

    static get isInline() {
        return true
    }

    render() {
        const button = document.createElement('button')
        button.type = 'button'
        button.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="16" viewBox="0 0 199.997 200"><path d="M235.177,4027.791l38.549-38.552,83.632-83.63-77.816-77.818-83.632,83.635-38.549,38.549Zm31.834-45.265L235.735,4013.8l-64.386-64.392,31.274-31.274Z" transform="translate(-157.361 -3827.791)"/></svg>'
        return button
    }

    surround(range) {
    }


    checkState(selection) {
        return true // 今回はステータスでの制御は行わないので、とりあえずtrueを返却しています
    }
}

このままだとボタンが押されている状態になっているので this.button.classList.add(this.api.styles.inlineToolButton)でボタンにクラスを適用します。

export default class Test {

    constructor({api}) {
        this.api = api
    }

    static get isInline() {
        return true
    }

    render() {
        const button = document.createElement('button')
        button.type = 'button'
        button.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="16" viewBox="0 0 199.997 200"><path d="M235.177,4027.791l38.549-38.552,83.632-83.63-77.816-77.818-83.632,83.635-38.549,38.549Zm31.834-45.265L235.735,4013.8l-64.386-64.392,31.274-31.274Z" transform="translate(-157.361 -3827.791)"/></svg>'
        this.button.classList.add(this.api.styles.inlineToolButton)
        return button
    }

    surround(range) {
    }


    checkState(selection) {
        return true
    }
}

これでボタンの表示はOKです。
次に文字を削除する処理を書いていきます。

export default class Test {

    constructor({api}) {
        this.api = api
    }

    static get isInline() {
        return true
    }

    render() {
        const button = document.createElement('button')
        button.type = 'button'
        button.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="16" viewBox="0 0 199.997 200"><path d="M235.177,4027.791l38.549-38.552,83.632-83.63-77.816-77.818-83.632,83.635-38.549,38.549Zm31.834-45.265L235.735,4013.8l-64.386-64.392,31.274-31.274Z" transform="translate(-157.361 -3827.791)"/></svg>'
        button.classList.add(this.api.styles.inlineToolButton)
        return button
    }

    surround(range) {
        const selectedText = range.extractContents()
        selectedText.textContent = ''

        range.insertNode(selectedText)
    }


    checkState(selection) {
        return true
    }
}

range.extractContents()で選択された文字のオブジェクトが取得できるので、textContentプロパティに空文字をセットすることで文字を削除します。
あとはrangeのinsertNodeで入れてあげれば完了です。
(本当はタグで囲まれていた時の処理も必要ですが今回は省略しています。)

まとめ

APIもあり公式のドキュメントも充実しているので、 簡単に作成することが出来ました。
次はもう少し複雑なカラーピッカーのようなものを作れたらと思っています。