Comparing version
@@ -0,1 +1,6 @@ | ||
## 0.9.0 | ||
- added support for custom Decorator class and accessing contentState #30 | ||
- fixed inline style key collision #29 | ||
- fix unicode-aware string splitting #27 | ||
## 0.8.0 | ||
@@ -2,0 +7,0 @@ - added decorator support (also added example in the README) |
@@ -30,5 +30,8 @@ 'use strict'; | ||
this.decorator = typeof props.decorator !== 'undefined' ? props.decorator : null; | ||
this.decoratorProps = props.decoratorProps || null; | ||
this.decoratedText = typeof props.decoratedText !== 'undefined' ? props.decoratedText : null; | ||
this.contentState = props.contentState; | ||
this.style = props.style || null; | ||
this.styles = props.styles || null; | ||
this.block = props.block || {}; | ||
} | ||
@@ -65,3 +68,3 @@ | ||
// we can just concat strings in case when both the pushed item | ||
// we can just concat strings when both the pushed item | ||
// and the last element of the content array is a string | ||
@@ -76,3 +79,3 @@ if (!stack || stack.length < 1) { | ||
} | ||
// hnadle flat structure | ||
// handle flat structure | ||
if (flat) { | ||
@@ -79,0 +82,0 @@ this.handleFlatPush(string, stack); |
@@ -1,2 +0,2 @@ | ||
"use strict"; | ||
'use strict'; | ||
@@ -13,3 +13,11 @@ Object.defineProperty(exports, "__esModule", { | ||
}).reduce(function (prev, next) { | ||
return Object.assign({}, prev, next); | ||
var mergedStyles = {}; | ||
if (next !== undefined) { | ||
var key = 'text-decoration' in next ? 'text-decoration' : 'textDecoration'; | ||
if (next[key] !== prev[key]) { | ||
// .trim() is necessary for IE9/10/11 and Edge | ||
mergedStyles[key] = [prev[key], next[key]].join(' ').trim(); | ||
} | ||
} | ||
return Object.assign(prev, next, mergedStyles); | ||
}, {}); | ||
@@ -16,0 +24,0 @@ }; |
@@ -9,2 +9,6 @@ 'use strict'; | ||
var _punycode = require('punycode'); | ||
var _punycode2 = _interopRequireDefault(_punycode); | ||
var _ContentNode = require('./ContentNode'); | ||
@@ -24,3 +28,3 @@ | ||
var getString = function getString(array, from, to) { | ||
return array.slice(from, to).join(''); | ||
return _punycode2.default.ucs2.encode(array.slice(from, to)); | ||
}; | ||
@@ -34,2 +38,3 @@ | ||
var textArray = arguments[2]; | ||
var block = arguments[3]; | ||
@@ -43,3 +48,3 @@ var lastIndex = 0; | ||
if (mergedRanges.length < 1) { | ||
nodes.push(new _ContentNode2.default({ start: 0, end: textArray.length })); | ||
nodes.push(new _ContentNode2.default({ block: block, start: 0, end: textArray.length })); | ||
return nodes; | ||
@@ -51,11 +56,14 @@ } | ||
if (range.offset > lastIndex) { | ||
nodes.push(new _ContentNode2.default({ start: lastIndex, end: range.offset })); | ||
nodes.push(new _ContentNode2.default({ block: block, start: lastIndex, end: range.offset })); | ||
} | ||
// push the node for the entity | ||
nodes.push(new _ContentNode2.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 | ||
end: range.offset + range.length, | ||
contentState: range.contentState | ||
})); | ||
@@ -68,2 +76,3 @@ lastIndex = range.offset + range.length; | ||
nodes.push(new _ContentNode2.default({ | ||
block: block, | ||
start: lastIndex, | ||
@@ -166,14 +175,14 @@ end: textArray.length | ||
key: 'parse', | ||
value: function parse(_ref2) { | ||
value: function parse(block) { | ||
var _this2 = this; | ||
var text = _ref2.text, | ||
ranges = _ref2.inlineStyleRanges, | ||
entityRanges = _ref2.entityRanges, | ||
_ref2$decoratorRanges = _ref2.decoratorRanges, | ||
decoratorRanges = _ref2$decoratorRanges === undefined ? [] : _ref2$decoratorRanges; | ||
var text = block.text, | ||
ranges = block.inlineStyleRanges, | ||
entityRanges = block.entityRanges, | ||
_block$decoratorRange = block.decoratorRanges, | ||
decoratorRanges = _block$decoratorRange === undefined ? [] : _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 = Array.from(text); | ||
this.textArray = _punycode2.default.ucs2.decode(text); | ||
this.ranges = ranges; | ||
@@ -184,7 +193,7 @@ this.iterator = 0; | ||
// create entity or empty nodes to place the inline styles in | ||
var nodes = createNodes(entityRanges, decoratorRanges, this.textArray); | ||
var nodes = createNodes(entityRanges, decoratorRanges, this.textArray, block); | ||
var parsedNodes = nodes.map(function (node) { | ||
return _this2.nodeIterator(node, node.start, node.end); | ||
}); | ||
return new _ContentNode2.default({ content: parsedNodes }); | ||
return new _ContentNode2.default({ block: block, content: parsedNodes }); | ||
} | ||
@@ -191,0 +200,0 @@ }]); |
@@ -42,2 +42,4 @@ 'use strict'; | ||
var KEY_DELIMITER = '.'; | ||
/** | ||
@@ -71,6 +73,12 @@ * Recursively renders a node with nested nodes with given callbacks | ||
if (node.decorator !== null) { | ||
return node.decorator({ | ||
// FIXME: few props are missing see https://github.com/facebook/draft-js/blob/0c609d9d3671fdbbe2a290ed160a0537f846f08e/src/component/contents/DraftEditorBlock.react.js#L196-L205 | ||
var decoratorOffsetKey = [node.block.key, node.start, 0].join(KEY_DELIMITER); | ||
return node.decorator(Object.assign({ | ||
children: (0, _checkJoin2.default)(children, options), | ||
decoratedText: node.decoratedText | ||
}); | ||
decoratedText: node.decoratedText, | ||
contentState: node.contentState, | ||
entityKey: node.entity, | ||
offsetKey: decoratorOffsetKey, | ||
key: decoratorOffsetKey | ||
}, node.decoratorProps)); | ||
} | ||
@@ -225,3 +233,3 @@ return children; | ||
var blocksWithDecorators = decorators ? (0, _withDecorators2.default)(raw.blocks, decorators, options) : raw.blocks; | ||
var blocksWithDecorators = decorators || options.Decorator ? (0, _withDecorators2.default)(raw, decorators, options) : raw.blocks; | ||
// Nest blocks by depth | ||
@@ -228,0 +236,0 @@ var blocks = byDepth(blocksWithDecorators); |
@@ -7,2 +7,6 @@ 'use strict'; | ||
var _CompositeDecorator = require('./helpers/CompositeDecorator'); | ||
var _CompositeDecorator2 = _interopRequireDefault(_CompositeDecorator); | ||
var _stubContentBlock = require('./helpers/stubContentBlock'); | ||
@@ -14,28 +18,53 @@ | ||
var populateDecoratorRanges = function populateDecoratorRanges(array, component) { | ||
return function (start, end) { | ||
return array.push({ offset: start, length: end - start, component: component }); | ||
}; | ||
}; | ||
/** | ||
* Calls strategy for each decorator with ContentBlock or its stub | ||
* Use CompositeDecorator to build decoratorRanges with ranges, components, and props | ||
*/ | ||
var decorateBlock = function decorateBlock(block, decorators, _ref) { | ||
var createContentBlock = _ref.createContentBlock; | ||
// TODO: Maybe it would be wold be good to check if CompositeDecorator | ||
// is a valid DraftDecoratorType | ||
var decorateBlock = function decorateBlock(block, decorators, contentState, _ref) { | ||
var createContentBlock = _ref.createContentBlock, | ||
_ref$Decorator = _ref.Decorator, | ||
Decorator = _ref$Decorator === undefined ? _CompositeDecorator2.default : _ref$Decorator; | ||
var decoratorRanges = []; | ||
// create a Decorator instance | ||
var decorator = new Decorator(decorators); | ||
// create ContentBlock or a stub | ||
var contentBlock = createContentBlock ? createContentBlock(block) : (0, _stubContentBlock2.default)(block); | ||
decorators.map(function (_ref2) { | ||
var strategy = _ref2.strategy, | ||
component = _ref2.component; | ||
return strategy(contentBlock, populateDecoratorRanges(decoratorRanges, component)); | ||
// Get decorations from CompositeDecorator instance | ||
var decorations = decorator.getDecorations(contentBlock, contentState).toArray(); | ||
// 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: decoratorRanges }); | ||
}; | ||
var withDecorators = function withDecorators(blocks, decorators, options) { | ||
return blocks.map(function (block) { | ||
return decorateBlock(block, decorators, options || {}); | ||
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 || {}); | ||
}); | ||
@@ -42,0 +71,0 @@ }; |
{ | ||
"name": "redraft", | ||
"version": "0.8.0", | ||
"version": "0.9.0", | ||
"description": "Renders the result of Draft.js convertToRaw using provided callbacks, works well with React", | ||
@@ -25,3 +25,3 @@ "main": "./lib/index.js", | ||
"devDependencies": { | ||
"babel-cli": "^6.6.5", | ||
"babel-cli": "^6.26.0", | ||
"babel-core": "^6.7.2", | ||
@@ -31,6 +31,7 @@ "babel-eslint": "^7.0.0", | ||
"babel-preset-env": "^1.2.1", | ||
"babel-preset-flow": "^6.23.0", | ||
"babel-preset-react": "^6.23.0", | ||
"babel-register": "^6.16.3", | ||
"chai": "^3.5.0", | ||
"draft-js": "^0.10.0", | ||
"draft-js": "^0.10.4", | ||
"eslint": "^3.7.1", | ||
@@ -41,2 +42,3 @@ "eslint-config-airbnb": "^11.2.0", | ||
"eslint-plugin-react": "^6.4.1", | ||
"flow-bin": "^0.57.3", | ||
"linkify-it": "^2.0.3", | ||
@@ -48,3 +50,6 @@ "mocha": "^3.0.2", | ||
"tlds": "^1.183.0" | ||
}, | ||
"dependencies": { | ||
"punycode": "^2.1.0" | ||
} | ||
} |
@@ -87,2 +87,3 @@ | ||
* inspired by https://facebook.github.io/draft-js/docs/advanced-topics-decorators.html | ||
* it's also possible to pass a Decorator class to options instead (or additionaly) | ||
*/ | ||
@@ -92,5 +93,7 @@ decorators: [ | ||
// by default linkStrategy receives a ContentBlock stub (more info under Creating the ContentBlock) | ||
// strategy only receives first two arguments, contentState is yet not provided | ||
strategy: linkStrategy, | ||
// component - a callback as with other renderers | ||
// decoratedText a plain string matched by the strategy | ||
// if your decorator depends on draft-js contentState you need to provide convertFromRaw in redraft options | ||
component: ({ children, decoratedText }) => <a href={decoratedText}>{children}/>, | ||
@@ -170,3 +173,3 @@ } | ||
const renderers = { | ||
style: createStylesRenderer(InlineWrapper, styleMap), | ||
styles: createStylesRenderer(InlineWrapper, styleMap), | ||
... | ||
@@ -189,2 +192,8 @@ }; | ||
### Using custom Decorator class | ||
`Decorator` - use this to pass a custom Decorator class that matches the [DraftDecoratorType](https://github.com/facebook/draft-js/blob/master/src/model/decorators/DraftDecoratorType.js). | ||
### Accessing contentState | ||
`convertFromRaw` - pass the draft-js convertFromRaw to provide the contentState object to both the components in your decorators and the custom Decorator class getDecorations method. | ||
### Creating the ContentBlock | ||
@@ -191,0 +200,0 @@ `createContentBlock` - a function that receives a block and returns a draft-js ContentBlock, if not provided when using decorators redraft will create a ContentBlock stub with only some basic ContentBlock functionality |
Sorry, the diff of this file is not supported yet
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
154912
13.68%26
13.04%985
40.51%213
4.41%1
Infinity%22
10%1
Infinity%+ Added
+ Added