Skip to content

Commit

Permalink
feat(typography.monospace): Update monospace properties
Browse files Browse the repository at this point in the history
For #16
  • Loading branch information
gadenbuie committed Sep 10, 2024
1 parent 7c24436 commit 18950e9
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 19 deletions.
102 changes: 84 additions & 18 deletions pkg-py/src/brand_yaml/typography.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,57 +195,94 @@ class BrandNamedColor(RootModel):
root: str


class BrandTypographyOptionsBase(BrandBase):
class BrandTypographyOptionsColor(BaseModel):
model_config = ConfigDict(populate_by_name=True)

weight: BrandTypographyFontWeightSimpleType | None = None
color: BrandNamedColor | None = None
background_color: BrandNamedColor | None = Field(
None, alias="background-color"
)


class BrandTypographyOptionsWeight(BaseModel):
weight: BrandTypographyFontWeightSimpleType | None = None

@field_validator("weight", mode="before")
@classmethod
def validate_weight(cls, value: int | str):
return validate_font_weight(value)


class BrandTypographyOptionsGenericText(BaseModel):
model_config = ConfigDict(populate_by_name=True)

class BrandTypographyOptionsGenericText(BrandTypographyOptionsWeight):
family: str | None = None
line_height: float | None = Field(None, alias="line-height")
style: SingleOrList[BrandTypographyFontStyleType] | None = None


class BrandTypographyOptions(
BrandTypographyOptionsBase,
class BrandTypographyOptionsSize(BaseModel):
size: str | None = None


class BrandTypographyOptionsBlockText(BaseModel):
line_height: float | None = Field(None, alias="line-height")


class BrandTypographyBase(
BrandBase,
BrandTypographyOptionsGenericText,
BrandTypographyOptionsBlockText,
BrandTypographyOptionsColor,
):
model_config = ConfigDict(extra="forbid")

size: str | None = None

class BrandTypographyHeadings(
BrandBase,
BrandTypographyOptionsGenericText,
BrandTypographyOptionsBlockText,
BrandTypographyOptionsColor,
):
model_config = ConfigDict(extra="forbid")


class BrandTypographyOptionsNoSize(
BrandTypographyOptionsBase,
class BrandTypographyMonospace(
BrandBase,
BrandTypographyOptionsGenericText,
BrandTypographyOptionsSize,
):
model_config = ConfigDict(extra="forbid")


class BrandTypographyEmphasis(BrandTypographyOptionsBase):
class BrandTypographyMonospaceInline(
BrandBase,
BrandTypographyOptionsGenericText,
BrandTypographyOptionsSize,
BrandTypographyOptionsColor,
):
model_config = ConfigDict(extra="forbid")


class BrandTypographyLink(BrandTypographyOptionsBase):
class BrandTypographyMonospaceBlock(
BrandBase,
BrandTypographyOptionsGenericText,
BrandTypographyOptionsSize,
BrandTypographyOptionsBlockText,
BrandTypographyOptionsColor,
):
model_config = ConfigDict(extra="forbid")


class BrandTypographyLink(
BrandBase,
BrandTypographyOptionsWeight,
BrandTypographyOptionsColor,
):
model_config = ConfigDict(extra="forbid")

decoration: str | None = None


class BrandTypography(BrandBase):
model_config = ConfigDict(extra="forbid")
model_config = ConfigDict(extra="forbid", populate_by_name=True)

fonts: list[
Annotated[
Expand All @@ -256,13 +293,42 @@ class BrandTypography(BrandBase):
Discriminator(brand_typography_font_discriminator),
]
] = Field(default_factory=list)
base: BrandTypographyOptions | None = None
headings: BrandTypographyOptionsNoSize | None = None
monospace: BrandTypographyOptions | None = None
emphasis: BrandTypographyEmphasis | None = None
base: BrandTypographyBase | None = None
headings: BrandTypographyHeadings | None = None
monospace: BrandTypographyMonospace | None = None
monospace_inline: BrandTypographyMonospaceInline | None = Field(
None, alias="monospace-inline"
)
monospace_block: BrandTypographyMonospaceBlock | None = Field(
None, alias="monospace-block"
)
link: BrandTypographyLink | None = None

def __repr_args__(self):
fields = [f for f in self.model_fields.keys()]
values = [getattr(self, f) for f in fields]
return ((f, v) for f, v in zip(fields, values) if v is not None)

@model_validator(mode="after")
def forward_monospace_values(self):
"""
Forward values from `monospace` to inline and block variants.
`monospace-inline` and `monospace-block` both inherit `family`, `style`,
`weight` and `size` from `monospace`.
"""

def use_fallback(obj: BaseModel | None, parent: BaseModel | None):
if parent is None or obj is None:
return

for field in ("family", "style", "weight", "size"):
fallback = getattr(parent, field)
if fallback is None:
continue
if getattr(obj, field) is None:
setattr(obj, field, fallback)

use_fallback(self.monospace_inline, self.monospace)
use_fallback(self.monospace_block, self.monospace)
return self
26 changes: 25 additions & 1 deletion pkg-py/tests/test_typography.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import pytest

from brand_yaml.typography import BrandTypographyFontFile
from brand_yaml.typography import BrandTypography, BrandTypographyFontFile


@pytest.mark.parametrize(
Expand Down Expand Up @@ -71,3 +71,27 @@ def test_brand_typography_font_file_weight():
).weight
== "normal"
)


def test_brand_typography_monospace():
bt = BrandTypography.model_validate(
{
"monospace": {"family": "Fira Code", "size": "1.2rem"},
"monospace-inline": {"size": "0.9rem"},
"monospace-block": {
"family": "Menlo",
},
}
)

assert bt.monospace is not None
assert bt.monospace.family == "Fira Code"
assert bt.monospace.size == "1.2rem"

assert bt.monospace_inline is not None
assert bt.monospace_inline.family == "Fira Code" # inherits family
assert bt.monospace_inline.size == "0.9rem" # overrides size

assert bt.monospace_block is not None
assert bt.monospace_block.family == "Menlo" # overrides family
assert bt.monospace_block.size == "1.2rem" # inherits size

0 comments on commit 18950e9

Please sign in to comment.