Skip to content

Commit e92fa3a

Browse files
committed
complex-case.html & template() light dom compatible with complex case unit test
1 parent 27417b5 commit e92fa3a

File tree

8 files changed

+607
-62
lines changed

8 files changed

+607
-62
lines changed

src/CssChain.js

Lines changed: 82 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,38 @@ function nodeProp( tag, prop, val ){ const el = createEl(tag); el[prop]=val; ret
88
export function isNode(n){ return !!n?.nodeType; }
99

1010
const nop = ()=>''
11-
, isArr = a => Array.isArray(a) || (a && 'function' === typeof a.forEach)
12-
, isT = (a,t) => typeof a === t
13-
, isStr = a => isT(a, 'string')
14-
, isNum = a => isT(a, 'number')
15-
, isFn = a => isT(a, 'function')
16-
, inWC = n => n.getRootNode().host
17-
, hasAssigned = n=> inWC(n) && n.assignedNodes
18-
, each = (arr, cb )=> (arr.forEach(cb),arr)
19-
, clear = n => hasAssigned(n)
20-
? n.assignedNodes().forEach( a => a.remove() )
21-
: n.innerHTML=''
11+
, isArr = a => Array.isArray(a) || (a && 'function' === typeof a.forEach)
12+
, isT = (a,t) => typeof a === t
13+
, isStr = a => isT(a, 'string')
14+
, isNum = a => isT(a, 'number')
15+
, isFn = a => isT(a, 'function')
16+
, inWC = n => n.getRootNode().host
17+
, hasAssigned = n=> inWC(n) && n.assignedNodes
18+
, each = (arr, cb )=> (arr.forEach(cb),arr)
19+
, clear = n => hasAssigned(n)
20+
? n.assignedNodes().forEach( a => a.remove() )
21+
: n.innerHTML=''
2222
;
2323

2424
const node2text = { 1: n=>n.assignedNodes
25-
? collectionText(n.assignedNodes()) || collectionText(n.childNodes)
26-
: [ 'SCRIPT','AUDIO','STYLE','CANVAS','DATALIST','EMBED','OBJECT'
27-
, 'PICTURE','IFRAME','METER','NOSCRIPT'
28-
, 'SELECT','OPTGROUP','PROGRESS','TEMPLATE','VIDEO'
29-
].includes(n.nodeName)? '' : n.innerText //collectionText(n.children)
30-
, 3: n=>n.nodeValue
31-
, 11:n=>collectionText(n.childNodes)
32-
};
25+
? collectionText(n.assignedNodes()) || collectionText(n.childNodes)
26+
: [ 'SCRIPT','AUDIO','STYLE','CANVAS','DATALIST','EMBED','OBJECT'
27+
, 'PICTURE','IFRAME','METER','NOSCRIPT'
28+
, 'SELECT','OPTGROUP','PROGRESS','TEMPLATE','VIDEO'
29+
].includes(n.nodeName)? '' : n.innerText //collectionText(n.children)
30+
, 3: n=>n.nodeValue
31+
, 11:n=>collectionText(n.childNodes)
32+
};
3333
export const getNodeText = n => (node2text[n.nodeType] || nop)(n);
3434
export const setNodeText = ( n, val ) =>
3535
hasAssigned(n)
3636
? n.assignedElements().forEach( e => e.innerText = val )
3737
: n.innerText = val;
3838
export const assignParent = (arr,n)=>arr.map( e=>n.appendChild(e))
3939
export const collectionHtml = arr => map( arr, n=>n.assignedElements
40-
? map( n.assignedElements(), e=>e.outerHTML ).join('')
41-
: n.innerHTML
42-
).join('');
40+
? map( n.assignedElements(), e=>e.outerHTML ).join('')
41+
: n.innerHTML
42+
).join('');
4343

