use crate::error::BlueprintResult;
use crate::template::Template;
pub const DEFAULT_YAML: &str = include_str!("../templates/default.yaml");
pub const GOV_PROPOSAL_YAML: &str = include_str!("../templates/gov_proposal.yaml");
pub fn builtin_default() -> BlueprintResult<Template> {
Template::from_yaml(DEFAULT_YAML)
}
pub fn builtin_gov_proposal() -> BlueprintResult<Template> {
Template::from_yaml(GOV_PROPOSAL_YAML)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::inheritance::resolve_template;
use crate::registry::StyleRegistry;
use hwpforge_foundation::{Alignment, HwpUnit};
use pretty_assertions::assert_eq;
use std::collections::HashMap;
#[test]
fn default_yaml_is_valid() {
let tmpl = builtin_default().unwrap();
assert_eq!(tmpl.meta.name, "default");
assert_eq!(tmpl.meta.version, "1.0.0");
assert!(tmpl.meta.extends.is_none());
}
#[test]
fn gov_proposal_yaml_is_valid() {
let tmpl = builtin_gov_proposal().unwrap();
assert_eq!(tmpl.meta.name, "gov_proposal");
assert_eq!(tmpl.meta.extends, Some("default".to_string()));
}
#[test]
fn default_has_expected_styles() {
let tmpl = builtin_default().unwrap();
let expected =
["body", "heading1", "heading2", "heading3", "code", "blockquote", "list_item"];
for name in &expected {
assert!(tmpl.styles.contains_key(*name), "missing style: {name}");
}
assert_eq!(tmpl.styles.len(), expected.len());
}
#[test]
fn default_has_a4_page() {
let tmpl = builtin_default().unwrap();
let page = tmpl.page.as_ref().unwrap();
let settings = page.to_page_settings();
assert!((settings.width.to_mm() - 210.0).abs() < 0.5);
assert!((settings.height.to_mm() - 297.0).abs() < 0.5);
}
#[test]
fn default_body_is_10pt_justify() {
let tmpl = builtin_default().unwrap();
let body = tmpl.styles.get("body").unwrap();
let cs = body.char_shape.as_ref().unwrap();
assert_eq!(cs.font, Some("한컴바탕".to_string()));
assert_eq!(cs.size, Some(HwpUnit::from_pt(10.0).unwrap()));
let ps = body.para_shape.as_ref().unwrap();
assert_eq!(ps.alignment, Some(Alignment::Justify));
}
#[test]
fn default_heading1_is_bold_16pt() {
let tmpl = builtin_default().unwrap();
let h1 = tmpl.styles.get("heading1").unwrap();
let cs = h1.char_shape.as_ref().unwrap();
assert_eq!(cs.size, Some(HwpUnit::from_pt(16.0).unwrap()));
assert_eq!(cs.bold, Some(true));
}
#[test]
fn default_has_markdown_mapping() {
let tmpl = builtin_default().unwrap();
let md = tmpl.markdown_mapping.as_ref().unwrap();
assert_eq!(md.body, Some("body".to_string()));
assert_eq!(md.heading1, Some("heading1".to_string()));
assert_eq!(md.code, Some("code".to_string()));
}
#[test]
fn gov_proposal_has_title_style() {
let tmpl = builtin_gov_proposal().unwrap();
assert!(tmpl.styles.contains_key("title"));
assert!(tmpl.styles.contains_key("subtitle"));
}
#[test]
fn gov_proposal_overrides_body_size() {
let tmpl = builtin_gov_proposal().unwrap();
let body = tmpl.styles.get("body").unwrap();
let cs = body.char_shape.as_ref().unwrap();
assert_eq!(cs.size, Some(HwpUnit::from_pt(11.0).unwrap()));
}
#[test]
fn gov_proposal_wider_left_margin() {
let tmpl = builtin_gov_proposal().unwrap();
let page = tmpl.page.as_ref().unwrap();
assert_eq!(page.margin_left, Some(HwpUnit::from_mm(30.0).unwrap()));
}
#[test]
fn gov_proposal_resolves_from_default() {
let default = builtin_default().unwrap();
let gov = builtin_gov_proposal().unwrap();
let mut provider = HashMap::new();
provider.insert("default".to_string(), default);
provider.insert("gov_proposal".to_string(), gov.clone());
let resolved = resolve_template(&gov, &provider).unwrap();
assert!(resolved.meta.extends.is_none());
assert!(resolved.styles.contains_key("body")); assert!(resolved.styles.contains_key("heading1")); assert!(resolved.styles.contains_key("title")); assert!(resolved.styles.contains_key("subtitle")); assert!(resolved.styles.contains_key("code"));
let body = resolved.styles.get("body").unwrap();
let cs = body.char_shape.as_ref().unwrap();
assert_eq!(cs.font, Some("한컴바탕".to_string()));
assert_eq!(cs.size, Some(HwpUnit::from_pt(11.0).unwrap()));
}
#[test]
fn default_template_creates_valid_registry() {
let tmpl = builtin_default().unwrap();
let registry = StyleRegistry::from_template(&tmpl).unwrap();
assert_eq!(registry.style_count(), 7);
assert!(registry.get_style("body").is_some());
assert!(registry.get_style("heading1").is_some());
}
#[test]
fn resolved_gov_proposal_creates_valid_registry() {
let default = builtin_default().unwrap();
let gov = builtin_gov_proposal().unwrap();
let mut provider = HashMap::new();
provider.insert("default".to_string(), default);
provider.insert("gov_proposal".to_string(), gov.clone());
let resolved = resolve_template(&gov, &provider).unwrap();
let registry = StyleRegistry::from_template(&resolved).unwrap();
assert_eq!(registry.style_count(), 9);
assert!(registry.get_style("title").is_some());
assert_eq!(registry.font_count(), 2);
}
#[test]
fn default_yaml_roundtrip() {
let original = builtin_default().unwrap();
let yaml = serde_yaml::to_string(&original).unwrap();
let roundtripped = Template::from_yaml(&yaml).unwrap();
assert_eq!(original.meta.name, roundtripped.meta.name);
assert_eq!(original.styles.len(), roundtripped.styles.len());
}
#[test]
fn gov_proposal_yaml_roundtrip() {
let original = builtin_gov_proposal().unwrap();
let yaml = serde_yaml::to_string(&original).unwrap();
let roundtripped = Template::from_yaml(&yaml).unwrap();
assert_eq!(original.meta.name, roundtripped.meta.name);
assert_eq!(original.styles.len(), roundtripped.styles.len());
}
}