fix(scoped-elements): keep descriptive tag name when building

This commit is contained in:
Manuel Martin
2020-02-12 22:23:52 +01:00
committed by Thomas Allmer
parent 1dcbe3c359
commit 64b8a44d23
5 changed files with 47 additions and 68 deletions

View File

@@ -5,9 +5,9 @@ const tagsCache = new Map();
const registerElement = (klass, tag) => tagsCache.set(klass, tag);
const getRegisteredTag = klass => tagsCache.get(klass);
const defineElement = klass => {
const defineElement = (tagName, klass) => {
const registry = customElements;
const tag = createUniqueTag(registry, klass);
const tag = createUniqueTag(registry, tagName);
// we extend it just in case the class has been defined manually
registry.define(tag, class extends klass {});
@@ -17,9 +17,9 @@ const defineElement = klass => {
};
export const registerElements = elements =>
Object.keys(elements).reduce((acc, key) => {
const klass = elements[key];
acc[key] = getRegisteredTag(klass) || defineElement(klass);
Object.keys(elements).reduce((acc, tagName) => {
const klass = elements[tagName];
acc[tagName] = getRegisteredTag(klass) || defineElement(tagName, klass);
return acc;
}, {});

View File

@@ -1,51 +1,30 @@
let counter = 0;
const NAME_REGEX = /[^a-zA-Z0-9]/g;
const toDashCase = name => {
const dashCaseLetters = [];
const chars = `- | \\. | [0-9] | [a-z]`;
const tagRegExp = new RegExp(`[a-z](${chars})*-(${chars})*`);
for (let i = 0; i < name.length; i += 1) {
const letter = name[i];
const letterLowerCase = letter.toLowerCase();
if (letter !== letterLowerCase && i !== 0) {
dashCaseLetters.push('-');
}
dashCaseLetters.push(letterLowerCase);
}
return dashCaseLetters.join('');
};
const isValid = tag => tagRegExp.exec(tag) !== null;
const isTagRegistered = (registry, name) => !!registry.get(name);
const incrementTagName = (registry, tag) => {
const newName = `${tag}-${(counter += 1)}`;
const incrementTagName = (registry, tagName) => {
const newTagName = `${tagName}-${(counter += 1)}`;
if (isTagRegistered(registry, newName)) {
return incrementTagName(registry, tag);
if (isTagRegistered(registry, newTagName)) {
return incrementTagName(registry, tagName);
}
return newName;
return newTagName;
};
export const createUniqueTag = (registry, klass) => {
const name = klass && klass.name && klass.name.replace(NAME_REGEX, '');
if (name) {
let tag = toDashCase(name);
if (tag.indexOf('-') === -1) {
tag = `c-${tag}`;
}
if (isTagRegistered(registry, tag)) {
return incrementTagName(registry, tag);
}
return tag;
export const createUniqueTag = (registry, tagName) => {
if (!isValid(tagName)) {
throw new Error('tagName is invalid');
}
return incrementTagName(registry, 'c');
if (isTagRegistered(registry, tagName)) {
return incrementTagName(registry, tagName);
}
return tagName;
};

View File

@@ -15,9 +15,9 @@ describe('scoped-elements', () => {
});
expect(result).to.deep.equal({
'naboo-planet': 'c-naboo',
'alderaan-planet': 'c-alderaan',
'bespin-planet': 'c-bespin',
'naboo-planet': `naboo-planet`,
'alderaan-planet': `alderaan-planet`,
'bespin-planet': `bespin-planet`,
});
});
});

View File

@@ -21,8 +21,8 @@ describe('createScopedHtml', () => {
expect($div.innerHTML).to.be.equal(
'<!---->\n ' +
'<c-onderon><!---->text sample<!----></c-onderon>' +
'<c-ossus><!---->text sample<!----></c-ossus>' +
`<onderon-planet><!---->text sample<!----></onderon-planet>` +
`<ossus-planet><!---->text sample<!----></ossus-planet>` +
'\n <!---->',
);
});

View File

@@ -3,33 +3,33 @@ import { createUniqueTag } from '../src/tag.js';
describe('tags', () => {
describe('createUniqueTag', () => {
it('should create a valid tag name for an anonymous class', () => {
const tag = createUniqueTag(customElements, class extends HTMLElement {});
expect(tag).to.match(/[a-z][a-z0-9-\\._]*-[a-z0-9-\\._]*/);
it('should throw an error if tagName is invalid', () => {
expect(() => createUniqueTag(customElements)).to.throw(/tagName is invalid/);
expect(() => createUniqueTag(customElements, '')).to.throw(/tagName is invalid/);
expect(() => createUniqueTag(customElements, ' ')).to.throw(/tagName is invalid/);
expect(() => createUniqueTag(customElements, 'mustafar')).to.throw(/tagName is invalid/);
expect(() => createUniqueTag(customElements, 'NAL-HUTTA')).to.throw(/tagName is invalid/);
});
it('should add a prefix if name is no valid', () => {
expect(createUniqueTag(customElements, class Mustafar extends HTMLElement {})).to.be.equal(
'c-mustafar',
);
expect(createUniqueTag(customElements, class _Sample2 extends HTMLElement {})).to.be.equal(
'c-sample2',
);
it('should return a valid tag name', () => {
const tagName = 'nal-hutta';
const tag = createUniqueTag(customElements, `${tagName}`);
expect(tag).to.equal(`${tagName}`);
});
it('should return the name in dash case if is valid', () => {
expect(createUniqueTag(customElements, class MonCalamari extends HTMLElement {})).to.be.equal(
'mon-calamari',
);
});
it('should increment a counter if tag is already registered', () => {
const tagName = 'mon-calamari';
it('should return the name in dash case and a counter if is valid and is already registered', () => {
customElements.define('nal-hutta', class extends HTMLElement {});
customElements.define(`${tagName}`, class extends HTMLElement {});
// eslint-disable-next-line wc/no-invalid-element-name
customElements.define(`${tagName}-1`, class extends HTMLElement {});
// eslint-disable-next-line wc/no-invalid-element-name
customElements.define(`${tagName}-2`, class extends HTMLElement {});
expect(createUniqueTag(customElements, class NalHutta extends HTMLElement {})).to.match(
/nal-hutta-\d+/,
);
const tag = createUniqueTag(customElements, `${tagName}`);
expect(tag).to.equal(`${tagName}-3`);
});
});
});