///|
pub enum TokenKind {
Color
Number
Text
Boolean
} derive(Debug, Eq)
///|
pub enum ThemeValue {
ColorValue(String)
NumberValue(Int)
TextValue(String)
BooleanValue(Bool)
} derive(Debug, Eq)
///|
pub struct ThemeToken {
path : TokenPath
kind : TokenKind
value : ThemeValue
description : String
} derive(Debug, Eq)
///|
pub struct ThemeAlias {
name : TokenPath
target : TokenPath
} derive(Debug, Eq)
///|
pub struct ThemeDocument {
tokens : Array[ThemeToken]
aliases : Array[ThemeAlias]
provenance : Array[ThemeProvenance]
} derive(Debug, Eq)
///|
pub fn ThemeToken::color(
path : String,
value : String,
description : String,
) -> ThemeToken {
{
path: TokenPath::from_string(path),
kind: Color,
value: ColorValue(value),
description,
}
}
///|
pub fn ThemeToken::number(
path : String,
value : Int,
description : String,
) -> ThemeToken {
{
path: TokenPath::from_string(path),
kind: Number,
value: NumberValue(value),
description,
}
}
///|
pub fn ThemeToken::text(
path : String,
value : String,
description : String,
) -> ThemeToken {
{
path: TokenPath::from_string(path),
kind: Text,
value: TextValue(value),
description,
}
}
///|
pub fn ThemeToken::boolean(
path : String,
value : Bool,
description : String,
) -> ThemeToken {
{
path: TokenPath::from_string(path),
kind: Boolean,
value: BooleanValue(value),
description,
}
}
///|
pub fn ThemeDocument::empty() -> ThemeDocument {
{ tokens: [], aliases: [], provenance: [] }
}
///|
pub fn ThemeDocument::add(
self : ThemeDocument,
token : ThemeToken,
) -> ThemeDocument {
let tokens : Array[ThemeToken] = []
for item in self.tokens {
tokens.push(item)
}
tokens.push(token)
{ tokens, aliases: self.aliases, provenance: self.provenance }
}
///|
pub fn ThemeDocument::with_alias(
self : ThemeDocument,
name : String,
target : String,
) -> ThemeDocument {
let aliases : Array[ThemeAlias] = []
for item in self.aliases {
aliases.push(item)
}
aliases.push({
name: TokenPath::from_string(name),
target: TokenPath::from_string(target),
})
{ tokens: self.tokens, aliases, provenance: self.provenance }
}
///|
pub fn ThemeDocument::find(self : ThemeDocument, path : String) -> ThemeToken? {
let wanted = TokenPath::from_string(path).canonical()
for token in self.tokens {
if token.path.canonical() == wanted {
return Some(token)
}
}
None
}
///|
pub fn ThemeDocument::sorted(self : ThemeDocument) -> ThemeDocument {
let sorted : Array[ThemeToken] = []
for token in self.tokens {
let mut position = sorted.length()
for i, existing in sorted {
if compare_stable_names(token.path.canonical(), existing.path.canonical()) <
0 {
position = i
break
}
}
sorted.push(token)
let last = sorted.length() - 1
let mut i = last
while i > position {
sorted[i] = sorted[i - 1]
i -= 1
}
sorted[position] = token
}
{ tokens: sorted, aliases: self.aliases, provenance: self.provenance }
}
///|
pub fn ThemeDocument::token_count(self : ThemeDocument) -> Int {
self.tokens.length()
}
///|
pub fn BrandBook::theme_document(self : BrandBook) -> ThemeDocument {
let document = ThemeDocument::empty()
let mut current = document
for color in self.palette.colors {
current = current.add(
ThemeToken::color("colors." + color.name, color.value, color.role),
)
}
for family in self.typography.families {
current = current.add(
ThemeToken::text(
"typography.font." + family.name,
family.name,
family.usage,
),
)
}
for step in self.typography.scale {
current = current.add(
ThemeToken::number(
"typography." + step.name + ".size",
step.size_px,
"font size in pixels",
),
)
current = current.add(
ThemeToken::number(
"typography." + step.name + ".line-height",
step.line_height_px,
"line height in pixels",
),
)
}
current
}