use crate::config::ThemeConfig;
pub fn build_css(theme: &ThemeConfig) -> String {
fn compile_scss() -> (
&'static str,
std::collections::HashMap<&'static str, &'static str>,
) {
tairitsu_macros::scss! {
file: "styles/layout.scss",
no_hash
}
}
let core = compile_scss().0;
let components = hikari_component_css();
let overrides = theme_overrides(theme);
format!("{HIKARI_VARS}\n{core}\n{components}\n{overrides}")
}
fn hikari_component_css() -> String {
use hikari_components::styled::StyleRegistry;
use hikari_components::StyledComponent as _;
let mut registry = StyleRegistry::default();
registry.register_available();
hikari_components::basic::link::LinkComponent::register(&mut registry);
hikari_components::production::code_highlight::CodeHighlightComponent::register(&mut registry);
let all = registry.get_all();
let mut names: Vec<&'static str> = all.keys().copied().collect();
names.sort_unstable();
let css = names.iter().map(|n| all[n]).collect::<Vec<_>>().join("\n");
let mut bridge = String::new();
let mut rest = css.as_str();
while let Some(pos) = rest.find(".hk-code-highlight") {
let sel_start = rest[..pos].rfind('}').map(|x| x + 1).unwrap_or(0);
if let Some(brace) = rest[sel_start..].find('{') {
let brace_abs = sel_start + brace;
if let Some(close) = rest[brace_abs..].find('}') {
let close_abs = brace_abs + close;
let sel = &rest[sel_start..brace_abs];
let body = &rest[brace_abs..=close_abs];
let aliased = sel.replace(".hk-code-highlight", ".hi-code-highlight");
bridge.push_str(&format!("{aliased}{body}\n"));
rest = &rest[close_abs..];
continue;
}
}
break;
}
format!("{css}\n/* lagrange: hi-code-highlight aliases for hikari hk- classes */\n{bridge}")
}
const HIKARI_VARS: &str = r#":root {
--hi-radius-sm: 4px; --hi-radius-md: 8px; --hi-radius-lg: 12px; --hi-radius-full: 9999px;
--hi-blur-sm: 8px; --hi-blur-md: 16px;
--hi-ease-out-expo: cubic-bezier(.16, 1, .3, 1);
--hi-shadow-panel: 0 2px 12px rgba(0, 0, 0, .06);
--hi-shadow-elevated: 0 4px 20px rgba(0, 0, 0, .08);
--hi-shadow-focus: 0 0 0 3px rgba(58, 110, 165, .12);
--hi-z-modal: 1000; --hi-z-toast: 9999; --hi-z-tooltip: 10000;
--hi-scroll-size: 8px; --hi-scroll-thumb: 4px;
/* hikari component color tokens, mapped onto lagrange's palette so hi-*
markup (code blocks, alerts, tags, ...) renders on-palette even though
hikari-theme's own stylesheet is not shipped. The component CSS also
carries fallbacks, but they are light-scheme only. */
--hi-color-primary: var(--accent);
--hi-color-primary-glow: color-mix(in srgb, var(--accent) 35%, transparent);
--hi-color-bg-container: var(--code-bg);
--hi-color-bg-elevated: var(--bg-subtle);
--hi-color-border: var(--border);
--hi-color-text-primary: var(--fg);
--hi-color-text-secondary: var(--fg-sec);
--hi-color-text-tertiary: var(--fg-sec);
--hi-color-info: var(--accent);
--hi-color-success: #3fb950;
--hi-color-warning: #d29922;
--hi-color-danger: #f85149;
}
.hi-glass { background: var(--bg-subtle); backdrop-filter: blur(16px); }
.hi-glass-panel { background: var(--bg-subtle); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--hi-shadow-panel); }
.hi-scroll-container { overflow: auto; scrollbar-width: none; }
"#;
fn theme_overrides(theme: &ThemeConfig) -> String {
let mut s = String::new();
if let Some(v) = &theme.accent {
s.push_str(&format!(":root{{--accent:{v}}}\n"));
}
if let Some(v) = &theme.bg {
s.push_str(&format!(":root{{--bg:{v}}}\n"));
}
if let Some(v) = &theme.bg_subtle {
s.push_str(&format!(":root{{--bg-subtle:{v}}}\n"));
}
if let Some(v) = &theme.fg {
s.push_str(&format!(":root{{--fg:{v}}}\n"));
}
if let Some(v) = &theme.fg_sec {
s.push_str(&format!(":root{{--fg-sec:{v}}}\n"));
}
if let Some(v) = &theme.code_bg {
s.push_str(&format!(":root{{--code-bg:{v}}}\n"));
}
if let Some(v) = &theme.border {
s.push_str(&format!(":root{{--border:{v}}}\n"));
}
s
}