feat(style): generate checked class tokens
Add a boring CSS/SCSS class-token surface: slhx-build discovers static class tokens from hemplate/templates/stylesheets and emits generated CssClass constants. Add CssClasses for hemplate +class/view data and migrate techdemo dynamic/effect fragments toward hemplate-owned views with DOM-aware assertions. req: style/001 req: style/002 req: style/003 req: html_safety/002 req: view/001 req: test/005
This commit is contained in:
@@ -143,6 +143,85 @@ impl SafeHtml {
|
||||
}
|
||||
}
|
||||
|
||||
/// A generated, checked CSS class token.
|
||||
///
|
||||
/// Plain CSS/SCSS owns appearance; slhx only gives Rust a typed reference to
|
||||
/// class names discovered from build inputs. req: style/001
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
pub struct CssClass {
|
||||
name: &'static str,
|
||||
}
|
||||
|
||||
impl CssClass {
|
||||
pub const fn new(name: &'static str) -> Self {
|
||||
Self { name }
|
||||
}
|
||||
|
||||
pub const fn as_str(self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for CssClass {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for CssClass {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.write_str(self.name)
|
||||
}
|
||||
}
|
||||
|
||||
/// A small displayable list of generated CSS class tokens for hemplate `+class`.
|
||||
/// req: style/003
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub struct CssClasses {
|
||||
names: String,
|
||||
}
|
||||
|
||||
impl CssClasses {
|
||||
pub fn new(classes: impl IntoIterator<Item = CssClass>) -> Self {
|
||||
let mut names = String::new();
|
||||
for class in classes {
|
||||
if !names.is_empty() {
|
||||
names.push(' ');
|
||||
}
|
||||
names.push_str(class.as_str());
|
||||
}
|
||||
Self { names }
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.names
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CssClass> for CssClasses {
|
||||
fn from(class: CssClass) -> Self {
|
||||
Self::new([class])
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> From<[CssClass; N]> for CssClasses {
|
||||
fn from(classes: [CssClass; N]) -> Self {
|
||||
Self::new(classes)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for CssClasses {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Display for CssClasses {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.write_str(&self.names)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
pub struct FormContract {
|
||||
pub fields: &'static [FormField],
|
||||
|
||||
Reference in New Issue
Block a user