4444
export const html2NodeArr = html =>
4545
{ let n = createEl('div');
@@ -62,14 +62,14 @@ export const html2NodeArr = html =>
6262
export const addNodeHtml = ( n, val ) =>
6363
{
6464
const set = ( to, v )=> ( v instanceof Node
65-
? v.remove() || to.append(v)
66-
: html2NodeArr(v).forEach( e=>to.append(e) )
67-
)
68-
, append = v => hasAssigned(n)
69-
? n.assign( ...n.assignedNodes()
70-
, ...assignParent( each( html2NodeArr(v), e=>e.slot=n.name )
71-
, n.getRootNode().host ) )
72-
: set(n,v);
65+
? v.remove() || to.append(v)
66+
: html2NodeArr(v).forEach( e=>to.append(e) )
67+
)
68+
, append = v => hasAssigned(n)
69+
? n.assign( ...n.assignedNodes()
70+
, ...assignParent( each( html2NodeArr(v), e=>e.slot=n.name )
71+
, n.getRootNode().host ) )
72+
: set(n,v);
7373

7474
val instanceof NodeList || isArr(val)
7575
? [ ...val ].forEach( append )
@@ -130,27 +130,47 @@ CssChainT extends Array
130130
return CssChain([...ss,...ret]);
131131
}
132132
template(n)
133+
{ if( n === undefined )
133134
{
134-
if( n === undefined )
135-
{
136-
const $s = this.$('[slot]')
137-
.forEach( n => this.$(n.slot ? `slot[name="${n.slot}"]`:'slot:not([name])').length
138-
|| n.parentNode.insertBefore( nodeProp('slot','name',n.slot), n ));
139-
$s.remove();
140-
n = createEl('template');
141-
this.childNodes.forEach( c=>n.content.append(c) );
142-
this.append($s);
143-
}else if( isStr(n) )
144-
{ n = this.$( n );
145-
n.remove();
146-
}
147-
const c = CssChain( n.content ? n.content.childNodes : n ).clone(this);
135+
const $s = this.$('[slot]')
136+
.forEach( n => this.$(n.slot ? `slot[name="${n.slot}"]`:'slot:not([name])').length
137+
|| n.parentNode.insertBefore( nodeProp('slot','name',n.slot), n ));
138+
$s.remove();
139+
n = createEl('template');
140+
this.childNodes.forEach( c=>n.content.append(c) );
141+
this.append($s);
142+
}else if( isStr(n) )
143+
{ n = this.$( n );
144+
n.remove();
145+
}
146+
n = n.cloneNode(true);
147+
const content = n.content ? n.content.childNodes : n;
148+
const c = CssChain( content );
148149
c.slots().forEach( s =>
149150
{ const v = this.children.filter( n=>n.slot===s.name );
150-
v.length && setNodeHtml(s,v)
151+
const p = s.parentNode;
152+
each(v, e=>e.cssChainSlot = s);
153+
if(s.id ==='s3'){
154+
debugger;
155+
}
156+
const injectInSlot = (e,s)=>
157+
{
158+
if( e.tagName === 'SLOT' )
159+
{ const q = e.parentNode;
160+
const r = p.insertBefore( e, s);
161+
each( q.querySelectorAll(`[slot="${e.name}"]`), n=> p.insertBefore( n, r) );
162+
}else
163+
p.insertBefore( e, s);
164+
}
165+
v.length ? each( v, e=>injectInSlot( e, s) )
166+
: s.name==="" &&
167+
each ( [...(n.content ? n.content.childNodes : n.childNodes)]
168+
.filter(e=>!e.hasArttribute ||e.hasArttribute('slot'))
169+
, e=>p.insertBefore( e, s) );
170+
if( v.length ) s.hidden=true;
151171
});
152-
this.children.remove();
153-
this.append(c);
172+
this.children.filter(e=>!e.cssChainSlot).remove();
173+
this.append( CssChain( html2NodeArr('<light-dom></light-dom>') ).append(content) );
154174
return this;
155175
}
156176
get innerText(){ return this.txt() }
@@ -160,18 +180,18 @@ CssChainT extends Array
160180
if( val === undefined )
161181
return collectionText( arr );
162182
arr.forEach( isFn(val)
163-
? (n,i)=>setNodeText(n,val(n,i,arr))
164-
: n=>setNodeText(n,val) );
183+
? (n,i)=>setNodeText(n,val(n,i,arr))
184+
: n=>setNodeText(n,val) );
165185
return this
166186
}
167187
get outerHTML(){ return this.map( e=>e.outerHTML ).join('') }
168188
set outerHTML( val )
169189
{ return this.forEach( (n,i,arr)=>
170-
{ const p = n.parentNode;
171-
html2NodeArr(isFn(val) ? val(n,i,arr): val )
172-
.forEach( e=> p.insertBefore( (arr[i]=e), n));
173-
n.remove();
174-
})
190+
{ const p = n.parentNode;
191+
html2NodeArr(isFn(val) ? val(n,i,arr): val )
192+
.forEach( e=> p.insertBefore( (arr[i]=e), n));
193+
n.remove();
194+
})
175195
}
176196
get innerHTML(){ return this.html() }
177197
set innerHTML( val ){ return this.html(val) }
@@ -180,8 +200,8 @@ CssChainT extends Array
180200
if( val === undefined )
181201
return collectionHtml( arr );
182202
arr.forEach( isFn(val)
183-
? (n,i)=>setNodeHtml(n,val(n,i,arr))
184-
: n=>setNodeHtml(n,val) );
203+
? (n,i)=>setNodeHtml(n,val(n,i,arr))
204+
: n=>setNodeHtml(n,val) );
185205
return this
186206
}
187207
assignedElements(opts){ return CssChain([].concat( ...this.map( el=>el.assignedElements ? el.assignedElements(opts):[] ) ) ) }
@@ -201,8 +221,8 @@ CssChainT extends Array
201221
isStr(x)
202222
? ret.push( ...html2NodeArr(x) )
203223
: isArr(x)
204-
? ret.push(...x)
205-
: ret.push( isNode(x) ? x : m )
224+
? ret.push(...x)
225+
: ret.push( isNode(x) ? x : m )
206226
}));
207227
return CssChain( ret );
208228
}
@@ -216,9 +236,9 @@ CssChainT extends Array
216236
}
217237

