UNPKG

slate

Version:

A completely customizable framework for building rich text editors.

1,337 lines (1,317 loc) 232 kB
// eslint-disable-next-line no-redeclare var PathRef = { transform(ref, op) { var { current, affinity } = ref; if (current == null) { return; } var path = Path.transform(current, op, { affinity }); ref.current = path; if (path == null) { ref.unref(); } } }; // eslint-disable-next-line no-redeclare var PointRef = { transform(ref, op) { var { current, affinity } = ref; if (current == null) { return; } var point = Point.transform(current, op, { affinity }); ref.current = point; if (point == null) { ref.unref(); } } }; // eslint-disable-next-line no-redeclare var RangeRef = { transform(ref, op) { var { current, affinity } = ref; if (current == null) { return; } var path = Range.transform(current, op, { affinity }); ref.current = path; if (path == null) { ref.unref(); } } }; var DIRTY_PATHS = new WeakMap(); var DIRTY_PATH_KEYS = new WeakMap(); var FLUSHING = new WeakMap(); var NORMALIZING = new WeakMap(); var PATH_REFS = new WeakMap(); var POINT_REFS = new WeakMap(); var RANGE_REFS = new WeakMap(); // eslint-disable-next-line no-redeclare var Path = { ancestors(path) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var { reverse = false } = options; var paths = Path.levels(path, options); if (reverse) { paths = paths.slice(1); } else { paths = paths.slice(0, -1); } return paths; }, common(path, another) { var common = []; for (var i = 0; i < path.length && i < another.length; i++) { var av = path[i]; var bv = another[i]; if (typeof av !== 'number' || typeof bv !== 'number') { throw new Error('Got non-numeric path index'); } if (av !== bv) { break; } common.push(av); } return common; }, compare(path, another) { var min = Math.min(path.length, another.length); for (var i = 0; i < min; i++) { if (path[i] < another[i]) return -1; if (path[i] > another[i]) return 1; } return 0; }, endsAfter(path, another) { var i = path.length - 1; var as = path.slice(0, i); var bs = another.slice(0, i); var av = path[i]; var bv = another[i]; return Path.equals(as, bs) && av > bv; }, endsAt(path, another) { var i = path.length; var as = path.slice(0, i); var bs = another.slice(0, i); return Path.equals(as, bs); }, endsBefore(path, another) { var i = path.length - 1; var as = path.slice(0, i); var bs = another.slice(0, i); var av = path[i]; var bv = another[i]; return Path.equals(as, bs) && av < bv; }, equals(path, another) { return path.length === another.length && path.every((n, i) => n === another[i]); }, hasPrevious(path) { return path[path.length - 1] > 0; }, isAfter(path, another) { return Path.compare(path, another) === 1; }, isAncestor(path, another) { return path.length < another.length && Path.compare(path, another) === 0; }, isBefore(path, another) { return Path.compare(path, another) === -1; }, isChild(path, another) { return path.length === another.length + 1 && Path.compare(path, another) === 0; }, isCommon(path, another) { return path.length <= another.length && Path.compare(path, another) === 0; }, isDescendant(path, another) { return path.length > another.length && Path.compare(path, another) === 0; }, isParent(path, another) { return path.length + 1 === another.length && Path.compare(path, another) === 0; }, isPath(value) { return Array.isArray(value) && value.every(n => typeof n === 'number'); }, isSibling(path, another) { if (path.length !== another.length) { return false; } var as = path.slice(0, -1); var bs = another.slice(0, -1); var al = path[path.length - 1]; var bl = another[another.length - 1]; return al !== bl && Path.equals(as, bs); }, levels(path) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var { reverse = false } = options; var list = []; for (var i = 0; i <= path.length; i++) { list.push(path.slice(0, i)); } if (reverse) { list.reverse(); } return list; }, next(path) { if (path.length === 0) { throw new Error("Cannot get the next path of a root path [".concat(path, "], because it has no next index.")); } var last = path[path.length - 1]; return path.slice(0, -1).concat(last + 1); }, operationCanTransformPath(operation) { switch (operation.type) { case 'insert_node': case 'remove_node': case 'merge_node': case 'split_node': case 'move_node': return true; default: return false; } }, parent(path) { if (path.length === 0) { throw new Error("Cannot get the parent path of the root path [".concat(path, "].")); } return path.slice(0, -1); }, previous(path) { if (path.length === 0) { throw new Error("Cannot get the previous path of a root path [".concat(path, "], because it has no previous index.")); } var last = path[path.length - 1]; if (last <= 0) { throw new Error("Cannot get the previous path of a first child path [".concat(path, "] because it would result in a negative index.")); } return path.slice(0, -1).concat(last - 1); }, relative(path, ancestor) { if (!Path.isAncestor(ancestor, path) && !Path.equals(path, ancestor)) { throw new Error("Cannot get the relative path of [".concat(path, "] inside ancestor [").concat(ancestor, "], because it is not above or equal to the path.")); } return path.slice(ancestor.length); }, transform(path, operation) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (!path) return null; // PERF: use destructing instead of immer var p = [...path]; var { affinity = 'forward' } = options; // PERF: Exit early if the operation is guaranteed not to have an effect. if (path.length === 0) { return p; } switch (operation.type) { case 'insert_node': { var { path: op } = operation; if (Path.equals(op, p) || Path.endsBefore(op, p) || Path.isAncestor(op, p)) { p[op.length - 1] += 1; } break; } case 'remove_node': { var { path: _op } = operation; if (Path.equals(_op, p) || Path.isAncestor(_op, p)) { return null; } else if (Path.endsBefore(_op, p)) { p[_op.length - 1] -= 1; } break; } case 'merge_node': { var { path: _op2, position } = operation; if (Path.equals(_op2, p) || Path.endsBefore(_op2, p)) { p[_op2.length - 1] -= 1; } else if (Path.isAncestor(_op2, p)) { p[_op2.length - 1] -= 1; p[_op2.length] += position; } break; } case 'split_node': { var { path: _op3, position: _position } = operation; if (Path.equals(_op3, p)) { if (affinity === 'forward') { p[p.length - 1] += 1; } else if (affinity === 'backward') ; else { return null; } } else if (Path.endsBefore(_op3, p)) { p[_op3.length - 1] += 1; } else if (Path.isAncestor(_op3, p) && path[_op3.length] >= _position) { p[_op3.length - 1] += 1; p[_op3.length] -= _position; } break; } case 'move_node': { var { path: _op4, newPath: onp } = operation; // If the old and new path are the same, it's a no-op. if (Path.equals(_op4, onp)) { return p; } if (Path.isAncestor(_op4, p) || Path.equals(_op4, p)) { var copy = onp.slice(); if (Path.endsBefore(_op4, onp) && _op4.length < onp.length) { copy[_op4.length - 1] -= 1; } return copy.concat(p.slice(_op4.length)); } else if (Path.isSibling(_op4, onp) && (Path.isAncestor(onp, p) || Path.equals(onp, p))) { if (Path.endsBefore(_op4, p)) { p[_op4.length - 1] -= 1; } else { p[_op4.length - 1] += 1; } } else if (Path.endsBefore(onp, p) || Path.equals(onp, p) || Path.isAncestor(onp, p)) { if (Path.endsBefore(_op4, p)) { p[_op4.length - 1] -= 1; } p[onp.length - 1] += 1; } else if (Path.endsBefore(_op4, p)) { if (Path.equals(onp, p)) { p[onp.length - 1] += 1; } p[_op4.length - 1] -= 1; } break; } } return p; } }; function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } var _excluded$4 = ["anchor", "focus"]; function ownKeys$g(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread$g(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$g(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$g(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // eslint-disable-next-line no-redeclare var Range = { edges(range) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var { reverse = false } = options; var { anchor, focus } = range; return Range.isBackward(range) === reverse ? [anchor, focus] : [focus, anchor]; }, end(range) { var [, end] = Range.edges(range); return end; }, equals(range, another) { return Point.equals(range.anchor, another.anchor) && Point.equals(range.focus, another.focus); }, surrounds(range, target) { var intersectionRange = Range.intersection(range, target); if (!intersectionRange) { return false; } return Range.equals(intersectionRange, target); }, includes(range, target) { if (Location.isRange(target)) { if (Range.includes(range, target.anchor) || Range.includes(range, target.focus)) { return true; } var [rs, re] = Range.edges(range); var [ts, te] = Range.edges(target); return Point.isBefore(rs, ts) && Point.isAfter(re, te); } var [start, end] = Range.edges(range); var isAfterStart = false; var isBeforeEnd = false; if (Location.isPoint(target)) { isAfterStart = Point.compare(target, start) >= 0; isBeforeEnd = Point.compare(target, end) <= 0; } else { isAfterStart = Path.compare(target, start.path) >= 0; isBeforeEnd = Path.compare(target, end.path) <= 0; } return isAfterStart && isBeforeEnd; }, intersection(range, another) { var { anchor, focus } = range, rest = _objectWithoutProperties(range, _excluded$4); var [s1, e1] = Range.edges(range); var [s2, e2] = Range.edges(another); var start = Point.isBefore(s1, s2) ? s2 : s1; var end = Point.isBefore(e1, e2) ? e1 : e2; if (Point.isBefore(end, start)) { return null; } else { return _objectSpread$g({ anchor: start, focus: end }, rest); } }, isBackward(range) { var { anchor, focus } = range; return Point.isAfter(anchor, focus); }, isCollapsed(range) { var { anchor, focus } = range; return Point.equals(anchor, focus); }, isExpanded(range) { return !Range.isCollapsed(range); }, isForward(range) { return !Range.isBackward(range); }, isRange(value) { return isObject(value) && Point.isPoint(value.anchor) && Point.isPoint(value.focus); }, *points(range) { yield [range.anchor, 'anchor']; yield [range.focus, 'focus']; }, start(range) { var [start] = Range.edges(range); return start; }, transform(range, op) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (range === null) { return null; } var { affinity = 'inward' } = options; var affinityAnchor; var affinityFocus; if (affinity === 'inward') { // If the range is collapsed, make sure to use the same affinity to // avoid the two points passing each other and expanding in the opposite // direction var isCollapsed = Range.isCollapsed(range); if (Range.isForward(range)) { affinityAnchor = 'forward'; affinityFocus = isCollapsed ? affinityAnchor : 'backward'; } else { affinityAnchor = 'backward'; affinityFocus = isCollapsed ? affinityAnchor : 'forward'; } } else if (affinity === 'outward') { if (Range.isForward(range)) { affinityAnchor = 'backward'; affinityFocus = 'forward'; } else { affinityAnchor = 'forward'; affinityFocus = 'backward'; } } else { affinityAnchor = affinity; affinityFocus = affinity; } var anchor = Point.transform(range.anchor, op, { affinity: affinityAnchor }); var focus = Point.transform(range.focus, op, { affinity: affinityFocus }); if (!anchor || !focus) { return null; } return { anchor, focus }; } }; /** * Shared the function with isElementType utility */ var isElement = function isElement(value) { var { deep = false } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (!isObject(value)) return false; // PERF: No need to use the full Editor.isEditor here var isEditor = typeof value.apply === 'function'; if (isEditor) return false; var isChildrenValid = deep ? Node.isNodeList(value.children) : Array.isArray(value.children); return isChildrenValid; }; // eslint-disable-next-line no-redeclare var Element = { isAncestor(value) { var { deep = false } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return isObject(value) && Node.isNodeList(value.children, { deep }); }, isElement, isElementList(value) { var { deep = false } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return Array.isArray(value) && value.every(val => Element.isElement(val, { deep })); }, isElementProps(props) { return props.children !== undefined; }, isElementType: function isElementType(value, elementVal) { var elementKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'type'; return isElement(value) && value[elementKey] === elementVal; }, matches(element, props) { for (var key in props) { if (key === 'children') { continue; } if (element[key] !== props[key]) { return false; } } return true; } }; var _excluded$3 = ["text"], _excluded2$3 = ["children"]; function ownKeys$f(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread$f(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$f(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$f(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // eslint-disable-next-line no-redeclare var Node = { ancestor(root, path) { var node = Node.get(root, path); if (Node.isText(node)) { throw new Error("Cannot get the ancestor node at path [".concat(path, "] because it refers to a text node instead: ").concat(Scrubber.stringify(node))); } return node; }, ancestors(root, path) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return function* () { for (var p of Path.ancestors(path, options)) { var n = Node.ancestor(root, p); var entry = [n, p]; yield entry; } }(); }, child(root, index) { if (Node.isText(root)) { throw new Error("Cannot get the child of a text node: ".concat(Scrubber.stringify(root))); } if (typeof index !== 'number') { throw new Error('Expected index to be a number'); } var c = root.children[index]; if (c == null) { throw new Error("Cannot get child at index `".concat(index, "` in node: ").concat(Scrubber.stringify(root))); } return c; }, children(root, path) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return function* () { var { reverse = false } = options; var ancestor = Node.ancestor(root, path); var { children } = ancestor; var index = reverse ? children.length - 1 : 0; while (reverse ? index >= 0 : index < children.length) { var child = Node.child(ancestor, index); var childPath = path.concat(index); yield [child, childPath]; index = reverse ? index - 1 : index + 1; } }(); }, common(root, path, another) { var p = Path.common(path, another); var n = Node.get(root, p); return [n, p]; }, descendant(root, path) { var node = Node.get(root, path); if (Node.isEditor(node)) { throw new Error("Cannot get the descendant node at path [".concat(path, "] because it refers to the root editor node instead: ").concat(Scrubber.stringify(node))); } return node; }, descendants(root) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return function* () { for (var [node, path] of Node.nodes(root, options)) { if (path.length !== 0) { // NOTE: we have to coerce here because checking the path's length does // guarantee that `node` is not a `Editor`, but TypeScript doesn't know. yield [node, path]; } } }(); }, elements(root) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return function* () { for (var [node, path] of Node.nodes(root, options)) { if (Node.isElement(node)) { yield [node, path]; } } }(); }, extractProps(node) { if (Node.isText(node)) { var { text } = node, properties = _objectWithoutProperties(node, _excluded$3); return properties; } else { var { children } = node, properties = _objectWithoutProperties(node, _excluded2$3); return properties; } }, first(root, path) { var p = path.slice(); var n = Node.get(root, p); while (n) { if (Node.isText(n) || n.children.length === 0) { break; } else { n = n.children[0]; p.push(0); } } return [n, p]; }, fragment(root, range) { var newRoot = { children: root.children }; var [start, end] = Range.edges(range); var nodeEntries = Node.nodes(newRoot, { reverse: true, pass: _ref => { var [, path] = _ref; return !Range.includes(range, path); } }); var _loop = function _loop() { if (!Range.includes(range, path)) { var index = path[path.length - 1]; modifyChildren(newRoot, Path.parent(path), children => removeChildren(children, index, 1)); } if (Path.equals(path, end.path)) { modifyLeaf(newRoot, path, node => { var before = node.text.slice(0, end.offset); return _objectSpread$f(_objectSpread$f({}, node), {}, { text: before }); }); } if (Path.equals(path, start.path)) { modifyLeaf(newRoot, path, node => { var before = node.text.slice(start.offset); return _objectSpread$f(_objectSpread$f({}, node), {}, { text: before }); }); } }; for (var [, path] of nodeEntries) { _loop(); } return newRoot.children; }, get(root, path) { var node = Node.getIf(root, path); if (node === undefined) { throw new Error("Cannot find a descendant at path [".concat(path, "] in node: ").concat(Scrubber.stringify(root))); } return node; }, getIf(root, path) { var node = root; for (var i = 0; i < path.length; i++) { var p = path[i]; if (typeof p !== 'number') { throw new Error('Got non-numeric path index'); } if (Node.isText(node) || !node.children[p]) { return; } node = node.children[p]; } return node; }, has(root, path) { var node = root; for (var i = 0; i < path.length; i++) { var p = path[i]; if (typeof p !== 'number') { throw new Error('Got non-numeric path index'); } if (Node.isText(node) || !node.children[p]) { return false; } node = node.children[p]; } return true; }, isAncestor(node) { return !Node.isText(node); }, isEditor(node) { return typeof node.apply === 'function'; }, isElement(node) { return Array.isArray(node.children) && typeof node.apply !== 'function'; }, isNode(value) { var { deep = false } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return Text.isText(value) || Element.isElement(value, { deep }) || Editor.isEditor(value, { deep }); }, isNodeList(value) { var { deep = false } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return Array.isArray(value) && value.every(val => Node.isNode(val, { deep })); }, isText(node) { return typeof node.text === 'string'; }, last(root, path) { var p = path.slice(); var n = Node.get(root, p); while (n) { if (Node.isText(n) || n.children.length === 0) { break; } else { var i = n.children.length - 1; n = n.children[i]; p.push(i); } } return [n, p]; }, leaf(root, path) { var node = Node.get(root, path); if (!Node.isText(node)) { throw new Error("Cannot get the leaf node at path [".concat(path, "] because it refers to a non-leaf node: ").concat(Scrubber.stringify(node))); } return node; }, levels(root, path) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return function* () { for (var p of Path.levels(path, options)) { var n = Node.get(root, p); yield [n, p]; } }(); }, matches(node, props) { return Node.isElement(node) && Element.isElementProps(props) && Element.matches(node, props) || Node.isText(node) && Text.isTextProps(props) && Text.matches(node, props); }, nodes(root) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return function* () { var { pass, reverse = false } = options; var { from = [], to } = options; var visited = new Set(); var p = []; var n = root; while (true) { if (to && (reverse ? Path.isBefore(p, to) : Path.isAfter(p, to))) { break; } if (!visited.has(n)) { yield [n, p]; } // If we're allowed to go downward and we haven't descended yet, do. if (!visited.has(n) && !Node.isText(n) && n.children.length !== 0 && (pass == null || pass([n, p]) === false)) { visited.add(n); var nextIndex = reverse ? n.children.length - 1 : 0; if (Path.isAncestor(p, from)) { nextIndex = from[p.length]; } p = p.concat(nextIndex); n = Node.get(root, p); continue; } // If we're at the root and we can't go down, we're done. if (p.length === 0) { break; } // If we're going forward... if (!reverse) { var newPath = Path.next(p); if (Node.has(root, newPath)) { p = newPath; n = Node.get(root, p); continue; } } // If we're going backward... if (reverse && p[p.length - 1] !== 0) { var _newPath = Path.previous(p); p = _newPath; n = Node.get(root, p); continue; } // Otherwise we're going upward... p = Path.parent(p); n = Node.get(root, p); visited.add(n); } }(); }, parent(root, path) { var parentPath = Path.parent(path); var node = Node.get(root, parentPath); if (Node.isText(node)) { // this can happen if `path` points somewhere that doesnt exist and it's where a child of a text node would be throw new Error("Cannot get the parent of path [".concat(path, "] because it does not exist in the root.")); } return node; }, string(node) { if (Node.isText(node)) { return node.text; } else { return node.children.map(Node.string).join(''); } }, texts(root) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return function* () { for (var [node, path] of Node.nodes(root, options)) { if (Node.isText(node)) { yield [node, path]; } } }(); } }; function ownKeys$e(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread$e(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$e(Object(t), true).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$e(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // eslint-disable-next-line no-redeclare var Operation = { isNodeOperation(value) { return Operation.isOperation(value) && value.type.endsWith('_node'); }, isOperation(value) { if (!isObject(value)) { return false; } switch (value.type) { case 'insert_node': return Path.isPath(value.path) && Node.isNode(value.node); case 'insert_text': return typeof value.offset === 'number' && typeof value.text === 'string' && Path.isPath(value.path); case 'merge_node': return typeof value.position === 'number' && Path.isPath(value.path) && isObject(value.properties); case 'move_node': return Path.isPath(value.path) && Path.isPath(value.newPath); case 'remove_node': return Path.isPath(value.path) && Node.isNode(value.node); case 'remove_text': return typeof value.offset === 'number' && typeof value.text === 'string' && Path.isPath(value.path); case 'set_node': return Path.isPath(value.path) && isObject(value.properties) && isObject(value.newProperties); case 'set_selection': return value.properties === null && Range.isRange(value.newProperties) || value.newProperties === null && Range.isRange(value.properties) || isObject(value.properties) && isObject(value.newProperties); case 'split_node': return Path.isPath(value.path) && typeof value.position === 'number' && isObject(value.properties); default: return false; } }, isOperationList(value) { return Array.isArray(value) && value.every(val => Operation.isOperation(val)); }, isSelectionOperation(value) { return Operation.isOperation(value) && value.type.endsWith('_selection'); }, isTextOperation(value) { return Operation.isOperation(value) && value.type.endsWith('_text'); }, inverse(op) { switch (op.type) { case 'insert_node': { return _objectSpread$e(_objectSpread$e({}, op), {}, { type: 'remove_node' }); } case 'insert_text': { return _objectSpread$e(_objectSpread$e({}, op), {}, { type: 'remove_text' }); } case 'merge_node': { return _objectSpread$e(_objectSpread$e({}, op), {}, { type: 'split_node', path: Path.previous(op.path) }); } case 'move_node': { var { newPath, path } = op; // PERF: in this case the move operation is a no-op anyways. if (Path.equals(newPath, path)) { return op; } // If the move happens completely within a single parent the path and // newPath are stable with respect to each other. if (Path.isSibling(path, newPath)) { return _objectSpread$e(_objectSpread$e({}, op), {}, { path: newPath, newPath: path }); } // If the move does not happen within a single parent it is possible // for the move to impact the true path to the location where the node // was removed from and where it was inserted. We have to adjust for this // and find the original path. We can accomplish this (only in non-sibling) // moves by looking at the impact of the move operation on the node // after the original move path. var inversePath = Path.transform(path, op); var inverseNewPath = Path.transform(Path.next(path), op); return _objectSpread$e(_objectSpread$e({}, op), {}, { path: inversePath, newPath: inverseNewPath }); } case 'remove_node': { return _objectSpread$e(_objectSpread$e({}, op), {}, { type: 'insert_node' }); } case 'remove_text': { return _objectSpread$e(_objectSpread$e({}, op), {}, { type: 'insert_text' }); } case 'set_node': { var { properties, newProperties } = op; return _objectSpread$e(_objectSpread$e({}, op), {}, { properties: newProperties, newProperties: properties }); } case 'set_selection': { var { properties: _properties, newProperties: _newProperties } = op; if (_properties == null) { return _objectSpread$e(_objectSpread$e({}, op), {}, { properties: _newProperties, newProperties: null }); } else if (_newProperties == null) { return _objectSpread$e(_objectSpread$e({}, op), {}, { properties: null, newProperties: _properties }); } else { return _objectSpread$e(_objectSpread$e({}, op), {}, { properties: _newProperties, newProperties: _properties }); } } case 'split_node': { return _objectSpread$e(_objectSpread$e({}, op), {}, { type: 'merge_node', path: Path.next(op.path) }); } } } }; var isObject = value => typeof value === 'object' && value !== null; /** * Custom deep equal comparison for Slate nodes. Since Slate only supports plain * values, arrays and nested objects, we don't need a general purpose deep * equality check. * * Slate objects are designed to be serialised, so missing keys are deliberately * normalised to undefined. */ var isDeepEqual = (a, b) => { if (Array.isArray(a) && Array.isArray(b)) { if (a.length !== b.length) return false; for (var i = 0; i < a.length; i++) { if (!isDeepEqual(a[i], b[i])) return false; } return true; } if (isObject(a) && isObject(b)) { for (var key in a) { var valueA = Object.hasOwn(a, key) ? a[key] : undefined; var valueB = Object.hasOwn(b, key) ? b[key] : undefined; if (!isDeepEqual(valueA, valueB)) return false; } // Deep object equality is only necessary in one direction; in the reverse // direction we are only looking for keys that are missing. As above, // undefined keys treated the same as missing keys. for (var _key in b) { if (a[_key] === undefined && b[_key] !== undefined) return false; } return true; } return a === b; }; /** * Get the default location to insert content into the editor. * By default, use the selection as the target location. But if there is * no selection, insert at the end of the document since that is such a * common use case when inserting from a non-selected state. */ var getDefaultInsertLocation = editor => { if (editor.selection) { return editor.selection; } else if (editor.children.length > 0) { return Editor.end(editor, []); } else { return [0]; } }; var matchPath = (editor, path) => { var [node] = Editor.node(editor, path); return n => n === node; }; // Character (grapheme cluster) boundaries are determined according to // the default grapheme cluster boundary specification, extended grapheme clusters variant[1]. // // References: // // [1] https://www.unicode.org/reports/tr29/#Default_Grapheme_Cluster_Table // [2] https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakProperty.txt // [3] https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.html // [4] https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt /** * Get the distance to the end of the first character in a string of text. */ var getCharacterDistance = function getCharacterDistance(str) { var isRTL = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var isLTR = !isRTL; var codepoints = isRTL ? codepointsIteratorRTL(str) : str; var left = CodepointType.None; var right = CodepointType.None; var distance = 0; // Evaluation of these conditions are deferred. var gb11 = null; // Is GB11 applicable? var gb12Or13 = null; // Is GB12 or GB13 applicable? var gb9c = null; // Is GB9c applicable? for (var char of codepoints) { var code = char.codePointAt(0); if (!code) break; var type = getCodepointType(char, code); [left, right] = isLTR ? [right, type] : [type, left]; if (intersects(left, CodepointType.ZWJ) && intersects(right, CodepointType.ExtPict)) { if (isLTR) { gb11 = endsWithEmojiZWJ(str.substring(0, distance)); } else { gb11 = endsWithEmojiZWJ(str.substring(0, str.length - distance)); } if (!gb11) break; } if (intersects(left, CodepointType.RI) && intersects(right, CodepointType.RI)) { if (gb12Or13 !== null) { gb12Or13 = !gb12Or13; } else { if (isLTR) { gb12Or13 = true; } else { gb12Or13 = endsWithOddNumberOfRIs(str.substring(0, str.length - distance)); } } if (!gb12Or13) break; } if (intersects(left, CodepointType.InCBLinker | CodepointType.InCBExtend) && intersects(right, CodepointType.InCBConsonant)) { if (isLTR) { gb9c = endsWithConjunctLinker(str.substring(0, distance)); } else { gb9c = endsWithConjunctLinker(str.substring(0, str.length - distance)); } if (!gb9c) break; } if (left !== CodepointType.None && right !== CodepointType.None && isBoundaryPair(left, right)) { break; } distance += char.length; } return distance || 1; }; var SPACE = /\s/; var PUNCTUATION = /[\u002B\u0021-\u0023\u0025-\u002A\u002C-\u002F\u003A\u003B\u003F\u0040\u005B-\u005D\u005F\u007B\u007D\u00A1\u00A7\u00AB\u00B6\u00B7\u00BB\u00BF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E3B\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]/; var CHAMELEON = /['\u2018\u2019]/; /** * Get the distance to the end of the first word in a string of text. */ var getWordDistance = function getWordDistance(text) { var isRTL = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var dist = 0; var started = false; while (text.length > 0) { var charDist = getCharacterDistance(text, isRTL); var [char, remaining] = splitByCharacterDistance(text, charDist, isRTL); if (isWordCharacter(char, remaining, isRTL)) { started = true; dist += charDist; } else if (!started) { dist += charDist; } else { break; } text = remaining; } return dist; }; /** * Split a string in two parts at a given distance starting from the end when * `isRTL` is set to `true`. */ var splitByCharacterDistance = (str, dist, isRTL) => { if (isRTL) { var at = str.length - dist; return [str.slice(at, str.length), str.slice(0, at)]; } return [str.slice(0, dist), str.slice(dist)]; }; /** * Check if a character is a word character. The `remaining` argument is used * because sometimes you must read subsequent characters to truly determine it. */ var isWordCharacter = function isWordCharacter(char, remaining) { var isRTL = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (SPACE.test(char)) { return false; } // Chameleons count as word characters as long as they're in a word, so // recurse to see if the next one is a word character or not. if (CHAMELEON.test(char)) { var charDist = getCharacterDistance(remaining, isRTL); var [nextChar, nextRemaining] = splitByCharacterDistance(remaining, charDist, isRTL); if (isWordCharacter(nextChar, nextRemaining, isRTL)) { return true; } } if (PUNCTUATION.test(char)) { return false; } return true; }; /** * Iterate on codepoints from right to left. */ var codepointsIteratorRTL = function* codepointsIteratorRTL(str) { var end = str.length - 1; for (var i = 0; i < str.length; i++) { var char1 = str.charAt(end - i); if (isLowSurrogate(char1.charCodeAt(0))) { var char2 = str.charAt(end - i - 1); if (isHighSurrogate(char2.charCodeAt(0))) { yield char2 + char1; i++; continue; } } yield char1; } }; /** * Is `charCode` a high surrogate. * * https://en.wikipedia.org/wiki/Universal_Character_Set_characters#Surrogates */ var isHighSurrogate = charCode => { return charCode >= 0xd800 && charCode <= 0xdbff; }; /** * Is `charCode` a low surrogate. * * https://en.wikipedia.org/wiki/Universal_Character_Set_characters#Surrogates */ var isLowSurrogate = charCode => { return charCode >= 0xdc00 && charCode <= 0xdfff; }; var CodepointType; (function (CodepointType) { CodepointType[CodepointType["None"] = 0] = "None"; CodepointType[CodepointType["Extend"] = 1] = "Extend"; CodepointType[CodepointType["ZWJ"] = 2] = "ZWJ"; CodepointType[CodepointType["RI"] = 4] = "RI"; CodepointType[CodepointType["Prepend"] = 8] = "Prepend"; CodepointType[CodepointType["SpacingMark"] = 16] = "SpacingMark"; CodepointType[CodepointType["L"] = 32] = "L"; CodepointType[CodepointType["V"] = 64] = "V"; CodepointType[CodepointType["T"] = 128] = "T"; CodepointType[CodepointType["LV"] = 256] = "LV"; CodepointType[CodepointType["LVT"] = 512] = "LVT"; CodepointType[CodepointType["ExtPict"] = 1024] = "ExtPict"; CodepointType[CodepointType["Any"] = 2048] = "Any"; CodepointType[CodepointType["InCBConsonant"] = 4096] = "InCBConsonant"; CodepointType[CodepointType["InCBExtend"] = 8192] = "InCBExtend"; CodepointType[CodepointType["InCBLinker"] = 16384] = "InCBLinker"; })(CodepointType || (CodepointType = {})); var reExtend = /^(?:[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u0898-\u089F\u08CA-\u08E1\u08E3-\u0902\u093A\u093C\u0941-\u0948\u094D\u0951-\u0957\u0962\u0963\u0981\u09BC\u09BE\u09C1-\u09C4\u09CD\u09D7\u09E2\u09E3\u09FE\u0A01\u0A02\u0A3C\u0A41\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81\u0A82\u0ABC\u0AC1-\u0AC5\u0AC7\u0AC8\u0ACD\u0AE2\u0AE3\u0AFA-\u0AFF\u0B01\u0B3C\u0B3E\u0B3F\u0B41-\u0B44\u0B4D\u0B55-\u0B57\u0B62\u0B63\u0B82\u0BBE\u0BC0\u0BCD\u0BD7\u0C00\u0C04\u0C3C\u0C3E-\u0C40\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81\u0CBC\u0CBF\u0CC2\u0CC6\u0CCC\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D00\u0D01\u0D3B\u0D3C\u0D3E\u0D41-\u0D44\u0D4D\u0D57\u0D62\u0D63\u0D81\u0DCA\u0DCF\u0DD2-\u0DD4\u0DD6\u0DDF\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EBC\u0EC8-\u0ECE\u0F18\u0F19\u0F35\u0F37\u0F39\u0F71-\u0F7E\u0F80-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102D-\u1030\u1032-\u1037\u1039\u103A\u103D\u103E\u1058\u1059\u105E-\u1060\u1071-\u1074\u1082\u1085\u1086\u108D\u109D\u135D-\u135F\u1712-\u1714\u1732\u1733\u1752\u1753\u1772\u1773\u17B4\u17B5\u17B7-\u17BD\u17C6\u17C9-\u17D3\u17DD\u180B-\u180D\u180F\u1885\u1886\u18A9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193B\u1A17\u1A18\u1A1B\u1A56\u1A58-\u1A5E\u1A60\u1A62\u1A65-\u1A6C\u1A73-\u1A7C\u1A7F\u1AB0-\u1ACE\u1B00-\u1B03\u1B34-\u1B3A\u1B3C\u1B42\u1B6B-\u1B73\u1B80\u1B81\u1BA2-\u1BA5\u1BA8\u1BA9\u1BAB-\u1BAD\u1BE6\u1BE8\u1BE9\u1BED\u1BEF-\u1BF1\u1C2C-\u1C33\u1C36\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE0\u1CE2-\u1CE8\u1CED\u1CF4\u1CF8\u1CF9\u1DC0-\u1DFF\u200C\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA825\uA826\uA82C\uA8C4\uA8C5\uA8E0-\uA8F1\uA8FF\uA926-\uA92D\uA947-\uA951\uA980-\uA982\uA9B3\uA9B6-\uA9B9\uA9BC\uA9BD\uA9E5\uAA29-\uAA2E\uAA31\uAA32\uAA35\uAA36\uAA43\uAA4C\uAA7C\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEC\uAAED\uAAF6\uABE5\uABE8\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F\uFF9E\uFF9F]|\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD803[\uDD24-\uDD27\uDEAB\uDEAC\uDEFD-\uDEFF\uDF46-\uDF50\uDF82-\uDF85]|\uD804[\uDC01\uDC38-\uDC46\uDC70\uDC73\uDC74\uDC7F-\uDC81\uDCB3-\uDCB6\uDCB9\uDCBA\uDCC2\uDD00-\uDD02\uDD27-\uDD2B\uDD2D-\uDD34\uDD73\uDD80\uDD81\uDDB6-\uDDBE\uDDC9-\uDDCC\uDDCF\uDE2F-\uDE31\uDE34\uDE36\uDE37\uDE3E\uDE41\uDEDF\uDEE3-\uDEEA\uDF00\uDF01\uDF3B\uDF3C\uDF3E\uDF40\uDF57\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC38-\uDC3F\uDC42-\uDC44\uDC46\uDC5E\uDCB0\uDCB3-\uDCB8\uDCBA\uDCBD\uDCBF\uDCC0\uDCC2\uDCC3\uDDAF\uDDB2-\uDDB5\uDDBC\uDDBD\uDDBF\uDDC0\uDDDC\uDDDD\uDE33-\uDE3A\uDE3D\uDE3F\uDE40\uDEAB\uDEAD\uDEB0-\uDEB5\uDEB7\uDF1D-\uDF1F\uDF22-\uDF25\uDF27-\uDF2B]|\uD806[\uDC2F-\uDC37\uDC39\uDC3A\uDD30\uDD3B\uDD3C\uDD3E\uDD43\uDDD4-\uDDD7\uDDDA\uDDDB\uDDE0\uDE01-\uDE0A\uDE33-\uDE38\uDE3B-\uDE3E\uDE47\uDE51-\uDE56\uDE59-\uDE5B\uDE8A-\uDE96\uDE98\uDE99]|\uD807[\uDC30-\uDC36\uDC38-\uDC3D\uDC3F\uDC92-\uDCA7\uDCAA-\uDCB0\uDCB2\uDCB3\uDCB5\uDCB6\uDD31-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD45\uDD47\uDD90\uDD91\uDD95\uDD97\uDEF3\uDEF4\uDF00\uDF01\uDF36-\uDF3A\uDF40\uDF42]|\uD80D[\uDC40\uDC47-\uDC55]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF4F\uDF8F-\uDF92\uDFE4]|\uD82F[\uDC9D\uDC9E]|\uD833[\uDF00-\uDF2D\uDF30-\uDF46]|\uD834[\uDD65\uDD67-\uDD69\uDD6E-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A\uDC8F\uDD30-\uDD36\uDEAE\uDEEC-\uDEEF]|\uD839[\uDCEC-\uDCEF]|\uD83A[\uDCD0-\uDCD6\uDD44-\uDD4A]|\uD83C[\uDFFB-\uDFFF]|\uDB40[\uDC20-\uDC7F\uDD00-\uDDEF])$/; var rePrepend = /^(?:[\u0600-\u0605\u06DD\u070F\u0890\u0891\u08E2\u0D4E]|\uD804[\uDCBD\uDCCD\uDDC2\uDDC3]|\uD806[\uDD3F\uDD41\uDE3A\uDE84-\uDE89]|\uD807\uDD46)$/; var reSpacingMark = /^(?:[\u0903\u093B\u093E-\u0940\u0949-\u094C\u094E\u094F\u0982\u0983\u09BF\u09C0\u09C7\u09C8\u09CB\u09CC\u0A03\u0A3E-\u0A40\u0A83\u0ABE-\u0AC0\u0AC9\u0ACB\u0ACC\u0B02\u0B03\u0B40\u0B47\u0B48\u0B4B\u0B4C\u0BBF\u0BC1\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCC\u0C01-\u0C03\u0C41-\u0C44\u0C82\u0C83\u0CBE\u0CC0\u0CC1\u0CC3\u0CC4\u0CC7\u0CC8\u0CCA\u0CCB\u0D02\u0D03\u0D3F\u0D40\u0D46-\u0D48\u0D4A-\u0D4C\u0D82\u0D83\u0DD0\u0DD1\u0DD8-\u0DDE\u0DF2\u0DF3\u0E33\u0EB3\u0F3E\u0F3F\u0F7F\u1031\u103B\u103C\u1056\u1057\u1084\u1715\u1734\u17B6\u17BE-\u17C5\u17C7\u17C8\u1923-\u1926\u1929-\u192B\u1930\u1931\u1933-\u1938\u1A19\u1A1A\u1A55\u1A57\u1A6D-\u1A72\u1B04\u1B3B\u1B3D-\u1B41\u1B43\u1B44\u1B82\u1BA1\u1BA6\u1BA7\u1BAA\u1BE7\u1BEA-\u1BEC\u1BEE\u1BF2\u1BF3\u1C24-\u1C2B\u1C34\u1C35\u1CE1\u1CF7\uA823\uA824\uA827\uA880\uA881\uA8B4-\uA8C3\uA952\uA953\uA983\uA9B4\uA9B5\uA9BA\uA9BB\uA9BE-\uA9C0\uAA2F\uAA30\uAA33\uAA34\uAA4D\uAAEB\uAAEE\uAAEF\uAAF5\uABE3\uABE4\uABE6\uABE7\uABE9\uABEA\uABEC]|\uD804[\uDC00\uDC02\uDC82\uDCB0-\uDCB2\uDCB7\uDCB8\uDD2C\uDD45\uDD46\uDD82\uDDB3-\uDDB5\uDDBF\uDDC0\uDDCE\uDE2C-\uDE2E\uDE32\uDE33\uDE35\uDEE0-\uDEE2\uDF02\uDF03\uDF3F\uDF41-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF62\uDF63]|\uD805[\uDC35-\uDC37\uDC40\uDC41\uDC45\uDCB1\uDCB2\uDCB9\uDCBB\uDCBC\uDCBE\uDCC1\uDDB0\uDDB1\uDDB8-\uDDBB\uDDBE\uDE30-\uDE32\uDE3B\uDE3C\uDE3E\uDEAC\uDEAE\uDEAF\uDEB6\uDF26]|\uD806[\uDC2C-\uDC2E\uDC38\uDD31-\uDD35\uDD37\uDD38\uDD3D\uDD40\uDD42\uDDD1-\uDDD3\uDDDC-\uDDDF\uDDE4\uDE39\uDE57\uDE58\uDE97]|\uD807[\uDC2F\uDC3E\uDCA9\uDCB1\uDCB4\uDD8A-\uDD8E\uDD93\uDD94\uDD96\uDEF5\uDEF6]|\uD81B[\uDF51-\uDF87\uDFF0\uDFF1]|\uD834[\uDD66\uDD6D])$/; var reL = /^[\u1100-\u115F\uA960-\uA97C]$/; var reV = /^[\u1160-\u11A7\uD7B0-\uD7C6]$/; var reT = /^[\u11A8-\u11FF\uD7CB-\uD7FB]$/; var reLV = /^[\uAC00\uAC1C\uAC38\uAC54\uAC70\uAC8C\uACA8\uACC4\uACE0\uACFC\uAD18\uAD34\uAD50\uAD6C\uAD88\uADA4\uADC0\uADDC\uADF8\uAE14\uAE30\uAE4C\uAE68\uAE84\uAEA0\uAEBC\uAED8\uAEF4\uAF10\uAF2C\uAF48\uAF64\uAF80\uAF9C\uAFB8\uAFD4\uAFF0\uB00C\uB028\uB044\uB060\uB07C\uB098\uB0B4\uB0D0\uB0EC\uB108\uB124\uB140\uB15C\uB178\uB194\uB1B0\uB1CC\uB1E8\uB204\uB220\uB23C\uB258\uB274\uB290\uB2AC\uB2C8\uB2E4\uB300\uB31C\uB338\uB354\uB37