diff --git a/js/test_cases/filters/README.md b/js/test_cases/filters/README.md new file mode 100644 index 0000000..3325603 --- /dev/null +++ b/js/test_cases/filters/README.md @@ -0,0 +1,8 @@ +HTML Escaping +------------- + +Dust automatically applies the `|h` filter to html escape unless `|s` is applied to disable automatic html escaping. It seems that if you manually specify `|h` and `|s` in the same filter, then it still html escapes, so my theory on the logic is: + +Iterate over all filters +If `|s` or `|h` is not present append `|h`, otherwise, leave filters as-in +During render, `|s` does nothing, so we can just remove it on the dust side to prevent confusion. diff --git a/src/bin.rs b/src/bin.rs index a8e46d3..102d53d 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -93,12 +93,30 @@ fn apply_filter( filter: &Filter, ) -> Result { match (json_value, filter) { + // Html escape filter (serde_json::Value::String(string), Filter::HtmlEncode) => { Ok(serde_json::Value::String(html_escape(string))) } (_, Filter::HtmlEncode) => Ok(serde_json::Value::String(html_escape( &json_value.render(&Vec::new())?, ))), + // Disable html escape filter + (_, Filter::DisableHtmlEncode) => panic!("The |s filter is automatically removed by the renderer since it is a no-op during rendering."), + // Parse JSON filter + (serde_json::Value::String(string), Filter::JsonParse) => { + serde_json::from_str(&string).or(Err(RenderError::InvalidJson(string.to_owned()))) + } + (_, Filter::JsonParse) => { + let rendered_value = json_value.render(&Vec::new())?; + serde_json::from_str(&rendered_value).or(Err(RenderError::InvalidJson(rendered_value))) + } + // Json Stringify filter + (_, Filter::JsonStringify) => { + Ok(serde_json::Value::String(json_value.to_string())) + } + // TODO: javascript string escape + // TODO: EncodeUri + // TODO: EncodeUriComponent _ => panic!("Unimplemented"), } } @@ -121,9 +139,9 @@ impl ContextElement for serde_json::Value {} impl Renderable for serde_json::Value { fn render(&self, _filters: &Vec) -> Result { let after_apply = if _filters.is_empty() { - Some(apply_filters(self, _filters)?) - } else { None + } else { + Some(apply_filters(self, _filters)?) }; match after_apply.as_ref().unwrap_or(self) { diff --git a/src/renderer/errors.rs b/src/renderer/errors.rs index a72ef61..8c458d7 100644 --- a/src/renderer/errors.rs +++ b/src/renderer/errors.rs @@ -8,6 +8,7 @@ use std::fmt; pub enum RenderError { Generic(String), TemplateNotFound(String), + InvalidJson(String), } #[derive(PartialEq)] @@ -27,6 +28,11 @@ impl fmt::Display for RenderError { RenderError::TemplateNotFound(name) => { write!(f, "No template named {} in context", name) } + RenderError::InvalidJson(invalid_json) => write!( + f, + "Attempted to parse the following invalid JSON: {}", + invalid_json + ), } } } @@ -38,6 +44,11 @@ impl fmt::Debug for RenderError { RenderError::TemplateNotFound(name) => { write!(f, "No template named {} in context", name) } + RenderError::InvalidJson(invalid_json) => write!( + f, + "Attempted to parse the following invalid JSON: {}", + invalid_json + ), } } }