Skip to content

Commit 5920000

Browse files
committed
[ Optimize ] walkDOM() supports Sub trees
[ Fix ] scanDOM() ignores Attributes of Matched elements
1 parent b814b1c commit 5920000

File tree

8 files changed

+343
-384
lines changed

8 files changed

+343
-384
lines changed

ReadMe.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@
2727
}
2828
```
2929

30-
`source/index.html` [**Template syntax**](https://web-cell/DOM-Renderer/manual/Template.html)
30+
`source/index.html` [**Template syntax**](https://web-cell.tk/DOM-Renderer/manual/Template.html)
3131

3232
```HTML
3333
<template>
3434
<h1 hidden="${! view.name}">
3535
Hello, ${view.name} !
3636
</h1>
3737

38-
<ul data-view="profile">
38+
<ul data-view="profile" hidden="${! view.name}">
3939
<template>
4040
<li title="${scope.name}">
4141
${view.URL}
@@ -44,7 +44,7 @@
4444
</template>
4545
</ul>
4646

47-
<ol data-view="job">
47+
<ol data-view="job" hidden="${! view.name}">
4848
<template>
4949
<li>${view.title}</li>
5050
</template>
@@ -100,7 +100,7 @@ view.render( data ).then(() => console.log(view + ''));
100100
### Web browser
101101

102102
```HTML
103-
<script src="https://cdn.jsdelivr.net/npm/@babel/polyfill@7.2.5/dist/polyfill.min.js"></script>
103+
<script src="https://cdn.jsdelivr.net/npm/@babel/polyfill/dist/polyfill.min.js"></script>
104104
<script src="https://cdn.jsdelivr.net/npm/dom-renderer"></script>
105105
```
106106

