OverviewFilesCommitsIssuesDocsReleasesPeers

keet-deobfuscated / @holepunchto / keet-editor / src / extensions / code-block.js

112 lines · javascript ref:
import { nodeInputRule as e, textblockTypeInputRule as t } from "@tiptap/core"
import { CodeBlock as n } from "@tiptap/extension-code-block"
export const lineBeginingBacktickInputRegex = /^```[a-z]*[\s\n]$/
export const backtickInputRegex = /(?<=\s|\n)```[a-z]*[\s\n]$/
export const lineBeginingTildeInputRegex = /^~~~[a-z]*[\s\n]$/
export const tildeInputRegex = /(?<=\s|\n)~~~[a-z]*[\s\n]$/
export const CodeBlock = n.extend({
  addInputRules() {
    return [
      e({ find: backtickInputRegex, type: this.type, getAttributes: (e) => ({ language: e[1] }) }),
      t({
        find: lineBeginingBacktickInputRegex,
        type: this.type,
        getAttributes: (e) => ({ language: e[1] }),
      }),
      e({ find: tildeInputRegex, type: this.type, getAttributes: (e) => ({ language: e[1] }) }),
      t({
        find: lineBeginingTildeInputRegex,
        type: this.type,
        getAttributes: (e) => ({ language: e[1] }),
      }),
    ]
  },
  addKeyboardShortcuts() {
    return {
      "Mod-Alt-c": () => this.editor.commands.toggleCodeBlock(),
      Backspace: () => {
        const { empty: e, $anchor: t } = this.editor.state.selection,
          n = 1 === t.pos
        return (
          !(!e || t.parent.type.name !== this.name) &&
          !(!n && t.parent.textContent.length) &&
          this.editor.commands.clearNodes()
        )
      },
      Enter: () => {
        const { state: e } = this.editor,
          { from: t, to: n } = e.selection
        if (t > 1 && t === n) {
          let o = !1
          if (
            (e.doc.nodesBetween(t - 1, n - 1, (e) => {
              "codeBlock" === e.type.name && (o = !0)
            }),
            o)
          )
            return this.editor.commands.exitCode()
        }
        return !1
      },
      ArrowDown: () => {
        const { state: e } = this.editor,
          { from: t, to: n } = e.selection
        if (t > 1 && t === n) {
          let o = !1
          e.doc.nodesBetween(t - 1, n - 1, (e) => {
            "codeBlock" === e.type.name && (o = !0)
          })
          const i = n === e.doc.content.size - 1
          if (o && i) return this.editor.commands.exitCode()
        }
        return !1
      },
      "Shift-Enter": () => {
        const { state: e } = this.editor,
          { from: t, to: n } = e.selection
        if (t > 1 && t === n) {
          let o = !1
          if (
            (e.doc.nodesBetween(t - 1, n - 1, (e) => {
              "codeBlock" === e.type.name && (o = !0)
            }),
            o)
          )
            return this.editor.commands.newlineInCode()
        }
        return !1
      },
      "Mod-Enter": () => {
        const { state: e } = this.editor,
          { from: t, to: n } = e.selection
        if (t > 1 && t === n) {
          let o = !1
          if (
            (e.doc.nodesBetween(t - 1, n - 1, (e) => {
              "codeBlock" === e.type.name && (o = !0)
            }),
            o)
          )
            return this.editor.commands.newlineInCode()
        }
        return !1
      },
      "Alt-Enter": () => {
        const { state: e } = this.editor,
          { from: t, to: n } = e.selection
        if (t > 1 && t === n) {
          let o = !1
          if (
            (e.doc.nodesBetween(t - 1, n - 1, (e) => {
              "codeBlock" === e.type.name && (o = !0)
            }),
            o)
          )
            return this.editor.commands.newlineInCode()
        }
        return !1
      },
    }
  },
})