Skip to content

Commit 2e27fb9

Browse files
geotrevgeorge treviranusGeorge Treviranus
authored
Merge tags to main (#6)
* update patchChildren to update nodes before removing; otherwise removes then re-adds nodes that already existed * use for..in loop on key generation * update tests and package name when bundling * 0.2.2 * update metadata & cdn tags * update metadata & cdn tags * update metadata & cdn tags * add npm publish tag to update-origin step of publish * 0.2.3 * [npm publish] update metadata & cdn tags Co-authored-by: george treviranus <george.treviranus@servicenow.com> Co-authored-by: George Treviranus <hello@geotrev.com>
1 parent c007ca7 commit 2e27fb9

File tree

12 files changed

+60
-1111
lines changed

12 files changed

+60
-1111
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ debug.log
55
dist/
66
lib/
77
node_modules/
8-
demo/bundle.js
8+
test/bundle.js

.npmignore

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ debug.log
88
# build helpers
99
build/
1010

11-
# tests
11+
# unit tests
1212
src/__tests__/
1313

14-
# demo
15-
demo/
14+
# live tests
15+
test/
1616

1717
# configs
1818
.browserslistrc

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,16 @@ patch(...)
3737
<!-- The unminified bundle for development -->
3838
<script
3939
type="text/javascript"
40-
src="https://cdn.jsdelivr.net/npm/omdomdom@0.2.1/dist/omdomdom.js"
41-
integrity="sha256-0NKRNWXlyGHJqE2rt9TL0ZfUKZOTpl9yDaV2IDrVOtU="
40+
src="https://cdn.jsdelivr.net/npm/omdomdom@0.2.3/dist/omdomdom.js"
41+
integrity="sha256-HBLiViWpBlIc3sW3GXN1ZDGOqzCCZSzP4COMH2ToKrk="
4242
crossorigin="anonymous"
4343
></script>
4444

4545
<!-- Minified/uglified bundle for production -->
4646
<script
4747
type="text/javascript"
48-
src="https://cdn.jsdelivr.net/npm/omdomdom@0.2.1/dist/omdomdom.min.js"
49-
integrity="sha256-z2QunatqIwvTpeWq5IoXEI+thliEu0jLGUKIikVuv4I="
48+
src="https://cdn.jsdelivr.net/npm/omdomdom@0.2.3/dist/omdomdom.min.js"
49+
integrity="sha256-hQMZhQOXCXn6iVdmSzECnZ/C+NszStwrZSkKBpBCsZw="
5050
crossorigin="anonymous"
5151
></script>
5252
```

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"name": "omdomdom",
3-
"version": "0.2.1",
3+
"version": "0.2.3",
44
"description": "A virtual DOM implementation that turns strings into HTML",
5-
"main": "lib/omdomdom.cjs.min.js",
6-
"module": "lib/omdomdom.es.min.js",
7-
"browser": "dist/omdomdom.min.js",
5+
"main": "lib/omdomdom.cjs.js",
6+
"module": "lib/omdomdom.es.js",
7+
"browser": "dist/omdomdom.js",
88
"type": "module",
99
"scripts": {
1010
"test": "jest",
@@ -13,7 +13,7 @@
1313
"build": "BABEL_ENV=build rollup -c",
1414
"build:publish": "BABEL_ENV=publish rollup -c",
1515
"lint": "eslint . --ext .js -c .eslintrc.json --ignore-path .eslintignore",
16-
"git:update-origin": "git add . && git commit -m 'update metadata & cdn tags' && git push && git push --tags",
16+
"git:update-origin": "git add . && git commit -m '[npm publish] update metadata & cdn tags' && git push && git push --tags",
1717
"prepublishOnly": "paopu && npm run git:update-origin",
1818
"preversion": "npm test",
1919
"postversion": "npm run build:publish"
@@ -53,7 +53,7 @@
5353
"files": [
5454
"lib/*.{js,map}",
5555
"dist/*.{js,map}",
56-
"src/*.js"
56+
"src/**/*.js"
5757
],
5858
"repository": {
5959
"type": "git",

rollup.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ const terserPlugin = terser({
3333
}
3434
},
3535
},
36-
mangle: { reserved: ["OmDomDom"] },
36+
mangle: { reserved: ["omdomdom"] },
3737
})
3838

3939
const baseOutput = (format) => ({
4040
banner,
4141
format,
42-
name: "OmDomDom",
42+
name: "omdomdom",
4343
sourcemap: true,
4444
})
4545

src/__tests__/utilities.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ describe("utilities", () => {
7676
]
7777

7878
it("returns null if no keys were detected", () => {
79-
expect(createKeyMap(withNoKeys)).toBeNull()
79+
expect(createKeyMap(withNoKeys)).toBeUndefined()
8080
})
8181

8282
it("returns the map object if keys were detected", () => {

src/children/index.js

Lines changed: 30 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,75 +7,62 @@ const DATA_KEY_ATTRIBUTE = "data-key"
77
* @param {VirtualNode} template - new virtual node tree.
88
* @param {VirtualNode} vNode - existing virtual node tree.
99
*/
10-
export const updateChildren = (template, vNode, update) => {
10+
export function patchChildren(template, vNode, patch) {
1111
const templateChildrenLength = template.children.length
1212
const vNodeChildrenLength = vNode.children.length
1313

1414
if (!templateChildrenLength && !vNodeChildrenLength) return
1515

1616
const vNodeKeyMap = createKeyMap(vNode.children)
17+
let nextChildren = Array(templateChildrenLength)
1718

18-
// There were no keys found:
19+
if (vNodeKeyMap !== undefined) {
20+
forEach(template.children, (templateChild, idx) => {
21+
const childNodes = vNode.node.childNodes
22+
const key = templateChild.attributes[DATA_KEY_ATTRIBUTE]
1923

20-
if (!vNodeKeyMap) {
21-
// Remove extra nodes if template.children is smaller
22-
let delta = vNodeChildrenLength - templateChildrenLength
23-
if (delta > 0) {
24-
while (delta-- > 0) {
25-
const child = vNode.children.pop()
26-
vNode.node.removeChild(child.node)
27-
}
28-
}
24+
if (Object.prototype.hasOwnProperty.call(vNodeKeyMap, key)) {
25+
const keyedChild = vNodeKeyMap[key]
26+
27+
if (Array.prototype.indexOf.call(childNodes, keyedChild.node) !== idx) {
28+
insertBefore(vNode, keyedChild, childNodes[idx])
29+
}
30+
31+
nextChildren[idx] = keyedChild
2932

30-
return forEach(template.children, (templateChild, idx) => {
33+
// Remove entry to prevent dupes
34+
delete vNodeKeyMap[key]
35+
patch(templateChild, nextChildren[idx])
36+
} else {
37+
insertBefore(vNode, templateChild, childNodes[idx])
38+
nextChildren[idx] = templateChild
39+
}
40+
})
41+
} else {
42+
forEach(template.children, (templateChild, idx) => {
3143
const vNodeChild = vNode.children[idx]
3244

3345
if (typeof vNodeChild !== "undefined") {
34-
update(templateChild, vNodeChild)
46+
patch(templateChild, vNodeChild)
47+
nextChildren[idx] = vNodeChild
3548
} else {
3649
vNode.node.appendChild(templateChild.node)
37-
vNode.children.push(templateChild)
50+
nextChildren[idx] = templateChild
3851
}
3952
})
4053
}
4154

42-
// There were keys found, resolve them:
43-
44-
let nextChildren = Array(templateChildrenLength)
45-
46-
// Match keys and update/move children in-place
47-
forEach(template.children, (child, idx) => {
48-
const childNodes = vNode.node.childNodes
49-
const key = child.attributes[DATA_KEY_ATTRIBUTE]
50-
51-
if (Object.prototype.hasOwnProperty.call(vNodeKeyMap, key)) {
52-
const keyChild = vNodeKeyMap[key]
53-
54-
if (Array.prototype.indexOf.call(childNodes, keyChild.node) !== idx) {
55-
insertBefore(vNode, keyChild, childNodes[idx])
56-
}
57-
58-
nextChildren[idx] = keyChild
59-
60-
// Prevent duplicates, remove the entry and let it insert at
61-
// its natural index in the `else` block.
62-
delete vNodeKeyMap[key]
63-
update(child, nextChildren[idx])
64-
} else {
65-
insertBefore(vNode, child, childNodes[idx])
66-
nextChildren[idx] = child
67-
}
68-
})
69-
7055
vNode.children = nextChildren
7156

7257
// Remove any real nodes that are left over from the diff
7358
let childNodesLength = vNode.node.childNodes.length
7459
let delta = childNodesLength - templateChildrenLength
60+
7561
if (delta > 0) {
76-
while (delta-- > 0) {
62+
while (delta > 0) {
7763
vNode.node.removeChild(vNode.node.childNodes[childNodesLength - 1])
7864
childNodesLength--
65+
delta--
7966
}
8067
}
8168
}

src/omdomdom.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { forEach, assignVNode } from "./utilities"
22
import { toHTML } from "./parsers"
33
import { updateAttributes, getAttributes } from "./attributes"
4-
import { updateChildren } from "./children"
4+
import { patchChildren } from "./children"
55

66
/**
77
* Object representation of a DOM element.
@@ -39,7 +39,7 @@ export const patch = (template, vNode, rootNode) => {
3939
updateAttributes(template, vNode)
4040

4141
// Diff child nodes recursively
42-
updateChildren(template, vNode, patch)
42+
patchChildren(template, vNode, patch)
4343
}
4444

4545
/**

src/utilities/index.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,23 @@ export const forEach = (items, fn) => {
4949
/**
5050
* Generates a <key: vNode> map of a virtual node list.
5151
* @param {VirtualNode[]} children
52-
* @returns {Object.<string, VirtualNode>}
52+
* @returns {Object.<string, VirtualNode>|undefined}
5353
*/
5454
export const createKeyMap = (children) => {
5555
const map = {}
56-
let hasKeys = false
5756

5857
forEach(children, (child) => {
5958
const key = child.attributes[DATA_KEY_ATTRIBUTE]
6059
if (keyIsValid(map, key)) {
6160
map[key] = child
62-
if (!hasKeys) hasKeys = true
6361
}
6462
})
6563

66-
return hasKeys ? map : null
64+
// Cheap way to check if the map contains keys,
65+
// and if so, returns the map on the first iteration.
66+
for (const _ in map) {
67+
return map
68+
}
6769
}
6870

6971
export const insertBefore = (parent, child, refNode) => {

0 commit comments

Comments
 (0)