//! Computed-style lite: parse inline CSS declarations plus a small UA default //! sheet into the layout-relevant subset of [`crate::LayoutStyle`]. //! //! This is deliberately not a full CSS cascade. It handles the properties that //! influence phase-1 box layout (display, width/height, margin, padding, border //! width) from inline `style="..."` attributes, layered on a tiny built-in UA //! sheet. A real cascade with selector matching and `cssparser` can harden this //! later; for inline-style attributes a compact tokenizer is enough and keeps //! the crate dependency-light. use crate::{Display, Edges, LayoutStyle}; /// Compute the layout-relevant style for an element: UA defaults for its tag, /// overridden by its inline `style="..."` declarations. pub fn compute_style(tag: &str, inline_css: Option<&str>) -> LayoutStyle { let mut style = ua_style(tag); if let Some(css) = inline_css { apply_inline(&mut style, css); } style } /// Built-in UA defaults. Inline elements currently map to block layout; real /// inline/text layout arrives with the text/paint phase. pub fn ua_style(tag: &str) -> LayoutStyle { let mut style = LayoutStyle::default(); if tag == "b" || tag == "strong" { style.font_weight = Some("bold".into()); } style.display = match tag { // Phrasing / inline-level content defaults to inline so a paragraph // that mixes these with text stays one inline formatting context that // cosmic-text can shape and wrap as a whole, instead of each element // becoming its own block box (which forces the flex word-promotion // fallback and its fragile one-word-per-line wrapping). Author CSS // (e.g. `code{display:block}`) still overrides this in the cascade. "span" | "a" | "b" | "i" | "strong" | "em" | "font" | "code" | "small" | "sub" | "sup" | "mark" | "abbr" | "cite" | "var" | "dfn" | "kbd" | "samp" | "q" | "time" | "s" | "u" | "del" | "ins" | "tt" | "big" | "bdi" | "bdo" | "wbr" | "data" | "output" | "label" | "ruby" | "rt" | "rp" => Display::Inline, "tr" => Display::Flex, _ => Display::Block, }; if tag == "center" { style.display = Display::Flex; style.flex_direction = Some(taffy::FlexDirection::Column); style.align_items = Some(taffy::AlignItems::CENTER); } else if tag == "head" || tag == "script" || tag == "style" || tag == "title" || tag == "meta" || tag == "link" || tag == "noscript" || tag == "template" || tag == "desc" || tag == "metadata" || tag == "option" || tag == "optgroup" || tag == "source" || tag == "track" || tag == "param" || tag == "area" { // `noscript` content is only for scripting-disabled agents; with JS on // (as here) the parser keeps it as raw text and the browser hides it, // so a site's no-JS nav fallback must not paint as literal markup. // `template` content is inert and never rendered. svg `title`/`desc`/ // `metadata` are AX/tooltip metadata, never rendered in flow (an inline // we cannot rasterize would otherwise leak its `` text). // `option`/`optgroup` render only inside the native select popup, so a // closed