LoginSignup
4
3

More than 3 years have passed since last update.

tiptapのコードブロックの下に空行を挿入する方法

Last updated at Posted at 2019-07-11
  • Vue: ^2.6.10
  • tiptap: ^1.23.1

tiptapを使っていて、困ったことがありました。
tiptapを使えば、ハイライト付きのコードブロックが簡単に実装できます。
しかし、挿入されたコードブロックからカーソルを外すには、command+Z(macだと)するか、コードブロック以外の要素をクリックするかしかないみたいでした。
これだと、エディト領域の一番下にコードブロックが作られた場合に不便です。
コードブロックが挿入されたら、その下に空行を挿入することで、上記の問題を解決したので、共有します。

editor.vue
<template>
  <div class="editor" style="width: 100%;">
    <editor-menu-bar :editor="editor" v-slot="{ commands, isActive }">
      <div class="menubar">

        <button
          class="menubar__button"
          :class="{ 'is-active-button': isActive.code_block() }"
          @click="startCodeBlock(commands, isActive)">
          <font-awesome-icon icon="code" />
        </button>

      </div>
    </editor-menu-bar>

    <editor-content class="editor__content" :editor="editor" />
  </div>
</template>

<script>
import { Editor, EditorContent, EditorMenuBar } from 'tiptap'
import { safeInsert, findBlockNodes } from 'prosemirror-utils'
import python from 'highlight.js/lib/languages/python'
import {
  CodeBlock,
  CodeBlockHighlight
} from 'tiptap-extensions'
export default {
  components: {
    EditorContent,
    EditorMenuBar,
  },
  data() {
    return {
      editor: new Editor({
        extensions: [
          new CodeBlock(),
          new CodeBlockHighlight({
            languages: { python }
          })
        ],
        content: ``,
      }),
    }
  },
  beforeDestroy() {
    this.editor.destroy()
  },
  methods: {
    startCodeBlock(commands, isActive) {
      commands.code_block()
      if (isActive.code_block()) {
        this.insertEmptyLineBelowCodeBlock()
      }
    },
    insertEmptyLineBelowCodeBlock() {
      const { schema, state, view } = this.editor
      const selection = state.tr.selection
      const anchorPos = selection.$anchor.pos
      const blockNodes = findBlockNodes(view.state.doc)
      for (const { node, pos } of blockNodes) {
        // コードブロックの場所より下に何らかのnodeがある時は空行を挿入する必要がないので、return
        if (anchorPos < pos) {
          return
        }
      }
      // <p>をコードブロックの下にinsertする(https://github.com/atlassian/prosemirror-utilsのsafeInsertを利用)
      const p = schema.nodes.paragraph.create()
      view.dispatch(safeInsert(p, anchorPos)(state.tr))
      // 選択カーソルをコードブロック内に戻す
      view.dispatch(view.state.tr.setSelection(selection))
    }
  }
}
</script>
<style>
.ProseMirror pre {
  white-space: pre-wrap;
  width: 100%;
}
.editor__content pre {
  padding: .7rem 1rem;
  border-radius: 5px;
  background: #000;
  color: #fff;
  font-size: .8rem;
  overflow-x: auto;
}
.editor__content * {
    caret-color: currentColor;
}
.is-active-button {
  background-color: antiquewhite
}
</style>
4
3
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
4
3