@atlaskit/editor-plugin-block-type
Version:
BlockType plugin for @atlaskit/editor-core
104 lines (100 loc) • 3.69 kB
JavaScript
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;