@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
80 lines (75 loc) • 2.9 kB
JavaScript
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
import { findWrapping } from '@atlaskit/editor-prosemirror/transform';
import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
import { removeBlockMarks } from './editor-core-utils';
/**
* This function creates a new transaction that wraps the current selection
* in the specified node type if it results in a valid transaction.
* If not valid, it performs a safe insert operation.
*
* Example of when wrapping might not be valid is when attempting to wrap
* content that is already inside a panel with another panel
*/
export function createWrapSelectionTransaction(_ref) {
var state = _ref.state,
type = _ref.type,
nodeAttributes = _ref.nodeAttributes;
var tr = state.tr;
var _state$schema$marks = state.schema.marks,
alignment = _state$schema$marks.alignment,
indentation = _state$schema$marks.indentation;
/** Alignment or Indentation is not valid inside block types */
var removeAlignTr = removeBlockMarks(state, [alignment, indentation]);
tr = removeAlignTr || tr;
/**Get range and wrapping needed for the selection*/
var _getWrappingOptions = getWrappingOptions(state, type, nodeAttributes),
range = _getWrappingOptions.range,
wrapping = _getWrappingOptions.wrapping;
if (wrapping) {
tr.wrap(range, wrapping).scrollIntoView();
} else {
/** We always want to append a block type */
safeInsert(type.createAndFill(nodeAttributes))(tr).scrollIntoView();
}
return tr;
}
export function getWrappingOptions(state, type,
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any
nodeAttributes) {
var _state$selection = state.selection,
$from = _state$selection.$from,
$to = _state$selection.$to,
from = _state$selection.from;
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var range = $from.blockRange($to);
var isMediaSelection = state.selection instanceof NodeSelection && state.selection.node.type === state.schema.nodes.media;
/**
* To wrap a media group we need to start the range from one position
* before a media selection's from position.
*/
if (isMediaSelection) {
var prev = from - 1;
range = state.doc.resolve(from > 0 ? prev : from).blockRange($to);
}
var isAllowedChild = true;
/**
* Added a check to avoid wrapping codeblock
*/
if (state.selection.empty) {
state.doc.nodesBetween($from.pos, $to.pos, function (node) {
if (!isAllowedChild) {
return false;
}
return isAllowedChild = node.type !== state.schema.nodes.codeBlock;
});
}
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var wrapping = isAllowedChild && range && findWrapping(range, type, nodeAttributes);
return {
range: range,
wrapping: wrapping
};
}