Repository: typst/typst
File: crates/typst-html/src/css.rs (Rust)

Code before:

    /// Adds a new property to the list.
    pub fn push(&mut self, property: &str, value: impl Display) {
        if !self.0.is_empty() {
            self.0.push_str("; ");
        }
        write!(&mut self.0, "{property}: {value}").unwrap();
    }

    /// Adds a new property in builder-style.
    pub fn with(mut self, property: &str, value: impl Display) -> Self {
        self.push(property, value);
        self
    }

    /// Turns this into a string suitable for use as an inline `style`
    /// attribute.
    pub fn into_inline_styles(self) -> Option<EcoString> {
        (!self.0.is_empty()).then_some(self.0)
    }
}

pub fn rel(rel: Rel) -> impl Display {
    typst_utils::display(move |f| match (rel.abs.is_zero(), rel.rel.is_zero()) {
        (false, false) => {
            write!(f, "calc({}% + {})", rel.rel.get() * 100.0, length(rel.abs))
        }
        (true, false) => write!(f, "{}%", rel.rel.get() * 100.0),
        (_, true) => write!(f, "{}", length(rel.abs)),
    })
}

pub fn length(length: Length) -> impl Display {
    typst_utils::display(move |f| match (length.abs.is_zero(), length.em.is_zero()) {
        (false, false) => {
            write!(f, "calc({}pt + {}em)", length.abs.to_pt(), length.em.get())
        }
        (true, false) => write!(f, "{}em", length.em.get()),
        (_, true) => write!(f, "{}pt", length.abs.to_pt()),
    })
}

pub fn color(color: Color) -> impl Display {
    typst_utils::display(move |f| match color {
        Color::Rgb(_) | Color::Cmyk(_) | Color::Luma(_) => rgb(f, color.to_rgb()),
        Color::Oklab(v) => oklab(f, v),
        Color::Oklch(v) => oklch(f, v),
        Color::LinearRgb(v) => linear_rgb(f, v),
        Color::Hsl(_) | Color::Hsv(_) => hsl(f, color.to_hsl()),
    })
}

Review comment (suggestion):
this should use the existing `percent` function instead

Code after:

    /// Adds a new property to the list.
    pub fn push(&mut self, property: &str, value: impl Display) {
        if !self.0.is_empty() {
            self.0.push_str("; ");
        }
        write!(&mut self.0, "{property}: {value}").unwrap();
    }

    /// Adds a new property in builder-style.
    pub fn with(mut self, property: &str, value: impl Display) -> Self {
        self.push(property, value);
        self
    }

    /// Turns this into a string suitable for use as an inline `style`
    /// attribute.
    pub fn into_inline_styles(self) -> Option<EcoString> {
        (!self.0.is_empty()).then_some(self.0)
    }
}

pub fn rel(rel: Rel) -> impl Display {
    typst_utils::display(move |f| match (rel.abs.is_zero(), rel.rel.is_zero()) {
        (false, false) => {
            write!(f, "calc({} + {})", percent(rel.rel.get() as f32), length(rel.abs))
        }
        (true, false) => write!(f, "{}", percent(rel.rel.get() as f32)),
        (_, true) => write!(f, "{}", length(rel.abs)),
    })
}

pub fn length(length: Length) -> impl Display {
    typst_utils::display(move |f| match (length.abs.is_zero(), length.em.is_zero()) {
        (false, false) => {
            write!(f, "calc({}pt + {}em)", length.abs.to_pt(), length.em.get())
        }
        (true, false) => write!(f, "{}em", length.em.get()),
        (_, true) => write!(f, "{}pt", length.abs.to_pt()),
    })
}

pub fn color(color: Color) -> impl Display {
    typst_utils::display(move |f| match color {
        Color::Rgb(_) | Color::Cmyk(_) | Color::Luma(_) => rgb(f, color.to_rgb()),
        Color::Oklab(v) => oklab(f, v),
        Color::Oklch(v) => oklch(f, v),
        Color::LinearRgb(v) => linear_rgb(f, v),
        Color::Hsl(_) | Color::Hsv(_) => hsl(f, color.to_hsl()),
    })
}