You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
4.2KB

  1. use std::collections::HashMap;
  2. use base64::{decode, encode};
  3. use pulldown_cmark as cmark;
  4. use tera::{to_value, Result as TeraResult, Value};
  5. pub fn markdown(value: &Value, args: &HashMap<String, Value>) -> TeraResult<Value> {
  6. let s = try_get_value!("markdown", "value", String, value);
  7. let inline = match args.get("inline") {
  8. Some(val) => try_get_value!("markdown", "inline", bool, val),
  9. None => false,
  10. };
  11. let mut opts = cmark::Options::empty();
  12. opts.insert(cmark::Options::ENABLE_TABLES);
  13. opts.insert(cmark::Options::ENABLE_FOOTNOTES);
  14. let mut html = String::new();
  15. let parser = cmark::Parser::new_ext(&s, opts);
  16. cmark::html::push_html(&mut html, parser);
  17. if inline {
  18. html = html
  19. .trim_start_matches("<p>")
  20. // pulldown_cmark finishes a paragraph with `</p>\n`
  21. .trim_end_matches("</p>\n")
  22. .to_string();
  23. }
  24. Ok(to_value(&html).unwrap())
  25. }
  26. pub fn base64_encode(value: &Value, _: &HashMap<String, Value>) -> TeraResult<Value> {
  27. let s = try_get_value!("base64_encode", "value", String, value);
  28. Ok(to_value(&encode(s.as_bytes())).unwrap())
  29. }
  30. pub fn base64_decode(value: &Value, _: &HashMap<String, Value>) -> TeraResult<Value> {
  31. let s = try_get_value!("base64_decode", "value", String, value);
  32. Ok(to_value(&String::from_utf8(decode(s.as_bytes()).unwrap()).unwrap()).unwrap())
  33. }
  34. #[cfg(test)]
  35. mod tests {
  36. use std::collections::HashMap;
  37. use tera::to_value;
  38. use super::{base64_decode, base64_encode, markdown};
  39. #[test]
  40. fn markdown_filter() {
  41. let result = markdown(&to_value(&"# Hey").unwrap(), &HashMap::new());
  42. assert!(result.is_ok());
  43. assert_eq!(result.unwrap(), to_value(&"<h1>Hey</h1>\n").unwrap());
  44. }
  45. #[test]
  46. fn markdown_filter_inline() {
  47. let mut args = HashMap::new();
  48. args.insert("inline".to_string(), to_value(true).unwrap());
  49. let result = markdown(
  50. &to_value(&"Using `map`, `filter`, and `fold` instead of `for`").unwrap(),
  51. &args,
  52. );
  53. assert!(result.is_ok());
  54. assert_eq!(result.unwrap(), to_value(&"Using <code>map</code>, <code>filter</code>, and <code>fold</code> instead of <code>for</code>").unwrap());
  55. }
  56. // https://github.com/Keats/gutenberg/issues/417
  57. #[test]
  58. fn markdown_filter_inline_tables() {
  59. let mut args = HashMap::new();
  60. args.insert("inline".to_string(), to_value(true).unwrap());
  61. let result = markdown(
  62. &to_value(
  63. &r#"
  64. |id|author_id| timestamp_created|title |content |
  65. |-:|--------:|-----------------------:|:---------------------|:-----------------|
  66. | 1| 1|2018-09-05 08:03:43.141Z|How to train your ORM |Badly written blog|
  67. | 2| 1|2018-08-22 13:11:50.050Z|How to bake a nice pie|Badly written blog|
  68. "#,
  69. )
  70. .unwrap(),
  71. &args,
  72. );
  73. assert!(result.is_ok());
  74. assert!(result.unwrap().as_str().unwrap().contains("<table>"));
  75. }
  76. #[test]
  77. fn base64_encode_filter() {
  78. // from https://tools.ietf.org/html/rfc4648#section-10
  79. let tests = vec![
  80. ("", ""),
  81. ("f", "Zg=="),
  82. ("fo", "Zm8="),
  83. ("foo", "Zm9v"),
  84. ("foob", "Zm9vYg=="),
  85. ("fooba", "Zm9vYmE="),
  86. ("foobar", "Zm9vYmFy"),
  87. ];
  88. for (input, expected) in tests {
  89. let args = HashMap::new();
  90. let result = base64_encode(&to_value(input).unwrap(), &args);
  91. assert!(result.is_ok());
  92. assert_eq!(result.unwrap(), to_value(expected).unwrap());
  93. }
  94. }
  95. #[test]
  96. fn base64_decode_filter() {
  97. let tests = vec![
  98. ("", ""),
  99. ("Zg==", "f"),
  100. ("Zm8=", "fo"),
  101. ("Zm9v", "foo"),
  102. ("Zm9vYg==", "foob"),
  103. ("Zm9vYmE=", "fooba"),
  104. ("Zm9vYmFy", "foobar"),
  105. ];
  106. for (input, expected) in tests {
  107. let args = HashMap::new();
  108. let result = base64_decode(&to_value(input).unwrap(), &args);
  109. assert!(result.is_ok());
  110. assert_eq!(result.unwrap(), to_value(expected).unwrap());
  111. }
  112. }
  113. }