Comparing version 3.0.1 to 4.0.0
var assert = require('assert') | ||
var morph = require('./morph') | ||
var morph = require('./lib/morph') | ||
@@ -4,0 +4,0 @@ module.exports = nanomorph |
{ | ||
"name": "nanomorph", | ||
"version": "3.0.1", | ||
"version": "4.0.0", | ||
"description": "Hyper fast diffing algorithm for real DOM nodes", | ||
@@ -8,4 +8,3 @@ "main": "index.js", | ||
"deps": "dependency-check . && dependency-check . --extra --no-dev", | ||
"test": "standard && npm run deps && NODE_ENV=test node test", | ||
"test:cov": "standard && npm run deps && NODE_ENV=test istanbul cover test.js" | ||
"test": "standard && npm run deps && browserify test.js | tape-run" | ||
}, | ||
@@ -23,12 +22,12 @@ "repository": "yoshuawuyts/nanomorph", | ||
"license": "MIT", | ||
"dependencies": { | ||
"xtend": "^4.0.1" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"bel": "^4.4.3", | ||
"browserify": "^14.1.0", | ||
"dependency-check": "^2.5.1", | ||
"istanbul": "^0.4.4", | ||
"math-random-seed": "^1.0.0", | ||
"standard": "^7.1.2", | ||
"tape": "^4.6.0" | ||
"tape": "^4.6.0", | ||
"tape-run": "^3.0.0" | ||
} | ||
} |
# nanomorph [![stability][0]][1] | ||
[![npm version][2]][3] [![build status][4]][5] [![test coverage][6]][7] | ||
[![npm version][2]][3] [![build status][4]][5] | ||
[![downloads][8]][9] [![js-standard-style][10]][11] | ||
@@ -17,19 +17,12 @@ | ||
## Appending to the DOM | ||
## Clearing Input Values | ||
To remove values from inputs, there's a few options: | ||
```js | ||
var update = require('nanomorph/update') | ||
var html = require('bel') | ||
html`<input class="beep" value=${null}>` // set the value to null | ||
html`<input class="beep">` // omit property all together | ||
``` | ||
// create the initial tree, save it and append to DOM | ||
var tree = html`<div>hello people</div>` | ||
var morph = update(tree) | ||
document.body.appendChild(tree) | ||
## Reordering Lists | ||
[tbi] | ||
// now each consecutive update will be rendered on the DOM | ||
morph(html`<div>hello people</div>`, tree) | ||
// even if the type of the root node changes | ||
morph(html`<p>nanananana-na-no</p>`, tree) | ||
``` | ||
## Caching DOM elements | ||
@@ -51,3 +44,12 @@ Sometimes we want to tell the algorithm to not evaluate certain nodes (and its | ||
## Building your own | ||
## FAQ | ||
### How is this different from morphdom? | ||
It's quite similar actually; the API of this library is completely compatible | ||
with `morphdom` and we've borrowed a fair few bits. The main difference is that | ||
we copy event handlers like `onclick`, don't support browsers that are over a | ||
decade old, and don't provide custom behavior by removing all hooks. This way | ||
we can guarantee a consistent, out-of-the box experience for all your diffing | ||
needs. | ||
### This library seems cool, I'd like to build my own! | ||
Nanomorph was optimized for simplicity, but different situations might require | ||
@@ -58,6 +60,2 @@ different tradeoffs. So in order to allow folks to build their own | ||
the same tests we use for your own implementation. Yay! :sparkles: | ||
```js | ||
var test = require('nanomorph/test') | ||
test(require('./my-morph-implementation')) | ||
``` | ||
@@ -69,10 +67,2 @@ ## API | ||
### morph = update(newTree) | ||
Create a diffing function that morphs one tree into another, even if the type | ||
of the root node changes | ||
### tree = morph(newTree) | ||
Diff the previous tree with a new tree using the function returned from | ||
`update()` | ||
:warning: nanomorph will modify the newTree and it should be discarded after use | ||
@@ -79,0 +69,0 @@ |
350
test.js
@@ -1,2 +0,3 @@ | ||
var test = require('tape') | ||
var seed = require('math-random-seed') | ||
var tape = require('tape') | ||
var html = require('bel') | ||
@@ -13,7 +14,7 @@ var nanomorph = require('./') | ||
function specificTests (morph) { | ||
test('nanomorph', function (t) { | ||
tape('nanomorph', function (t) { | ||
t.test('should assert input types', function (t) { | ||
t.plan(2) | ||
t.throws(morph, /oldTree/) | ||
t.throws(morph.bind(null, {}), /newTree/) | ||
t.throws(morph, /a/) | ||
t.throws(morph.bind(null, {}), /b/) | ||
}) | ||
@@ -24,13 +25,11 @@ }) | ||
function abstractMorph (morph) { | ||
test('abstract morph', function (t) { | ||
tape('abstract morph', function (t) { | ||
t.test('root level', function (t) { | ||
t.test('should replace a node', function (t) { | ||
t.plan(1) | ||
var oldTree = html`<p>hello world</p>` | ||
var newTree = html`<div>hello world</div>` | ||
var res = morph(oldTree, newTree) | ||
var expected = '<div>hello world</div>' | ||
t.equal(String(res), expected, 'result was expected') | ||
var a = html`<p>hello world</p>` | ||
var b = html`<div>hello world</div>` | ||
var expected = b.outerHTML | ||
var res = morph(a, b) | ||
t.equal(res.outerHTML, expected, 'result was expected') | ||
}) | ||
@@ -40,9 +39,7 @@ | ||
t.plan(1) | ||
var oldTree = html`<p>hello world</p>` | ||
var newTree = html`<p>hello you</p>` | ||
var res = morph(oldTree, newTree) | ||
var expected = '<p>hello you</p>' | ||
t.equal(String(res), expected, 'result was expected') | ||
var a = html`<p>hello world</p>` | ||
var b = html`<p>hello you</p>` | ||
var expected = b.outerHTML | ||
var res = morph(a, b) | ||
t.equal(res.outerHTML, expected, 'result was expected') | ||
}) | ||
@@ -52,9 +49,7 @@ | ||
t.plan(1) | ||
var oldTree = html`<svg><use xlink:href="#heybooboo"></use></svg>` | ||
var newTree = html`<svg><use xlink:href="#boobear"></use></svg>` | ||
var res = morph(oldTree, newTree) | ||
var expected = '<svg><use xlink:href="#boobear"></use></svg>' | ||
t.equal(String(res), expected, 'result was expected') | ||
var a = html`<svg><use xlink:href="#heybooboo"></use></svg>` | ||
var b = html`<svg><use xlink:href="#boobear"></use></svg>` | ||
var expected = b.outerHTML | ||
var res = morph(a, b) | ||
t.equal(res.outerHTML, expected, 'result was expected') | ||
}) | ||
@@ -64,8 +59,6 @@ | ||
t.plan(1) | ||
var oldTree = html`<p>hello world</p>` | ||
var res = morph(oldTree, oldTree) | ||
var expected = oldTree | ||
t.equal(res, expected, 'result was expected') | ||
var a = html`<p>hello world</p>` | ||
var expected = a.outerHTML | ||
var res = morph(a, a) | ||
t.equal(res.outerHTML, expected, 'result was expected') | ||
}) | ||
@@ -77,13 +70,7 @@ }) | ||
t.plan(1) | ||
var oldTree = html` | ||
<main><p>hello world</p></main> | ||
` | ||
var newTree = html` | ||
<main><div>hello world</div></main> | ||
` | ||
var res = morph(oldTree, newTree) | ||
var expected = '<main><div>hello world</div></main>' | ||
t.equal(String(res), expected, 'result was expected') | ||
var a = html`<main><p>hello world</p></main>` | ||
var b = html`<main><div>hello world</div></main>` | ||
var expected = b.outerHTML | ||
var res = morph(a, b) | ||
t.equal(res.outerHTML, expected, 'result was expected') | ||
}) | ||
@@ -93,13 +80,7 @@ | ||
t.plan(1) | ||
var oldTree = html` | ||
<main><p>hello world</p></main> | ||
` | ||
var newTree = html` | ||
<main><p>hello you</p></main> | ||
` | ||
var res = morph(oldTree, newTree) | ||
var expected = '<main><p>hello you</p></main>' | ||
t.equal(String(res), expected, 'result was expected') | ||
var a = html`<main><p>hello world</p></main>` | ||
var b = html`<main><p>hello you</p></main>` | ||
var res = morph(a, b) | ||
var expected = b.outerHTML | ||
t.equal(res.outerHTML, expected, 'result was expected') | ||
}) | ||
@@ -109,10 +90,6 @@ | ||
t.plan(1) | ||
var oldTree = html` | ||
<main><p>hello world</p></main> | ||
` | ||
var res = morph(oldTree, oldTree) | ||
var expected = oldTree | ||
t.equal(res, expected, 'result was expected') | ||
var a = html`<main><p>hello world</p></main>` | ||
var res = morph(a, a) | ||
var expected = a.outerHTML | ||
t.equal(res.outerHTML, expected, 'result was expected') | ||
}) | ||
@@ -122,13 +99,7 @@ | ||
t.plan(1) | ||
var oldTree = html` | ||
<main></main> | ||
` | ||
var newTree = html` | ||
<main><p>hello you</p></main> | ||
` | ||
var res = morph(oldTree, newTree) | ||
var expected = '<main><p>hello you</p></main>' | ||
t.equal(String(res), expected, 'result was expected') | ||
var a = html`<main></main>` | ||
var b = html`<main><p>hello you</p></main>` | ||
var expected = b.outerHTML | ||
var res = morph(a, b) | ||
t.equal(res.outerHTML, expected, 'result was expected') | ||
}) | ||
@@ -138,14 +109,7 @@ | ||
t.plan(1) | ||
var oldTree = html` | ||
<main><p>hello you</p></main> | ||
` | ||
var newTree = html` | ||
<main></main> | ||
` | ||
var res = morph(oldTree, newTree) | ||
var expected = '<main></main>' | ||
t.equal(String(res), expected, 'result was expected') | ||
var a = html`<main><p>hello you</p></main>` | ||
var b = html`<main></main>` | ||
var expected = b.outerHTML | ||
var res = morph(a, b) | ||
t.equal(res.outerHTML, expected, 'result was expected') | ||
}) | ||
@@ -156,30 +120,24 @@ }) | ||
t.test('should copy onclick events', function (t) { | ||
t.plan(2) | ||
var oldTree = html` | ||
<button | ||
onclick=${function () { | ||
t.ok(true) | ||
}} | ||
> | ||
TEST | ||
</button>` | ||
var newTree = html`<button>UPDATED</button>` | ||
var res = morph(oldTree, newTree) | ||
t.ok(typeof res.onclick === 'function') | ||
res.onclick() | ||
}) | ||
t.plan(1) | ||
var a = html`<button onclick=${fail}>OLD</button>` | ||
var b = html`<button>NEW</button>` | ||
var res = morph(a, b) | ||
t.test('should copy onsubmit events', function (t) { | ||
var oldTree = html` | ||
<form | ||
onsubmit=${function () { t.ok(false) }} | ||
> | ||
<button>Sup</button> | ||
</form>` | ||
var newTree = html`<form> | ||
<button>Sup</button> | ||
</form>` | ||
var res = morph(oldTree, newTree) | ||
t.ok(typeof res.onsubmit === 'function') | ||
t.end() | ||
res.click() | ||
a = html`<button>OLD</button>` | ||
b = html`<button onclick=${pass}>NEW</button>` | ||
res = morph(a, b) | ||
res.click() | ||
function fail (e) { | ||
e.preventDefault() | ||
t.fail('should not be called') | ||
} | ||
function pass (e) { | ||
e.preventDefault() | ||
t.ok('called') | ||
} | ||
}) | ||
@@ -189,18 +147,22 @@ }) | ||
t.test('values', function (t) { | ||
t.test('should be copied to new tree when it has no value', function (t) { | ||
t.plan(1) | ||
var oldTree = html`<input type="text" />` | ||
oldTree.value = 'howdy' | ||
var newTree = html`<input type="text" />` | ||
var res = morph(oldTree, newTree) | ||
t.equal(res.value, 'howdy') | ||
t.test('if new tree has no value and old tree does, remove value', function (t) { | ||
t.plan(4) | ||
var a = html`<input type="text" value="howdy" />` | ||
var b = html`<input type="text" />` | ||
var res = morph(a, b) | ||
t.equal(res.getAttribute('value'), null) | ||
t.equal(res.value, '') | ||
a = html`<input type="text" value="howdy" />` | ||
b = html`<input type="text" value=${null} />` | ||
res = morph(a, b) | ||
t.equal(res.getAttribute('value'), null) | ||
t.equal(res.value, '') | ||
}) | ||
t.test('should be copied to old tree when new tree has a value', function (t) { | ||
t.test('if new tree has value and old tree does too, set value from new tree', function (t) { | ||
t.plan(1) | ||
var oldTree = html`<input type="text" />` | ||
oldTree.value = 'howdy' | ||
var newTree = html`<input type="text" />` | ||
newTree.value = 'hi' | ||
var res = morph(oldTree, newTree) | ||
var a = html`<input type="text" value="howdy" />` | ||
var b = html`<input type="text" value="hi" />` | ||
var res = morph(a, b) | ||
t.equal(res.value, 'hi') | ||
@@ -211,21 +173,21 @@ }) | ||
t.test('isSameNode', function (t) { | ||
t.test('should return oldTree if true', function (t) { | ||
t.test('should return a if true', function (t) { | ||
t.plan(1) | ||
var oldTree = html`<div>YOLO</div>` | ||
var newTree = html`<div>FOMO</div>` | ||
newTree.isSameNode = function (el) { | ||
var a = html`<div>YOLO</div>` | ||
var b = html`<div>FOMO</div>` | ||
b.isSameNode = function (el) { | ||
return true | ||
} | ||
var res = morph(oldTree, newTree) | ||
var res = morph(a, b) | ||
t.equal(res.childNodes[0].data, 'YOLO') | ||
}) | ||
t.test('should return newTree if false', function (t) { | ||
t.test('should return b if false', function (t) { | ||
t.plan(1) | ||
var oldTree = html`<div>YOLO</div>` | ||
var newTree = html`<div>FOMO</div>` | ||
newTree.isSameNode = function (el) { | ||
var a = html`<div>YOLO</div>` | ||
var b = html`<div>FOMO</div>` | ||
b.isSameNode = function (el) { | ||
return false | ||
} | ||
var res = morph(oldTree, newTree) | ||
var res = morph(a, b) | ||
t.equal(res.childNodes[0].data, 'FOMO') | ||
@@ -238,9 +200,7 @@ }) | ||
t.plan(1) | ||
var oldTree = html`<ul></ul>` | ||
var newTree = html`<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>` | ||
var res = morph(oldTree, newTree) | ||
var expected = '<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>' | ||
t.equal(String(res), expected, 'result was expected') | ||
var a = html`<ul></ul>` | ||
var b = html`<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>` | ||
var expected = b.outerHTML | ||
var res = morph(a, b) | ||
t.equal(res.outerHTML, expected, 'result was expected') | ||
}) | ||
@@ -250,9 +210,7 @@ | ||
t.plan(1) | ||
var oldTree = html`<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>` | ||
var newTree = html`<ul></ul>` | ||
var res = morph(oldTree, newTree) | ||
var expected = '<ul></ul>' | ||
t.equal(String(res), expected, 'result was expected') | ||
var a = html`<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>` | ||
var b = html`<ul></ul>` | ||
var res = morph(a, b) | ||
var expected = b.outerHTML | ||
t.equal(res.outerHTML, expected, 'result was expected') | ||
}) | ||
@@ -263,9 +221,7 @@ }) | ||
t.plan(1) | ||
var oldTree = html`<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>` | ||
var newTree = html`<ul><div>1</div><li>2</li><p>3</p><li>4</li><li>5</li></ul>` | ||
var expected = '<ul><div>1</div><li>2</li><p>3</p><li>4</li><li>5</li></ul>' | ||
oldTree = nanomorph(oldTree, newTree) | ||
t.equal(String(oldTree), expected, 'result was expected') | ||
var a = html`<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>` | ||
var b = html`<ul><div>1</div><li>2</li><p>3</p><li>4</li><li>5</li></ul>` | ||
var expected = b.outerHTML | ||
a = nanomorph(a, b) | ||
t.equal(a.outerHTML, expected, 'result was expected') | ||
}) | ||
@@ -276,16 +232,80 @@ | ||
var oldTree = html`<ul></ul>` | ||
var newTree = html`<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>` | ||
var expected = '<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>' | ||
var a = html`<ul></ul>` | ||
var b = html`<ul><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>` | ||
var expected = b.outerHTML | ||
oldTree = nanomorph(oldTree, newTree) | ||
t.equal(String(oldTree), expected, 'result was expected') | ||
a = nanomorph(a, b) | ||
t.equal(a.outerHTML, expected, 'result was expected') | ||
newTree = html`<ul><div>1</div><li>2</li><p>3</p><li>4</li><li>5</li></ul>` | ||
expected = '<ul><div>1</div><li>2</li><p>3</p><li>4</li><li>5</li></ul>' | ||
b = html`<ul><div>1</div><li>2</li><p>3</p><li>4</li><li>5</li></ul>` | ||
expected = b.outerHTML | ||
oldTree = nanomorph(oldTree, newTree) | ||
t.equal(String(oldTree), expected, 'result was expected') | ||
a = nanomorph(a, b) | ||
t.equal(a.outerHTML, expected, 'result was expected') | ||
}) | ||
}) | ||
} | ||
tape('chaos monkey #1', function (t) { | ||
var a, b | ||
a = html`<div r="r"><div></div></div>` | ||
b = html`<div io="iO" vq="Vq"><div></div></div>` | ||
compare(a, b, t) | ||
t.end() | ||
}) | ||
// modeled after | ||
// https://github.com/mafintosh/hypercore/blob/master/test/tree-index.js | ||
var random = seed('choo choo') | ||
var props = null | ||
tape('fuzz tests', function (t) { | ||
var a, b | ||
for (var i = 0; i < 7; i++) { | ||
for (var j = 0; j < 5; j++) { | ||
a = create(i, j, 0) | ||
for (var k = 0; k < 3; k++) { | ||
b = create(i, k, 1) | ||
props = { depth: i, propCount: j, offset: k } | ||
compare(a, b, t, props) | ||
} | ||
} | ||
} | ||
t.end() | ||
}) | ||
function create (depth, propCount, offset) { | ||
var chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' | ||
var root = document.createElement('div') | ||
var el = root | ||
var _el = null | ||
var str = '' | ||
offset += 100 | ||
for (var i = 0; i < depth; i++) { | ||
_el = document.createElement('div') | ||
el.appendChild(_el) | ||
for (var j = 0; j < propCount; j++) { | ||
str = '' | ||
for (var k = propCount; k > 0; --k) { | ||
str += chars[Math.floor(random() * 100) % chars.length] | ||
} | ||
el.setAttribute(str, str) | ||
offset++ | ||
} | ||
el = _el | ||
} | ||
return root | ||
} | ||
function compare (a, b, t, props) { | ||
props = props ? JSON.stringify(props) : undefined | ||
var expected = b.cloneNode(true) | ||
var res = nanomorph(a, b) | ||
deepEqualNode(res, expected, t, props) | ||
} | ||
function deepEqualNode (a, b, t, props) { | ||
t.ok(a.isEqualNode(b), props) | ||
for (var i = a.childNodes.length - 1; i >= 0; --i) { | ||
deepEqualNode(a.childNodes[i], a.childNodes[i], t, props) | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
22730
0
509
7
110
1
- Removedxtend@^4.0.1
- Removedxtend@4.0.2(transitive)