/*! by [extinct](https://extinct.at/) A dsl (domain specific language) for writing html. This is NOT an html template. This library focus is on html composability. It uses a FILO stack paradigm. ## usage ``` use html_stack::Stack ; fn myhomepage() ->String { let s = Stack::new() ; s .put("my homepage") .wrp("title") .wrp("head") ; s .put("my homepage") .wrp("h1") ; s .put("Lorem ipsum dolor sit amet, consectetur adipiscing elit.") .wrp("p class=someclass") .add() ; s .put("Lorem ipsum dolor sit amet, consectetur adipiscing elit.") .wrp("p class='class1 class2'") .add() ; s .put("") .wrp("img src=/img/image.jpg") .add() ; s .wrp("body") .add() ; s .put("") .wrp("script type=module src=/js/main.js") .add() ; s .wrp("html") ; return s .doctype() ; ``` */ use std::collections::HashSet ; fn tag(c:&str ,t:&str) ->String { let mut ts:Vec<&str> = t .split(" ") .map(|i| i.trim()) .collect() ; let head = ts .remove(0) ; let t = ts .join(" ") ; if t == "" { return format!("\n<{head}>{c}") ;} return format!("\n<{head} {t}>{c}") ;} // tag attribute values do not always need to be quoted ; pub struct Stack(Vec); impl Stack { pub fn new()->Self { return Stack(vec!()) ;} pub fn print(&mut self) { let mut i = 0 ; for x in &mut self.0 { println!("{}{}\n" ,i ,x) ; i += 1 ;}} pub fn preview(&mut self) { let mut i = 0 ; println!("\n\tSTACK") ; for x in &mut self.0 { let n = x .len() ; let mut y = x .replace("\n" ,"") ; if n > 100 { y = y[..100].to_string() ;} println!("\n\t[{}] {} . . ." ,i ,y) ; i += 1 ;} println!("\n") ;} pub fn finish(&mut self)->String { if self.0 .len() != 1 { self .preview() ; panic!("\n\n\tfinish: STACK MUST END WITH ONLY ONE ELEMENT!\n\n") ;} return self.0[0].to_string() ;} pub fn doctype(&mut self)->String { return format!("{}" ,self .finish()) ;} pub fn clear(&mut self)->&mut Self { self.0 = vec!() ; return self ;}} impl Stack { pub fn put(&mut self ,c:&str)->&mut Self { self.0 .push(c.to_string()) ; return self ;} pub fn add(&mut self)->&mut Self { if self.0 .len() < 2 { self .preview() ; panic!("\n\n\tadd(): STACK NEEDS TO HAVE AT LEAST TWO ELEMENTS\n\n!") ;} let x = self.0 .pop().unwrap() ; let y = self.0 .pop().unwrap() ; self.0 .push(format!("{}{}" ,y ,x)) ; return self ;} pub fn wrp(&mut self ,t:&str)->&mut Self { if self.0 .len() < 1 { self .preview() ; panic!("\n\n\twrp({}): STACK NEEDS TO HAVE AT LEAST ONE ELEMENT\n\n!" ,t) ;} let c = self.0 .pop().unwrap() ; self.0 .push(tag(&c ,t)) ; return self ;} pub fn swap(&mut self)->&mut Self { if self.0 .len() < 2 { self .preview() ; panic!("\n\n\tswap: STACK NEEDS TO HAVE AT LEAST TWO ELEMENTS\n\n!") ;} let y = self.0 .pop().unwrap() ; let x = self.0 .pop().unwrap() ; self.0 .push(y) ; self.0 .push(x) ; return self ;} pub fn dup(&mut self)->&mut Self { if self.0 .len() < 1 { self .preview() ; panic!("\n\n\tswap: STACK NEEDS TO HAVE AT LEAST ONE ELEMENT\n\n!") ;} self.0 .push(self.0.last().unwrap().to_string()) ; return self ;} pub fn drop(&mut self)->&mut Self { if self.0 .len() < 1 { self .preview() ; panic!("\n\n\tswap: STACK NEEDS TO HAVE AT LEAST ONE ELEMENT\n\n!") ;} self.0 .pop() ; return self ;}} impl Stack { pub fn one(&mut self)->&mut Self { let mut y = "".to_string() ; for i in &self.0 { y += &i ;} self.0 = vec!(y) ; return self ;} pub fn shuffle(&mut self)->&mut Self { if self.0 .len() < 2 { self .preview() ; panic!("\n\n\tshuffle: STACK NEEDS TO HAVE AT LEAST TWO ELEMENTS\n\n!") ;} let mut hs:HashSet = HashSet::new() ; loop { let x = self.0 .pop() ; if x .is_none() { break ;} hs .insert(x.unwrap()) ;} for i in hs { self.0 .push(i) ;} return self ;}}