diff --git a/README.md b/README.md index 2a35e7e..062d139 100644 --- a/README.md +++ b/README.md @@ -348,9 +348,9 @@ within template [github-image]: https://cdnjs.cloudflare.com/ajax/libs/octicons/8.5.0/svg/mark-github.svg [npm-image]: https://img.shields.io/npm/v/@epa-wg/custom-element.svg [npm-url]: https://npmjs.org/package/@epa-wg/custom-element -[coverage-image]: https://unpkg.com/@epa-wg/custom-element-dist@0.0.24/coverage/src/custom-element/coverage.svg -[coverage-url]: https://unpkg.com/@epa-wg/custom-element-dist@0.0.24/coverage/src/custom-element/index.html -[storybook-url]: https://unpkg.com/@epa-wg/custom-element-dist@0.0.24/storybook-static/index.html?path=/story/welcome--introduction +[coverage-image]: https://unpkg.com/@epa-wg/custom-element-dist@0.0.26/coverage/src/custom-element/coverage.svg +[coverage-url]: https://unpkg.com/@epa-wg/custom-element-dist@0.0.26/coverage/src/custom-element/index.html +[storybook-url]: https://unpkg.com/@epa-wg/custom-element-dist@0.0.26/storybook-static/index.html?path=/story/welcome--introduction [sandbox-url]: https://stackblitz.com/github/EPA-WG/custom-element?file=index.html [webcomponents-url]: https://www.webcomponents.org/element/@epa-wg/custom-element [webcomponents-img]: https://img.shields.io/badge/webcomponents.org-published-blue.svg diff --git a/bin/xslDtd2Ide.mjs b/bin/xslDtd2Ide.mjs index 4018850..d7c69e9 100644 --- a/bin/xslDtd2Ide.mjs +++ b/bin/xslDtd2Ide.mjs @@ -116,7 +116,7 @@ writeFileSync( '.././ide/customData-xsl.json', JSON.stringify( vsCode, undefined const intelliJ = { "$schema": "http://json.schemastore.org/web-types", "name": "@epa-wg/custom-element", - "version": "0.0.24", + "version": "0.0.26", "js-types-syntax": "typescript", "description-markup": "markdown", "contributions": { diff --git a/custom-element.js b/custom-element.js index 8f1cb7c..1e74172 100644 --- a/custom-element.js +++ b/custom-element.js @@ -259,7 +259,7 @@ createXsltFromDom( templateNode, S = 'xsl:stylesheet' ) for( const c of fr.childNodes ) payload.append(xslDom.importNode(c,true)) - const embeddedTemplates = [...payload.querySelectorAll('template')]; + const embeddedTemplates = [...payload.getElementsByTagName('xsl:template')]; embeddedTemplates.forEach(t=>payload.ownerDocument.documentElement.append(t)); const slotCall = $(xslDom,'call-template[name="slot"]') @@ -288,8 +288,9 @@ xhrTemplate(src) // xhr.overrideMimeType("text/xml"); xhr.onload = () => { if( xhr.readyState === xhr.DONE && xhr.status === 200 ) - resolve( xhr.responseXML || create('div', xhr.responseText ) ) - reject(xhr.statusText) + resolve( xhr.responseXML?.body || xhr.responseXML || create('div', xhr.responseText ) ) + else + reject(`${xhr.statusText} - ${src}`) }; xhr.addEventListener("error", ev=>reject(ev) ); @@ -372,7 +373,7 @@ event2slice( x, sliceNames, ev, dce ) s.append( obj2node(new FormData(el),'value', s.ownerDocument) ) return s } - const v = el.value ?? attr( sel, 'value' ) ; + const v = el.value ?? attr( el, 'value' ) ; cleanSliceValue(); if( v === null || v === undefined ) [...s.childNodes].filter(n=>n.localName!=='event').map(n=>n.remove()); @@ -396,19 +397,27 @@ const loadTemplateRoots = async ( src, dce )=> return [dce] if( src.startsWith('#') ) return ( n => - { if(!n) return [] - const a = n.querySelectorAll(src) - if( a.length ) - return [...a] - const r = n.getRootNode(); - return r===n ? []: getByHashId(r) + { const a = n.querySelectorAll(src) + return [...( a.length ? a : n.getRootNode().querySelectorAll(src) )] })(dce.parentElement) try - { // todo cache - const dom = await xhrTemplate(src) - const hash = new URL(src, location).hash + { const [path, hash] = src.split('#'); + if( '.' === src.charAt(0)) + src = new URL(path, dce.closest('[base]')?.getAttribute('base') || location ).href; + else + try + { src = import.meta.resolve( path ); + if(hash) + src +='#'+hash; + } + catch( e ) + { console.error(e.message) } + // todo cache + const dom = await xhrTemplate(src); + dce.setAttributeNS('xml', 'base', src ); + if( hash ) - { const ret = dom.querySelectorAll(hash); + { const ret = dom.querySelectorAll('#'+hash); if( ret.length ) return [...ret] return [dce] @@ -454,8 +463,11 @@ export function appendByDceId(parent,e,k) } export function merge( parent, fromArr ) { - if(!fromArr.length) - return removeChildren(parent); + if( 'dce-root' === parent.firstElementChild?.localName && 'dce-root' !== fromArr[0].localName) + return; + if( !fromArr.length ) + return 'dce-root' !== parent.firstElementChild?.localName && removeChildren(parent); + const id2old = {}; for( let c of parent.childNodes) { ASSERT( !id2old[c.dceId] ); @@ -482,7 +494,8 @@ export function merge( parent, fromArr ) appendByDceId(parent,e,k) } for( let v of Object.values(id2old) ) - v.remove(); + if( v.localName !== 'dce-root') + v.remove(); } export function assureUID(n,attr) { if( !n.hasAttribute(attr) ) @@ -523,7 +536,7 @@ export const xPath = (x,root)=> ret += n.textContent; return ret } -export const xslTags = 'stylesheet,transform,import,include,strip-space,preserve-space,output,key,decimal-format,namespace-alias,template,value-of,copy-of,number,apply-templates,apply-imports,for-each,sort,if,choose,when,otherwise,attribute-set,call-template,with-param,variable,param,text,processing-instruction,element,attribute,comment,copy,message,fallback'.split(','); +export const xslTags = 'stylesheet,transform,import,include,strip-space,preserve-space,output,key,decimal-format,namespace-alias,value-of,copy-of,number,apply-templates,apply-imports,for-each,sort,if,choose,when,otherwise,attribute-set,call-template,with-param,variable,param,text,processing-instruction,element,attribute,comment,copy,message,fallback'.split(','); export const toXsl = (el, defParent) => { const x = create('xsl:'+el.localName); for( let a of el.attributes ) @@ -725,13 +738,17 @@ CustomElement extends HTMLElement applySlices(); } #applyAttribute(name, newValue) - { let a = this.xml.querySelector(`attributes>${name}`); + { if( 'value' === name ) + this.value = newValue; + let a = this.xml.querySelector(`attributes>${name}`); if( a ) emptyNode(a).append( createText(a,newValue) ); else { a = create( name, newValue, this.xml ); this.xml.querySelector('attributes').append( a ); } + + this.dispatchEvent(new CustomEvent('change', { bubbles: true,detail: { [name]: newValue }})) } attributeChangedCallback(name, oldValue, newValue) { if( !this.xml || this.#inTransform ) diff --git a/demo/confused.svg b/demo/confused.svg index 1dc9863..053859b 100644 --- a/demo/confused.svg +++ b/demo/confused.svg @@ -1,5 +1,6 @@ + Confused diff --git a/demo/demo.css b/demo/demo.css index e851ab3..382c9a8 100644 --- a/demo/demo.css +++ b/demo/demo.css @@ -11,9 +11,13 @@ custom-element:not([tag]), dce-link,dce-1-slot,dce-2-slot,dce-3-slot,dce-4-slot,dce-2-slots,greet-element,pokemon-tile, dce-1,dce-2,dce-3,dce-4,dce-internal,dce-hash { box-shadow: 0 0 0.5rem lime; padding: 1rem; display: inline-block; flex:1; } +script{ display:none !important; } dd{ padding: 1rem;} p{ margin: 0;} - +code{ font-weight: bold; color: green; text-wrap: nowrap; } +*{ + gap: 1rem; +} html-demo-element h3 { text-shadow: 0 0 0.25em white; diff --git a/demo/embed-1.html b/demo/embed-1.html index 5684082..fa184a0 100644 --- a/demo/embed-1.html +++ b/demo/embed-1.html @@ -1,3 +1,2 @@

embed-1.html

- -? \ No newline at end of file + diff --git a/demo/external-template.html b/demo/external-template.html index 0f829f1..a814c42 100644 --- a/demo/external-template.html +++ b/demo/external-template.html @@ -3,26 +3,61 @@ http-request Declarative Custom Element implementation demo - + @@ -35,15 +70,16 @@

Loading DCE template by SRC attribute

@@ -51,67 +87,67 @@

Loading DCE template by SRC attribute

- + +> tree.xsl html-template.html @@ -119,10 +155,10 @@

Loading DCE template by SRC attribute

html-template.html @@ -132,13 +168,37 @@

Loading DCE template by SRC attribute

description="Should render Vulcan Salute 🖖" > +
+ + + + - + + + + + + +