slate-hyperscript
Advanced tools
Comparing version
@@ -7,2 +7,23 @@ # Changelog | ||
### `0.7.0` — August 3, 2018 | ||
###### NEW | ||
**Updated to work with `slate@0.37.0` with points.** This isn't a breaking change to any of the API's in `slate-hyperscript` itself, but it does update it to no longer depend on the core API's that were deprecated in `0.37.0`. | ||
###### DEPRECATED | ||
**The `<selection>` tag now takes `<anchor />` and `<focus />` children.** Previously you would set properties like `anchorKey=` or `focusOffset=` directly on the `<selection>` itself, but now these are handled as two children point tags: | ||
```jsx | ||
const selection = ( | ||
<selection> | ||
<anchor key="a" offset={1} /> | ||
<focus key="a" offset={3} /> | ||
</selection> | ||
) | ||
``` | ||
--- | ||
### `0.6.0` — July 27, 2018 | ||
@@ -9,0 +30,0 @@ |
@@ -7,81 +7,2 @@ (function (global, factory) { | ||
/** | ||
* Has own property. | ||
* | ||
* @type {Function} | ||
*/ | ||
var has = Object.prototype.hasOwnProperty; | ||
/** | ||
* To string. | ||
* | ||
* @type {Function} | ||
*/ | ||
var toString = Object.prototype.toString; | ||
/** | ||
* Test whether a value is "empty". | ||
* | ||
* @param {Mixed} val | ||
* @return {Boolean} | ||
*/ | ||
function isEmpty(val) { | ||
// Null and Undefined... | ||
if (val == null) return true | ||
// Booleans... | ||
if ('boolean' == typeof val) return false | ||
// Numbers... | ||
if ('number' == typeof val) return val === 0 | ||
// Strings... | ||
if ('string' == typeof val) return val.length === 0 | ||
// Functions... | ||
if ('function' == typeof val) return val.length === 0 | ||
// Arrays... | ||
if (Array.isArray(val)) return val.length === 0 | ||
// Errors... | ||
if (val instanceof Error) return val.message === '' | ||
// Objects... | ||
if (val.toString == toString) { | ||
switch (val.toString()) { | ||
// Maps, Sets, Files and Errors... | ||
case '[object File]': | ||
case '[object Map]': | ||
case '[object Set]': { | ||
return val.size === 0 | ||
} | ||
// Plain objects... | ||
case '[object Object]': { | ||
for (var key in val) { | ||
if (has.call(val, key)) return false | ||
} | ||
return true | ||
} | ||
} | ||
} | ||
// Anything else... | ||
return false | ||
} | ||
/** | ||
* Export `isEmpty`. | ||
* | ||
* @type {Function} | ||
*/ | ||
var lib = isEmpty; | ||
/*! | ||
@@ -178,24 +99,73 @@ * isobject <https://github.com/jonschlinkert/isobject> | ||
/** | ||
* Create selection point constants, for comparison by reference. | ||
* Point classes that can be created at different points in the document and | ||
* then searched for afterwards, for creating ranges. | ||
* | ||
* @type {Object} | ||
* @type {Class} | ||
*/ | ||
var ANCHOR = {}; | ||
var CURSOR = {}; | ||
var FOCUS = {}; | ||
var CursorPoint = function CursorPoint() { | ||
classCallCheck(this, CursorPoint); | ||
/** | ||
* wrappers for decorator points, for comparison by instanceof, | ||
* and for composition into ranges (anchor.combine(focus), etc) | ||
*/ | ||
this.offset = null; | ||
}; | ||
var DecoratorPoint = function DecoratorPoint(_ref, marks) { | ||
var key = _ref.key, | ||
data = _ref.data; | ||
classCallCheck(this, DecoratorPoint); | ||
var AnchorPoint = function AnchorPoint() { | ||
var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
classCallCheck(this, AnchorPoint); | ||
var _attrs$key = attrs.key, | ||
key = _attrs$key === undefined ? null : _attrs$key, | ||
_attrs$offset = attrs.offset, | ||
offset = _attrs$offset === undefined ? null : _attrs$offset, | ||
_attrs$path = attrs.path, | ||
path = _attrs$path === undefined ? null : _attrs$path; | ||
_initialiseProps.call(this); | ||
this.key = key; | ||
this.offset = offset; | ||
this.path = path; | ||
}; | ||
this._key = key; | ||
var FocusPoint = function FocusPoint() { | ||
var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
classCallCheck(this, FocusPoint); | ||
var _attrs$key2 = attrs.key, | ||
key = _attrs$key2 === undefined ? null : _attrs$key2, | ||
_attrs$offset2 = attrs.offset, | ||
offset = _attrs$offset2 === undefined ? null : _attrs$offset2, | ||
_attrs$path2 = attrs.path, | ||
path = _attrs$path2 === undefined ? null : _attrs$path2; | ||
this.key = key; | ||
this.offset = offset; | ||
this.path = path; | ||
}; | ||
var DecorationPoint = function DecorationPoint(attrs) { | ||
var _this = this; | ||
classCallCheck(this, DecorationPoint); | ||
this.combine = function (focus) { | ||
if (!(focus instanceof DecorationPoint)) throw new Error('misaligned decorations'); | ||
return slate.Range.create(_extends({ | ||
anchor: { | ||
key: _this.key, | ||
offset: _this.offset | ||
}, | ||
focus: { | ||
key: focus.key, | ||
offset: focus.offset | ||
}, | ||
marks: _this.marks, | ||
isAtomic: _this.isAtomic | ||
}, _this.attribs)); | ||
}; | ||
var _attrs$key3 = attrs.key, | ||
key = _attrs$key3 === undefined ? null : _attrs$key3, | ||
_attrs$data = attrs.data, | ||
data = _attrs$data === undefined ? {} : _attrs$data, | ||
marks = attrs.marks; | ||
this.id = key; | ||
this.offset = 0; | ||
this.marks = marks; | ||
@@ -214,36 +184,5 @@ this.attribs = data || {}; | ||
var _initialiseProps = function _initialiseProps() { | ||
var _this = this; | ||
this.withPosition = function (offset) { | ||
_this.offset = offset; | ||
return _this; | ||
}; | ||
this.addOffset = function (offset) { | ||
_this.offset += offset; | ||
return _this; | ||
}; | ||
this.withKey = function (key) { | ||
_this.key = key; | ||
return _this; | ||
}; | ||
this.combine = function (focus) { | ||
if (!(focus instanceof DecoratorPoint)) throw new Error('misaligned decorations'); | ||
return slate.Range.create(_extends({ | ||
anchorKey: _this.key, | ||
focusKey: focus.key, | ||
anchorOffset: _this.offset, | ||
focusOffset: focus.offset, | ||
marks: _this.marks, | ||
isAtomic: _this.isAtomic | ||
}, _this.attribs)); | ||
}; | ||
}; | ||
var CREATORS = { | ||
anchor: function anchor(tagName, attributes, children) { | ||
return ANCHOR; | ||
return new AnchorPoint(attributes); | ||
}, | ||
@@ -256,3 +195,3 @@ block: function block(tagName, attributes, children) { | ||
cursor: function cursor(tagName, attributes, children) { | ||
return CURSOR; | ||
return new CursorPoint(); | ||
}, | ||
@@ -265,3 +204,3 @@ document: function document(tagName, attributes, children) { | ||
focus: function focus(tagName, attributes, children) { | ||
return FOCUS; | ||
return new FocusPoint(attributes); | ||
}, | ||
@@ -280,8 +219,14 @@ inline: function inline(tagName, attributes, children) { | ||
if (attributes.key) { | ||
return new DecoratorPoint(attributes, [{ type: tagName }]); | ||
return new DecorationPoint(_extends({}, attributes, { | ||
marks: [{ type: tagName }] | ||
})); | ||
} | ||
var nodes = createChildren(children, { key: attributes.key }); | ||
var nodes = createChildren(children); | ||
var node = nodes[0]; | ||
nodes[0].__decorations = (nodes[0].__decorations || []).concat([{ | ||
var _node$__decorations = node.__decorations, | ||
__decorations = _node$__decorations === undefined ? [] : _node$__decorations; | ||
var __decoration = { | ||
anchorOffset: 0, | ||
@@ -293,7 +238,29 @@ focusOffset: nodes.reduce(function (len, n) { | ||
isAtomic: !!attributes.data.atomic | ||
}]); | ||
}; | ||
__decorations.push(__decoration); | ||
node.__decorations = __decorations; | ||
return nodes; | ||
}, | ||
selection: function selection(tagName, attributes, children) { | ||
return slate.Range.create(attributes); | ||
var anchor = children.find(function (c) { | ||
return c instanceof AnchorPoint; | ||
}); | ||
var focus = children.find(function (c) { | ||
return c instanceof FocusPoint; | ||
}); | ||
var selection = slate.Range.create(_extends({}, attributes, { | ||
anchor: anchor && { | ||
key: anchor.key, | ||
offset: anchor.offset, | ||
path: anchor.path | ||
}, | ||
focus: focus && { | ||
key: focus.key, | ||
offset: focus.offset, | ||
path: focus.path | ||
} | ||
})); | ||
return selection; | ||
}, | ||
@@ -307,48 +274,62 @@ value: function value(tagName, attributes, children) { | ||
var selection = children.find(slate.Range.isRange) || slate.Range.create(); | ||
var props = {}; | ||
var anchor = void 0; | ||
var focus = void 0; | ||
var decorations = []; | ||
var partialDecorations = {}; | ||
var partials = {}; | ||
// Search the document's texts to see if any of them have the anchor or | ||
// focus information saved, so we can set the selection. | ||
// focus information saved, or decorations applied. | ||
if (document) { | ||
document.getTexts().forEach(function (text) { | ||
if (text.__anchor != null) { | ||
props.anchorKey = text.key; | ||
props.anchorOffset = text.__anchor; | ||
props.isFocused = true; | ||
anchor = slate.Point.create({ key: text.key, offset: text.__anchor.offset }); | ||
} | ||
if (text.__focus != null) { | ||
props.focusKey = text.key; | ||
props.focusOffset = text.__focus; | ||
props.isFocused = true; | ||
focus = slate.Point.create({ key: text.key, offset: text.__focus.offset }); | ||
} | ||
}); | ||
// now check for decorations and hoist them to the top | ||
document.getTexts().forEach(function (text) { | ||
if (text.__decorations != null) { | ||
// add in all mark-like (keyless) decorations | ||
decorations = decorations.concat(text.__decorations.filter(function (d) { | ||
return d._key === undefined; | ||
}).map(function (d) { | ||
return slate.Range.create(_extends({}, d, { | ||
anchorKey: text.key, | ||
focusKey: text.key | ||
})); | ||
})); | ||
text.__decorations.forEach(function (dec) { | ||
var id = dec.id; | ||
// store or combine partial decorations (keyed with anchor / focus) | ||
text.__decorations.filter(function (d) { | ||
return d._key !== undefined; | ||
}).forEach(function (partial) { | ||
if (partialDecorations[partial._key]) { | ||
decorations.push(partialDecorations[partial._key].combine(partial.withKey(text.key))); | ||
var range = void 0; | ||
delete partialDecorations[partial._key]; | ||
return; | ||
if (!id) { | ||
range = slate.Range.create({ | ||
anchor: { | ||
key: text.key, | ||
offset: dec.anchorOffset | ||
}, | ||
focus: { | ||
key: text.key, | ||
offset: dec.focusOffset | ||
}, | ||
marks: dec.marks, | ||
isAtomic: dec.isAtomic | ||
}); | ||
} else if (partials[id]) { | ||
var partial = partials[id]; | ||
delete partials[id]; | ||
range = slate.Range.create({ | ||
anchor: { | ||
key: partial.key, | ||
offset: partial.offset | ||
}, | ||
focus: { | ||
key: text.key, | ||
offset: dec.offset | ||
}, | ||
marks: partial.marks, | ||
isAtomic: partial.isAtomic | ||
}); | ||
} else { | ||
dec.key = text.key; | ||
partials[id] = dec; | ||
} | ||
partialDecorations[partial._key] = partial.withKey(text.key); | ||
if (range) { | ||
decorations.push(range); | ||
} | ||
}); | ||
@@ -359,13 +340,12 @@ } | ||
// should have no more parital decorations outstanding (all paired) | ||
if (Object.keys(partialDecorations).length > 0) { | ||
throw new Error('Slate hyperscript must have both an anchor and focus defined for each keyed decorator.'); | ||
if (Object.keys(partials).length > 0) { | ||
throw new Error('Slate hyperscript must have both a start and an end defined for each decoration using the `key=` prop.'); | ||
} | ||
if (props.anchorKey && !props.focusKey) { | ||
throw new Error('Slate hyperscript must have both `<anchor/>` and `<focus/>` defined if one is defined, but you only defined `<anchor/>`. For collapsed selections, use `<cursor/>`.'); | ||
if (anchor && !focus) { | ||
throw new Error('Slate hyperscript ranges must have both `<anchor />` and `<focus />` defined if one is defined, but you only defined `<anchor />`. For collapsed selections, use `<cursor />` instead.'); | ||
} | ||
if (!props.anchorKey && props.focusKey) { | ||
throw new Error('Slate hyperscript must have both `<anchor/>` and `<focus/>` defined if one is defined, but you only defined `<focus/>`. For collapsed selections, use `<cursor/>`.'); | ||
if (!anchor && focus) { | ||
throw new Error('Slate hyperscript ranges must have both `<anchor />` and `<focus />` defined if one is defined, but you only defined `<focus />`. For collapsed selections, use `<cursor />` instead.'); | ||
} | ||
@@ -375,4 +355,6 @@ | ||
if (!lib(props)) { | ||
selection = selection.merge(props).normalize(value.document); | ||
if (anchor || focus) { | ||
selection = selection.setPoints([anchor, focus]); | ||
selection = selection.merge({ isFocused: true }); | ||
selection = selection.normalize(value.document); | ||
value = value.set('selection', selection); | ||
@@ -523,12 +505,24 @@ } | ||
if (__anchor != null) node.__anchor = __anchor + length; | ||
if (__focus != null) node.__focus = __focus + length; | ||
if (__anchor != null) { | ||
node.__anchor = new AnchorPoint(); | ||
node.__anchor.offset = __anchor.offset + length; | ||
} | ||
if (__focus != null) { | ||
node.__focus = new FocusPoint(); | ||
node.__focus.offset = __focus.offset + length; | ||
} | ||
if (__decorations != null) { | ||
node.__decorations = (node.__decorations || []).concat(__decorations.map(function (d) { | ||
return d instanceof DecoratorPoint ? d.addOffset(length) : _extends({}, d, { | ||
anchorOffset: d.anchorOffset + length, | ||
focusOffset: d.focusOffset + length | ||
}); | ||
})); | ||
__decorations.forEach(function (d) { | ||
if (d instanceof DecorationPoint) { | ||
d.offset += length; | ||
} else { | ||
d.anchorOffset += length; | ||
d.focusOffset += length; | ||
} | ||
}); | ||
node.__decorations = node.__decorations || []; | ||
node.__decorations = node.__decorations.concat(__decorations); | ||
} | ||
@@ -539,10 +533,17 @@ | ||
// If the child is a selection object store the current position. | ||
if (child == ANCHOR || child == CURSOR) node.__anchor = length; | ||
if (child == FOCUS || child == CURSOR) node.__focus = length; | ||
if (child instanceof AnchorPoint || child instanceof CursorPoint) { | ||
child.offset = length; | ||
node.__anchor = child; | ||
} | ||
// if child is a decorator point, store it as partial decorator | ||
if (child instanceof DecoratorPoint) { | ||
node.__decorations = (node.__decorations || []).concat([child.withPosition(length)]); | ||
if (child instanceof FocusPoint || child instanceof CursorPoint) { | ||
child.offset = length; | ||
node.__focus = child; | ||
} | ||
if (child instanceof DecorationPoint) { | ||
child.offset = length; | ||
node.__decorations = node.__decorations || []; | ||
node.__decorations = node.__decorations.concat(child); | ||
} | ||
}); | ||
@@ -549,0 +550,0 @@ |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("slate")):"function"==typeof define&&define.amd?define(["exports","slate"],t):t(e.SlateHyperscript={},e.Slate)}(this,function(e,t){"use strict";var n=Object.prototype.hasOwnProperty,r=Object.prototype.toString;var o=function(e){if(null==e)return!0;if("boolean"==typeof e)return!1;if("number"==typeof e)return 0===e;if("string"==typeof e)return 0===e.length;if("function"==typeof e)return 0===e.length;if(Array.isArray(e))return 0===e.length;if(e instanceof Error)return""===e.message;if(e.toString==r)switch(e.toString()){case"[object File]":case"[object Map]":case"[object Set]":return 0===e.size;case"[object Object]":for(var t in e)if(n.call(e,t))return!1;return!0}return!1},c=function(e){return null!=e&&"object"==typeof e&&!1===Array.isArray(e)};function i(e){return!0===c(e)&&"[object Object]"===Object.prototype.toString.call(e)}var a=function(e){var t,n;return!1!==i(e)&&("function"==typeof(t=e.constructor)&&(!1!==i(n=t.prototype)&&!1!==n.hasOwnProperty("isPrototypeOf")))},s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},u=function(e,t){var n={};for(var r in e)t.indexOf(r)>=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n},f={},l={},y={},h=function e(t,n){var r=t.key,o=t.data;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),d.call(this),this._key=r,this.marks=n,this.attribs=o||{},this.isAtomic=!!this.attribs.atomic,delete this.attribs.atomic,this},d=function(){var e=this;this.withPosition=function(t){return e.offset=t,e},this.addOffset=function(t){return e.offset+=t,e},this.withKey=function(t){return e.key=t,e},this.combine=function(n){if(!(n instanceof h))throw new Error("misaligned decorations");return t.Range.create(s({anchorKey:e.key,focusKey:n.key,anchorOffset:e.offset,focusOffset:n.offset,marks:e.marks,isAtomic:e.isAtomic},e.attribs))}},p={anchor:function(e,t,n){return f},block:function(e,n,r){return t.Block.create(s({},n,{nodes:k(r)}))},cursor:function(e,t,n){return l},document:function(e,n,r){return t.Document.create(s({},n,{nodes:k(r)}))},focus:function(e,t,n){return y},inline:function(e,n,r){return t.Inline.create(s({},n,{nodes:k(r)}))},mark:function(e,n,r){return k(r,{marks:t.Mark.createSet([n])})},decoration:function(e,t,n){if(t.key)return new h(t,[{type:e}]);var r=k(n,{key:t.key});return r[0].__decorations=(r[0].__decorations||[]).concat([{anchorOffset:0,focusOffset:r.reduce(function(e,t){return e+t.text.length},0),marks:[{type:e}],isAtomic:!!t.data.atomic}]),r},selection:function(e,n,r){return t.Range.create(n)},value:function(e,n,r){var c=n.data,i=n.normalize,a=void 0===i||i,u=r.find(t.Document.isDocument),f=r.find(t.Range.isRange)||t.Range.create(),l={},y=[],h={};if(u&&(u.getTexts().forEach(function(e){null!=e.__anchor&&(l.anchorKey=e.key,l.anchorOffset=e.__anchor,l.isFocused=!0),null!=e.__focus&&(l.focusKey=e.key,l.focusOffset=e.__focus,l.isFocused=!0)}),u.getTexts().forEach(function(e){null!=e.__decorations&&(y=y.concat(e.__decorations.filter(function(e){return void 0===e._key}).map(function(n){return t.Range.create(s({},n,{anchorKey:e.key,focusKey:e.key}))})),e.__decorations.filter(function(e){return void 0!==e._key}).forEach(function(t){if(h[t._key])return y.push(h[t._key].combine(t.withKey(e.key))),void delete h[t._key];h[t._key]=t.withKey(e.key)}))})),Object.keys(h).length>0)throw new Error("Slate hyperscript must have both an anchor and focus defined for each keyed decorator.");if(l.anchorKey&&!l.focusKey)throw new Error("Slate hyperscript must have both `<anchor/>` and `<focus/>` defined if one is defined, but you only defined `<anchor/>`. For collapsed selections, use `<cursor/>`.");if(!l.anchorKey&&l.focusKey)throw new Error("Slate hyperscript must have both `<anchor/>` and `<focus/>` defined if one is defined, but you only defined `<focus/>`. For collapsed selections, use `<cursor/>`.");var d=t.Value.fromJSON({data:c,document:u,selection:f},{normalize:a});return o(l)||(f=f.merge(l).normalize(d.document),d=d.set("selection",f)),y.length>0&&(y=y.map(function(e){return e.normalize(d.document)}),y=t.Range.createList(y),d=d.set("decorations",y)),d},text:function(e,t,n){return k(n,{key:t.key})}};function _(){var e=function(e){var t=e.blocks,n=void 0===t?{}:t,r=e.inlines,o=void 0===r?{}:r,c=e.marks,i=void 0===c?{}:c,u=e.decorators,f=void 0===u?{}:u,l=s({},p,e.creators||{});return Object.keys(n).map(function(e){l[e]=m(e,n[e],"block")}),Object.keys(o).map(function(e){l[e]=m(e,o[e],"inline")}),Object.keys(i).map(function(e){l[e]=function(e,t){if("function"==typeof t)return t;if("string"==typeof t&&(t={type:t}),a(t))return function(e,n,r){var o=s({},t,{data:s({},t.data||{},n)});return p.mark(e,o,r)};throw new Error("Slate hyperscript mark creators can be either functions, objects or strings, but you passed: "+t)}(0,i[e])}),Object.keys(f).map(function(e){l[e]=m(e,f[e],"decoration")}),l}(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{});return function(t,n){for(var r=arguments.length,o=Array(r>2?r-2:0),c=2;c<r;c++)o[c-2]=arguments[c];var i=e[t];if(!i)throw new Error('No hyperscript creator found for tag: "'+t+'"');return null==n&&(n={}),a(n)||(o=[n].concat(o),n={}),i(t,n,o=o.filter(function(e){return Boolean(e)}).reduce(function(e,t){return e.concat(t)},[]))}}function k(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=[],o=0,c=e.find(function(e){return"string"!=typeof e}),i=t.Text.isText(c)?c:null,a=n.key?n.key:i?i.key:void 0,u=t.Text.create({key:a,leaves:[{text:"",marks:n.marks}]});function d(e){var t=u,n=t.__anchor,r=t.__focus,o=t.__decorations;null!=n&&(e.__anchor=n),null!=r&&(e.__focus=r),null!=o&&(e.__decorations=o),u=e}return e.forEach(function(c,i){var a=i===e.length-1;if(t.Node.isNode(c)&&!t.Text.isText(c)&&((u.text.length||null!=u.__anchor||null!=u.__focus||u.getMarksAtIndex(0).size)&&r.push(u),r.push(c),u=a?null:t.Text.create({leaves:[{text:"",marks:n.marks}]}),o=0),"string"==typeof c&&(d(u.insertText(u.text.length,c,n.marks)),o+=c.length),t.Text.isText(c)){var p=c.__anchor,_=c.__focus,k=c.__decorations,m=u.text.length;n.key||0!=u.text.length||d(u.set("key",c.key)),c.getLeaves().forEach(function(e){var t=e.marks;n.marks&&(t=t.union(n.marks)),d(u.insertText(m,e.text,t)),m+=e.text.length}),null!=p&&(u.__anchor=p+o),null!=_&&(u.__focus=_+o),null!=k&&(u.__decorations=(u.__decorations||[]).concat(k.map(function(e){return e instanceof h?e.addOffset(o):s({},e,{anchorOffset:e.anchorOffset+o,focusOffset:e.focusOffset+o})}))),o+=c.text.length}c!=f&&c!=l||(u.__anchor=o),c!=y&&c!=l||(u.__focus=o),c instanceof h&&(u.__decorations=(u.__decorations||[]).concat([c.withPosition(o)]))}),null!=u&&r.push(u),r}function m(e,t,n){if("function"==typeof t)return t;if("string"==typeof t&&(t={type:t}),a(t))return function(e,r,o){var c=r.key,i=u(r,["key"]),a=s({},t,{object:n,key:c,data:s({},t.data||{},i)});return p[n](e,a,o)};throw new Error("Slate hyperscript "+n+" creators can be either functions, objects or strings, but you passed: "+t)}var v=_();e.default=v,e.createHyperscript=_,Object.defineProperty(e,"__esModule",{value:!0})}); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("slate")):"function"==typeof define&&define.amd?define(["exports","slate"],t):t(e.SlateHyperscript={},e.Slate)}(this,function(e,t){"use strict";var n=function(e){return null!=e&&"object"==typeof e&&!1===Array.isArray(e)};function o(e){return!0===n(e)&&"[object Object]"===Object.prototype.toString.call(e)}var r=function(e){var t,n;return!1!==o(e)&&("function"==typeof(t=e.constructor)&&(!1!==o(n=t.prototype)&&!1!==n.hasOwnProperty("isPrototypeOf")))},i=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},a=function(e,t){var n={};for(var o in e)t.indexOf(o)>=0||Object.prototype.hasOwnProperty.call(e,o)&&(n[o]=e[o]);return n},c=function e(){i(this,e),this.offset=null},f=function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};i(this,e);var n=t.key,o=void 0===n?null:n,r=t.offset,s=void 0===r?null:r,a=t.path,c=void 0===a?null:a;this.key=o,this.offset=s,this.path=c},u=function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};i(this,e);var n=t.key,o=void 0===n?null:n,r=t.offset,s=void 0===r?null:r,a=t.path,c=void 0===a?null:a;this.key=o,this.offset=s,this.path=c},l=function e(n){var o=this;i(this,e),this.combine=function(n){if(!(n instanceof e))throw new Error("misaligned decorations");return t.Range.create(s({anchor:{key:o.key,offset:o.offset},focus:{key:n.key,offset:n.offset},marks:o.marks,isAtomic:o.isAtomic},o.attribs))};var r=n.key,a=void 0===r?null:r,c=n.data,f=void 0===c?{}:c,u=n.marks;return this.id=a,this.offset=0,this.marks=u,this.attribs=f||{},this.isAtomic=!!this.attribs.atomic,delete this.attribs.atomic,this},d={anchor:function(e,t,n){return new f(t)},block:function(e,n,o){return t.Block.create(s({},n,{nodes:y(o)}))},cursor:function(e,t,n){return new c},document:function(e,n,o){return t.Document.create(s({},n,{nodes:y(o)}))},focus:function(e,t,n){return new u(t)},inline:function(e,n,o){return t.Inline.create(s({},n,{nodes:y(o)}))},mark:function(e,n,o){return y(o,{marks:t.Mark.createSet([n])})},decoration:function(e,t,n){if(t.key)return new l(s({},t,{marks:[{type:e}]}));var o=y(n),r=o[0],i=r.__decorations,a=void 0===i?[]:i,c={anchorOffset:0,focusOffset:o.reduce(function(e,t){return e+t.text.length},0),marks:[{type:e}],isAtomic:!!t.data.atomic};return a.push(c),r.__decorations=a,o},selection:function(e,n,o){var r=o.find(function(e){return e instanceof f}),i=o.find(function(e){return e instanceof u}),a=t.Range.create(s({},n,{anchor:r&&{key:r.key,offset:r.offset,path:r.path},focus:i&&{key:i.key,offset:i.offset,path:i.path}}));return a},value:function(e,n,o){var r=n.data,i=n.normalize,s=void 0===i||i,a=o.find(t.Document.isDocument),c=o.find(t.Range.isRange)||t.Range.create(),f=void 0,u=void 0,l=[],d={};if(a&&a.getTexts().forEach(function(e){null!=e.__anchor&&(f=t.Point.create({key:e.key,offset:e.__anchor.offset})),null!=e.__focus&&(u=t.Point.create({key:e.key,offset:e.__focus.offset})),null!=e.__decorations&&e.__decorations.forEach(function(n){var o=n.id,r=void 0;if(o)if(d[o]){var i=d[o];delete d[o],r=t.Range.create({anchor:{key:i.key,offset:i.offset},focus:{key:e.key,offset:n.offset},marks:i.marks,isAtomic:i.isAtomic})}else n.key=e.key,d[o]=n;else r=t.Range.create({anchor:{key:e.key,offset:n.anchorOffset},focus:{key:e.key,offset:n.focusOffset},marks:n.marks,isAtomic:n.isAtomic});r&&l.push(r)})}),Object.keys(d).length>0)throw new Error("Slate hyperscript must have both a start and an end defined for each decoration using the `key=` prop.");if(f&&!u)throw new Error("Slate hyperscript ranges must have both `<anchor />` and `<focus />` defined if one is defined, but you only defined `<anchor />`. For collapsed selections, use `<cursor />` instead.");if(!f&&u)throw new Error("Slate hyperscript ranges must have both `<anchor />` and `<focus />` defined if one is defined, but you only defined `<focus />`. For collapsed selections, use `<cursor />` instead.");var h=t.Value.fromJSON({data:r,document:a,selection:c},{normalize:s});return(f||u)&&(c=(c=(c=c.setPoints([f,u])).merge({isFocused:!0})).normalize(h.document),h=h.set("selection",c)),l.length>0&&(l=l.map(function(e){return e.normalize(h.document)}),l=t.Range.createList(l),h=h.set("decorations",l)),h},text:function(e,t,n){return y(n,{key:t.key})}};function h(){var e=function(e){var t=e.blocks,n=void 0===t?{}:t,o=e.inlines,i=void 0===o?{}:o,a=e.marks,c=void 0===a?{}:a,f=e.decorators,u=void 0===f?{}:f,l=s({},d,e.creators||{});return Object.keys(n).map(function(e){l[e]=k(e,n[e],"block")}),Object.keys(i).map(function(e){l[e]=k(e,i[e],"inline")}),Object.keys(c).map(function(e){l[e]=function(e,t){if("function"==typeof t)return t;if("string"==typeof t&&(t={type:t}),r(t))return function(e,n,o){var r=s({},t,{data:s({},t.data||{},n)});return d.mark(e,r,o)};throw new Error("Slate hyperscript mark creators can be either functions, objects or strings, but you passed: "+t)}(0,c[e])}),Object.keys(u).map(function(e){l[e]=k(e,u[e],"decoration")}),l}(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{});return function(t,n){for(var o=arguments.length,i=Array(o>2?o-2:0),s=2;s<o;s++)i[s-2]=arguments[s];var a=e[t];if(!a)throw new Error('No hyperscript creator found for tag: "'+t+'"');return null==n&&(n={}),r(n)||(i=[n].concat(i),n={}),a(t,n,i=i.filter(function(e){return Boolean(e)}).reduce(function(e,t){return e.concat(t)},[]))}}function y(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=[],r=0,i=e.find(function(e){return"string"!=typeof e}),s=t.Text.isText(i)?i:null,a=n.key?n.key:s?s.key:void 0,d=t.Text.create({key:a,leaves:[{text:"",marks:n.marks}]});function h(e){var t=d,n=t.__anchor,o=t.__focus,r=t.__decorations;null!=n&&(e.__anchor=n),null!=o&&(e.__focus=o),null!=r&&(e.__decorations=r),d=e}return e.forEach(function(i,s){var a=s===e.length-1;if(t.Node.isNode(i)&&!t.Text.isText(i)&&((d.text.length||null!=d.__anchor||null!=d.__focus||d.getMarksAtIndex(0).size)&&o.push(d),o.push(i),d=a?null:t.Text.create({leaves:[{text:"",marks:n.marks}]}),r=0),"string"==typeof i&&(h(d.insertText(d.text.length,i,n.marks)),r+=i.length),t.Text.isText(i)){var y=i.__anchor,k=i.__focus,p=i.__decorations,_=d.text.length;n.key||0!=d.text.length||h(d.set("key",i.key)),i.getLeaves().forEach(function(e){var t=e.marks;n.marks&&(t=t.union(n.marks)),h(d.insertText(_,e.text,t)),_+=e.text.length}),null!=y&&(d.__anchor=new f,d.__anchor.offset=y.offset+r),null!=k&&(d.__focus=new u,d.__focus.offset=k.offset+r),null!=p&&(p.forEach(function(e){e instanceof l?e.offset+=r:(e.anchorOffset+=r,e.focusOffset+=r)}),d.__decorations=d.__decorations||[],d.__decorations=d.__decorations.concat(p)),r+=i.text.length}(i instanceof f||i instanceof c)&&(i.offset=r,d.__anchor=i),(i instanceof u||i instanceof c)&&(i.offset=r,d.__focus=i),i instanceof l&&(i.offset=r,d.__decorations=d.__decorations||[],d.__decorations=d.__decorations.concat(i))}),null!=d&&o.push(d),o}function k(e,t,n){if("function"==typeof t)return t;if("string"==typeof t&&(t={type:t}),r(t))return function(e,o,r){var i=o.key,c=a(o,["key"]),f=s({},t,{object:n,key:i,data:s({},t.data||{},c)});return d[n](e,f,r)};throw new Error("Slate hyperscript "+n+" creators can be either functions, objects or strings, but you passed: "+t)}var p=h();e.default=p,e.createHyperscript=h,Object.defineProperty(e,"__esModule",{value:!0})}); |
@@ -1,4 +0,3 @@ | ||
import isEmpty from 'is-empty'; | ||
import isPlainObject from 'is-plain-object'; | ||
import { Block, Document, Inline, Mark, Node, Range, Text, Value } from 'slate'; | ||
import { Block, Document, Inline, Mark, Node, Point, Range, Text, Value } from 'slate'; | ||
@@ -58,24 +57,73 @@ var classCallCheck = function (instance, Constructor) { | ||
/** | ||
* Create selection point constants, for comparison by reference. | ||
* Point classes that can be created at different points in the document and | ||
* then searched for afterwards, for creating ranges. | ||
* | ||
* @type {Object} | ||
* @type {Class} | ||
*/ | ||
var ANCHOR = {}; | ||
var CURSOR = {}; | ||
var FOCUS = {}; | ||
var CursorPoint = function CursorPoint() { | ||
classCallCheck(this, CursorPoint); | ||
/** | ||
* wrappers for decorator points, for comparison by instanceof, | ||
* and for composition into ranges (anchor.combine(focus), etc) | ||
*/ | ||
this.offset = null; | ||
}; | ||
var DecoratorPoint = function DecoratorPoint(_ref, marks) { | ||
var key = _ref.key, | ||
data = _ref.data; | ||
classCallCheck(this, DecoratorPoint); | ||
var AnchorPoint = function AnchorPoint() { | ||
var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
classCallCheck(this, AnchorPoint); | ||
var _attrs$key = attrs.key, | ||
key = _attrs$key === undefined ? null : _attrs$key, | ||
_attrs$offset = attrs.offset, | ||
offset = _attrs$offset === undefined ? null : _attrs$offset, | ||
_attrs$path = attrs.path, | ||
path = _attrs$path === undefined ? null : _attrs$path; | ||
_initialiseProps.call(this); | ||
this.key = key; | ||
this.offset = offset; | ||
this.path = path; | ||
}; | ||
this._key = key; | ||
var FocusPoint = function FocusPoint() { | ||
var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
classCallCheck(this, FocusPoint); | ||
var _attrs$key2 = attrs.key, | ||
key = _attrs$key2 === undefined ? null : _attrs$key2, | ||
_attrs$offset2 = attrs.offset, | ||
offset = _attrs$offset2 === undefined ? null : _attrs$offset2, | ||
_attrs$path2 = attrs.path, | ||
path = _attrs$path2 === undefined ? null : _attrs$path2; | ||
this.key = key; | ||
this.offset = offset; | ||
this.path = path; | ||
}; | ||
var DecorationPoint = function DecorationPoint(attrs) { | ||
var _this = this; | ||
classCallCheck(this, DecorationPoint); | ||
this.combine = function (focus) { | ||
if (!(focus instanceof DecorationPoint)) throw new Error('misaligned decorations'); | ||
return Range.create(_extends({ | ||
anchor: { | ||
key: _this.key, | ||
offset: _this.offset | ||
}, | ||
focus: { | ||
key: focus.key, | ||
offset: focus.offset | ||
}, | ||
marks: _this.marks, | ||
isAtomic: _this.isAtomic | ||
}, _this.attribs)); | ||
}; | ||
var _attrs$key3 = attrs.key, | ||
key = _attrs$key3 === undefined ? null : _attrs$key3, | ||
_attrs$data = attrs.data, | ||
data = _attrs$data === undefined ? {} : _attrs$data, | ||
marks = attrs.marks; | ||
this.id = key; | ||
this.offset = 0; | ||
this.marks = marks; | ||
@@ -94,36 +142,5 @@ this.attribs = data || {}; | ||
var _initialiseProps = function _initialiseProps() { | ||
var _this = this; | ||
this.withPosition = function (offset) { | ||
_this.offset = offset; | ||
return _this; | ||
}; | ||
this.addOffset = function (offset) { | ||
_this.offset += offset; | ||
return _this; | ||
}; | ||
this.withKey = function (key) { | ||
_this.key = key; | ||
return _this; | ||
}; | ||
this.combine = function (focus) { | ||
if (!(focus instanceof DecoratorPoint)) throw new Error('misaligned decorations'); | ||
return Range.create(_extends({ | ||
anchorKey: _this.key, | ||
focusKey: focus.key, | ||
anchorOffset: _this.offset, | ||
focusOffset: focus.offset, | ||
marks: _this.marks, | ||
isAtomic: _this.isAtomic | ||
}, _this.attribs)); | ||
}; | ||
}; | ||
var CREATORS = { | ||
anchor: function anchor(tagName, attributes, children) { | ||
return ANCHOR; | ||
return new AnchorPoint(attributes); | ||
}, | ||
@@ -136,3 +153,3 @@ block: function block(tagName, attributes, children) { | ||
cursor: function cursor(tagName, attributes, children) { | ||
return CURSOR; | ||
return new CursorPoint(); | ||
}, | ||
@@ -145,3 +162,3 @@ document: function document(tagName, attributes, children) { | ||
focus: function focus(tagName, attributes, children) { | ||
return FOCUS; | ||
return new FocusPoint(attributes); | ||
}, | ||
@@ -160,8 +177,14 @@ inline: function inline(tagName, attributes, children) { | ||
if (attributes.key) { | ||
return new DecoratorPoint(attributes, [{ type: tagName }]); | ||
return new DecorationPoint(_extends({}, attributes, { | ||
marks: [{ type: tagName }] | ||
})); | ||
} | ||
var nodes = createChildren(children, { key: attributes.key }); | ||
var nodes = createChildren(children); | ||
var node = nodes[0]; | ||
nodes[0].__decorations = (nodes[0].__decorations || []).concat([{ | ||
var _node$__decorations = node.__decorations, | ||
__decorations = _node$__decorations === undefined ? [] : _node$__decorations; | ||
var __decoration = { | ||
anchorOffset: 0, | ||
@@ -173,7 +196,29 @@ focusOffset: nodes.reduce(function (len, n) { | ||
isAtomic: !!attributes.data.atomic | ||
}]); | ||
}; | ||
__decorations.push(__decoration); | ||
node.__decorations = __decorations; | ||
return nodes; | ||
}, | ||
selection: function selection(tagName, attributes, children) { | ||
return Range.create(attributes); | ||
var anchor = children.find(function (c) { | ||
return c instanceof AnchorPoint; | ||
}); | ||
var focus = children.find(function (c) { | ||
return c instanceof FocusPoint; | ||
}); | ||
var selection = Range.create(_extends({}, attributes, { | ||
anchor: anchor && { | ||
key: anchor.key, | ||
offset: anchor.offset, | ||
path: anchor.path | ||
}, | ||
focus: focus && { | ||
key: focus.key, | ||
offset: focus.offset, | ||
path: focus.path | ||
} | ||
})); | ||
return selection; | ||
}, | ||
@@ -187,48 +232,62 @@ value: function value(tagName, attributes, children) { | ||
var selection = children.find(Range.isRange) || Range.create(); | ||
var props = {}; | ||
var anchor = void 0; | ||
var focus = void 0; | ||
var decorations = []; | ||
var partialDecorations = {}; | ||
var partials = {}; | ||
// Search the document's texts to see if any of them have the anchor or | ||
// focus information saved, so we can set the selection. | ||
// focus information saved, or decorations applied. | ||
if (document) { | ||
document.getTexts().forEach(function (text) { | ||
if (text.__anchor != null) { | ||
props.anchorKey = text.key; | ||
props.anchorOffset = text.__anchor; | ||
props.isFocused = true; | ||
anchor = Point.create({ key: text.key, offset: text.__anchor.offset }); | ||
} | ||
if (text.__focus != null) { | ||
props.focusKey = text.key; | ||
props.focusOffset = text.__focus; | ||
props.isFocused = true; | ||
focus = Point.create({ key: text.key, offset: text.__focus.offset }); | ||
} | ||
}); | ||
// now check for decorations and hoist them to the top | ||
document.getTexts().forEach(function (text) { | ||
if (text.__decorations != null) { | ||
// add in all mark-like (keyless) decorations | ||
decorations = decorations.concat(text.__decorations.filter(function (d) { | ||
return d._key === undefined; | ||
}).map(function (d) { | ||
return Range.create(_extends({}, d, { | ||
anchorKey: text.key, | ||
focusKey: text.key | ||
})); | ||
})); | ||
text.__decorations.forEach(function (dec) { | ||
var id = dec.id; | ||
// store or combine partial decorations (keyed with anchor / focus) | ||
text.__decorations.filter(function (d) { | ||
return d._key !== undefined; | ||
}).forEach(function (partial) { | ||
if (partialDecorations[partial._key]) { | ||
decorations.push(partialDecorations[partial._key].combine(partial.withKey(text.key))); | ||
var range = void 0; | ||
delete partialDecorations[partial._key]; | ||
return; | ||
if (!id) { | ||
range = Range.create({ | ||
anchor: { | ||
key: text.key, | ||
offset: dec.anchorOffset | ||
}, | ||
focus: { | ||
key: text.key, | ||
offset: dec.focusOffset | ||
}, | ||
marks: dec.marks, | ||
isAtomic: dec.isAtomic | ||
}); | ||
} else if (partials[id]) { | ||
var partial = partials[id]; | ||
delete partials[id]; | ||
range = Range.create({ | ||
anchor: { | ||
key: partial.key, | ||
offset: partial.offset | ||
}, | ||
focus: { | ||
key: text.key, | ||
offset: dec.offset | ||
}, | ||
marks: partial.marks, | ||
isAtomic: partial.isAtomic | ||
}); | ||
} else { | ||
dec.key = text.key; | ||
partials[id] = dec; | ||
} | ||
partialDecorations[partial._key] = partial.withKey(text.key); | ||
if (range) { | ||
decorations.push(range); | ||
} | ||
}); | ||
@@ -239,13 +298,12 @@ } | ||
// should have no more parital decorations outstanding (all paired) | ||
if (Object.keys(partialDecorations).length > 0) { | ||
throw new Error('Slate hyperscript must have both an anchor and focus defined for each keyed decorator.'); | ||
if (Object.keys(partials).length > 0) { | ||
throw new Error('Slate hyperscript must have both a start and an end defined for each decoration using the `key=` prop.'); | ||
} | ||
if (props.anchorKey && !props.focusKey) { | ||
throw new Error('Slate hyperscript must have both `<anchor/>` and `<focus/>` defined if one is defined, but you only defined `<anchor/>`. For collapsed selections, use `<cursor/>`.'); | ||
if (anchor && !focus) { | ||
throw new Error('Slate hyperscript ranges must have both `<anchor />` and `<focus />` defined if one is defined, but you only defined `<anchor />`. For collapsed selections, use `<cursor />` instead.'); | ||
} | ||
if (!props.anchorKey && props.focusKey) { | ||
throw new Error('Slate hyperscript must have both `<anchor/>` and `<focus/>` defined if one is defined, but you only defined `<focus/>`. For collapsed selections, use `<cursor/>`.'); | ||
if (!anchor && focus) { | ||
throw new Error('Slate hyperscript ranges must have both `<anchor />` and `<focus />` defined if one is defined, but you only defined `<focus />`. For collapsed selections, use `<cursor />` instead.'); | ||
} | ||
@@ -255,4 +313,6 @@ | ||
if (!isEmpty(props)) { | ||
selection = selection.merge(props).normalize(value.document); | ||
if (anchor || focus) { | ||
selection = selection.setPoints([anchor, focus]); | ||
selection = selection.merge({ isFocused: true }); | ||
selection = selection.normalize(value.document); | ||
value = value.set('selection', selection); | ||
@@ -403,12 +463,24 @@ } | ||
if (__anchor != null) node.__anchor = __anchor + length; | ||
if (__focus != null) node.__focus = __focus + length; | ||
if (__anchor != null) { | ||
node.__anchor = new AnchorPoint(); | ||
node.__anchor.offset = __anchor.offset + length; | ||
} | ||
if (__focus != null) { | ||
node.__focus = new FocusPoint(); | ||
node.__focus.offset = __focus.offset + length; | ||
} | ||
if (__decorations != null) { | ||
node.__decorations = (node.__decorations || []).concat(__decorations.map(function (d) { | ||
return d instanceof DecoratorPoint ? d.addOffset(length) : _extends({}, d, { | ||
anchorOffset: d.anchorOffset + length, | ||
focusOffset: d.focusOffset + length | ||
}); | ||
})); | ||
__decorations.forEach(function (d) { | ||
if (d instanceof DecorationPoint) { | ||
d.offset += length; | ||
} else { | ||
d.anchorOffset += length; | ||
d.focusOffset += length; | ||
} | ||
}); | ||
node.__decorations = node.__decorations || []; | ||
node.__decorations = node.__decorations.concat(__decorations); | ||
} | ||
@@ -419,10 +491,17 @@ | ||
// If the child is a selection object store the current position. | ||
if (child == ANCHOR || child == CURSOR) node.__anchor = length; | ||
if (child == FOCUS || child == CURSOR) node.__focus = length; | ||
if (child instanceof AnchorPoint || child instanceof CursorPoint) { | ||
child.offset = length; | ||
node.__anchor = child; | ||
} | ||
// if child is a decorator point, store it as partial decorator | ||
if (child instanceof DecoratorPoint) { | ||
node.__decorations = (node.__decorations || []).concat([child.withPosition(length)]); | ||
if (child instanceof FocusPoint || child instanceof CursorPoint) { | ||
child.offset = length; | ||
node.__focus = child; | ||
} | ||
if (child instanceof DecorationPoint) { | ||
child.offset = length; | ||
node.__decorations = node.__decorations || []; | ||
node.__decorations = node.__decorations.concat(child); | ||
} | ||
}); | ||
@@ -429,0 +508,0 @@ |
@@ -7,3 +7,2 @@ 'use strict'; | ||
var isEmpty = _interopDefault(require('is-empty')); | ||
var isPlainObject = _interopDefault(require('is-plain-object')); | ||
@@ -65,24 +64,73 @@ var slate = require('slate'); | ||
/** | ||
* Create selection point constants, for comparison by reference. | ||
* Point classes that can be created at different points in the document and | ||
* then searched for afterwards, for creating ranges. | ||
* | ||
* @type {Object} | ||
* @type {Class} | ||
*/ | ||
var ANCHOR = {}; | ||
var CURSOR = {}; | ||
var FOCUS = {}; | ||
var CursorPoint = function CursorPoint() { | ||
classCallCheck(this, CursorPoint); | ||
/** | ||
* wrappers for decorator points, for comparison by instanceof, | ||
* and for composition into ranges (anchor.combine(focus), etc) | ||
*/ | ||
this.offset = null; | ||
}; | ||
var DecoratorPoint = function DecoratorPoint(_ref, marks) { | ||
var key = _ref.key, | ||
data = _ref.data; | ||
classCallCheck(this, DecoratorPoint); | ||
var AnchorPoint = function AnchorPoint() { | ||
var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
classCallCheck(this, AnchorPoint); | ||
var _attrs$key = attrs.key, | ||
key = _attrs$key === undefined ? null : _attrs$key, | ||
_attrs$offset = attrs.offset, | ||
offset = _attrs$offset === undefined ? null : _attrs$offset, | ||
_attrs$path = attrs.path, | ||
path = _attrs$path === undefined ? null : _attrs$path; | ||
_initialiseProps.call(this); | ||
this.key = key; | ||
this.offset = offset; | ||
this.path = path; | ||
}; | ||
this._key = key; | ||
var FocusPoint = function FocusPoint() { | ||
var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
classCallCheck(this, FocusPoint); | ||
var _attrs$key2 = attrs.key, | ||
key = _attrs$key2 === undefined ? null : _attrs$key2, | ||
_attrs$offset2 = attrs.offset, | ||
offset = _attrs$offset2 === undefined ? null : _attrs$offset2, | ||
_attrs$path2 = attrs.path, | ||
path = _attrs$path2 === undefined ? null : _attrs$path2; | ||
this.key = key; | ||
this.offset = offset; | ||
this.path = path; | ||
}; | ||
var DecorationPoint = function DecorationPoint(attrs) { | ||
var _this = this; | ||
classCallCheck(this, DecorationPoint); | ||
this.combine = function (focus) { | ||
if (!(focus instanceof DecorationPoint)) throw new Error('misaligned decorations'); | ||
return slate.Range.create(_extends({ | ||
anchor: { | ||
key: _this.key, | ||
offset: _this.offset | ||
}, | ||
focus: { | ||
key: focus.key, | ||
offset: focus.offset | ||
}, | ||
marks: _this.marks, | ||
isAtomic: _this.isAtomic | ||
}, _this.attribs)); | ||
}; | ||
var _attrs$key3 = attrs.key, | ||
key = _attrs$key3 === undefined ? null : _attrs$key3, | ||
_attrs$data = attrs.data, | ||
data = _attrs$data === undefined ? {} : _attrs$data, | ||
marks = attrs.marks; | ||
this.id = key; | ||
this.offset = 0; | ||
this.marks = marks; | ||
@@ -101,36 +149,5 @@ this.attribs = data || {}; | ||
var _initialiseProps = function _initialiseProps() { | ||
var _this = this; | ||
this.withPosition = function (offset) { | ||
_this.offset = offset; | ||
return _this; | ||
}; | ||
this.addOffset = function (offset) { | ||
_this.offset += offset; | ||
return _this; | ||
}; | ||
this.withKey = function (key) { | ||
_this.key = key; | ||
return _this; | ||
}; | ||
this.combine = function (focus) { | ||
if (!(focus instanceof DecoratorPoint)) throw new Error('misaligned decorations'); | ||
return slate.Range.create(_extends({ | ||
anchorKey: _this.key, | ||
focusKey: focus.key, | ||
anchorOffset: _this.offset, | ||
focusOffset: focus.offset, | ||
marks: _this.marks, | ||
isAtomic: _this.isAtomic | ||
}, _this.attribs)); | ||
}; | ||
}; | ||
var CREATORS = { | ||
anchor: function anchor(tagName, attributes, children) { | ||
return ANCHOR; | ||
return new AnchorPoint(attributes); | ||
}, | ||
@@ -143,3 +160,3 @@ block: function block(tagName, attributes, children) { | ||
cursor: function cursor(tagName, attributes, children) { | ||
return CURSOR; | ||
return new CursorPoint(); | ||
}, | ||
@@ -152,3 +169,3 @@ document: function document(tagName, attributes, children) { | ||
focus: function focus(tagName, attributes, children) { | ||
return FOCUS; | ||
return new FocusPoint(attributes); | ||
}, | ||
@@ -167,8 +184,14 @@ inline: function inline(tagName, attributes, children) { | ||
if (attributes.key) { | ||
return new DecoratorPoint(attributes, [{ type: tagName }]); | ||
return new DecorationPoint(_extends({}, attributes, { | ||
marks: [{ type: tagName }] | ||
})); | ||
} | ||
var nodes = createChildren(children, { key: attributes.key }); | ||
var nodes = createChildren(children); | ||
var node = nodes[0]; | ||
nodes[0].__decorations = (nodes[0].__decorations || []).concat([{ | ||
var _node$__decorations = node.__decorations, | ||
__decorations = _node$__decorations === undefined ? [] : _node$__decorations; | ||
var __decoration = { | ||
anchorOffset: 0, | ||
@@ -180,7 +203,29 @@ focusOffset: nodes.reduce(function (len, n) { | ||
isAtomic: !!attributes.data.atomic | ||
}]); | ||
}; | ||
__decorations.push(__decoration); | ||
node.__decorations = __decorations; | ||
return nodes; | ||
}, | ||
selection: function selection(tagName, attributes, children) { | ||
return slate.Range.create(attributes); | ||
var anchor = children.find(function (c) { | ||
return c instanceof AnchorPoint; | ||
}); | ||
var focus = children.find(function (c) { | ||
return c instanceof FocusPoint; | ||
}); | ||
var selection = slate.Range.create(_extends({}, attributes, { | ||
anchor: anchor && { | ||
key: anchor.key, | ||
offset: anchor.offset, | ||
path: anchor.path | ||
}, | ||
focus: focus && { | ||
key: focus.key, | ||
offset: focus.offset, | ||
path: focus.path | ||
} | ||
})); | ||
return selection; | ||
}, | ||
@@ -194,48 +239,62 @@ value: function value(tagName, attributes, children) { | ||
var selection = children.find(slate.Range.isRange) || slate.Range.create(); | ||
var props = {}; | ||
var anchor = void 0; | ||
var focus = void 0; | ||
var decorations = []; | ||
var partialDecorations = {}; | ||
var partials = {}; | ||
// Search the document's texts to see if any of them have the anchor or | ||
// focus information saved, so we can set the selection. | ||
// focus information saved, or decorations applied. | ||
if (document) { | ||
document.getTexts().forEach(function (text) { | ||
if (text.__anchor != null) { | ||
props.anchorKey = text.key; | ||
props.anchorOffset = text.__anchor; | ||
props.isFocused = true; | ||
anchor = slate.Point.create({ key: text.key, offset: text.__anchor.offset }); | ||
} | ||
if (text.__focus != null) { | ||
props.focusKey = text.key; | ||
props.focusOffset = text.__focus; | ||
props.isFocused = true; | ||
focus = slate.Point.create({ key: text.key, offset: text.__focus.offset }); | ||
} | ||
}); | ||
// now check for decorations and hoist them to the top | ||
document.getTexts().forEach(function (text) { | ||
if (text.__decorations != null) { | ||
// add in all mark-like (keyless) decorations | ||
decorations = decorations.concat(text.__decorations.filter(function (d) { | ||
return d._key === undefined; | ||
}).map(function (d) { | ||
return slate.Range.create(_extends({}, d, { | ||
anchorKey: text.key, | ||
focusKey: text.key | ||
})); | ||
})); | ||
text.__decorations.forEach(function (dec) { | ||
var id = dec.id; | ||
// store or combine partial decorations (keyed with anchor / focus) | ||
text.__decorations.filter(function (d) { | ||
return d._key !== undefined; | ||
}).forEach(function (partial) { | ||
if (partialDecorations[partial._key]) { | ||
decorations.push(partialDecorations[partial._key].combine(partial.withKey(text.key))); | ||
var range = void 0; | ||
delete partialDecorations[partial._key]; | ||
return; | ||
if (!id) { | ||
range = slate.Range.create({ | ||
anchor: { | ||
key: text.key, | ||
offset: dec.anchorOffset | ||
}, | ||
focus: { | ||
key: text.key, | ||
offset: dec.focusOffset | ||
}, | ||
marks: dec.marks, | ||
isAtomic: dec.isAtomic | ||
}); | ||
} else if (partials[id]) { | ||
var partial = partials[id]; | ||
delete partials[id]; | ||
range = slate.Range.create({ | ||
anchor: { | ||
key: partial.key, | ||
offset: partial.offset | ||
}, | ||
focus: { | ||
key: text.key, | ||
offset: dec.offset | ||
}, | ||
marks: partial.marks, | ||
isAtomic: partial.isAtomic | ||
}); | ||
} else { | ||
dec.key = text.key; | ||
partials[id] = dec; | ||
} | ||
partialDecorations[partial._key] = partial.withKey(text.key); | ||
if (range) { | ||
decorations.push(range); | ||
} | ||
}); | ||
@@ -246,13 +305,12 @@ } | ||
// should have no more parital decorations outstanding (all paired) | ||
if (Object.keys(partialDecorations).length > 0) { | ||
throw new Error('Slate hyperscript must have both an anchor and focus defined for each keyed decorator.'); | ||
if (Object.keys(partials).length > 0) { | ||
throw new Error('Slate hyperscript must have both a start and an end defined for each decoration using the `key=` prop.'); | ||
} | ||
if (props.anchorKey && !props.focusKey) { | ||
throw new Error('Slate hyperscript must have both `<anchor/>` and `<focus/>` defined if one is defined, but you only defined `<anchor/>`. For collapsed selections, use `<cursor/>`.'); | ||
if (anchor && !focus) { | ||
throw new Error('Slate hyperscript ranges must have both `<anchor />` and `<focus />` defined if one is defined, but you only defined `<anchor />`. For collapsed selections, use `<cursor />` instead.'); | ||
} | ||
if (!props.anchorKey && props.focusKey) { | ||
throw new Error('Slate hyperscript must have both `<anchor/>` and `<focus/>` defined if one is defined, but you only defined `<focus/>`. For collapsed selections, use `<cursor/>`.'); | ||
if (!anchor && focus) { | ||
throw new Error('Slate hyperscript ranges must have both `<anchor />` and `<focus />` defined if one is defined, but you only defined `<focus />`. For collapsed selections, use `<cursor />` instead.'); | ||
} | ||
@@ -262,4 +320,6 @@ | ||
if (!isEmpty(props)) { | ||
selection = selection.merge(props).normalize(value.document); | ||
if (anchor || focus) { | ||
selection = selection.setPoints([anchor, focus]); | ||
selection = selection.merge({ isFocused: true }); | ||
selection = selection.normalize(value.document); | ||
value = value.set('selection', selection); | ||
@@ -410,12 +470,24 @@ } | ||
if (__anchor != null) node.__anchor = __anchor + length; | ||
if (__focus != null) node.__focus = __focus + length; | ||
if (__anchor != null) { | ||
node.__anchor = new AnchorPoint(); | ||
node.__anchor.offset = __anchor.offset + length; | ||
} | ||
if (__focus != null) { | ||
node.__focus = new FocusPoint(); | ||
node.__focus.offset = __focus.offset + length; | ||
} | ||
if (__decorations != null) { | ||
node.__decorations = (node.__decorations || []).concat(__decorations.map(function (d) { | ||
return d instanceof DecoratorPoint ? d.addOffset(length) : _extends({}, d, { | ||
anchorOffset: d.anchorOffset + length, | ||
focusOffset: d.focusOffset + length | ||
}); | ||
})); | ||
__decorations.forEach(function (d) { | ||
if (d instanceof DecorationPoint) { | ||
d.offset += length; | ||
} else { | ||
d.anchorOffset += length; | ||
d.focusOffset += length; | ||
} | ||
}); | ||
node.__decorations = node.__decorations || []; | ||
node.__decorations = node.__decorations.concat(__decorations); | ||
} | ||
@@ -426,10 +498,17 @@ | ||
// If the child is a selection object store the current position. | ||
if (child == ANCHOR || child == CURSOR) node.__anchor = length; | ||
if (child == FOCUS || child == CURSOR) node.__focus = length; | ||
if (child instanceof AnchorPoint || child instanceof CursorPoint) { | ||
child.offset = length; | ||
node.__anchor = child; | ||
} | ||
// if child is a decorator point, store it as partial decorator | ||
if (child instanceof DecoratorPoint) { | ||
node.__decorations = (node.__decorations || []).concat([child.withPosition(length)]); | ||
if (child instanceof FocusPoint || child instanceof CursorPoint) { | ||
child.offset = length; | ||
node.__focus = child; | ||
} | ||
if (child instanceof DecorationPoint) { | ||
child.offset = length; | ||
node.__decorations = node.__decorations || []; | ||
node.__decorations = node.__decorations.concat(child); | ||
} | ||
}); | ||
@@ -436,0 +515,0 @@ |
{ | ||
"name": "slate-hyperscript", | ||
"description": "A hyperscript helper for creating Slate documents.", | ||
"version": "0.6.3", | ||
"version": "0.7.0", | ||
"license": "MIT", | ||
@@ -21,7 +21,7 @@ "repository": "git://github.com/ianstormtaylor/slate.git", | ||
"peerDependencies": { | ||
"slate": ">=0.35.0" | ||
"slate": ">=0.37.0" | ||
}, | ||
"devDependencies": { | ||
"mocha": "^2.5.3", | ||
"slate": "^0.36.2" | ||
"slate": "^0.37.0" | ||
}, | ||
@@ -28,0 +28,0 @@ "scripts": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
116458
9.16%1556
11.06%