Skip to content

Commit

Permalink
feat: [#1441] Adds support for the CSS font-face rule (#1474)
Browse files Browse the repository at this point in the history
* feat: [#1441] Support font-face

* chore: [#1441] Adds unit test and support for CSSFontFaceRule.cssText

* chore: [#1441] Linting

---------

Co-authored-by: David Ortner <[email protected]>
  • Loading branch information
m-shaka and capricorn86 authored Aug 29, 2024
1 parent 343dfd2 commit 99639e5
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3170,6 +3170,8 @@ export default class CSSStyleDeclarationPropertySetParser {
} else if (trimmedPart[0] !== '"' && trimmedPart[trimmedPart.length - 1] !== '"') {
trimmedPart = `"${trimmedPart}"`;
}
} else {
trimmedPart = trimmedPart.replace(/"/g, '');
}

if (i > 0) {
Expand Down
11 changes: 10 additions & 1 deletion packages/happy-dom/src/css/rules/CSSFontFaceRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import CSSStyleDeclaration from '../declaration/CSSStyleDeclaration.js';
export default class CSSFontFaceRule extends CSSRule {
public readonly type = CSSRule.FONT_FACE_RULE;
public [PropertySymbol.cssText] = '';
#style: CSSStyleDeclaration = null;
#style: CSSStyleDeclaration | null = null;

/**
* Returns style.
Expand All @@ -23,4 +23,13 @@ export default class CSSFontFaceRule extends CSSRule {
}
return this.#style;
}

/**
* Returns css text.
*
* @returns CSS text.
*/
public get cssText(): string {
return `@font-face { ${this.style.cssText} }`;
}
}
2 changes: 1 addition & 1 deletion packages/happy-dom/src/css/rules/CSSKeyframeRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default class CSSKeyframeRule extends CSSRule {
public readonly type = CSSRule.KEYFRAME_RULE;
public readonly keyText: string;
public [PropertySymbol.cssText] = '';
#style: CSSStyleDeclaration = null;
#style: CSSStyleDeclaration | null = null;

/**
* Returns style.
Expand Down
2 changes: 1 addition & 1 deletion packages/happy-dom/src/css/rules/CSSStyleRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default class CSSStyleRule extends CSSRule {
public readonly selectorText = '';
public readonly styleMap = new Map();
public [PropertySymbol.cssText] = '';
#style: CSSStyleDeclaration = null;
#style: CSSStyleDeclaration | null = null;

/**
* Returns style.
Expand Down
9 changes: 9 additions & 0 deletions packages/happy-dom/src/css/utilities/CSSParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import CSSKeyframesRule from '../rules/CSSKeyframesRule.js';
import CSSMediaRule from '../rules/CSSMediaRule.js';
import CSSContainerRule from '../rules/CSSContainerRule.js';
import CSSSupportsRule from '../rules/CSSSupportsRule.js';
import CSSFontFaceRule from '../rules/CSSFontFaceRule.js';
import SelectorParser from '../../query-selector/SelectorParser.js';

const COMMENT_REGEXP = /\/\*[\s\S]*?\*\//gm;
Expand Down Expand Up @@ -78,6 +79,14 @@ export default class CSSParser {
newRule.parentStyleSheet = parentStyleSheet;
cssRules.push(newRule);
parentRule = newRule;
} else if (selectorText.startsWith('@font-face')) {
const conditionText = selectorText.replace('@font-face', '');
const newRule = new CSSFontFaceRule();

newRule[PropertySymbol.cssText] = conditionText;
newRule.parentStyleSheet = parentStyleSheet;
cssRules.push(newRule);
parentRule = newRule;
} else if (selectorText.startsWith('@')) {
// Unknown rule.
// We will create a new rule to let it grab its content, but we will not add it to the cssRules array.
Expand Down
20 changes: 20 additions & 0 deletions packages/happy-dom/test/css/CSSParser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,5 +219,25 @@ describe('CSSParser', () => {
expect((<CSSStyleRule>cssRules[10]).style.length).toBe(1);
expect((<CSSStyleRule>cssRules[10]).style.cssText).toBe('color: pink;');
});

it('Supports @font-face.', () => {
const css = `
@font-face {
font-family: "Ionicons";
src: url("~react-native-vector-icons/Fonts/Ionicons.ttf");
}
`;
const cssStyleSheet = new CSSStyleSheet();
const cssRules = CSSParser.parseFromString(cssStyleSheet, css);

expect(cssRules.length).toBe(1);
expect((<CSSStyleRule>cssRules[0]).cssText).toBe(
'@font-face { font-family: Ionicons; src: url("~react-native-vector-icons/Fonts/Ionicons.ttf"); }'
);
expect((<CSSStyleRule>cssRules[0]).style.fontFamily).toBe('Ionicons');
expect((<CSSStyleRule>cssRules[0]).style.src).toBe(
'url("~react-native-vector-icons/Fonts/Ionicons.ttf")'
);
});
});
});

0 comments on commit 99639e5

Please sign in to comment.