UNPKG

usxeditor

Version:

USX editor react component.

159 lines (158 loc) 7.44 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.defaultDeleteBackward = exports.backspaceDeletesComponent = exports.allowMerge = exports.postIncrementStartOffset = exports.parentTag = exports.getTagName = exports.readTagFromRaw = exports.toOuterUsx = exports.toAttributesString = exports.serializeMerge = exports.serialize = exports.addHandlersToChildren = void 0; var react_1 = __importDefault(require("react")); // Add needed handlers to a react components child components. // Currently adds: // onChanged + onInsertMarker. // The onChanged handler implementation responds to a child components change event and // calculates how that change should be applied to the current component and invokes // the current components onChange property, with the resultant value. // The onInsertMarker handler implementation just passes the event upwards, after updating the events // newValue argument if needed. function addHandlersToChildren(parentProps) { var children = parentProps.children; if (!children) return; var singleChild = false; if (!("length" in children)) { singleChild = true; children = [children]; } var ret = children.filter(function (x) { return x; }).map(function (child, index) { return react_1.default.cloneElement(child, { onChanged: function (v) { return parentProps.onChanged(serialize(children, index, v)); }, onSelectionChanged: parentProps.onSelectionChanged, onInsertMarker: function (isPara, style, newValue) { return parentProps.onInsertMarker(isPara, style, serialize(children, index, newValue)); }, onDeleteBackward: function () { var _a; return (_a = parentProps.onDeleteBackward) === null || _a === void 0 ? void 0 : _a.call(parentProps, index); } }); }); return singleChild ? ret[0] : ret; } exports.addHandlersToChildren = addHandlersToChildren; function serialize(children, replacementIndex, replacementValue) { if (replacementIndex === void 0) { replacementIndex = -1; } if (replacementValue === void 0) { replacementValue = undefined; } if (!children) return ''; if (!("length" in children)) return replacementIndex === 0 ? replacementValue || '' : children.props.raw; return children.filter(function (x) { return x; }).map(function (child, index) { return index === replacementIndex && replacementValue !== undefined ? replacementValue : child.props.raw; }).join(''); } exports.serialize = serialize; function serializeMerge(children, from, to) { if (!children) return ''; if (!("length" in children)) return children.props.raw; return children.map(function (child, index) { var _a, _b; if (!child) return null; // This makes no sense so ignore the merge. if (from === to) return child.props.raw; if (index !== from && index !== to) return child.props.raw; if (index === from) return null; var fromObject = children[from]; var fromObjectContent = (_a = fromObject.props.value) !== null && _a !== void 0 ? _a : serialize(fromObject.props.children); var toObjectContent = (_b = child.props.value) !== null && _b !== void 0 ? _b : serialize(child.props.children); // (from > to) If merging from right into left // (to > from) If merging from left into right var newContents = from > to ? toObjectContent + fromObjectContent : fromObjectContent + toObjectContent; // If EditableText (text node), then just return contents. if (child.props.value) return newContents; return toOuterUsx(readTagFromRaw(child.props.raw), child.props.attrs, newContents); }).join(''); } exports.serializeMerge = serializeMerge; function toAttributesString(attrs) { if (!attrs) return ''; return Object.keys(attrs).map(function (key) { return "".concat(key, "=\"").concat(attrs[key], "\""); }).join(' '); } exports.toAttributesString = toAttributesString; function toOuterUsx(tag, attrs, content) { return "<".concat(tag, " ").concat(toAttributesString(attrs), ">").concat(content, "</").concat(tag, ">"); } exports.toOuterUsx = toOuterUsx; function readTagFromRaw(raw) { if (!raw) return ''; var index = raw.indexOf(' '); if (index === -1) { var endMarker = raw.indexOf('>'); index = raw.indexOf('/>'); if (index !== -1 && endMarker !== -1) index = Math.min(index, endMarker); } if (index === -1) index = raw.indexOf('>'); return raw.substring(1, index); } exports.readTagFromRaw = readTagFromRaw; function getTagName(child) { if (child.props.value) return ''; return readTagFromRaw(child.props.raw); } exports.getTagName = getTagName; function parentTag(tagStack) { if (!tagStack) return null; if (tagStack.length <= 1) return null; return tagStack[tagStack.length - 2]; } exports.parentTag = parentTag; function postIncrementStartOffset(data, text) { var ret = data.startOffset; var implicitOffsetSeparator = 1; // Having an extra offset between text nodes allows distinguishing between being at the end of text node and the start of the next text node. data.startOffset += text.length + implicitOffsetSeparator; return ret; } exports.postIncrementStartOffset = postIncrementStartOffset; function allowMerge(toTag, fromTag) { // Expand this as needed. if (toTag === 'note' || toTag === 'verse' || toTag === 'unmatched') return false; if (fromTag === 'annot') return false; return true; } exports.allowMerge = allowMerge; function backspaceDeletesComponent(toTag) { if (toTag === 'verse') return true; if (toTag === 'unmatched') return true; return false; } exports.backspaceDeletesComponent = backspaceDeletesComponent; function defaultDeleteBackward(props, index, componentTagName, attrs) { var _a; // From first child in paragraph, just pass up for parent component to handle if (index === 0) { (_a = props.onDeleteBackward) === null || _a === void 0 ? void 0 : _a.call(props); } // Combine the child component with it's preceding component. else { var currentComponentTag = getTagName(props.children[index]); var previousComponentTag = getTagName(props.children[index - 1]); if (allowMerge(previousComponentTag, currentComponentTag)) { props.onChanged(toOuterUsx(componentTagName, attrs, serializeMerge(props.children, index, index - 1))); var newSelectionOffset = props.children[index].props.startOffset - 1; props.onSelectionChanged(newSelectionOffset, newSelectionOffset); } else if (backspaceDeletesComponent(previousComponentTag)) { // We could allow just deleting it. (ie. just call serialize(props.children, index - 1, '')) props.onChanged(toOuterUsx(componentTagName, attrs, serialize(props.children, index - 1, ''))); } } } exports.defaultDeleteBackward = defaultDeleteBackward;