From 8e2d219042860f2f979236c9f8cc7121ef25d751 Mon Sep 17 00:00:00 2001 From: d3m1d0v Date: Fri, 16 Jun 2023 16:35:22 +0300 Subject: [PATCH] feat: add logging keymap actions --- demo/Playground.tsx | 1 + src/extensions/base/BaseSchema/index.ts | 5 ++++- src/extensions/behavior/History/index.ts | 5 +++-- src/extensions/markdown/Blockquote/index.ts | 5 ++++- src/extensions/markdown/Bold/index.ts | 5 ++++- src/extensions/markdown/Code/index.ts | 5 ++++- src/extensions/markdown/CodeBlock/index.ts | 5 ++++- src/extensions/markdown/Heading/index.ts | 13 +++++++------ src/extensions/markdown/Italic/index.ts | 5 ++++- src/extensions/markdown/Lists/index.ts | 5 +++-- src/extensions/markdown/Strike/index.ts | 5 ++++- src/extensions/markdown/Underline/index.ts | 5 ++++- src/extensions/yfm/YfmCut/index.ts | 3 ++- src/extensions/yfm/YfmHeading/index.ts | 13 +++++++------ src/extensions/yfm/YfmNote/index.ts | 3 ++- src/logger.ts | 12 ++++++++++++ src/utils/keymap.ts | 10 ++++++++++ 17 files changed, 79 insertions(+), 26 deletions(-) create mode 100644 src/utils/keymap.ts diff --git a/demo/Playground.tsx b/demo/Playground.tsx index 0f3b09fd..844b9581 100644 --- a/demo/Playground.tsx +++ b/demo/Playground.tsx @@ -42,6 +42,7 @@ const enum PreviewType { logger.setLogger({ metrics: console.info, + action: console.info, ...console, }); diff --git a/src/extensions/base/BaseSchema/index.ts b/src/extensions/base/BaseSchema/index.ts index 54b961a0..5202783d 100644 --- a/src/extensions/base/BaseSchema/index.ts +++ b/src/extensions/base/BaseSchema/index.ts @@ -2,6 +2,7 @@ import type {Command} from 'prosemirror-state'; import {setBlockType} from 'prosemirror-commands'; import {hasParentNodeOfType} from 'prosemirror-utils'; import type {Action, ExtensionAuto} from '../../../core'; +import {withLogAction} from '../../../utils/keymap'; import {BaseSchemaSpecs, BaseSchemaSpecsOptions, pType} from './BaseSchemaSpecs'; export {BaseNode, pType} from './BaseSchemaSpecs'; @@ -20,7 +21,9 @@ export const BaseSchema: ExtensionAuto = (builder, opts) => { const {paragraphKey} = opts; if (paragraphKey) { - builder.addKeymap(({schema}) => ({[paragraphKey]: setBlockType(pType(schema))})); + builder.addKeymap(({schema}) => ({ + [paragraphKey]: withLogAction('paragraph', setBlockType(pType(schema))), + })); } builder.addAction(pAction, ({schema}) => { diff --git a/src/extensions/behavior/History/index.ts b/src/extensions/behavior/History/index.ts index 4b23db7c..3f01da41 100644 --- a/src/extensions/behavior/History/index.ts +++ b/src/extensions/behavior/History/index.ts @@ -1,6 +1,7 @@ import type {Command} from 'prosemirror-state'; import {history, redo, undo} from 'prosemirror-history'; import type {Action, ActionSpec, ExtensionAuto, Keymap} from '../../../core'; +import {withLogAction} from '../../../utils/keymap'; enum HistoryAction { Undo = 'undo', @@ -18,8 +19,8 @@ export const History: ExtensionAuto = (builder, opts) => { builder.addKeymap(() => { const {undoKey, redoKey} = opts ?? {}; const bindings: Keymap = {}; - if (undoKey) bindings[undoKey] = undo; - if (redoKey) bindings[redoKey] = redo; + if (undoKey) bindings[undoKey] = withLogAction('undo', undo); + if (redoKey) bindings[redoKey] = withLogAction('redo', redo); return bindings; }); builder diff --git a/src/extensions/markdown/Blockquote/index.ts b/src/extensions/markdown/Blockquote/index.ts index d1043f91..7e155a2d 100644 --- a/src/extensions/markdown/Blockquote/index.ts +++ b/src/extensions/markdown/Blockquote/index.ts @@ -3,6 +3,7 @@ import type {NodeType} from 'prosemirror-model'; import {wrappingInputRule} from 'prosemirror-inputrules'; import {hasParentNodeOfType} from 'prosemirror-utils'; import type {Action, ExtensionAuto} from '../../../core'; +import {withLogAction} from '../../../utils/keymap'; import {liftFromQuote, toggleQuote, joinPrevQuote} from './commands'; import {BlockquoteSpecs, blockquoteType} from './BlockquoteSpecs'; @@ -18,7 +19,9 @@ export const Blockquote: ExtensionAuto = (builder, opts) => { if (opts?.qouteKey) { const {qouteKey} = opts; - builder.addKeymap(({schema}) => ({[qouteKey]: wrapIn(blockquoteType(schema))})); + builder.addKeymap(({schema}) => ({ + [qouteKey]: withLogAction('blockquote', wrapIn(blockquoteType(schema))), + })); } builder.addKeymap(() => ({ diff --git a/src/extensions/markdown/Bold/index.ts b/src/extensions/markdown/Bold/index.ts index f65a9103..73fce5b2 100644 --- a/src/extensions/markdown/Bold/index.ts +++ b/src/extensions/markdown/Bold/index.ts @@ -1,4 +1,5 @@ import {toggleMark} from 'prosemirror-commands'; +import {withLogAction} from '../../../utils/keymap'; import {createToggleMarkAction} from '../../../utils/actions'; import type {Action, ExtensionAuto} from '../../../core'; import {markInputRule} from '../../../utils/inputrules'; @@ -19,7 +20,9 @@ export const Bold: ExtensionAuto = (builder, opts) => { if (opts?.boldKey) { const {boldKey} = opts; - builder.addKeymap(({schema}) => ({[boldKey]: toggleMark(boldType(schema))})); + builder.addKeymap(({schema}) => ({ + [boldKey]: withLogAction('bold', toggleMark(boldType(schema))), + })); } builder.addInputRules(({schema}) => ({ diff --git a/src/extensions/markdown/Code/index.ts b/src/extensions/markdown/Code/index.ts index 2dc3eba4..04d3d8eb 100644 --- a/src/extensions/markdown/Code/index.ts +++ b/src/extensions/markdown/Code/index.ts @@ -1,6 +1,7 @@ import {toggleMark} from 'prosemirror-commands'; import codemark from 'prosemirror-codemark'; import {Plugin} from 'prosemirror-state'; +import {withLogAction} from '../../../utils/keymap'; import {createToggleMarkAction} from '../../../utils/actions'; import type {Action, ExtensionAuto} from '../../../core'; import {codeMarkName, CodeSpecs, codeType} from './CodeSpecs'; @@ -22,7 +23,9 @@ export const Code: ExtensionAuto = (builder, opts) => { if (opts?.codeKey) { const {codeKey} = opts; - builder.addKeymap(({schema}) => ({[codeKey]: toggleMark(codeType(schema))})); + builder.addKeymap(({schema}) => ({ + [codeKey]: withLogAction('code_inline', toggleMark(codeType(schema))), + })); } builder diff --git a/src/extensions/markdown/CodeBlock/index.ts b/src/extensions/markdown/CodeBlock/index.ts index 707cb4b9..0b676859 100644 --- a/src/extensions/markdown/CodeBlock/index.ts +++ b/src/extensions/markdown/CodeBlock/index.ts @@ -3,6 +3,7 @@ import {textblockTypeInputRule} from 'prosemirror-inputrules'; import {Fragment, NodeType, Slice} from 'prosemirror-model'; import {Command, Plugin} from 'prosemirror-state'; import {hasParentNodeOfType} from 'prosemirror-utils'; +import {withLogAction} from '../../../utils/keymap'; import type {Action, ExtensionAuto, Keymap} from '../../../core'; import {CodeBlockSpecs, CodeBlockSpecsOptions} from './CodeBlockSpecs'; import {resetCodeblock} from './commands'; @@ -22,7 +23,9 @@ export const CodeBlock: ExtensionAuto = (builder, opts) => { builder.addKeymap((deps) => { const {codeBlockKey} = opts; const bindings: Keymap = {Backspace: resetCodeblock}; - if (codeBlockKey) bindings[codeBlockKey] = setBlockType(cbType(deps.schema)); + if (codeBlockKey) { + bindings[codeBlockKey] = withLogAction('code_block', setBlockType(cbType(deps.schema))); + } return bindings; }); diff --git a/src/extensions/markdown/Heading/index.ts b/src/extensions/markdown/Heading/index.ts index 95b0696a..569954ff 100644 --- a/src/extensions/markdown/Heading/index.ts +++ b/src/extensions/markdown/Heading/index.ts @@ -1,5 +1,6 @@ import {setBlockType} from 'prosemirror-commands'; import type {Action, ExtensionAuto, Keymap} from '../../../core'; +import {withLogAction} from '../../../utils/keymap'; import {headingAction} from './actions'; import {HeadingAction, HeadingLevel, headingLevelAttr} from './const'; import {headingRule, hType} from './utils'; @@ -29,12 +30,12 @@ export const Heading: ExtensionAuto = (builder, opts) => { setBlockType(hType(schema), {[headingLevelAttr]: level}); const bindings: Keymap = {Backspace: resetHeading}; - if (h1Key) bindings[h1Key] = cmd4lvl(1); - if (h2Key) bindings[h2Key] = cmd4lvl(2); - if (h3Key) bindings[h3Key] = cmd4lvl(3); - if (h4Key) bindings[h4Key] = cmd4lvl(4); - if (h5Key) bindings[h5Key] = cmd4lvl(5); - if (h6Key) bindings[h6Key] = cmd4lvl(6); + if (h1Key) bindings[h1Key] = withLogAction('heading1', cmd4lvl(1)); + if (h2Key) bindings[h2Key] = withLogAction('heading2', cmd4lvl(2)); + if (h3Key) bindings[h3Key] = withLogAction('heading3', cmd4lvl(3)); + if (h4Key) bindings[h4Key] = withLogAction('heading4', cmd4lvl(4)); + if (h5Key) bindings[h5Key] = withLogAction('heading5', cmd4lvl(5)); + if (h6Key) bindings[h6Key] = withLogAction('heading6', cmd4lvl(6)); return bindings; }) .addInputRules(({schema}) => ({rules: [headingRule(hType(schema), 6)]})); diff --git a/src/extensions/markdown/Italic/index.ts b/src/extensions/markdown/Italic/index.ts index 1a4338f9..8c706e0e 100644 --- a/src/extensions/markdown/Italic/index.ts +++ b/src/extensions/markdown/Italic/index.ts @@ -1,4 +1,5 @@ import {toggleMark} from 'prosemirror-commands'; +import {withLogAction} from '../../../utils/keymap'; import {createToggleMarkAction} from '../../../utils/actions'; import type {Action, ExtensionAuto} from '../../../core'; import {markInputRule} from '../../../utils/inputrules'; @@ -28,7 +29,9 @@ export const Italic: ExtensionAuto = (builder, opts) => { if (opts?.italicKey) { const {italicKey} = opts; - builder.addKeymap(({schema}) => ({[italicKey]: toggleMark(italicType(schema))})); + builder.addKeymap(({schema}) => ({ + [italicKey]: withLogAction('italic', toggleMark(italicType(schema))), + })); } }; diff --git a/src/extensions/markdown/Lists/index.ts b/src/extensions/markdown/Lists/index.ts index f860dc96..ed3df503 100644 --- a/src/extensions/markdown/Lists/index.ts +++ b/src/extensions/markdown/Lists/index.ts @@ -1,6 +1,7 @@ import {chainCommands} from 'prosemirror-commands'; import {liftListItem, sinkListItem, splitListItem} from 'prosemirror-schema-list'; import type {Action, ExtensionAuto, Keymap} from '../../../core'; +import {withLogAction} from '../../../utils/keymap'; import {actions} from './actions'; import {ListAction} from './const'; import {ListsInputRulesExtension, ListsInputRulesOptions} from './inputrules'; @@ -21,8 +22,8 @@ export const Lists: ExtensionAuto = (builder, opts) => { builder.addKeymap(({schema}) => { const {ulKey, olKey} = opts ?? {}; const bindings: Keymap = {}; - if (ulKey) bindings[ulKey] = toList(blType(schema)); - if (olKey) bindings[olKey] = toList(olType(schema)); + if (ulKey) bindings[ulKey] = withLogAction('bulletList', toList(blType(schema))); + if (olKey) bindings[olKey] = withLogAction('orderedList', toList(olType(schema))); return { Enter: splitListItem(liType(schema)), diff --git a/src/extensions/markdown/Strike/index.ts b/src/extensions/markdown/Strike/index.ts index 4be87f1a..1c79902b 100644 --- a/src/extensions/markdown/Strike/index.ts +++ b/src/extensions/markdown/Strike/index.ts @@ -1,5 +1,6 @@ import {toggleMark} from 'prosemirror-commands'; import type {Action, ExtensionAuto} from '../../../core'; +import {withLogAction} from '../../../utils/keymap'; import {createToggleMarkAction} from '../../../utils/actions'; import {markInputRule} from '../../../utils/inputrules'; import {strikeMarkName, StrikeSpecs, strikeType} from './StrikeSpecs'; @@ -26,7 +27,9 @@ export const Strike: ExtensionAuto = (builder, opts) => { if (opts?.strikeKey) { const {strikeKey} = opts; - builder.addKeymap(({schema}) => ({[strikeKey]: toggleMark(strikeType(schema))})); + builder.addKeymap(({schema}) => ({ + [strikeKey]: withLogAction('strike', toggleMark(strikeType(schema))), + })); } }; diff --git a/src/extensions/markdown/Underline/index.ts b/src/extensions/markdown/Underline/index.ts index 04cddc2c..dda92dc4 100644 --- a/src/extensions/markdown/Underline/index.ts +++ b/src/extensions/markdown/Underline/index.ts @@ -1,5 +1,6 @@ import {toggleMark} from 'prosemirror-commands'; import type {Action, ExtensionAuto} from '../../../core'; +import {withLogAction} from '../../../utils/keymap'; import {createToggleMarkAction} from '../../../utils/actions'; import {markInputRule} from '../../../utils/inputrules'; import {underlineMarkName, UnderlineSpecs, underlineType} from './UnderlineSpecs'; @@ -26,7 +27,9 @@ export const Underline: ExtensionAuto = (builder, opts) => { if (opts?.underlineKey) { const {underlineKey} = opts; - builder.addKeymap(({schema}) => ({[underlineKey]: toggleMark(underlineType(schema))})); + builder.addKeymap(({schema}) => ({ + [underlineKey]: withLogAction('underline', toggleMark(underlineType(schema))), + })); } }; diff --git a/src/extensions/yfm/YfmCut/index.ts b/src/extensions/yfm/YfmCut/index.ts index 9ee8133a..b16bb410 100644 --- a/src/extensions/yfm/YfmCut/index.ts +++ b/src/extensions/yfm/YfmCut/index.ts @@ -1,5 +1,6 @@ import {chainCommands} from 'prosemirror-commands'; import type {Action, ExtensionAuto} from '../../../core'; +import {withLogAction} from '../../../utils/keymap'; import {nodeInputRule} from '../../../utils/inputrules'; import {cutType} from './const'; import {createYfmCut, toYfmCut} from './actions/toYfmCut'; @@ -48,7 +49,7 @@ export const YfmCut: ExtensionAuto = (builder, opts) => { if (opts?.yfmCutKey) { const {yfmCutKey} = opts; - builder.addKeymap(() => ({[yfmCutKey]: createYfmCut})); + builder.addKeymap(() => ({[yfmCutKey]: withLogAction('yfm_cut', createYfmCut)})); } }; diff --git a/src/extensions/yfm/YfmHeading/index.ts b/src/extensions/yfm/YfmHeading/index.ts index 3c224fb4..9868bbb4 100644 --- a/src/extensions/yfm/YfmHeading/index.ts +++ b/src/extensions/yfm/YfmHeading/index.ts @@ -1,4 +1,5 @@ import type {Action, ExtensionAuto, Keymap} from '../../../core'; +import {withLogAction} from '../../../utils/keymap'; import {HeadingAction} from './const'; import {headingRule, hType} from './YfmHeadingSpecs/utils'; import {headingAction} from './actions'; @@ -24,12 +25,12 @@ export const YfmHeading: ExtensionAuto = (builder, opts) => { .addKeymap(() => { const {h1Key, h2Key, h3Key, h4Key, h5Key, h6Key} = opts ?? {}; const bindings: Keymap = {Backspace: resetHeading}; - if (h1Key) bindings[h1Key] = toHeading(1); - if (h2Key) bindings[h2Key] = toHeading(2); - if (h3Key) bindings[h3Key] = toHeading(3); - if (h4Key) bindings[h4Key] = toHeading(4); - if (h5Key) bindings[h5Key] = toHeading(5); - if (h6Key) bindings[h6Key] = toHeading(6); + if (h1Key) bindings[h1Key] = withLogAction('heading1', toHeading(1)); + if (h2Key) bindings[h2Key] = withLogAction('heading2', toHeading(2)); + if (h3Key) bindings[h3Key] = withLogAction('heading3', toHeading(3)); + if (h4Key) bindings[h4Key] = withLogAction('heading4', toHeading(4)); + if (h5Key) bindings[h5Key] = withLogAction('heading5', toHeading(5)); + if (h6Key) bindings[h6Key] = withLogAction('heading6', toHeading(6)); return bindings; }) .addInputRules(({schema}) => ({rules: [headingRule(hType(schema), 6)]})); diff --git a/src/extensions/yfm/YfmNote/index.ts b/src/extensions/yfm/YfmNote/index.ts index 993046f3..51e589b7 100644 --- a/src/extensions/yfm/YfmNote/index.ts +++ b/src/extensions/yfm/YfmNote/index.ts @@ -1,5 +1,6 @@ import {chainCommands} from 'prosemirror-commands'; import type {Action, ExtensionAuto} from '../../../core'; +import {withLogAction} from '../../../utils/keymap'; import {createYfmNote, toYfmNote} from './actions/toYfmNote'; import {nodeInputRule} from '../../../utils/inputrules'; import {backToNoteTitle, exitFromNoteTitle, removeNote} from './commands'; @@ -31,7 +32,7 @@ export const YfmNote: ExtensionAuto = (builder, opts) => { if (opts?.yfmNoteKey) { const {yfmNoteKey} = opts; - builder.addKeymap(() => ({[yfmNoteKey]: createYfmNote})); + builder.addKeymap(() => ({[yfmNoteKey]: withLogAction('yfm_note', createYfmNote)})); } }; diff --git a/src/logger.ts b/src/logger.ts index 652d6f1e..8f4fe31b 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -9,12 +9,19 @@ declare global { meta?: Record; }; + interface ActionData { + action: string; + source: string; + [key: string]: any; + } + interface Logger { log(...data: any[]): void; info(...data: any[]): void; error(...data: any[]): void; warn(...data: any[]): void; metrics(data: MetricsData): void; + action(data: ActionData): void; } interface Settings extends Partial {} @@ -44,6 +51,10 @@ class Logger implements YfmEditorLogger.Logger { return this.#logger.metrics; } + get action() { + return this.#logger.action; + } + setLogger(settings: YfmEditorLogger.Settings = {}) { this.#logger = this.createLogger(settings); } @@ -60,6 +71,7 @@ class Logger implements YfmEditorLogger.Logger { warn: settings.warn ?? noop, error: settings.error ?? noop, metrics: settings.metrics ?? noop, + action: settings.action ?? noop, }; } } diff --git a/src/utils/keymap.ts b/src/utils/keymap.ts new file mode 100644 index 00000000..0e261bee --- /dev/null +++ b/src/utils/keymap.ts @@ -0,0 +1,10 @@ +import type {Command} from 'prosemirror-state'; +import {logger} from '../logger'; + +export function withLogAction(action: string, command: Command): Command { + return (...args) => { + const res = command(...args); + if (res) logger.action({action, source: 'keymap'}); + return res; + }; +}