UNPKG

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

Version:

Paste options toolbar for @atlaskit/editor-core

183 lines (176 loc) 7.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.formatRichText = exports.formatPlainText = exports.formatMarkdown = void 0; exports.getMarkdownSlice = getMarkdownSlice; var _monitoring = require("@atlaskit/editor-common/monitoring"); var _paste = require("@atlaskit/editor-common/paste"); var _editorMarkdownTransformer = require("@atlaskit/editor-markdown-transformer"); var _model = require("@atlaskit/editor-prosemirror/model"); var _state = require("@atlaskit/editor-prosemirror/state"); var _transform = require("@atlaskit/editor-prosemirror/transform"); var _index = require("./index"); var formatMarkdown = exports.formatMarkdown = function formatMarkdown(tr, pluginState) { var pasteStartPos = pluginState.pasteStartPos; var pasteEndPos = pluginState.pasteEndPos; var plaintext = pluginState.plaintext; if (pasteStartPos < 0) { return tr; } var resolvedPasteStartPos = tr.doc.resolve(pasteStartPos); var parentOffset = resolvedPasteStartPos.parentOffset; if (parentOffset === 0 && resolvedPasteStartPos.depth > 0) { pasteStartPos = resolvedPasteStartPos.before(); } var markdownSlice = getMarkdownSlice(plaintext, tr.doc.type.schema, tr.selection); if (!markdownSlice) { return tr; } pasteSliceIntoTransactionWithSelectionAdjust({ tr: tr, pasteStartPos: pasteStartPos, pasteEndPos: pasteEndPos, slice: markdownSlice }); return tr; }; var formatRichText = exports.formatRichText = function formatRichText(tr, pluginState) { var pasteStartPos = pluginState.pasteStartPos; var pasteEndPos = pluginState.pasteEndPos; var richTextSlice = pluginState.richTextSlice; if (pasteStartPos < 0) { return tr; } if (richTextSlice.content.size === 0) { return tr; } var resolvedPasteStartPos = tr.doc.resolve(pasteStartPos); var parentOffset = resolvedPasteStartPos.parentOffset; if (parentOffset === 0 && resolvedPasteStartPos.depth > 0) { pasteStartPos = resolvedPasteStartPos.before(); } richTextSliceTransactionWithSelectionAdjust({ tr: tr, pasteStartPos: pasteStartPos, pasteEndPos: pasteEndPos, slice: richTextSlice }); return tr; }; var formatPlainText = exports.formatPlainText = function formatPlainText(tr, pluginState) { var pasteStartPos = pluginState.pasteStartPos; var pasteEndPos = pluginState.pasteEndPos; var plaintext = pluginState.plaintext; //not possible to create plain text slice with empty string if (pasteStartPos < 0 || plaintext === '') { return tr; } var resolvedPasteStartPos = tr.doc.resolve(pasteStartPos); var parentOffset = resolvedPasteStartPos.parentOffset; if (parentOffset === 0 && resolvedPasteStartPos.depth > 0) { pasteStartPos = resolvedPasteStartPos.before(); } var schema = tr.doc.type.schema; var plainTextNode = schema.text(plaintext); var plainTextFragment = _model.Fragment.from(schema.nodes.paragraph.createAndFill(null, plainTextNode)); var plainTextSlice = new _model.Slice(plainTextFragment, resolvedPasteStartPos.depth, resolvedPasteStartPos.depth); pasteSliceIntoTransactionWithSelectionAdjust({ tr: tr, pasteStartPos: pasteStartPos, pasteEndPos: pasteEndPos, slice: plainTextSlice }); return tr; }; function pasteSliceIntoTransactionWithSelectionAdjust(_ref) { var tr = _ref.tr, pasteStartPos = _ref.pasteStartPos, pasteEndPos = _ref.pasteEndPos, slice = _ref.slice; tr.replaceRange(pasteStartPos, pasteEndPos, slice); // ProseMirror doesn't give a proper way to tell us where something was inserted. // However, we can know "how" it inserted something. // // So, instead of weird depth calculations, we can use the step produced by the transform. // For instance: // The `replaceStep.to and replaceStep.from`, tell us the real position // where the content will be insert. // Then, we can use the `tr.mapping.map` to the updated position after the replace operation var replaceStep = tr.steps[0]; if (!(replaceStep instanceof _transform.ReplaceStep)) { return tr; } var lastInsertNode = replaceStep.slice.content.lastChild; var emptyNodeReference = lastInsertNode === null || lastInsertNode === void 0 ? void 0 : lastInsertNode.type.createAndFill(); var isLastNodeEmpty = (emptyNodeReference === null || emptyNodeReference === void 0 ? void 0 : emptyNodeReference.nodeSize) === (lastInsertNode === null || lastInsertNode === void 0 ? void 0 : lastInsertNode.nodeSize); var isStepSplitingTarget = !(lastInsertNode !== null && lastInsertNode !== void 0 && lastInsertNode.isLeaf) && isLastNodeEmpty; var $nextHead = tr.doc.resolve(tr.mapping.map(replaceStep.to)); var $nextPosition = isStepSplitingTarget && $nextHead.depth > 0 ? tr.doc.resolve($nextHead.before()) : $nextHead; // The findFrom will make search for both: TextSelection and NodeSelections. var nextSelection = _state.Selection.findFrom($nextPosition, -1); if (nextSelection) { tr.setSelection(nextSelection); } } function richTextSliceTransactionWithSelectionAdjust(_ref2) { var tr = _ref2.tr, pasteStartPos = _ref2.pasteStartPos, pasteEndPos = _ref2.pasteEndPos, slice = _ref2.slice; tr.replaceRange(pasteStartPos, pasteEndPos, slice); // ProseMirror doesn't give a proper way to tell us where something was inserted. // However, we can know "how" it inserted something. // // So, instead of weird depth calculations, we can use the step produced by the transform. // For instance: // The `replaceStep.to and replaceStep.from`, tell us the real position // where the content will be insert. // Then, we can use the `tr.mapping.map` to the updated position after the replace operation var replaceStep = tr.steps[0]; if (!(replaceStep instanceof _transform.ReplaceStep)) { return tr; } var nextPosition = tr.mapping.map(replaceStep.to); // The findFrom will make search for both: TextSelection and NodeSelections. var nextSelection = _state.Selection.findFrom(tr.doc.resolve(Math.min(nextPosition, tr.doc.content.size)), -1); if (nextSelection) { tr.setSelection(nextSelection); } } function getMarkdownSlice(text, schema, selection) { var targetOpenStartNode = selection.$from.parent; var targetOpenEndNode = selection.$to.parent; try { var _doc$content$firstChi, _doc$content$lastChil; var textInput = text; // Ignored via go/ees005 // eslint-disable-next-line require-unicode-regexp var textSplitByCodeBlock = textInput.split(/```/); for (var i = 0; i < textSplitByCodeBlock.length; i++) { if (i % 2 === 0) { // Ignored via go/ees005 // eslint-disable-next-line require-unicode-regexp, @atlassian/perf-linting/no-expensive-split-replace -- Ignored via go/ees017 (to be fixed) textSplitByCodeBlock[i] = textSplitByCodeBlock[i].replace(/\\/g, '\\\\'); } } textInput = textSplitByCodeBlock.join('```'); var atlassianMarkDownParser = new _editorMarkdownTransformer.MarkdownTransformer(schema, _paste.md); var doc = atlassianMarkDownParser.parse((0, _index.escapeLinks)(textInput)); if (!doc || !doc.content) { return; } var canMergeOpenStart = targetOpenStartNode.type === ((_doc$content$firstChi = doc.content.firstChild) === null || _doc$content$firstChi === void 0 ? void 0 : _doc$content$firstChi.type); var canMergeOpenEnd = targetOpenEndNode.type === ((_doc$content$lastChil = doc.content.lastChild) === null || _doc$content$lastChil === void 0 ? void 0 : _doc$content$lastChil.type); var $start = _state.Selection.atStart(doc).$from; var $end = _state.Selection.atEnd(doc).$from; var openStart = canMergeOpenStart ? $start.depth : 0; var openEnd = canMergeOpenEnd ? $end.depth : 0; return new _model.Slice(doc.content, openStart, openEnd); } catch (error) { (0, _monitoring.logException)(error, { location: 'editor-plugin-paste-options-toolbar/util' }); return; } }