218238
const appliedTypes = new Set()
219-
, OBJ_prototype = Object.getPrototypeOf( {} );
239+
, OBJ_prototype = Object.getPrototypeOf( {} );
220240

221-
export function
241+
export function
222242
applyPrototype( nodeOrTag, ApiChain )
223243
{ const node = isStr(nodeOrTag) ? createEl(nodeOrTag) : nodeOrTag;
224244
if( appliedTypes.has(node.tagName) )
@@ -241,7 +261,7 @@ Object.getOwnPropertyNames(window)
241261
.map( key=>key.substring(4,key.length-7).toLowerCase() )
242262
.forEach( tag=>applyPrototype( createEl(tag), CssChainT ) );
243263

244-
export function
264+
export function
245265
CssChain( css, el=document, protoArr=[] )
246266
{
247267
const arr = 'string'===typeof css
@@ -250,7 +270,7 @@ CssChain( css, el=document, protoArr=[] )
250270

251271
if( isArr( protoArr ) )
252272
{ if( !protoArr.length )
253-
protoArr = [...arr].slice(0,256);
273+
protoArr = [...arr].slice(0,256);
254274
}else
255275
protoArr = [ protoArr ];
256276

test/complex-case-1.html

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<html>
2+
<head>
3+
4+
<style>
5+
body,#test_complex{ display: flex; }
6+
div{ padding: 0 1rem;}
7+
.native{ background: #00A0D9}
8+
.shadowroot{ background: #4080F0}
9+
.shadow{ background: lightgreen}
10+
.light{ background: yellow}
11+
#refNode:before{content: 'ref'; }
12+
.native:before{content: 'native'; }
13+
.shadowroot:before{content: 'shadowroot'; }
14+
.light:before{content: 'light'; }
15+
.shadow:before{content: 'shadow'; }
16+
</style>
17+
</head>
18+
<body>
19+
<ul>
20+
<li> <b>ref</b> reference dom </li>
21+
<li> <b>shadow</b> generated by browser test code </li>
22+
<li> <b>light</b> generated by light dom </li>
23+
<li> <code> shadowroot="open" </code> inline template </li>
24+
</ul>
25+
<div id="test_complex">
26+
<div id="refNode">
27+
<template data-mode="open">
28+
<div id="host2">
29+
<template data-mode="open">
30+
<slot id="s5" name="slot5">#s5</slot>
31+
</template>
32+
<slot id="s1" name="slot1" slot="slot5">#s1</slot>
33+
<div id="c5" slot="slot5">#c5</div>
34+
</div>
35+
</template>
36+
<div id="c1" slot="slot1">#c1</div>
37+
</div>
38+
</div>
39+
40+
41+
<div class="shadowroot">
42+
<div id="host1">
43+
<template data-mode="open" shadowroot="open">
44+
<div id="host2">
45+
<template data-mode="open" shadowroot="open">
46+
<slot id="s5" name="slot5">#s5</slot>
47+
</template>
48+
<slot id="s1" name="slot1" slot="slot5">#s1</slot>
49+
<div id="c5" slot="slot5">#c5</div>
50+
</div>
51+
</template>
52+
<div id="c1" slot="slot1">#c1</div>
53+
</div>
54+
</div>
55+
<script type="module" >
56+
import {createTestTree} from '../src/slots-light-vs-shadow.js';
57+
let n = createTestTree(window.test_complex.firstElementChild);
58+
59+
</script>
60+
</body>
61+
</html>

test/complex-case-2.html

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<html>
2+
<head>
3+
4+
<style>
5+
body,#test_complex{ display: flex; }
6+
div{ padding: 0 1rem;}
7+
.native{ background: #00A0D9}
8+
.shadowroot{ background: #4080F0}
9+
.shadow{ background: lightgreen}
10+
.light{ background: yellow}
11+
#refNode:before{content: 'ref'; }
12+
.native:before{content: 'native'; }
13+
.shadowroot:before{content: 'shadowroot'; }
14+
.light:before{content: 'light'; }
15+
.shadow:before{content: 'shadow'; }
16+
</style>
17+
</head>
18+
<body>
19+
<ul>
20+
<li> <b>ref</b> reference dom </li>
21+
<li> <b>shadow</b> generated by browser test code </li>
22+
<li> <b>light</b> generated by light dom </li>
23+
<li> <code> shadowroot="open" </code> inline template </li>
24+
</ul>
25+
<div id="test_complex">
26+
<div id="refNode">
27+
<template data-mode="open">
28+
<div id="host2">
29+
<template data-mode="open">
30+
<slot id="s5" name="slot5">#s5</slot>
31+
<slot id="s6" name="slot6">#s6</slot>
32+
</template>
33+
<slot id="s1" name="slot1" slot="slot5">#s1</slot>
34+
<slot id="s2" name="slot2" slot="slot6">#s2</slot>
35+
<div id="c5" slot="slot5">#c5</div>
36+
</div>
37+
</template>
38+
<div id="c1" slot="slot1">#c1</div>
39+
<div id="c2" slot="slot2">#c2</div>
40+
</div>
41+
</div>
42+
43+
44+
<div class="shadowroot">
45+
<div id="host1">
46+
<template data-mode="open" shadowroot="open">
47+
<div id="host2">
48+
<template data-mode="open" shadowroot="open">
49+
<slot id="s5" name="slot5">#s5</slot>
50+
<slot id="s6" name="slot6">#s6</slot>
51+
</template>
52+
<slot id="s1" name="slot1" slot="slot5">#s1</slot>
53+
<slot id="s2" name="slot2" slot="slot6">#s2</slot>
54+
<div id="c5" slot="slot5">#c5</div>
55+
</div>
56+
</template>
57+
<div id="c1" slot="slot1">#c1</div>
58+
<div id="c2" slot="slot2">#c2</div>
59+
</div>
60+
</div>
61+
<script type="module" >
62+
import {createTestTree} from '../src/slots-light-vs-shadow.js';
63+
let n = createTestTree(window.test_complex.firstElementChild);
64+
65+
</script>
66+
</body>
67+
</html>

0 commit comments

Comments
 (0)