UNPKG

@atlaskit/editor-plugin-paste-options-toolbar

Version:

Paste options toolbar for @atlaskit/editor-core

137 lines (125 loc) 5.36 kB
import { hasMixedNodes } from './hasMixedNodes'; import { hasTableNode } from './hasTableNode'; import { isNotProse } from './isNotProse'; import { isNotSingleLink } from './isNotSingleLink'; /** * Returns a rule that hides the paste-menu button when the pasted plain-text * is shorter than `minChars` characters. */ const minCharsRule = minChars => context => context.getPlaintextLength() < minChars; /** * Returns a rule that hides the paste-menu button when the pasted plain-text * is longer than `maxChars` characters. */ const maxCharsRule = maxChars => context => context.getPlaintextLength() > maxChars; /** * A rule that hides the paste-menu button when the pasted content is plain * text (i.e. not rich-text / prose). */ const notProseRule = context => { // The pasted slice being empty or missing indicates plain-text paste. const slice = context.getPastedSlice(); const pastedText = context.getPastedText(); return slice === undefined && isNotProse(pastedText); }; /** * A rule that hides the paste-menu button when the pasted content contains a * table node as an ancestor at the insertion point. */ const containsTableRule = context => hasTableNode(context.getPastedSlice()); /** * Returns a rule that hides the paste-menu button when any of the provided * node names appear in the ancestor list at the insertion point. */ const excludedAncestorRule = excludedNames => context => context.getAncestorNodeNames().some(name => excludedNames.includes(name)); /** * Returns a rule that hides the paste-menu button when the pasted content contains * more than one node type (e.g. a mix of paragraphs and headings, or a table * with multiple cell types). */ const hideIfMixedNodesRule = context => { const slice = context.getPastedSlice(); if (!slice) { return false; } return hasMixedNodes(slice); }; /** * Returns a rule that hides the paste-menu button when the pasted content contains * only a single node type (e.g. a single paragraph, or a table with only one cell type). * This is the inverse of `hideIfMixedNodesRule` and can be used in combination with it * to target pastes that contain either exactly one node type or more than one node type. */ const hideIfSingleNodeRule = context => { const slice = context.getPastedSlice(); if (!slice) { return false; } return !hasMixedNodes(slice); }; /** * A rule that hides the paste-menu button when the paste source is NOT an * external application (i.e. the content was pasted from within the Fabric * editor or renderer rather than from a third-party source). */ const notExternalPasteRule = context => { const source = context.getPasteSource(); return source === 'fabric-editor' || source === 'fabric-renderer'; }; /** * A rule that hides the paste-menu button when the pasted content is a single * standalone link — i.e. a bare URL link (text equals href) alone in a * paragraph, or a single inline card (smartlink) alone in a paragraph. * * Returns `true` (hidden) when the paste is NOT a single link — e.g. a link * with a custom label, a link accompanied by other text or sibling nodes, or * multiple paragraphs. */ const notSingleLinkRule = context => isNotSingleLink(context.getPastedSlice()); /** * A rule that hides the paste-menu button when the pasted content IS a single * standalone link (the inverse of `notSingleLinkRule`). * * Use this to suppress buttons (e.g. Improve Writing, Fix Spelling) that * should not appear for single-link pastes. */ const isSingleLinkRule = context => !isNotSingleLink(context.getPastedSlice()); /** * Combines multiple context-aware rules with short-circuit evaluation. * Returns `true` (hidden) as soon as the first rule returns `true`; returns * `false` only when all rules return `false`. * Context is injected by `createPasteMenuRuleFactories` — callers never * construct or pass a context object. */ const allRules = (...rules) => context => { for (const rule of rules) { if (rule(context)) { return true; } } return false; }; /** * Binds a `PasteMenuRuleWithContext` to a context supplier, returning a * no-argument `PasteMenuRule` that re-reads the context on every invocation. */ const bind = (getContext, rule) => () => rule(getContext()); /** * Creates the `PasteMenuRuleFactories` object with every rule pre-bound to the * given context supplier. Called inside `getPasteMenuRules()` so the plugin * API and paste state are already available in the closure — external callers * never need to construct or pass a context object. */ export const createPasteMenuRuleFactories = getContext => ({ allRules: (...rules) => bind(getContext, allRules(...rules)), containsTableRule: bind(getContext, containsTableRule), excludedAncestorRule: excludedNames => bind(getContext, excludedAncestorRule(excludedNames)), hideIfMixedNodesRule: bind(getContext, hideIfMixedNodesRule), hideIfSingleNodeRule: bind(getContext, hideIfSingleNodeRule), isSingleLinkRule: bind(getContext, isSingleLinkRule), maxCharsRule: maxChars => bind(getContext, maxCharsRule(maxChars)), minCharsRule: minChars => bind(getContext, minCharsRule(minChars)), notExternalPasteRule: bind(getContext, notExternalPasteRule), notProseRule: bind(getContext, notProseRule), notSingleLinkRule: bind(getContext, notSingleLinkRule) });