package-lock.json

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

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "dom-renderer",
3-
"version": "0.8.0",
3+
"version": "0.8.1",
44
"description": "Template engine based on HTML 5, ECMAScript 6 & MVVM",
55
"keywords": [
66
"template",
@@ -48,24 +48,24 @@
4848
"devDependencies": {
4949
"@babel/cli": "^7.2.3",
5050
"@babel/polyfill": "^7.2.5",
51-
"@babel/preset-env": "^7.3.1",
51+
"@babel/preset-env": "^7.3.4",
5252
"@babel/register": "^7.0.0",
53-
"amd-bundle": "^1.7.5",
53+
"amd-bundle": "^1.7.7",
5454
"babel-plugin-inline-import": "^3.0.0",
5555
"cross-env": "^5.2.0",
5656
"esdoc": "^1.1.0",
5757
"esdoc-ecmascript-proposal-plugin": "^1.0.0",
5858
"esdoc-external-webapi-plugin": "^1.0.0",
5959
"esdoc-standard-plugin": "^1.0.0",
60-
"eslint": "^5.14.1",
60+
"eslint": "^5.15.1",
6161
"husky": "^1.3.1",
62-
"jsdom": "^13.2.0",
63-
"koapache": "^1.0.5",
64-
"mocha": "^6.0.1",
62+
"jsdom": "^14.0.0",
63+
"koapache": "^1.0.6",
64+
"mocha": "^6.0.2",
6565
"prettier": "^1.16.4",
6666
"should": "^13.2.3",
6767
"should-sinon": "0.0.6",
68-
"sinon": "^7.2.4"
68+
"sinon": "^7.2.7"
6969
},
7070
"prettier": {
7171
"tabWidth": 4,

source/DOM/utility.js

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export function parseDOM(markup) {
2525

2626
const Document_Level = ['#document', 'html', 'head', 'body'],
2727
serializer = new XMLSerializer(),
28-
documentXML = document.implementation.createDocument(null, 'xml');
28+
documentXML = document.implementation.createDocument(null, 'xml', null);
2929

3030
function stringOf(node) {
3131
if (node.querySelectorAll)
@@ -64,12 +64,13 @@ export function stringifyDOM(list) {
6464
}
6565

6666
/**
67-
* @param {Node} root
67+
* @param {Node} root
6868
* @param {function(node: Node): Number} [filter] - https://developer.mozilla.org/en-US/docs/Web/API/NodeFilter/acceptNode
69+
* @param {Boolean} [sub] - Go into Sub DOM
6970
*
7071
* @yield {Node}
7172
*/
72-
export function* walkDOM(root, filter) {
73+
export function* walkDOM(root, filter, sub) {
7374
var iterator = document.createNodeIterator(root, NodeFilter.SHOW_ALL, {
7475
acceptNode:
7576
filter instanceof Function
@@ -78,7 +79,16 @@ export function* walkDOM(root, filter) {
7879
}),
7980
node;
8081

81-
while ((node = iterator.nextNode())) yield node;
82+
while ((node = iterator.nextNode())) {
83+
yield node;
84+
85+
if (!sub) continue;
86+
87+
const subDOM = node.content || node.shadowRoot;
88+
89+
if (subDOM instanceof DocumentFragment)
90+
yield* walkDOM(subDOM, filter, sub);
91+
}
8292
}
8393

8494
/**
@@ -89,26 +99,29 @@ export function* walkDOM(root, filter) {
8999
* @param {function(text: Text): void} parser.text
90100
* @param {... function(node: Element): Boolean} parser.element - Key for CSS selector, Value for Callback
91101
*/
92-
export function scanTemplate(
93-
root,
94-
expression,
95-
{ attribute, text, ...element }
96-
) {
102+
export function scanDOM(root, expression, { attribute, text, ...element }) {
103+
function scanAttr(node) {
104+
Array.from(node.attributes).forEach(
105+
attr => expression.test(attr.value) && attribute(attr)
106+
);
107+
}
108+
97109
const iterator = walkDOM(root, node => {
98-
if (node.matches)
110+
if (node.matches) {
111+
scanAttr(node);
112+
99113
for (let selector in element)
100114
if (node.matches(selector) && element[selector](node) === false)
101115
return NodeFilter.FILTER_REJECT;
116+
}
102117

103118
return NodeFilter.FILTER_ACCEPT;
104119
});
105120

106121
Array.from(iterator, node => {
107122
switch (node.nodeType) {
108123
case 1:
109-
Array.from(node.attributes).forEach(
110-
attr => expression.test(attr.value) && attribute(attr)
111-
);
124+
scanAttr(node);
112125
break;
113126
case 3:
114127
if (expression.test(node.nodeValue)) text(node);

source/view/View.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Model from './Model';
22

33
import {
44
parseDOM,
5-
scanTemplate,
5+
scanDOM,
66
stringifyDOM,
77
attributeMap,
88
nextTick,
@@ -187,7 +187,7 @@ export default class View extends Model {
187187
Object.keys(this[view_injection])
188188
);
189189

190-
scanTemplate(root, Template.Expression, {
190+
scanDOM(root, Template.Expression, {
191191
attribute: ({ ownerElement, name, value }) => {
192192
var onChange;
193193

test/View.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ describe('DOM View', () => {
2424
Array.from(view, ({ type }) => type).should.match([
2525
'Attr',
2626
'Text',
27+
'Attr',
2728
'View',
29+
'Attr',
2830
'View'
2931
]);
3032

test/source/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ <h1 hidden="${! view.name}">
33
Hello, ${view.name} !
44
</h1>
55

6-
<ul data-view="profile">
6+
<ul data-view="profile" hidden="${! view.name}">
77
<template>
88
<li title="${scope.name}">
99
${view.URL}
@@ -12,7 +12,7 @@ <h1 hidden="${! view.name}">
1212
</template>
1313
</ul>
1414

15-
<ol data-view="job">
15+
<ol data-view="job" hidden="${! view.name}">
1616
<template>
1717
<li>${view.title}</li>
1818
</template>

test/utility.js

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
parseDOM,
33
walkDOM,
4-
scanTemplate,
4+
scanDOM,
55
stringifyDOM
66
} from '../source/DOM/utility';
77

@@ -38,36 +38,50 @@ describe('DOM utility', () => {
3838
* @test {walkDOM}
3939
*/
4040
it('DOM walking', () => {
41-
Array.from(walkDOM(fragment), ({ nodeName }) => nodeName).should.be.eql(
42-
[
43-
'#document-fragment',
44-
'#text',
45-
'H1',
46-
'#text',
47-
'#text',
48-
'UL',
49-
'#text',
50-
'TEMPLATE',
51-
'#text',
52-
'#text',
53-
'OL',
54-
'#text',
55-
'TEMPLATE',
56-
'#text',
57-
'#text',
58-
'TEXTAREA',
59-
'#text'
60-
]
61-
);
41+
Array.from(
42+
walkDOM(fragment, null, true),
43+
({ nodeValue, nodeName }) => (nodeValue || '').trim() || nodeName
44+
).should.be.eql([
45+
'#document-fragment',
46+
'#text',
47+
'H1',
48+
'Hello, ${view.name} !',
49+
'#text',
50+
'UL',
51+
'#text',
52+
'TEMPLATE',
53+
'#document-fragment',
54+
'#text',
55+
'LI',
56+
'${view.URL}',
57+
'#text',
58+
'LI',
59+
'${view.title}',
60+
'#text',
61+
'#text',
62+
'#text',
63+
'OL',
64+
'#text',
65+
'TEMPLATE',
66+
'#document-fragment',
67+
'#text',
68+
'LI',
69+
'${view.title}',
70+
'#text',
71+
'#text',
72+
'#text',
73+
'TEXTAREA',
74+
'#text'
75+
]);
6276
});
6377

6478
/**
65-
* @test {scanTemplate}
79+
* @test {scanDOM}
6680
*/
6781
it('Template scanning', () => {
6882
const key_node = [];
6983

70-
scanTemplate(fragment, Template.Expression, {
84+
scanDOM(fragment, Template.Expression, {
7185
attribute(node) {
7286
key_node.push(node.value);
7387
},
@@ -84,7 +98,9 @@ describe('DOM utility', () => {
8498
key_node.should.be.eql([
8599
'${! view.name}',
86100
'Hello, ${view.name} !',
101+
'${! view.name}',
87102
'UL',
103+
'${! view.name}',
88104
'OL'
89105
]);
90106
});

0 commit comments

Comments
 (0)