slate-hyperscript
Advanced tools
Comparing version
@@ -7,11 +7,2 @@ # Changelog | ||
### Unreleased | ||
* Accept `normalize` option for `<value>` tag. This allows to write | ||
invalid values, on purpose, for example to test validation logic. | ||
* Fixed a bug that added extra text nodes. You would not encounter these if you always wrapped things in a `<value>` tag, that was running a normalization. | ||
* **Decorations** can now also be specified in hyperscript, similarly to specifying a selection. See the examples under `./test/decorations/`. | ||
--- | ||
### `0.5.0` — January 4, 2018 | ||
@@ -18,0 +9,0 @@ |
@@ -124,2 +124,16 @@ (function (global, factory) { | ||
var classCallCheck = function (instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError("Cannot call a class as a function"); | ||
} | ||
}; | ||
var _extends = Object.assign || function (target) { | ||
@@ -174,2 +188,17 @@ for (var i = 1; i < arguments.length; i++) { | ||
/** | ||
* wrappers for decorator points, for comparison by instanceof, | ||
* and for composition into ranges (anchor.combine(focus), etc) | ||
*/ | ||
var DecoratorPoint = function DecoratorPoint(key, marks) { | ||
classCallCheck(this, DecoratorPoint); | ||
_initialiseProps.call(this); | ||
this._key = key; | ||
this.marks = marks; | ||
return this; | ||
}; | ||
/** | ||
* The default Slate hyperscript creator functions. | ||
@@ -180,2 +209,32 @@ * | ||
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({ | ||
anchorKey: _this.key, | ||
focusKey: focus.key, | ||
anchorOffset: _this.offset, | ||
focusOffset: focus.offset, | ||
marks: _this.marks | ||
}); | ||
}; | ||
}; | ||
var CREATORS = { | ||
@@ -211,2 +270,17 @@ anchor: function anchor(tagName, attributes, children) { | ||
}, | ||
decoration: function decoration(tagName, attributes, children) { | ||
if (attributes.key) { | ||
return new DecoratorPoint(attributes.key, [{ type: tagName }]); | ||
} | ||
var nodes = createChildren(children, { key: attributes.key }); | ||
nodes[0].__decorations = (nodes[0].__decorations || []).concat([{ | ||
anchorOffset: 0, | ||
focusOffset: nodes.reduce(function (len, n) { | ||
return len + n.text.length; | ||
}, 0), | ||
marks: [{ type: tagName }] | ||
}]); | ||
return nodes; | ||
}, | ||
selection: function selection(tagName, attributes, children) { | ||
@@ -216,3 +290,5 @@ return slate.Range.create(attributes); | ||
value: function value(tagName, attributes, children) { | ||
var data = attributes.data; | ||
var data = attributes.data, | ||
_attributes$normalize = attributes.normalize, | ||
normalize = _attributes$normalize === undefined ? true : _attributes$normalize; | ||
@@ -222,2 +298,4 @@ var document = children.find(slate.Document.isDocument); | ||
var props = {}; | ||
var decorations = []; | ||
var partialDecorations = {}; | ||
@@ -240,4 +318,35 @@ // Search the document's texts to see if any of them have the anchor or | ||
}); | ||
// 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 | ||
})); | ||
})); | ||
// 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))); | ||
delete partialDecorations[partial._key]; | ||
return; | ||
} | ||
partialDecorations[partial._key] = partial.withKey(text.key); | ||
}); | ||
} | ||
}); | ||
} | ||
// 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 (props.anchorKey && !props.focusKey) { | ||
@@ -255,3 +364,11 @@ 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/>`.'); | ||
var value = slate.Value.create({ data: data, document: document, selection: selection }); | ||
var value = slate.Value.fromJSON({ data: data, document: document, selection: selection }, { normalize: normalize }); | ||
// apply any decorations built | ||
if (decorations.length > 0) { | ||
value = value.change().setValue({ decorations: decorations.map(function (d) { | ||
return d.normalize(document); | ||
}) }).value; | ||
} | ||
return value; | ||
@@ -336,10 +453,13 @@ }, | ||
__anchor = _node.__anchor, | ||
__focus = _node.__focus; | ||
__focus = _node.__focus, | ||
__decorations = _node.__decorations; | ||
if (__anchor != null) next.__anchor = __anchor; | ||
if (__focus != null) next.__focus = __focus; | ||
if (__decorations != null) next.__decorations = __decorations; | ||
node = next; | ||
} | ||
children.forEach(function (child) { | ||
children.forEach(function (child, index) { | ||
var isLast = index === children.length - 1; | ||
// If the child is a non-text node, push the current node and the new child | ||
@@ -350,3 +470,3 @@ // onto the array, then creating a new node for future selection tracking. | ||
array.push(child); | ||
node = slate.Text.create(); | ||
node = isLast ? null : slate.Text.create(); | ||
length = 0; | ||
@@ -366,3 +486,4 @@ } | ||
var __anchor = child.__anchor, | ||
__focus = child.__focus; | ||
__focus = child.__focus, | ||
__decorations = child.__decorations; | ||
@@ -385,2 +506,10 @@ var i = node.text.length; | ||
if (__focus != null) node.__focus = __focus + 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 | ||
}); | ||
})); | ||
} | ||
@@ -393,6 +522,13 @@ length += child.text.length; | ||
if (child == FOCUS || child == CURSOR) node.__focus = length; | ||
// if child is a decorator point, store it as partial decorator | ||
if (child instanceof DecoratorPoint) { | ||
node.__decorations = (node.__decorations || []).concat([child.withPosition(length)]); | ||
} | ||
}); | ||
// Make sure the most recent node is added. | ||
array.push(node); | ||
if (node != null) { | ||
array.push(node); | ||
} | ||
@@ -415,3 +551,5 @@ return array; | ||
_options$marks = options.marks, | ||
marks = _options$marks === undefined ? {} : _options$marks; | ||
marks = _options$marks === undefined ? {} : _options$marks, | ||
_options$decorators = options.decorators, | ||
decorators = _options$decorators === undefined ? {} : _options$decorators; | ||
@@ -433,2 +571,6 @@ | ||
Object.keys(decorators).map(function (key) { | ||
creators[key] = normalizeNode(key, decorators[key], 'decoration'); | ||
}); | ||
return creators; | ||
@@ -435,0 +577,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 r=Object.prototype.hasOwnProperty,n=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==n)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(r.call(e,t))return!1;return!0}return!1},c=function(e){return null!=e&&"object"==typeof e&&!1===Array.isArray(e)};function u(e){return!0===c(e)&&"[object Object]"===Object.prototype.toString.call(e)}var i=function(e){var t,r;return!1!==u(e)&&("function"==typeof(t=e.constructor)&&(!1!==u(r=t.prototype)&&!1!==r.hasOwnProperty("isPrototypeOf")))},a=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e},f=function(e,t){var r={};for(var n in e)t.indexOf(n)>=0||Object.prototype.hasOwnProperty.call(e,n)&&(r[n]=e[n]);return r},s={},l={},y={},p={anchor:function(e,t,r){return s},block:function(e,r,n){return t.Block.create(a({},r,{nodes:d(n)}))},cursor:function(e,t,r){return l},document:function(e,r,n){return t.Document.create(a({},r,{nodes:d(n)}))},focus:function(e,t,r){return y},inline:function(e,r,n){return t.Inline.create(a({},r,{nodes:d(n)}))},mark:function(e,r,n){return d(n,{marks:t.Mark.createSet([r])})},selection:function(e,r,n){return t.Range.create(r)},value:function(e,r,n){var c=r.data,u=n.find(t.Document.isDocument),i=n.find(t.Range.isRange)||t.Range.create(),a={};if(u&&u.getTexts().forEach(function(e){null!=e.__anchor&&(a.anchorKey=e.key,a.anchorOffset=e.__anchor,a.isFocused=!0),null!=e.__focus&&(a.focusKey=e.key,a.focusOffset=e.__focus,a.isFocused=!0)}),a.anchorKey&&!a.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(!a.anchorKey&&a.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/>`.");o(a)||(i=i.merge(a).normalize(u));var f=t.Value.create({data:c,document:u,selection:i});return f},text:function(e,t,r){return d(r,{key:t.key})}};function h(){var e=function(e){var t=e.blocks,r=void 0===t?{}:t,n=e.inlines,o=void 0===n?{}:n,c=e.marks,u=void 0===c?{}:c,f=a({},p,e.creators||{});return Object.keys(r).map(function(e){f[e]=b(e,r[e],"block")}),Object.keys(o).map(function(e){f[e]=b(e,o[e],"inline")}),Object.keys(u).map(function(e){f[e]=function(e,t){if("function"==typeof t)return t;if("string"==typeof t&&(t={type:t}),i(t))return function(e,r,n){var o=a({},t,{data:a({},t.data||{},r)});return p.mark(e,o,n)};throw new Error("Slate hyperscript mark creators can be either functions, objects or strings, but you passed: "+t)}(0,u[e])}),f}(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{});return function(t,r){for(var n=arguments.length,o=Array(n>2?n-2:0),c=2;c<n;c++)o[c-2]=arguments[c];var u=e[t];if(!u)throw new Error('No hyperscript creator found for tag: "'+t+'"');return null==r&&(r={}),i(r)||(o=[r].concat(o),r={}),u(t,r,o=o.filter(function(e){return Boolean(e)}).reduce(function(e,t){return e.concat(t)},[]))}}function d(e){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=[],o=0,c=e.find(function(e){return t.Text.isText(e)}),u=r.key?r.key:c?c.key:void 0,i=t.Text.create({key:u});function a(e){var t=i,r=t.__anchor,n=t.__focus;null!=r&&(e.__anchor=r),null!=n&&(e.__focus=n),i=e}return e.forEach(function(e){if(t.Node.isNode(e)&&!t.Text.isText(e)&&((i.text.length||null!=i.__anchor||null!=i.__focus)&&n.push(i),n.push(e),i=t.Text.create(),o=0),"string"==typeof e&&(a(i.insertText(i.text.length,e,r.marks)),o+=e.length),t.Text.isText(e)){var c=e.__anchor,u=e.__focus,f=i.text.length;r.key||0!=i.text.length||a(i.set("key",e.key)),e.getLeaves().forEach(function(e){var t=e.marks;r.marks&&(t=t.union(r.marks)),a(i.insertText(f,e.text,t)),f+=e.text.length}),null!=c&&(i.__anchor=c+o),null!=u&&(i.__focus=u+o),o+=e.text.length}e!=s&&e!=l||(i.__anchor=o),e!=y&&e!=l||(i.__focus=o)}),n.push(i),n}function b(e,t,r){if("function"==typeof t)return t;if("string"==typeof t&&(t={type:t}),i(t))return function(e,n,o){var c=n.key,u=f(n,["key"]),i=a({},t,{object:r,key:c,data:a({},t.data||{},u)});return p[r](e,i,o)};throw new Error("Slate hyperscript "+r+" creators can be either functions, objects or strings, but you passed: "+t)}var g=h();e.default=g,e.createHyperscript=h,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=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")))},u=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},f=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},s={},l={},y={},h=function e(t,n){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=t,this.marks=n,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({anchorKey:e.key,focusKey:n.key,anchorOffset:e.offset,focusOffset:n.offset,marks:e.marks})}},p={anchor:function(e,t,n){return s},block:function(e,n,r){return t.Block.create(u({},n,{nodes:k(r)}))},cursor:function(e,t,n){return l},document:function(e,n,r){return t.Document.create(u({},n,{nodes:k(r)}))},focus:function(e,t,n){return y},inline:function(e,n,r){return t.Inline.create(u({},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.key,[{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}]}]),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,f=r.find(t.Document.isDocument),s=r.find(t.Range.isRange)||t.Range.create(),l={},y=[],h={};if(f&&(f.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)}),f.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(u({},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/>`.");o(l)||(s=s.merge(l).normalize(f));var d=t.Value.fromJSON({data:c,document:f,selection:s},{normalize:a});return y.length>0&&(d=d.change().setValue({decorations:y.map(function(e){return e.normalize(f)})}).value),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,f=e.decorators,s=void 0===f?{}:f,l=u({},p,e.creators||{});return Object.keys(n).map(function(e){l[e]=v(e,n[e],"block")}),Object.keys(o).map(function(e){l[e]=v(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=u({},t,{data:u({},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(s).map(function(e){l[e]=v(e,s[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 t.Text.isText(e)}),i=n.key?n.key:c?c.key:void 0,a=t.Text.create({key:i});function f(e){var t=a,n=t.__anchor,r=t.__focus,o=t.__decorations;null!=n&&(e.__anchor=n),null!=r&&(e.__focus=r),null!=o&&(e.__decorations=o),a=e}return e.forEach(function(c,i){var d=i===e.length-1;if(t.Node.isNode(c)&&!t.Text.isText(c)&&((a.text.length||null!=a.__anchor||null!=a.__focus)&&r.push(a),r.push(c),a=d?null:t.Text.create(),o=0),"string"==typeof c&&(f(a.insertText(a.text.length,c,n.marks)),o+=c.length),t.Text.isText(c)){var p=c.__anchor,_=c.__focus,k=c.__decorations,v=a.text.length;n.key||0!=a.text.length||f(a.set("key",c.key)),c.getLeaves().forEach(function(e){var t=e.marks;n.marks&&(t=t.union(n.marks)),f(a.insertText(v,e.text,t)),v+=e.text.length}),null!=p&&(a.__anchor=p+o),null!=_&&(a.__focus=_+o),null!=k&&(a.__decorations=(a.__decorations||[]).concat(k.map(function(e){return e instanceof h?e.addOffset(o):u({},e,{anchorOffset:e.anchorOffset+o,focusOffset:e.focusOffset+o})}))),o+=c.text.length}c!=s&&c!=l||(a.__anchor=o),c!=y&&c!=l||(a.__focus=o),c instanceof h&&(a.__decorations=(a.__decorations||[]).concat([c.withPosition(o)]))}),null!=a&&r.push(a),r}function v(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=f(r,["key"]),a=u({},t,{object:n,key:c,data:u({},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 g=_();e.default=g,e.createHyperscript=_,Object.defineProperty(e,"__esModule",{value:!0})}); |
{ | ||
"name": "slate-hyperscript", | ||
"description": "A hyperscript helper for creating Slate documents.", | ||
"version": "0.5.11", | ||
"version": "0.5.12", | ||
"license": "MIT", | ||
@@ -25,3 +25,3 @@ "repository": "git://github.com/ianstormtaylor/slate.git", | ||
"mocha": "^2.5.3", | ||
"slate": "^0.33.5" | ||
"slate": "^0.33.6" | ||
}, | ||
@@ -28,0 +28,0 @@ "scripts": { |
101956
6.27%1364
10.09%