From fbfb7861a275ab0c28fde39b44604c6b3a1e6c2f Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Mon, 30 Dec 2019 08:12:44 +1000 Subject: [PATCH] handle <% %> template syntax --- rs/ankirs/src/backend.rs | 7 +++++-- rs/ankirs/src/template.rs | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/rs/ankirs/src/backend.rs b/rs/ankirs/src/backend.rs index 5236c9bfc..65f7bf38e 100644 --- a/rs/ankirs/src/backend.rs +++ b/rs/ankirs/src/backend.rs @@ -2,7 +2,9 @@ use crate::backend_proto as pt; use crate::backend_proto::backend_input::Value; use crate::err::{AnkiError, Result}; use crate::sched::sched_timing_today; -use crate::template::{FieldMap, FieldRequirements, ParsedTemplate}; +use crate::template::{ + without_legacy_template_directives, FieldMap, FieldRequirements, ParsedTemplate, +}; use prost::Message; use std::collections::HashSet; use std::path::PathBuf; @@ -110,7 +112,8 @@ impl Backend { .template_front .into_iter() .map(|template| { - if let Ok(tmpl) = ParsedTemplate::from_text(&template) { + let normalized = without_legacy_template_directives(&template); + if let Ok(tmpl) = ParsedTemplate::from_text(normalized.as_ref()) { // convert the rust structure into a protobuf one let val = match tmpl.requirements(&map) { FieldRequirements::Any(ords) => Value::Any(pt::TemplateRequirementAny { diff --git a/rs/ankirs/src/template.rs b/rs/ankirs/src/template.rs index ab1758f74..3e1d66961 100644 --- a/rs/ankirs/src/template.rs +++ b/rs/ankirs/src/template.rs @@ -4,6 +4,7 @@ use nom::branch::alt; use nom::bytes::complete::tag; use nom::error::ErrorKind; use nom::sequence::delimited; +use std::borrow::Cow; use std::collections::{HashMap, HashSet}; pub type FieldMap<'a> = HashMap<&'a str, u16>; @@ -107,7 +108,26 @@ enum ParsedNode<'a> { #[derive(Debug)] pub struct ParsedTemplate<'a>(Vec>); +static ALT_HANDLEBAR_DIRECTIVE: &str = "{{=<% %>=}}"; + +/// Convert legacy alternate syntax to standard syntax. +pub fn without_legacy_template_directives(text: &str) -> Cow { + if text.trim_start().starts_with(ALT_HANDLEBAR_DIRECTIVE) { + text.trim_start() + .trim_start_matches(ALT_HANDLEBAR_DIRECTIVE) + .replace("<%", "{{") + .replace("%>", "}}") + .into() + } else { + text.into() + } +} + impl ParsedTemplate<'_> { + /// Create a template from the provided text. + /// + /// The legacy alternate syntax is not supported, so the provided text + /// should be run through without_legacy_template_directives() first. pub fn from_text(template: &str) -> Result { let mut iter = tokens(template); Ok(Self(parse_inner(&mut iter, None)?)) @@ -260,7 +280,7 @@ impl ParsedTemplate<'_> { #[cfg(test)] mod test { use super::{FieldMap, ParsedNode::*, ParsedTemplate as PT}; - use crate::template::FieldRequirements; + use crate::template::{without_legacy_template_directives, FieldRequirements}; use std::collections::HashSet; use std::iter::FromIterator; @@ -357,4 +377,19 @@ mod test { FieldRequirements::Any(HashSet::from_iter(vec![0].into_iter())) ); } + + #[test] + fn test_alt_syntax() { + let input = " +{{=<% %>=}} +<%Front%> +<% #Back %> +<%/Back%>"; + let output = " +{{Front}} +{{ #Back }} +{{/Back}}"; + + assert_eq!(without_legacy_template_directives(input), output); + } }