redraft
Version:
Renders the result of Draft.js convertToRaw using provided callbacks, works well with React
111 lines (92 loc) • 4.19 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _punycode = require('punycode');
var _punycode2 = _interopRequireDefault(_punycode);
var _CompositeDecorator = require('./helpers/CompositeDecorator');
var _CompositeDecorator2 = _interopRequireDefault(_CompositeDecorator);
var _MultiDecorator = require('./helpers/MultiDecorator');
var _MultiDecorator2 = _interopRequireDefault(_MultiDecorator);
var _stubContentBlock = require('./helpers/stubContentBlock');
var _stubContentBlock2 = _interopRequireDefault(_stubContentBlock);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
/**
* Use CompositeDecorator to build decoratorRanges with ranges, components, and props
*/
// This offsets or rather recalculates ranges for decorators
// with punycode.ucs2.decode
var offsetRanges = function offsetRanges(ranges, block) {
// if there are no decorator skip this step
ranges.forEach(function (range) {
var pre = block.text.substring(0, range.offset);
var decorated = block.text.substring(range.offset, range.offset + range.length);
// eslint-disable-next-line no-param-reassign
range.offset = _punycode2.default.ucs2.decode(pre).length;
// eslint-disable-next-line no-param-reassign
range.length = _punycode2.default.ucs2.decode(decorated).length;
});
return ranges;
};
// Return true if decorator implements the DraftDecoratorType interface
// @see https://github.com/facebook/draft-js/blob/master/src/model/decorators/DraftDecoratorType.js
var decoratorIsCustom = function decoratorIsCustom(decorator) {
return typeof decorator.getDecorations === 'function' && typeof decorator.getComponentForKey === 'function' && typeof decorator.getPropsForKey === 'function';
};
var resolveDecorators = function resolveDecorators(decorators) {
var compositeDecorator = new _CompositeDecorator2.default(decorators.filter(function (decorator) {
return !decoratorIsCustom(decorator);
}));
var customDecorators = decorators.filter(function (decorator) {
return decoratorIsCustom(decorator);
});
var decor = [].concat(_toConsumableArray(customDecorators), [compositeDecorator]);
return new _MultiDecorator2.default(decor);
};
var decorateBlock = function decorateBlock(block, decorators, contentState, _ref) {
var createContentBlock = _ref.createContentBlock;
var decoratorRanges = [];
// create a Decorator instance
var decorator = resolveDecorators(decorators);
// create ContentBlock or a stub
var contentBlock = createContentBlock ? createContentBlock(block) : (0, _stubContentBlock2.default)(block);
// Get decorations from CompositeDecorator instance
var decorations = decorator.getDecorations(contentBlock, contentState);
// Keep track of offset for current key
var offset = 0;
decorations.forEach(function (key, index) {
// If no key just move the offset
if (!key) {
offset += 1;
return;
}
// get next key
var nextIndex = index + 1;
var next = decorations[nextIndex];
// if thers no next key or the key chages build a decoratorRange entry
if (!next || next !== key) {
decoratorRanges.push({
offset: offset,
length: nextIndex - offset,
component: decorator.getComponentForKey(key),
decoratorProps: decorator.getPropsForKey(key) || {},
// save reference to contentState
contentState: contentState
});
// reset the offset to next index
offset = nextIndex;
}
});
// merge the block with decoratorRanges
return Object.assign({}, block, {
decoratorRanges: offsetRanges(decoratorRanges, block)
});
};
var withDecorators = function withDecorators(raw, decorators, options) {
var contentState = options.convertFromRaw && options.convertFromRaw(raw);
return raw.blocks.map(function (block) {
return decorateBlock(block, decorators, contentState, options || {});
});
};
exports.default = withDecorators;