summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js
blob: eb1e4885ba6b9442ac96bdcb2106ac98e9eb30ab (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
64
65
66
67
import { mapValues } from 'lodash';
import { InputRule } from '@tiptap/core';
import { ENTER_KEY, BACKSPACE_KEY } from '~/lib/utils/keys';
import Tracking from '~/tracking';
import {
  CONTENT_EDITOR_TRACKING_LABEL,
  KEYBOARD_SHORTCUT_TRACKING_ACTION,
  INPUT_RULE_TRACKING_ACTION,
} from '../constants';

const trackKeyboardShortcut = (contentType, commandFn, shortcut) => () => {
  Tracking.event(undefined, KEYBOARD_SHORTCUT_TRACKING_ACTION, {
    label: CONTENT_EDITOR_TRACKING_LABEL,
    property: `${contentType}.${shortcut}`,
  });
  return commandFn();
};

const trackInputRule = (contentType, inputRule) => {
  return new InputRule({
    find: inputRule.find,
    handler: (...args) => {
      const result = inputRule.handler(...args);

      if (result !== null) {
        Tracking.event(undefined, INPUT_RULE_TRACKING_ACTION, {
          label: CONTENT_EDITOR_TRACKING_LABEL,
          property: contentType,
        });
      }

      return result;
    },
  });
};

const trackInputRulesAndShortcuts = (tiptapExtension) => {
  return tiptapExtension
    .extend({
      addKeyboardShortcuts() {
        const shortcuts = this.parent?.() || {};
        const { name } = this;
        /**
         * We don’t want to track keyboard shortcuts
         * that are not deliberately executed to create
         * new types of content
         */
        const dotNotTrackKeys = [ENTER_KEY, BACKSPACE_KEY];
        const decorated = mapValues(shortcuts, (commandFn, shortcut) =>
          dotNotTrackKeys.includes(shortcut)
            ? commandFn
            : trackKeyboardShortcut(name, commandFn, shortcut),
        );

        return decorated;
      },
      addInputRules() {
        const inputRules = this.parent?.() || [];
        const { name } = this;

        return inputRules.map((inputRule) => trackInputRule(name, inputRule));
      },
    })
    .configure(tiptapExtension.options);
};

export default trackInputRulesAndShortcuts;