Skip to content

Commit

Permalink
capricorn86#1176@patch: Implement custom element name validation.
Browse files Browse the repository at this point in the history
  • Loading branch information
mash-graz committed Dec 9, 2023
1 parent 806e960 commit fb72997
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
31 changes: 31 additions & 0 deletions packages/happy-dom/src/custom-element/CustomElementRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,37 @@ export default class CustomElementRegistry {
public _registry: { [k: string]: { elementClass: typeof HTMLElement; extends: string } } = {};
public _callbacks: { [k: string]: (() => void)[] } = {};

/**
* Validates the correctness of custom element tag names.
*
* @param tagName custom element tag name.
* @returns boolean True, if tag name is standard compliant.
*/
private isValidCustomElementName(tagName: string): boolean {
// Validation criteria based on:
// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
const PCENChar =
'[-_.]|[0-9]|[a-z]|\u{B7}|[\u{C0}-\u{D6}]|[\u{D8}-\u{F6}]' +
'|[\u{F8}-\u{37D}]|[\u{37F}-\u{1FFF}]' +
'|[\u{200C}-\u{200D}]|[\u{203F}-\u{2040}]|[\u{2070}-\u{218F}]' +
'|[\u{2C00}-\u{2FEF}]|[\u{3001}-\u{D7FF}]' +
'|[\u{F900}-\u{FDCF}]|[\u{FDF0}-\u{FFFD}]|[\u{10000}-\u{EFFFF}]';

const PCEN = new RegExp(`^[a-z](${PCENChar})*-(${PCENChar})*$`, 'u');

const forbiddenNames = [
'annotation-xml',
'color-profile',
'font-face',
'font-face-src',
'font-face-uri',
'font-face-format',
'font-face-name',
'missing-glyph'
];
return PCEN.test(tagName) && !forbiddenNames.includes(tagName);
}

/**
* Defines a custom element class.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ describe('CustomElementRegistry', () => {
CustomElement.observedAttributesCallCount = 0;
});

describe('isValidCustomElementName()', () => {
it('Validate custom elements tag name.', () => {
expect(customElements.isValidCustomElementName('a-b')).toBe(true);
expect(customElements.isValidCustomElementName('2a-b')).toBe(false);
expect(customElements.isValidCustomElementName('a2-b')).toBe(true);
expect(customElements.isValidCustomElementName('A-B')).toBe(false);
expect(customElements.isValidCustomElementName('aB-c')).toBe(false);
expect(customElements.isValidCustomElementName('ab')).toBe(false);
expect(customElements.isValidCustomElementName('a-\u00d9')).toBe(true);
expect(customElements.isValidCustomElementName('a_b.c-d')).toBe(true);
expect(customElements.isValidCustomElementName('font-face')).toBe(false);
});
});

describe('define()', () => {
it('Defines an HTML element and returns it with get().', () => {
customElements.define('custom-element', CustomElement);
Expand Down Expand Up @@ -43,7 +57,7 @@ describe('CustomElementRegistry', () => {
});

describe('get()', () => {
it('Returns element class if the tag name has been defined..', () => {
it('Returns element class if the tag name has been defined.', () => {
customElements.define('custom-element', CustomElement);
expect(customElements.get('custom-element')).toBe(CustomElement);
});
Expand Down

0 comments on commit fb72997

Please sign in to comment.