日本語

Unchecked values

A few forms reach the browser without a check. Each has its own name, so searching for that name finds every place that uses an unchecked value.

use hypersig::html::{Stylesheet, div};
use hypersig::style::Style;
use hypersig::style::value::raw;
use hypersig::{Page, Signals};
use serde::{Deserialize, Serialize};

#[derive(Signals, Serialize, Deserialize)]
struct Legacy {
    open: bool,
}

// A value with several parts goes through `raw`, which the browser checks.
let card = Style::new()
    .margin(raw("0 auto"))
    .box_shadow(raw("0 1px 3px rgb(0 0 0 / 0.1)"))
    .width(raw("calc(100% - 2rem)"));

// An existing stylesheet keeps working. `class` fails to compile unless the
// CSS has a selector for the class.
const LEGACY: Stylesheet = Stylesheet::new(".panel { padding: 1rem } .open { display: block }");
const PANEL: hypersig::html::Class = LEGACY.class("panel");
const OPEN: hypersig::html::Class = LEGACY.class("open");

let html = Page::new("Legacy", Legacy { open: false })
    .style(LEGACY)
    .child(div().css(card).class(PANEL).class_when(OPEN, Legacy::open()))
    .render();
assert!(html.contains("panel"));
  • raw(css) writes a value as given, for the forms a property's generated type leaves out, such as margin: 0 auto, a shadow, or a calc(). If the browser rejects the value, it ignores the declaration. raw panics on ;, {, }, and <, which would end the declaration or the rule, or close the <style> element.
  • Stylesheet::new(css) makes a Stylesheet from CSS you already have, and Page::style adds it to the page. Stylesheet::class("name") checks at compile time that the CSS has a selector for the class, and Class::new refers to a class by name without that check.
  • El::bind_style and El::bind_token set a property from a string expression over the signals. The expression is not checked.