@atlaskit/editor-plugin-code-block-advanced
Version:
CodeBlockAdvanced plugin for @atlaskit/editor-core
68 lines (67 loc) • 2.64 kB
JavaScript
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
/**
* Returns the extra offset to add when mapping a CodeMirror position to ProseMirror
* when the content may contain \r\n (CRLF). Each \r\n in the text before the given
* position counts as one extra character in PM.
*/
function crlfAdjustment(text, cmPos) {
let cmIdx = 0;
let pmIdx = 0;
while (pmIdx < text.length && cmIdx < cmPos) {
if (text[pmIdx] === '\r' && text[pmIdx + 1] === '\n') {
pmIdx++;
}
pmIdx++;
cmIdx++;
}
return pmIdx - cmIdx;
}
/**
*
* Synchronises the CodeMirror update changes with the Prosemirror editor
*
* @param props.view EditorView - Prosemirror EditorView
* @param props.update ViewUpdate - CodeMirror ViewUpdate
* @param props.offset number - position where the code block starts in prosemirror
*/
export const syncCMWithPM = ({
view,
update,
offset
}) => {
var _view$state$doc$nodeA, _view$state$doc$nodeA2;
const codeBlockText = (_view$state$doc$nodeA = (_view$state$doc$nodeA2 = view.state.doc.nodeAt(offset)) === null || _view$state$doc$nodeA2 === void 0 ? void 0 : _view$state$doc$nodeA2.textContent) !== null && _view$state$doc$nodeA !== void 0 ? _view$state$doc$nodeA : '';
const {
main
} = update.state.selection;
const selFrom = offset + main.from;
const selTo = offset + main.to;
const pmSel = view.state.selection;
if (update.docChanged || pmSel.from !== selFrom || pmSel.to !== selTo) {
const tr = view.state.tr;
update.changes.iterChanges((fromA, toA, fromB, toB, text) => {
if (expValEquals('platform_editor_fix_advanced_codeblocks_crlf_patch', 'isEnabled', true)) {
const adjFrom = crlfAdjustment(codeBlockText, fromA);
// If the from and to are the same, we don't need to run adjustment again
const adjTo = fromA === toA ? adjFrom : crlfAdjustment(codeBlockText, toA);
const pmFrom = offset + fromA + adjFrom;
const pmTo = offset + toA + adjTo;
if (text.length) {
tr.replaceWith(pmFrom, pmTo, view.state.schema.text(text.toString()));
} else {
tr.delete(pmFrom, pmTo);
}
} else {
if (text.length) {
tr.replaceWith(offset + fromA, offset + toA, view.state.schema.text(text.toString()));
} else {
tr.delete(offset + fromA, offset + toA);
}
}
offset += toB - fromB - (toA - fromA);
});
tr.setSelection(TextSelection.create(tr.doc, selFrom, selTo)).setMeta('scrollIntoView', false);
view.dispatch(tr);
}
};