diff options
Diffstat (limited to 'src/md.rs')
-rw-r--r-- | src/md.rs | 110 |
1 files changed, 83 insertions, 27 deletions
@@ -2,8 +2,8 @@ use crate::{ html::{parse, Attribute, Content, Element, ElementTag, Location}, - parse_scenario_snippet, Bindings, EmbeddedFile, EmbeddedFiles, Scenario, ScenarioStep, Style, - SubplotError, Warnings, + steps::parse_scenario_snippet, + Bindings, EmbeddedFile, EmbeddedFiles, Scenario, Style, SubplotError, Warnings, }; use log::trace; use std::collections::HashSet; @@ -88,8 +88,13 @@ impl Markdown { } /// Typeset. - pub fn typeset(&mut self, _style: Style, _bindings: &Bindings) -> Warnings { - let result = typeset::typeset_element(&self.html); + pub fn typeset( + &mut self, + _style: Style, + template: Option<&str>, + bindings: &Bindings, + ) -> Warnings { + let result = typeset::typeset_element(&self.html, template, bindings); if let Ok(html) = result { self.html = html; Warnings::default() @@ -278,7 +283,6 @@ fn extract_scenario(e: &[StructureElement]) -> Result<(Option<Scenario>, usize), StructureElement::Snippet(_, loc) => Err(SubplotError::ScenarioBeforeHeading(loc.clone())), StructureElement::Heading(title, level, loc) => { let mut scen = Scenario::new(title, loc.clone()); - let mut prevkind = None; for (i, item) in e.iter().enumerate().skip(1) { match item { StructureElement::Heading(_, level2, _loc) => { @@ -295,22 +299,9 @@ fn extract_scenario(e: &[StructureElement]) -> Result<(Option<Scenario>, usize), } } StructureElement::Snippet(text, loc) => { - for (idx, line) in parse_scenario_snippet(text).enumerate() { - let line_loc = match loc.clone() { - Location::Known { - filename, - line, - col, - } => Location::Known { - filename, - line: line + idx, - col, - }, - Location::Unknown => Location::Unknown, - }; - let step = ScenarioStep::new_from_str(line, prevkind, line_loc)?; + let steps = parse_scenario_snippet(text, loc)?; + for step in steps { scen.add(&step); - prevkind = Some(step.kind()); } } } @@ -327,21 +318,30 @@ fn extract_scenario(e: &[StructureElement]) -> Result<(Option<Scenario>, usize), mod typeset { const UNWANTED_ATTRS: &[&str] = &["add-newline"]; - use crate::html::{Attribute, Content, Element, ElementTag}; + use crate::{ + html::{Attribute, Content, Element, ElementTag, Location}, + Bindings, PartialStep, + }; // use crate::parser::parse_scenario_snippet; // use crate::Bindings; // use crate::PartialStep; // use crate::ScenarioStep; // use crate::StepKind; use crate::SubplotError; - use crate::{DiagramMarkup, DotMarkup, PikchrMarkup, PlantumlMarkup, Svg}; + use crate::{DiagramMarkup, DotMarkup, MatchedStep, PikchrMarkup, PlantumlMarkup, Svg}; // use crate::{Warning, Warnings}; use base64::prelude::{Engine as _, BASE64_STANDARD}; - pub(crate) fn typeset_element(e: &Element) -> Result<Element, SubplotError> { + pub(crate) fn typeset_element( + e: &Element, + template: Option<&str>, + bindings: &Bindings, + ) -> Result<Element, SubplotError> { let new = match e.tag() { - ElementTag::Pre if e.has_attr("class", "scenario") => typeset_scenario(e), + ElementTag::Pre if e.has_attr("class", "scenario") => { + typeset_scenario(e, template, bindings) + } ElementTag::Pre if e.has_attr("class", "file") => typeset_file(e), ElementTag::Pre if e.has_attr("class", "example") => typeset_example(e), ElementTag::Pre if e.has_attr("class", "dot") => typeset_dot(e), @@ -355,7 +355,7 @@ mod typeset { } for child in e.children() { if let Content::Elt(ce) = child { - new.push_child(Content::Elt(typeset_element(ce)?)); + new.push_child(Content::Elt(typeset_element(ce, template, bindings)?)); } else { new.push_child(child.clone()); } @@ -368,8 +368,64 @@ mod typeset { Ok(new) } - fn typeset_scenario(e: &Element) -> Result<Element, SubplotError> { - Ok(e.clone()) // FIXME + fn typeset_scenario( + e: &Element, + template: Option<&str>, + bindings: &Bindings, + ) -> Result<Element, SubplotError> { + let template = template.unwrap_or("python"); // FIXME + + let text = e.content(); + let steps = crate::steps::parse_scenario_snippet(&text, &Location::Unknown)?; + + let mut scenario = Element::new(ElementTag::Div); + scenario.push_attribute(Attribute::new("class", "scenario")); + + for step in steps { + if let Ok(matched) = bindings.find(template, &step) { + scenario.push_child(Content::Elt(typeset_step(&matched))); + } else { + scenario.push_child(Content::Text(step.text().into())); + } + } + + Ok(scenario) + } + + fn typeset_step(matched: &MatchedStep) -> Element { + let mut e = Element::new(ElementTag::Div); + let mut keyword = Element::new(ElementTag::Span); + keyword.push_attribute(Attribute::new("class", "keyword")); + keyword.push_child(Content::Text(matched.kind().to_string())); + keyword.push_child(Content::Text(" ".into())); + e.push_child(Content::Elt(keyword)); + for part in matched.parts() { + match part { + PartialStep::UncapturedText(snippet) => { + let text = snippet.text(); + if !text.trim().is_empty() { + let mut estep = Element::new(ElementTag::Span); + estep.push_attribute(Attribute::new("class", "uncaptured")); + estep.push_child(Content::Text(text.into())); + e.push_child(Content::Elt(estep)); + } + } + PartialStep::CapturedText { + name: _, + text, + kind, + } => { + if !text.trim().is_empty() { + let mut estep = Element::new(ElementTag::Span); + let class = format!("capture-{}", kind.as_str()); + estep.push_attribute(Attribute::new("class", &class)); + estep.push_child(Content::Text(text.into())); + e.push_child(Content::Elt(estep)); + } + } + } + } + e } fn typeset_file(e: &Element) -> Result<Element, SubplotError> { |