UNPKG

@atlaskit/editor-plugin-block-type

Version:

BlockType plugin for @atlaskit/editor-core

104 lines (100 loc) 3.69 kB
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics'; import { insertBlock } from '@atlaskit/editor-common/commands'; import { SafePlugin } from '@atlaskit/editor-common/safe-plugin'; import { createRule, inputRuleWithAnalytics } from '@atlaskit/editor-common/utils'; import { createPlugin, leafNodeReplacementCharacter } from '@atlaskit/prosemirror-input-rules'; import { createJoinNodesRule, createWrappingTextBlockRule } from './utils'; const MAX_HEADING_LEVEL = 6; function getHeadingLevel(match) { return { level: match[1].length }; } function headingRule(nodeType, maxLevel) { return createWrappingTextBlockRule({ // Ignored via go/ees005 // eslint-disable-next-line require-unicode-regexp match: new RegExp('^(#{1,' + maxLevel + '})\\s$'), nodeType, getAttrs: getHeadingLevel }); } function blockQuoteRule(nodeType) { // Ignored via go/ees005 // eslint-disable-next-line require-unicode-regexp return createJoinNodesRule(/^\s*>\s$/, nodeType); } /** * Get heading rules * * @param {Schema} schema * @returns {InputRuleWithHandler[]} */ function getHeadingRules(editorAnalyticsAPI, schema) { // '# ' for h1, '## ' for h2 and etc const hashRule = headingRule(schema.nodes.heading, MAX_HEADING_LEVEL); const leftNodeReplacementHashRule = createRule( // Ignored via go/ees005 // eslint-disable-next-line require-unicode-regexp new RegExp(`${leafNodeReplacementCharacter}(#{1,6})\\s$`), (state, match, start, end) => { const level = match[1].length; return insertBlock(state, schema.nodes.heading, start, end, { level }); }); // New analytics handler const ruleWithHeadingAnalytics = inputRuleWithAnalytics((_state, matchResult) => ({ action: ACTION.FORMATTED, actionSubject: ACTION_SUBJECT.TEXT, eventType: EVENT_TYPE.TRACK, actionSubjectId: ACTION_SUBJECT_ID.FORMAT_HEADING, attributes: { inputMethod: INPUT_METHOD.FORMATTING, newHeadingLevel: getHeadingLevel(matchResult).level } }), editorAnalyticsAPI); return [ruleWithHeadingAnalytics(hashRule), ruleWithHeadingAnalytics(leftNodeReplacementHashRule)]; } /** * Get all block quote input rules * * @param {Schema} schema * @returns {InputRuleWithHandler[]} */ function getBlockQuoteRules(editorAnalyticsAPI, schema) { // '> ' for blockquote const greatherThanRule = blockQuoteRule(schema.nodes.blockquote); const leftNodeReplacementGreatherRule = createRule( // Ignored via go/ees005 // eslint-disable-next-line require-unicode-regexp new RegExp(`${leafNodeReplacementCharacter}\\s*>\\s$`), (state, _match, start, end) => { return insertBlock(state, schema.nodes.blockquote, start, end); }); // Analytics V3 handler const ruleWithBlockQuoteAnalytics = inputRuleWithAnalytics({ action: ACTION.FORMATTED, actionSubject: ACTION_SUBJECT.TEXT, eventType: EVENT_TYPE.TRACK, actionSubjectId: ACTION_SUBJECT_ID.FORMAT_BLOCK_QUOTE, attributes: { inputMethod: INPUT_METHOD.FORMATTING } }, editorAnalyticsAPI); return [ruleWithBlockQuoteAnalytics(greatherThanRule), ruleWithBlockQuoteAnalytics(leftNodeReplacementGreatherRule)]; } function inputRulePlugin(editorAnalyticsAPI, schema, featureFlags) { const rules = []; if (schema.nodes.heading) { rules.push(...getHeadingRules(editorAnalyticsAPI, schema)); } if (schema.nodes.blockquote) { rules.push(...getBlockQuoteRules(editorAnalyticsAPI, schema)); } if (rules.length !== 0) { return new SafePlugin(createPlugin('block-type', rules, { isBlockNodeRule: true })); } return; } export default inputRulePlugin;