mirror of
https://github.com/jlengrand/open-wc.git
synced 2026-03-10 08:31:19 +00:00
fix(scoped-elements): support extending elements (#1272)
This commit defers the definition of web components until they are used, so it allows to extend parent components without define unused inherited web components.
This commit is contained in:
committed by
Thomas Allmer
parent
8855c88164
commit
9868bc7a1b
@@ -2,8 +2,8 @@
|
||||
import { createUniqueTag } from './tag.js';
|
||||
|
||||
const tagsCache = new Map();
|
||||
const registerElement = (klass, tag) => tagsCache.set(klass, tag);
|
||||
const getRegisteredTag = klass => tagsCache.get(klass);
|
||||
const addToTagsCache = (klass, tag) => tagsCache.set(klass, tag);
|
||||
const getFromTagsCache = klass => tagsCache.get(klass);
|
||||
|
||||
const defineElement = (tagName, klass) => {
|
||||
const registry = customElements;
|
||||
@@ -11,15 +11,10 @@ const defineElement = (tagName, klass) => {
|
||||
|
||||
// we extend it just in case the class has been defined manually
|
||||
registry.define(tag, class extends klass {});
|
||||
registerElement(klass, tag);
|
||||
addToTagsCache(klass, tag);
|
||||
|
||||
return tag;
|
||||
};
|
||||
|
||||
export const registerElements = elements =>
|
||||
Object.keys(elements).reduce((acc, tagName) => {
|
||||
const klass = elements[tagName];
|
||||
acc[tagName] = getRegisteredTag(klass) || defineElement(tagName, klass);
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
export const registerElement = (tagName, klass) =>
|
||||
getFromTagsCache(klass) || defineElement(tagName, klass);
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
/* eslint-disable prefer-spread */
|
||||
import { html } from 'lit-html';
|
||||
import { transform } from './transform.js';
|
||||
import { registerElements } from './scoped-elements.js';
|
||||
|
||||
export const createScopedHtml = tags => {
|
||||
const definedTags = registerElements(tags);
|
||||
|
||||
export const createScopedHtml = tags =>
|
||||
// eslint-disable-next-line func-names
|
||||
return function() {
|
||||
function() {
|
||||
// eslint-disable-next-line prefer-rest-params
|
||||
const args = Array.apply(null, arguments);
|
||||
const strings = args[0];
|
||||
const values = args.slice(1);
|
||||
|
||||
return html.apply(null, [].concat([transform(strings, definedTags)], values));
|
||||
return html.apply(null, [].concat([transform(strings, tags)], values));
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { fromCache, toCache } from './cache.js';
|
||||
import { registerElement } from './scoped-elements.js';
|
||||
|
||||
const re = /<\/?([a-zA-Z0-9-]+)/g;
|
||||
|
||||
@@ -22,13 +23,14 @@ const transformTemplate = (strings, tags) =>
|
||||
|
||||
for (let i = matches.length - 1; i >= 0; i -= 1) {
|
||||
const item = matches[i];
|
||||
const replacement = tags[item[1]];
|
||||
const klass = tags[item[1]];
|
||||
|
||||
if (replacement) {
|
||||
if (klass) {
|
||||
const tag = registerElement(item[1], klass);
|
||||
const start = item.index + item[0].length - item[1].length;
|
||||
const end = start + item[1].length;
|
||||
|
||||
acc = acc.slice(0, start) + replacement + acc.slice(end);
|
||||
acc = acc.slice(0, start) + tag + acc.slice(end);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect } from '@open-wc/testing';
|
||||
import { registerElements } from '../src/scoped-elements.js';
|
||||
import { registerElement } from '../src/scoped-elements.js';
|
||||
import { SUFFIX } from '../src/tag.js';
|
||||
|
||||
describe('scoped-elements', () => {
|
||||
@@ -9,17 +9,13 @@ describe('scoped-elements', () => {
|
||||
class Alderaan extends HTMLElement {}
|
||||
class Bespin extends HTMLElement {}
|
||||
|
||||
const result = registerElements({
|
||||
'naboo-planet': Naboo,
|
||||
'alderaan-planet': Alderaan,
|
||||
'bespin-planet': Bespin,
|
||||
});
|
||||
const nabooTag = registerElement('naboo-planet', Naboo);
|
||||
const alderaanTag = registerElement('alderaan-planet', Alderaan);
|
||||
const bespinTag = registerElement('bespin-planet', Bespin);
|
||||
|
||||
expect(result).to.deep.equal({
|
||||
'naboo-planet': `naboo-planet-${SUFFIX}`,
|
||||
'alderaan-planet': `alderaan-planet-${SUFFIX}`,
|
||||
'bespin-planet': `bespin-planet-${SUFFIX}`,
|
||||
});
|
||||
expect(nabooTag).to.equal(`naboo-planet-${SUFFIX}`);
|
||||
expect(alderaanTag).to.equal(`alderaan-planet-${SUFFIX}`);
|
||||
expect(bespinTag).to.equal(`bespin-planet-${SUFFIX}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -27,4 +27,21 @@ describe('createScopedHtml', () => {
|
||||
'\n <!---->',
|
||||
);
|
||||
});
|
||||
|
||||
it('defers the definition of components until they are used', () => {
|
||||
class Ithor extends HTMLElement {}
|
||||
class Taris extends HTMLElement {}
|
||||
|
||||
const html = createScopedHtml({
|
||||
'ithor-planet': Ithor,
|
||||
'taris-planet': Taris,
|
||||
});
|
||||
|
||||
html`
|
||||
<taris-planet></taris-planet>
|
||||
`;
|
||||
|
||||
expect(customElements.get(`ithor-planet-${SUFFIX}`)).to.be.undefined;
|
||||
expect(customElements.get(`taris-planet-${SUFFIX}`)).to.not.be.undefined;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,46 +1,33 @@
|
||||
import { expect } from '@open-wc/testing';
|
||||
import { transform } from '../src/transform.js';
|
||||
|
||||
const tags = {
|
||||
'mandalore-planet': class extends HTMLElement {},
|
||||
};
|
||||
|
||||
describe('html', () => {
|
||||
[
|
||||
{
|
||||
input: ['<naboo-planet>', '</naboo-planet>'],
|
||||
tags: { 'naboo-planet': 'c-naboo' },
|
||||
output: ['<c-naboo>', '</c-naboo>'],
|
||||
input: ['<mandalore-planet>', '</mandalore-planet>'],
|
||||
output: ['<mandalore-planet-se>', '</mandalore-planet-se>'],
|
||||
},
|
||||
{
|
||||
input: ['<naboo-planet class="sample">', '</naboo-planet>'],
|
||||
tags: { 'naboo-planet': 'c-naboo' },
|
||||
output: ['<c-naboo class="sample">', '</c-naboo>'],
|
||||
input: ['<mandalore-planet class="sample">', '</mandalore-planet>'],
|
||||
output: ['<mandalore-planet-se class="sample">', '</mandalore-planet-se>'],
|
||||
},
|
||||
{
|
||||
input: ['<naboo-planet\tclass="sample">', '</naboo-planet>'],
|
||||
tags: { 'naboo-planet': 'c-naboo' },
|
||||
output: ['<c-naboo\tclass="sample">', '</c-naboo>'],
|
||||
input: ['<mandalore-planet\tclass="sample">', '</mandalore-planet>'],
|
||||
output: ['<mandalore-planet-se\tclass="sample">', '</mandalore-planet-se>'],
|
||||
},
|
||||
{
|
||||
input: ['<naboo-planet\rclass="sample">', '</naboo-planet>'],
|
||||
tags: { 'naboo-planet': 'c-naboo' },
|
||||
output: ['<c-naboo\rclass="sample">', '</c-naboo>'],
|
||||
input: ['<mandalore-planet\rclass="sample">', '</mandalore-planet>'],
|
||||
output: ['<mandalore-planet-se\rclass="sample">', '</mandalore-planet-se>'],
|
||||
},
|
||||
{
|
||||
input: ['<naboo-planet class="sample"></naboo-planet>'],
|
||||
tags: { 'naboo-planet': 'c-naboo' },
|
||||
output: ['<c-naboo class="sample"></c-naboo>'],
|
||||
input: ['<mandalore-planet class="sample"></mandalore-planet>'],
|
||||
output: ['<mandalore-planet-se class="sample"></mandalore-planet-se>'],
|
||||
},
|
||||
{
|
||||
input: [
|
||||
'<naboo-planet class="sample">',
|
||||
'</naboo-planet><bespin-planet>',
|
||||
'</bespin-planet>',
|
||||
],
|
||||
tags: {
|
||||
'naboo-planet': 'c-naboo',
|
||||
'bespin-planet': 'c-bespin',
|
||||
},
|
||||
output: ['<c-naboo class="sample">', '</c-naboo><c-bespin>', '</c-bespin>'],
|
||||
},
|
||||
].forEach(({ input, tags, output }, index) => {
|
||||
].forEach(({ input, output }, index) => {
|
||||
it(`should transform strings tags into the actual registered tags - ${index}`, () => {
|
||||
expect(transform(input, tags)).to.be.deep.equal(output);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user