Based on the examples at WICG/webcomponents#645
<!-- components.html -->
<define name="x-image" export>
<img src="images/${this.dataset.src}">
</define>
<!-- implementation.html -->
<link rel="html" href="components.html" as="x-image" />
<x-image data-src="image.webp" />
<!-- becomes: -->
<img src="images/image.webp" />
<!-- components.html -->
<define name="x-image" export>
<img class="fallback" ${this.attrs.asAttrs()} src="images/${this.attrs.src}" />
</define>
<!-- implementation.html -->
<link rel="html" href="components.html" as="x-image" />
<x-image class="some-class" src="image.webp" />
<!-- becomes: -->
<img class="some-class" src="images/image.webp" />
<!-- components.html -->
<define name="x-image" export>
<img class="fallback" ${this.attrs.asAttrs()} src="images/${Object(this.query(':scope > x-src')).textContent}" />
</define>
<!-- implementation.html -->
<link rel="html" href="components.html" as="x-image" />
<x-image class="some-class">
<x-src>image.webp</x-src>
</x-image>
<!-- becomes: -->
<img class="some-class" src="images/image.webp" />
<!-- components.html -->
<define name="x-section" export>
<section ${this.attrs.asAttrs({ exclude: 'heading' })}>
<h3>${this.attrs.heading}</h3>
${this.innerHTML}
</section>
</define>
<!-- implementation.html -->
<link rel="html" href="components.html" as="x-section" />
<x-section class="some-class" heading="Example Heading">
<p>Lorem ipsum dolor sit amet.</p>
</x-section>
<!-- becomes: -->
<section class="some-class">
<h3>Example Heading</h3>
<p>Lorem ipsum dolor sit amet.</p>
</section>
This is beside the point — just stuff that could fully realize the above examples right now this very moment.
DOMStringMap.prototype.asDataAttrs = function asDataAttrs(opts) {
return (
Object(opts).include ? Array.from(Object(opts).include) : Object.keys(this)
)[Object(opts).exclude ? 'filter' : 'slice'](
Object(opts).exclude ? key => !Array.from(Object(opts).exclude).includes(key) : 0
).map(key => `data-${key.replace(/[A-Z]/g, '-$&').toLowerCase()}="${this[key]}"`).join(' ');
};
DOMStringMap.prototype.asAttrs = function asAttrs(opts) {
return (
Object(opts).include ? Array.from(Object(opts).include) : Object.keys(this)
)[Object(opts).exclude ? 'filter' : 'slice'](
Object(opts).exclude ? key => !Array.from(Object(opts).exclude).includes(key) : 0
).map(key => `${key.replace(/[A-Z]/g, '-$&').toLowerCase()}="${this[key]}"`).join(' ');
};
Object.defineProperty(Element.prototype, 'attrs', {
get() {
return Array.prototype.reduce.call(
this.attributes,
(object, attr) => Object.assign(domStringMap, {
[attr.name.replace(/-\w/g, $0 => $0.slice(1).toUpperCase())]: attr.value
}),
Object.create(DOMStringMap.prototype)
);
}
});