summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/content_editor/extensions/table_of_contents.js
blob: f64ed67199f021ce0c035c7147b5e4763e632691 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import { Node, InputRule } from '@tiptap/core';
import { VueNodeViewRenderer } from '@tiptap/vue-2';
import { __ } from '~/locale';
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
import TableOfContentsWrapper from '../components/wrappers/table_of_contents.vue';

export default Node.create({
  name: 'tableOfContents',

  inline: false,

  group: 'block',

  parseHTML() {
    return [
      {
        tag: 'ul.section-nav',
        priority: PARSE_HTML_PRIORITY_HIGHEST,
      },
    ];
  },

  renderHTML() {
    return [
      'div',
      {
        class:
          'table-of-contents gl-border-1 gl-border-solid gl-text-center gl-border-gray-100 gl-mb-5',
      },
      __('Table of contents'),
    ];
  },
  addNodeView() {
    return VueNodeViewRenderer(TableOfContentsWrapper);
  },

  addCommands() {
    return {
      insertTableOfContents: () => ({ commands }) => commands.insertContent({ type: this.name }),
    };
  },

  addInputRules() {
    const { type } = this;
    const inputRuleRegExps = [/^\[\[_TOC_\]\]$/, /^\[TOC\]$/];

    return inputRuleRegExps.map(
      (regex) =>
        new InputRule({
          find: regex,
          handler: ({ state, range: { from, to }, match }) => {
            const { tr } = state;

            if (match) {
              tr.replaceWith(from - 1, to, type.create());
            }

            return tr;
          },
        }),
    );
  },
});