UNPKG

@uiw/react-md-editor

Version:

A markdown editor with preview, implemented with React.js and TypeScript.

195 lines (185 loc) 6.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.executeCommand = executeCommand; exports.getBreaksNeededForEmptyLineAfter = getBreaksNeededForEmptyLineAfter; exports.getBreaksNeededForEmptyLineBefore = getBreaksNeededForEmptyLineBefore; exports.getSurroundingWord = getSurroundingWord; exports.insertBeforeEachLine = insertBeforeEachLine; exports.selectLine = selectLine; exports.selectWord = selectWord; function selectWord(_ref) { var text = _ref.text, selection = _ref.selection, prefix = _ref.prefix, _ref$suffix = _ref.suffix, suffix = _ref$suffix === void 0 ? prefix : _ref$suffix; var result = selection; if (text && text.length && selection.start === selection.end) { result = getSurroundingWord(text, selection.start); } if (result.start >= prefix.length && result.end <= text.length - suffix.length) { var selectedTextContext = text.slice(result.start - prefix.length, result.end + suffix.length); if (selectedTextContext.startsWith(prefix) && selectedTextContext.endsWith(suffix)) { return { start: result.start - prefix.length, end: result.end + suffix.length }; } } return result; } function selectLine(_ref2) { var text = _ref2.text, selection = _ref2.selection; var start = text.slice(0, selection.start).lastIndexOf('\n') + 1; var end = text.slice(selection.end).indexOf('\n') + selection.end; if (end === selection.end - 1) { end = text.length; } return { start: start, end: end }; } /** * Gets the number of line-breaks that would have to be inserted before the given 'startPosition' * to make sure there's an empty line between 'startPosition' and the previous text */ function getBreaksNeededForEmptyLineBefore() { var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var startPosition = arguments.length > 1 ? arguments[1] : undefined; if (startPosition === 0) return 0; // rules: // - If we're in the first line, no breaks are needed // - Otherwise there must be 2 breaks before the previous character. Depending on how many breaks exist already, we // may need to insert 0, 1 or 2 breaks var neededBreaks = 2; var isInFirstLine = true; for (var i = startPosition - 1; i >= 0 && neededBreaks >= 0; i--) { switch (text.charCodeAt(i)) { case 32: // blank space continue; case 10: // line break neededBreaks--; isInFirstLine = false; break; default: return neededBreaks; } } return isInFirstLine ? 0 : neededBreaks; } /** * Gets the number of line-breaks that would have to be inserted after the given 'startPosition' * to make sure there's an empty line between 'startPosition' and the next text */ function getBreaksNeededForEmptyLineAfter() { var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var startPosition = arguments.length > 1 ? arguments[1] : undefined; if (startPosition === text.length - 1) return 0; // rules: // - If we're in the first line, no breaks are needed // - Otherwise there must be 2 breaks before the previous character. Depending on how many breaks exist already, we // may need to insert 0, 1 or 2 breaks var neededBreaks = 2; var isInLastLine = true; for (var i = startPosition; i < text.length && neededBreaks >= 0; i++) { switch (text.charCodeAt(i)) { case 32: continue; case 10: { neededBreaks--; isInLastLine = false; break; } default: return neededBreaks; } } return isInLastLine ? 0 : neededBreaks; } function getSurroundingWord(text, position) { if (!text) throw Error("Argument 'text' should be truthy"); var isWordDelimiter = function isWordDelimiter(c) { return c === ' ' || c.charCodeAt(0) === 10; }; // leftIndex is initialized to 0 because if selection is 0, it won't even enter the iteration var start = 0; // rightIndex is initialized to text.length because if selection is equal to text.length it won't even enter the interation var end = text.length; // iterate to the left for (var i = position; i - 1 > -1; i--) { if (isWordDelimiter(text[i - 1])) { start = i; break; } } // iterate to the right for (var _i = position; _i < text.length; _i++) { if (isWordDelimiter(text[_i])) { end = _i; break; } } return { start: start, end: end }; } function executeCommand(_ref3) { var api = _ref3.api, selectedText = _ref3.selectedText, selection = _ref3.selection, prefix = _ref3.prefix, _ref3$suffix = _ref3.suffix, suffix = _ref3$suffix === void 0 ? prefix : _ref3$suffix; if (selectedText.length >= prefix.length + suffix.length && selectedText.startsWith(prefix) && selectedText.endsWith(suffix)) { api.replaceSelection(selectedText.slice(prefix.length, suffix.length ? -suffix.length : undefined)); api.setSelectionRange({ start: selection.start - prefix.length, end: selection.end - prefix.length }); } else { api.replaceSelection("".concat(prefix).concat(selectedText).concat(suffix)); api.setSelectionRange({ start: selection.start + prefix.length, end: selection.end + prefix.length }); } } /** * Inserts insertionString before each line */ function insertBeforeEachLine(selectedText, insertBefore) { var lines = selectedText.split(/\n/); var insertionLength = 0; var modifiedText = lines.map(function (item, index) { if (typeof insertBefore === 'string') { if (item.startsWith(insertBefore)) { insertionLength -= insertBefore.length; return item.slice(insertBefore.length); } insertionLength += insertBefore.length; return insertBefore + item; } if (typeof insertBefore === 'function') { if (item.startsWith(insertBefore(item, index))) { insertionLength -= insertBefore(item, index).length; return item.slice(insertBefore(item, index).length); } var insertionResult = insertBefore(item, index); insertionLength += insertionResult.length; return insertBefore(item, index) + item; } throw Error('insertion is expected to be either a string or a function'); }).join('\n'); return { modifiedText: modifiedText, insertionLength: insertionLength }; }