UNPKG

wix-redraft

Version:

Based on github.com/lokiuz/redraft. Adjusted for wix-rich-content needs.

215 lines (169 loc) 8.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _punycode = _interopRequireDefault(require("punycode")); var _ContentNode = _interopRequireDefault(require("./ContentNode")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } /** * Slices the decoded ucs2 array and encodes the result back to a string representation */ var getString = function getString(array, from, to) { return _punycode["default"].ucs2.encode(array.slice(from, to)); }; /** * creates nodes with entity keys and the endOffset */ function createNodes(entityRanges) { var decoratorRanges = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; var textArray = arguments.length > 2 ? arguments[2] : undefined; var block = arguments.length > 3 ? arguments[3] : undefined; var lastIndex = 0; var mergedRanges = [].concat(_toConsumableArray(entityRanges), _toConsumableArray(decoratorRanges)).sort(function (a, b) { return a.offset - b.offset; }); var nodes = []; // if thers no entities will return just a single item if (mergedRanges.length < 1) { nodes.push(new _ContentNode["default"]({ block: block, start: 0, end: textArray.length })); return nodes; } mergedRanges.forEach(function (range) { // create an empty node for content between previous and this entity if (range.offset > lastIndex) { nodes.push(new _ContentNode["default"]({ block: block, start: lastIndex, end: range.offset })); } // push the node for the entity nodes.push(new _ContentNode["default"]({ block: block, entity: range.key, decorator: range.component, decoratorProps: range.decoratorProps, decoratedText: range.component ? getString(textArray, range.offset, range.offset + range.length) : undefined, start: range.offset, end: range.offset + range.length, contentState: range.contentState })); lastIndex = range.offset + range.length; }); // finaly add a node for the remaining text if any if (lastIndex < textArray.length) { nodes.push(new _ContentNode["default"]({ block: block, start: lastIndex, end: textArray.length })); } return nodes; } function addIndexes(indexes, ranges) { ranges.forEach(function (range) { indexes.push(range.offset); indexes.push(range.offset + range.length); }); return indexes; } /** * Creates an array of sorted char indexes to avoid iterating over every single character */ function getRelevantIndexes(text, inlineRanges) { var entityRanges = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; var decoratorRanges = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : []; var relevantIndexes = []; // set indexes to corresponding keys to ensure uniquenes relevantIndexes = addIndexes(relevantIndexes, inlineRanges); relevantIndexes = addIndexes(relevantIndexes, entityRanges); relevantIndexes = addIndexes(relevantIndexes, decoratorRanges); // add text start and end to relevant indexes relevantIndexes.push(0); relevantIndexes.push(text.length); var uniqueRelevantIndexes = relevantIndexes.filter(function (value, index, self) { return self.indexOf(value) === index; }); // and sort it return uniqueRelevantIndexes.sort(function (aa, bb) { return aa - bb; }); } var RawParser = /*#__PURE__*/function () { function RawParser(_ref) { var _ref$flat = _ref.flat, flat = _ref$flat === void 0 ? false : _ref$flat; _classCallCheck(this, RawParser); this.flat = flat; } _createClass(RawParser, [{ key: "relevantStyles", value: function relevantStyles(offset) { var styles = this.ranges.filter(function (range) { return offset >= range.offset && offset < range.offset + range.length; }); return styles.map(function (style) { return style.style; }); } /** * Loops over relevant text indexes */ }, { key: "nodeIterator", value: function nodeIterator(node, start, end) { var _this = this; var indexes = this.relevantIndexes.slice(this.relevantIndexes.indexOf(start), this.relevantIndexes.indexOf(end)); // loops while next index is smaller than the endOffset indexes.forEach(function (index, key) { // figure out what styles this char and the next char need // (regardless of whether there *is* a next char or not) var characterStyles = _this.relevantStyles(index); // calculate distance or set it to 1 if thers no next index var distance = indexes[key + 1] ? indexes[key + 1] - index : 1; // add all the chars up to next relevantIndex var text = getString(_this.textArray, index, index + distance); node.pushContent(text, characterStyles, _this.flat); // if thers no next index and thers more text left to push if (!indexes[key + 1] && index < end) { node.pushContent(getString(_this.textArray, index + 1, end), _this.relevantStyles(end - 1), _this.flat); } }); return node; } /** * Converts raw block to object with nested style objects, * while it returns an object not a string * the idea is still mostly same as backdraft.js (https://github.com/evanc/backdraft-js) */ }, { key: "parse", value: function parse(block) { var _this2 = this; var text = block.text, ranges = block.inlineStyleRanges, entityRanges = block.entityRanges, _block$decoratorRange = block.decoratorRanges, decoratorRanges = _block$decoratorRange === void 0 ? [] : _block$decoratorRange; // Some unicode charactes actualy have length of more than 1 // this creates an array of code points using es6 string iterator this.textArray = _punycode["default"].ucs2.decode(text); this.ranges = ranges; this.iterator = 0; // get all the relevant indexes for whole block this.relevantIndexes = getRelevantIndexes(text, ranges, entityRanges, decoratorRanges); // create entity or empty nodes to place the inline styles in var nodes = createNodes(entityRanges, decoratorRanges, this.textArray, block); var parsedNodes = nodes.map(function (node) { return _this2.nodeIterator(node, node.start, node.end); }); return new _ContentNode["default"]({ block: block, content: parsedNodes }); } }]); return RawParser; }(); exports["default"] = RawParser;