UNPKG

zeplin-extension-style-kit

Version:

Models and utilities to generate CSS-like style code in Zeplin extensions.

111 lines (90 loc) 4.13 kB
import { Length } from "../values/length.js"; import { Color } from "../values/color.js"; import { FontFamily } from "../declarations/fontFamily.js"; import { FontSize } from "../declarations/fontSize.js"; import { FontStyle, FontStyleValue } from "../declarations/fontStyle.js"; import { FontStretch, StretchKeyword } from "../declarations/fontStretch.js"; import { FontWeight } from "../declarations/fontWeight.js"; import { FontVariationSettings } from "../declarations/fontVariationSettings.js"; import { FontColor } from "../declarations/fontColor.js"; import { TextAlign } from "../declarations/textAlign.js"; import { LineHeight } from "../declarations/lineHeight.js"; import { LetterSpacing } from "../declarations/letterSpacing.js"; import { RuleSet } from "../ruleSet.js"; import { selectorize } from "../utils.js"; import { StyleDeclaration } from "../common.js"; import { TextStyle as ExtensionTextStyle } from "@zeplin/extension-model"; // Reference: https://drafts.csswg.org/css-fonts-4/#valdef-font-style-oblique-angle const DEFAULT_OBLIQUE_ANGLE = 14; const useRemUnitForFont = ({ useForFontSizes }: { useForFontSizes: boolean }): boolean => useForFontSizes; export class TextStyle { textStyle: ExtensionTextStyle; declarations: StyleDeclaration[]; constructor(textStyle: ExtensionTextStyle) { this.textStyle = textStyle; this.declarations = this.collectDeclarations(); } private collectDeclarations(): StyleDeclaration[] { const fontVariationSettings = this.getFontVariationSettings(); const fontColor = this.getFontColor(); const textAlign = this.getTextAlign(); const declarations: StyleDeclaration[] = [ this.getFontFamily(), this.getFontSize(), this.getFontWeight(), this.getFontStretch(), this.getFontStyle(), ...(fontVariationSettings ? [fontVariationSettings] : []), this.getLineHeight(), this.getLetterSpacing(), ...(textAlign ? [textAlign] : []), ...(fontColor ? [fontColor] : []) ]; return declarations; } private getFontFamily(): FontFamily { return new FontFamily(this.textStyle.fontFamily); } private getFontSize(): FontSize { return new FontSize(new Length(this.textStyle.fontSize, { useRemUnit: useRemUnitForFont })); } private getFontStyle(): FontStyle { let style = this.textStyle.fontStyle; let angle: number | undefined; // Handle oblique with angle (e.g., "oblique 10deg") if (style.startsWith("oblique")) { const match = style.match(/(-?\d+)deg/); if (match) { angle = parseInt(match[1], 10); if (angle !== DEFAULT_OBLIQUE_ANGLE) { style = `oblique ${angle}deg`; } } } return new FontStyle(style as FontStyleValue); } private getFontWeight(): FontWeight { return new FontWeight(this.textStyle.fontWeight); } private getFontStretch(): FontStretch { return new FontStretch(this.textStyle.fontStretch as StretchKeyword); } private getFontVariationSettings(): FontVariationSettings | null { return this.textStyle.fontVariationSettings ? new FontVariationSettings(this.textStyle.fontVariationSettings) : null; } private getFontColor(): FontColor | null { return this.textStyle.color ? new FontColor(new Color(this.textStyle.color)) : null; } private getTextAlign(): TextAlign | null { return this.textStyle.textAlign ? new TextAlign(this.textStyle.textAlign) : null; } private getLineHeight(): LineHeight { return new LineHeight(this.textStyle.lineHeight || LineHeight.DEFAULT_VALUE, this.textStyle.fontSize); } private getLetterSpacing(): LetterSpacing { return new LetterSpacing(this.textStyle.letterSpacing || LetterSpacing.DEFAULT_VALUE); } get style(): RuleSet { return new RuleSet(selectorize(this.textStyle.name), this.declarations); } }