use std::path::Path; use askama::Template; use derive_more::From; use lazy_static::lazy_static; use svg_units::{SVGMeasure, SVGUnit}; #[derive(Template)] #[template(path = "document.xml")] struct DocumentTemplate<'a> { dimensions: &'a DocumentDimensions, keyboard: kle_serial::Keyboard, } struct DocumentDimensions { width: SVGMeasure, height: SVGMeasure, margin: SVGMeasure, } lazy_static! { static ref LETTER_LANDSCAPE: DocumentDimensions = DocumentDimensions { width: SVGMeasure::new(11.0, SVGUnit::Inch), height: SVGMeasure::new(8.5, SVGUnit::Inch), margin: SVGMeasure::new(0.25, SVGUnit::Inch), }; } mod filters { use svg_units::{SVGMeasure, SVGUnit}; pub fn kle_font_units(kle_font_units: &usize) -> askama::Result { Ok(SVGMeasure::new( (6 + kle_font_units * 2) as f64, SVGUnit::Pixel, )) } } #[derive(From, Debug)] pub enum Error { Io(std::io::Error), Template(askama::Error), LayoutParse(serde_json::Error), } pub type Result = std::result::Result; pub fn render_file(input_path: P, output_path: Q) -> Result<()> where P: AsRef, Q: AsRef, { use std::{ fs::{self, OpenOptions}, io::Write, }; let mut file = OpenOptions::new() .write(true) .truncate(true) .create(true) .open(output_path)?; write!(file, "{}", render(&fs::read_to_string(input_path)?)?)?; Ok(()) } pub fn render(input: &str) -> Result { let document = DocumentTemplate { dimensions: &LETTER_LANDSCAPE, keyboard: serde_json::from_str(input)?, }; Ok(document.render()?) }