summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
blob: ed04765c871c1bcf1918f1bc3b7dc5061263b0f2 (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
import { defaults, repeat } from 'lodash';

const DEFAULTS = {
  subListIndentSpaces: 4,
};

const countIndentSpaces = text => {
  const matches = text.match(/^\s+/m);

  return matches ? matches[0].length : 0;
};

const buildHTMLToMarkdownRender = (baseRenderer, formattingPreferences = {}) => {
  const { subListIndentSpaces } = defaults(formattingPreferences, DEFAULTS);
  // eslint-disable-next-line @gitlab/require-i18n-strings
  const sublistNode = 'LI OL, LI UL';

  return {
    TEXT_NODE(node) {
      return baseRenderer.getSpaceControlled(
        baseRenderer.trim(baseRenderer.getSpaceCollapsedText(node.nodeValue)),
        node,
      );
    },
    /*
     * This converter overwrites the default indented list converter
     * to allow us to parameterize the number of indent spaces for
     * sublists.
     *
     * See the original implementation in
     * https://github.com/nhn/tui.editor/blob/master/libs/to-mark/src/renderer.basic.js#L161
     */
    [sublistNode](node, subContent) {
      const baseResult = baseRenderer.convert(node, subContent);
      // Default to 1 to prevent possible divide by 0
      const firstLevelIndentSpacesCount = countIndentSpaces(baseResult) || 1;
      const reindentedList = baseResult
        .split('\n')
        .map(line => {
          const itemIndentSpacesCount = countIndentSpaces(line);
          const nestingLevel = Math.ceil(itemIndentSpacesCount / firstLevelIndentSpacesCount);
          const indentSpaces = repeat(' ', subListIndentSpaces * nestingLevel);

          return line.replace(/^ +/, indentSpaces);
        })
        .join('\n');

      return reindentedList;
    },
  };
};

export default buildHTMLToMarkdownRender;