summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js
blob: d26f32a7e7a6320ad8e269f41959298e2b8c2783 (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
import { mapValues } from 'lodash';
import { InputRule } from 'prosemirror-inputrules';
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(inputRule.match, (...args) => {
    const result = inputRule.handler(...args);

    if (result) {
      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));
    },
  });
};

export default trackInputRulesAndShortcuts;