@epa-wg/custom-element 0.0.32 → 0.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.idea/copilot.data.migration.agent.xml +6 -0
- package/README.md +5 -5
- package/bin/xslDtd2Ide.mjs +160 -160
- package/custom-element.d.ts +4 -0
- package/custom-element.js +119 -50
- package/demo/a.html +10 -3
- package/demo/{parameters.html → attributes.html} +71 -7
- package/demo/html-template.html +5 -4
- package/demo/s.xml +3859 -7
- package/demo/s.xslt +13 -48
- package/demo/s1.xml +3706 -0
- package/demo/ss.html +13 -4
- package/http-request.js +7 -0
- package/ide/web-types-dce.json +1 -1
- package/ide/web-types-xsl.json +1 -1
- package/index.html +1 -1
- package/package.json +1 -1
package/custom-element.js
CHANGED
|
@@ -5,7 +5,7 @@ const XSL_NS_URL = 'http://www.w3.org/1999/XSL/Transform'
|
|
|
5
5
|
|
|
6
6
|
// const log = x => console.debug( new XMLSerializer().serializeToString( x ) );
|
|
7
7
|
|
|
8
|
-
const attr = (el, attr)=> el
|
|
8
|
+
const attr = (el, attr)=> el?.getAttribute?.(attr)
|
|
9
9
|
, isText = e => e.nodeType === 3
|
|
10
10
|
, isString = s => typeof s === 'string'
|
|
11
11
|
, isNode = e => e && typeof e.nodeType === 'number'
|
|
@@ -89,7 +89,12 @@ obj2node( o, tag, doc )
|
|
|
89
89
|
return create(tag,o,doc);
|
|
90
90
|
if( t === 'number' )
|
|
91
91
|
return create(tag,''+o,doc);
|
|
92
|
-
|
|
92
|
+
if( isNode(o) )
|
|
93
|
+
{
|
|
94
|
+
const el = create(tag);
|
|
95
|
+
el.append(o);
|
|
96
|
+
return el;
|
|
97
|
+
}
|
|
93
98
|
if( o instanceof Array )
|
|
94
99
|
{ const ret = create('array','',doc);
|
|
95
100
|
o.map( ae => ret.append( obj2node(ae,tag,doc)) );
|
|
@@ -103,13 +108,20 @@ obj2node( o, tag, doc )
|
|
|
103
108
|
}
|
|
104
109
|
const ret = create(tag,'',doc);
|
|
105
110
|
for( let k in o )
|
|
106
|
-
|
|
111
|
+
{
|
|
112
|
+
if( typeof o[ k ] === 'function' || o[ k ] instanceof Window )
|
|
107
113
|
continue
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
114
|
+
if( isNode( o[ k ] ) )
|
|
115
|
+
{ if( k === 'data' || k==='value' )
|
|
116
|
+
;
|
|
111
117
|
else
|
|
112
|
-
|
|
118
|
+
continue
|
|
119
|
+
}
|
|
120
|
+
if( typeof o[ k ] !== "object" && isValidTagName( k ) )
|
|
121
|
+
ret.setAttribute( k, o[ k ] )
|
|
122
|
+
else
|
|
123
|
+
ret.append( obj2node( o[ k ], k, doc ) )
|
|
124
|
+
}
|
|
113
125
|
return ret;
|
|
114
126
|
}
|
|
115
127
|
export function
|
|
@@ -234,6 +246,8 @@ createXsltFromDom( templateNode, S = 'xsl:stylesheet' )
|
|
|
234
246
|
const d = xml2dom( '<xhtml/>' )
|
|
235
247
|
, n = d.importNode(r, true);
|
|
236
248
|
d.replaceChild(n,d.documentElement);
|
|
249
|
+
if( n.namespaceURI === HTML_NS_URL && !attr(n,'xmlns'))
|
|
250
|
+
n.setAttribute('xmlns',HTML_NS_URL);
|
|
237
251
|
return xslHtmlNs(n);
|
|
238
252
|
};
|
|
239
253
|
if( e )
|
|
@@ -294,6 +308,16 @@ createXsltFromDom( templateNode, S = 'xsl:stylesheet' )
|
|
|
294
308
|
fr.append(r)
|
|
295
309
|
}
|
|
296
310
|
|
|
311
|
+
[...fr.querySelectorAll('[test]')].forEach( n=>{
|
|
312
|
+
const t = attr(n,'test')
|
|
313
|
+
, r = t.replace(/hasBoolAttribute\((.*?)\)/g,
|
|
314
|
+
(match, p1, p2,p3,p4)=>
|
|
315
|
+
{ const a = p1.substring(1);
|
|
316
|
+
return `(not($${a} = \'false\') and ($${a} = '' or $${a} = '${a}' or $${a} = 'true' ))`
|
|
317
|
+
});
|
|
318
|
+
t!== r && n.setAttribute('test',r);
|
|
319
|
+
});
|
|
320
|
+
|
|
297
321
|
[...fr.querySelectorAll('dce-root>attribute')].forEach( a=>
|
|
298
322
|
{
|
|
299
323
|
keepAttributes(a,'namespace,name,select');
|
|
@@ -301,7 +325,7 @@ createXsltFromDom( templateNode, S = 'xsl:stylesheet' )
|
|
|
301
325
|
, name = attr(a,'name');
|
|
302
326
|
|
|
303
327
|
declaredAttributes.push(name);
|
|
304
|
-
if( a.childNodes.length)
|
|
328
|
+
if( a.childNodes.length )
|
|
305
329
|
hardcodedAttributes[name] = a.textContent;
|
|
306
330
|
|
|
307
331
|
payload.append(p);
|
|
@@ -317,10 +341,15 @@ createXsltFromDom( templateNode, S = 'xsl:stylesheet' )
|
|
|
317
341
|
if( select?.length>1 )
|
|
318
342
|
{ p.removeAttribute('select');
|
|
319
343
|
const c = $( xslDom, 'template[match="ignore"]>choose').cloneNode(true);
|
|
320
|
-
// todo multiple ?? operators
|
|
321
344
|
emptyNode(c.firstElementChild).append( createText(c,'{'+select[0]+'}'));
|
|
322
|
-
|
|
323
|
-
|
|
345
|
+
c.firstElementChild.setAttribute('test',select[0]);
|
|
346
|
+
for( let i=1; i<select.length-1; i++)
|
|
347
|
+
{ const when = c.firstElementChild.cloneNode(true);
|
|
348
|
+
emptyNode(when).append( createText(c,'{'+select[i]+'}'));
|
|
349
|
+
when.setAttribute('test',select[i]);
|
|
350
|
+
c.insertBefore(when, c.lastElementChild);
|
|
351
|
+
}
|
|
352
|
+
emptyNode(c.lastElementChild ).append( createText(c,'{'+select[select.length-1]+'}'));
|
|
324
353
|
p.append(c);
|
|
325
354
|
val = c.cloneNode(true);
|
|
326
355
|
}else
|
|
@@ -329,8 +358,12 @@ createXsltFromDom( templateNode, S = 'xsl:stylesheet' )
|
|
|
329
358
|
a.append(val);
|
|
330
359
|
a.removeAttribute('select');
|
|
331
360
|
}else
|
|
332
|
-
{
|
|
361
|
+
{
|
|
362
|
+
keepAttributes( p, 'name' );
|
|
333
363
|
p.setAttribute('select','/datadom/attributes/'+name)
|
|
364
|
+
|
|
365
|
+
if( !hardcodedAttributes[name] )
|
|
366
|
+
a.remove();
|
|
334
367
|
}
|
|
335
368
|
});
|
|
336
369
|
[...fr.querySelectorAll('[value]')].filter(el=>el.getAttribute('value').match( /\{(.*)\?\?(.*)\}/g )).forEach(el=>
|
|
@@ -460,12 +493,15 @@ event2slice( x, sliceNames, ev, dce )
|
|
|
460
493
|
const v = notChecked? '' : el.value ?? attr( el, 'value' );
|
|
461
494
|
cleanSliceValue();
|
|
462
495
|
if( v === null || v === undefined )
|
|
496
|
+
{
|
|
463
497
|
[...s.childNodes].filter(n=>n.localName!=='event').map(n=>n.remove());
|
|
498
|
+
s.removeAttribute('value');
|
|
499
|
+
}
|
|
464
500
|
else
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
501
|
+
{ const ve = isString(v) ? createText( d, v) : obj2node(v,'value',s.ownerDocument);
|
|
502
|
+
s.append( ve );
|
|
503
|
+
s.setAttribute('value',v);
|
|
504
|
+
}
|
|
469
505
|
}
|
|
470
506
|
return s
|
|
471
507
|
})
|
|
@@ -513,11 +549,26 @@ const loadTemplateRoots = async ( src, dce )=>
|
|
|
513
549
|
export function mergeAttr( from, to )
|
|
514
550
|
{ for( let a of from.attributes)
|
|
515
551
|
try
|
|
516
|
-
{
|
|
552
|
+
{ const name = a.name;
|
|
553
|
+
if( name.startsWith('xmlns') )
|
|
554
|
+
continue;
|
|
555
|
+
if( a.namespaceURI )
|
|
556
|
+
{ if( !to.hasAttributeNS(a.namespaceURI, name) || to.getAttributeNS(a.namespaceURI, name) !== a.value )
|
|
557
|
+
to.setAttributeNS( a.namespaceURI, name, a.value )
|
|
558
|
+
}else
|
|
559
|
+
{ if( !to.hasAttribute(name) || to.getAttribute(name) !== a.value )
|
|
560
|
+
to.setAttribute( a.name, a.value )
|
|
561
|
+
}
|
|
517
562
|
if( a.name === 'value')
|
|
518
563
|
to.value = a.value
|
|
519
564
|
}catch(e)
|
|
520
565
|
{ console.warn('attribute assignment error',e?.message || e); }
|
|
566
|
+
const ea = to.dceExportedAttributes
|
|
567
|
+
, aa = to.getAttribute('dce-exported-attributes')
|
|
568
|
+
, em = aa ? new Set( aa.split(' ') ) : null;
|
|
569
|
+
for( let a of to.getAttributeNames() )
|
|
570
|
+
if( !from.hasAttribute(a) && !ea?.has(a) && !em?.has(a) )
|
|
571
|
+
to.removeAttribute(a)
|
|
521
572
|
}
|
|
522
573
|
export function assureUnique(n, id=0)
|
|
523
574
|
{
|
|
@@ -630,14 +681,19 @@ export const toXsl = (el, defParent) => {
|
|
|
630
681
|
x.setAttribute( a.name, a.value );
|
|
631
682
|
while(el.firstChild)
|
|
632
683
|
x.append(el.firstChild);
|
|
684
|
+
const replacement = el.localName === 'if' || el.localName === 'choose' ? (() => {
|
|
685
|
+
const span = create('span');
|
|
686
|
+
span.append(x);
|
|
687
|
+
return span;
|
|
688
|
+
})() : x;
|
|
633
689
|
if( el.parentElement )
|
|
634
|
-
el.parentElement.replaceChild(
|
|
690
|
+
el.parentElement.replaceChild( replacement, el );
|
|
635
691
|
else
|
|
636
692
|
{ const p = (el.parentElement || defParent)
|
|
637
693
|
, arr = [...p.childNodes];
|
|
638
694
|
arr.forEach((n, i) => {
|
|
639
695
|
if (n === el)
|
|
640
|
-
arr[i] =
|
|
696
|
+
arr[i] = replacement;
|
|
641
697
|
});
|
|
642
698
|
p.replaceChildren(...arr);
|
|
643
699
|
}
|
|
@@ -650,7 +706,7 @@ CustomElement extends HTMLElement
|
|
|
650
706
|
async connectedCallback()
|
|
651
707
|
{
|
|
652
708
|
if(this.firstElementChild && this.firstElementChild.localName !== 'template')
|
|
653
|
-
console.
|
|
709
|
+
console.log('custom-element used without template wrapping content\n', this.outerHTML);
|
|
654
710
|
const templateRoots = await loadTemplateRoots( attr( this, 'src' ), this )
|
|
655
711
|
, tag = attr( this, 'tag' )
|
|
656
712
|
, tagName = tag ? tag : 'dce-'+crypto.randomUUID();
|
|
@@ -681,11 +737,13 @@ CustomElement extends HTMLElement
|
|
|
681
737
|
.map(splitSliceNames).flat();
|
|
682
738
|
|
|
683
739
|
const { declaredAttributes, hardcodedAttributes, exposedAttributes } = templateDocs[0];
|
|
740
|
+
const dceExportedAttributes = new Set([...Object.keys(hardcodedAttributes), ...Object.keys(exposedAttributes)]);
|
|
684
741
|
|
|
685
742
|
class DceElement extends HTMLElement
|
|
686
743
|
{
|
|
687
744
|
static get observedAttributes(){ return declaredAttributes; }
|
|
688
745
|
#inTransform = 0;
|
|
746
|
+
get dceExportedAttributes(){ return dceExportedAttributes; }
|
|
689
747
|
connectedCallback()
|
|
690
748
|
{ let payload = sanitizeBlankText(this.childNodes);
|
|
691
749
|
if( this.firstElementChild?.tagName === 'TEMPLATE' )
|
|
@@ -719,8 +777,9 @@ CustomElement extends HTMLElement
|
|
|
719
777
|
this.innerHTML='';
|
|
720
778
|
const attrsRoot = injectData( x, 'attributes' , this.attributes, e => createXmlNode( e.nodeName, e.value ) )
|
|
721
779
|
, inAttrs = a=> this.hasAttribute(a) || [...attrsRoot.children].find(e=>e.localName === a);
|
|
780
|
+
mergeAttr( this, attrsRoot );
|
|
722
781
|
Object.keys(hardcodedAttributes).map(a=> inAttrs(a) || attrsRoot.append(createXmlNode(a,hardcodedAttributes[a])) );
|
|
723
|
-
|
|
782
|
+
Object.keys(exposedAttributes).map(a=> inAttrs(a) || attrsRoot.append(createXmlNode(a)) );
|
|
724
783
|
|
|
725
784
|
injectData( x, 'dataset', Object.keys( this.dataset ), k => createXmlNode( k, this.dataset[ k ] ) );
|
|
726
785
|
const sliceRoot = injectData( x, 'slice', sliceNames, k => createXmlNode( k, '' ) )
|
|
@@ -753,34 +812,42 @@ CustomElement extends HTMLElement
|
|
|
753
812
|
const transform = this.transform = ()=>
|
|
754
813
|
{ if(this.#inTransform){ debugger }
|
|
755
814
|
this.#inTransform = 1;
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
{ this.
|
|
773
|
-
this
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
{ this.
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
815
|
+
const renderModel = ()=>
|
|
816
|
+
{
|
|
817
|
+
const ff = xp.map( (p,i) =>
|
|
818
|
+
{ const f = p.transformToFragment(x.ownerDocument, document)
|
|
819
|
+
if( !f )
|
|
820
|
+
console.error( "XSLT transformation error. xsl:\n", xmlString(templateDocs[i]), '\nxml:\n', xmlString(x) );
|
|
821
|
+
return f
|
|
822
|
+
});
|
|
823
|
+
ff.map( f =>
|
|
824
|
+
{ if( !f )
|
|
825
|
+
return;
|
|
826
|
+
assureUnique(f);
|
|
827
|
+
merge( this, f.childNodes )
|
|
828
|
+
})
|
|
829
|
+
let attrChangedCount = 0;
|
|
830
|
+
Object.entries(hardcodedAttributes).map(( [a,v] )=>
|
|
831
|
+
{ if( !this.hasAttribute(a) && v !== attr(this,a) )
|
|
832
|
+
{ this.setAttribute( a, v );
|
|
833
|
+
this.#applyAttribute( a, v );
|
|
834
|
+
attrChangedCount++;
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
Object.keys(exposedAttributes).map( a =>
|
|
839
|
+
{ let v = attr(this.firstElementChild,a);
|
|
840
|
+
if( v !== attr(this,a) )
|
|
841
|
+
{ this.setAttribute( a, v );
|
|
842
|
+
this.#applyAttribute( a, v );
|
|
843
|
+
attrChangedCount++;
|
|
844
|
+
}
|
|
845
|
+
});
|
|
846
|
+
return attrChangedCount;
|
|
847
|
+
};
|
|
848
|
+
if( renderModel() )
|
|
849
|
+
if( renderModel() )
|
|
850
|
+
console.warn("model update should not be the result of transform more than once");
|
|
784
851
|
|
|
785
852
|
function getSliceTarget(el)
|
|
786
853
|
{ let r = el;
|
|
@@ -868,13 +935,15 @@ CustomElement extends HTMLElement
|
|
|
868
935
|
#applyAttribute(name, newValue)
|
|
869
936
|
{ if( 'value' === name )
|
|
870
937
|
this.value = newValue;
|
|
938
|
+
const attrs = this.xml.querySelector('attributes');
|
|
871
939
|
let a = this.xml.querySelector(`attributes>${name}`);
|
|
872
940
|
if( a )
|
|
873
941
|
emptyNode(a).append( createText(a,newValue) );
|
|
874
942
|
else
|
|
875
943
|
{ a = create( name, newValue, this.xml );
|
|
876
|
-
|
|
944
|
+
attrs.append( a );
|
|
877
945
|
}
|
|
946
|
+
this.#inTransform || attrs.setAttribute(name,newValue);
|
|
878
947
|
|
|
879
948
|
this.dispatchEvent(new CustomEvent('change', { bubbles: true,detail: { [name]: newValue }}))
|
|
880
949
|
}
|
package/demo/a.html
CHANGED
|
@@ -63,11 +63,18 @@
|
|
|
63
63
|
<body>
|
|
64
64
|
|
|
65
65
|
|
|
66
|
+
<custom-element tag="dce-link2" >
|
|
67
|
+
<template>
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
<template><i>loading SVG from templates file ...</i></template>
|
|
69
|
-
</custom-element>
|
|
69
|
+
<attribute name="p3" select="//attributes/p3 ?? 'def_P3' "></attribute>
|
|
70
70
|
|
|
71
|
+
p3: <code data-testid="t3">{$p3}</code>
|
|
72
|
+
</template>
|
|
73
|
+
</custom-element>
|
|
74
|
+
<section>
|
|
75
|
+
<dce-link2 id="dce2" p1="123" p2="override ignored as select is defined"></dce-link2>
|
|
76
|
+
|
|
77
|
+
</section>
|
|
71
78
|
|
|
72
79
|
</body>
|
|
73
80
|
</html>
|
|
@@ -22,14 +22,30 @@
|
|
|
22
22
|
<nav>
|
|
23
23
|
<a href="../index.html"><h3><code>custom-element</code> demo</h3></a>
|
|
24
24
|
</nav>
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
<main>
|
|
26
|
+
<p><code>attribute</code> is used for DCE attributes declaration and track the attributes changes. It also be used by IDE and validation.</p>
|
|
27
|
+
<p>The attribute can be changed by component itself and used as output to the container.
|
|
28
|
+
Usual case is when <code>value</code> attribute is updated from inside.</p>
|
|
29
|
+
<p>Initial value of attribute is available on the <code>attributes</code> node attribute as in <code>/datadom/attributes/@attr1</code></p>
|
|
30
|
+
<p>The current, i.e. including the changes by component itself, attribute value is a child node of <code>attributes</code> as in <code>/datadom/attributes/attr1</code>.</p>
|
|
31
|
+
<p>To define the attribute which is modified from within, the 3 parts are usually used as in <code>//s[//s/event] ?? //attributes/@v ?? 'def' </code>
|
|
32
|
+
<ol>
|
|
33
|
+
<li><code>//s[//s/event]</code> the slice <code>s</code> with event gives the slice value which was modified by user event like input</li>
|
|
34
|
+
<li><code>//attributes/@v</code> the attribute passed by container</li>
|
|
35
|
+
<li><code>'def' </code> the default value which used when no user input or attribute set by container</li>
|
|
36
|
+
</ol>
|
|
37
|
+
</p>
|
|
38
|
+
</main>
|
|
39
|
+
<html-demo-element legend="attributes definition" >
|
|
40
|
+
<p slot="description">
|
|
41
|
+
<code>attribute</code> is used for DCE attributes declaration and track the attributes changes. It also be used by IDE and validation.
|
|
42
|
+
|
|
43
|
+
</p>
|
|
28
44
|
<template>
|
|
29
45
|
<custom-element tag="dce-link" hidden>
|
|
30
46
|
<attribute name="p1" >default_P1 </attribute>
|
|
31
47
|
<attribute name="p2" select="'always_p2'" ></attribute>
|
|
32
|
-
<attribute name="p3" select="//p3 ?? 'def_P3' " ></attribute>
|
|
48
|
+
<attribute name="p3" select="//attributes/@p3 ?? 'def_P3' " ></attribute>
|
|
33
49
|
p1:{$p1} <br/> p2: {$p2} <br/> p3: {$p3}
|
|
34
50
|
</custom-element>
|
|
35
51
|
<dce-link id="dce1" ></dce-link>
|
|
@@ -44,13 +60,15 @@ params needed to declare DCE attributes and track the attributes changes. It als
|
|
|
44
60
|
</template>
|
|
45
61
|
</html-demo-element>
|
|
46
62
|
|
|
47
|
-
<html-demo-element legend="attribute from slice"
|
|
48
|
-
|
|
49
|
-
|
|
63
|
+
<html-demo-element legend="attribute from slice">
|
|
64
|
+
<p slot="description">
|
|
65
|
+
When slice value points to attribute, it would be populated on slice change.<br/>
|
|
50
66
|
Type in the input field to see the variable $title change. <br/>
|
|
51
67
|
Hover the mouse to see the title attribute text popup.<br/>
|
|
52
68
|
Inspect DCE node in dev tools to see `title` attribute updated while typing.
|
|
53
69
|
|
|
70
|
+
</p>
|
|
71
|
+
|
|
54
72
|
<template>
|
|
55
73
|
<custom-element>
|
|
56
74
|
<template>
|
|
@@ -62,6 +80,52 @@ when slice value points to attribute, it would be populated on slice change
|
|
|
62
80
|
</template>
|
|
63
81
|
</html-demo-element>
|
|
64
82
|
|
|
83
|
+
|
|
84
|
+
<html-demo-element legend="V attribute matches input value" description="
|
|
85
|
+
Type in the input field and observe in DevTools the V attribute changed.
|
|
86
|
+
">
|
|
87
|
+
<template>
|
|
88
|
+
<custom-element tag="x-input" >
|
|
89
|
+
<template>
|
|
90
|
+
<attribute name="is-changed" select="count(//s/event) > 0"></attribute>
|
|
91
|
+
<attribute name="v" select="//s[//s/event] ?? //attributes/@v ?? 'def' "></attribute>
|
|
92
|
+
/datadom/attributes/v='{/datadom/attributes/v}'<br/>
|
|
93
|
+
same as v='{v}'<br/>
|
|
94
|
+
same as $v='{$v}'<br/>
|
|
95
|
+
//attributes/@v='{//attributes/@v}'<br/>
|
|
96
|
+
//s='{//s}'<br/>
|
|
97
|
+
is-changed ={ is-changed }<br/>
|
|
98
|
+
<input slice="s" slice-event="input" value="{//attributes/v}"/>
|
|
99
|
+
</template>
|
|
100
|
+
</custom-element>
|
|
101
|
+
<x-input></x-input>
|
|
102
|
+
<x-input v="V1"></x-input>
|
|
103
|
+
</template>
|
|
104
|
+
</html-demo-element>
|
|
105
|
+
|
|
106
|
+
<html-demo-element legend="attribute defaults, from container, and from slice" description="
|
|
107
|
+
Type in the input field and observe in DevTools the V attribute changed.
|
|
108
|
+
">
|
|
109
|
+
<template>
|
|
110
|
+
<custom-element tag="attr-demo">
|
|
111
|
+
<template>
|
|
112
|
+
<variable name="has-input" select="count(//s/*) > 0"></variable>
|
|
113
|
+
<attribute name="v" select="//s[//s/event] ?? //attributes/@v ?? 'def' "></attribute>
|
|
114
|
+
//attributes/v='{//attributes/v}'<br/>
|
|
115
|
+
//attributes/@v='{//attributes/@v}'<br/>
|
|
116
|
+
$v='{$v}'<br/>
|
|
117
|
+
//s='{//s}'<br/>
|
|
118
|
+
A='{//s[//s/event] | //attributes/v[not(//s/event)]}'<br/>
|
|
119
|
+
has-input ={ $has-input }<br/>
|
|
120
|
+
<input slice="s" slice-event="input" />
|
|
121
|
+
</template>
|
|
122
|
+
</custom-element>
|
|
123
|
+
|
|
124
|
+
<attr-demo></attr-demo>
|
|
125
|
+
<attr-demo v="From Container"></attr-demo>
|
|
126
|
+
</template>
|
|
127
|
+
</html-demo-element>
|
|
128
|
+
|
|
65
129
|
<details>
|
|
66
130
|
<summary>Attributes processing</summary>
|
|
67
131
|
To be available in template, <code>custom-element</code> attributes should be
|
package/demo/html-template.html
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
3
3
|
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
4
5
|
<title>template based on HTML file</title>
|
|
5
6
|
<style>svg {
|
|
6
7
|
width: 4rem;
|
|
@@ -8,9 +9,9 @@
|
|
|
8
9
|
</head>
|
|
9
10
|
<body>
|
|
10
11
|
<script>console.error('Stranger danger!')</script>
|
|
11
|
-
<b id="wave">👋</b>
|
|
12
|
-
<b id="ok">👌</b>
|
|
13
|
-
<svg id="dwc-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 216 209.18">
|
|
12
|
+
<b id="wave" data-testid="wave" >👋</b>
|
|
13
|
+
<b id="ok" data-testid="ok" >👌</b>
|
|
14
|
+
<svg id="dwc-logo" data-testid="dwc-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 216 209.18">
|
|
14
15
|
<defs>
|
|
15
16
|
<style>.cls-1 {
|
|
16
17
|
fill: #c2e6f1;
|
|
@@ -73,7 +74,7 @@
|
|
|
73
74
|
<path class="cls-1"
|
|
74
75
|
d="m184.02,96.93l20.64-11.92c.47-.27.47-.79,0-1.06l-20.65-11.92h0c-4.44-2.57-8.22-2.57-12.67,0l-20.65,11.92c-.47.27-.47.79,0,1.06l20.64,11.92c4.44,2.57,8.22,2.57,12.67,0h0Z"/>
|
|
75
76
|
</svg>
|
|
76
|
-
<math id="sophomores-dream" display="block">
|
|
77
|
+
<math id="sophomores-dream" data-testid="ml-test" display="block">
|
|
77
78
|
<mrow>
|
|
78
79
|
<msubsup>
|
|
79
80
|
<mo>∫</mo>
|