Properly parse shortcode arg value types
This commit is contained in:
parent
1d8df5774f
commit
bfdfe3bba3
|
@ -9,6 +9,7 @@
|
||||||
- Fix permalink generation for index page
|
- Fix permalink generation for index page
|
||||||
- Add Nim syntax highlighting
|
- Add Nim syntax highlighting
|
||||||
- Allow static folder to be missing
|
- Allow static folder to be missing
|
||||||
|
- Fix shortcodes args being only passed as strings
|
||||||
|
|
||||||
|
|
||||||
## 0.2.1 (2017-10-17)
|
## 0.2.1 (2017-10-17)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use tera::{Tera, Context};
|
use tera::{Tera, Context, Value, to_value};
|
||||||
|
|
||||||
use errors::{Result, ResultExt};
|
use errors::{Result, ResultExt};
|
||||||
|
|
||||||
|
@ -15,15 +15,15 @@ lazy_static!{
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ShortCode {
|
pub struct ShortCode {
|
||||||
name: String,
|
name: String,
|
||||||
args: HashMap<String, String>,
|
args: HashMap<String, Value>,
|
||||||
body: String,
|
body: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShortCode {
|
impl ShortCode {
|
||||||
pub fn new(name: &str, args: HashMap<String, String>) -> ShortCode {
|
pub fn new(name: &str, args: HashMap<String, Value>) -> ShortCode {
|
||||||
ShortCode {
|
ShortCode {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
args: args,
|
args,
|
||||||
body: String::new(),
|
body: String::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ impl ShortCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a shortcode without a body
|
/// Parse a shortcode without a body
|
||||||
pub fn parse_shortcode(input: &str) -> (String, HashMap<String, String>) {
|
pub fn parse_shortcode(input: &str) -> (String, HashMap<String, Value>) {
|
||||||
let mut args = HashMap::new();
|
let mut args = HashMap::new();
|
||||||
let caps = SHORTCODE_RE.captures(input).unwrap();
|
let caps = SHORTCODE_RE.captures(input).unwrap();
|
||||||
// caps[0] is the full match
|
// caps[0] is the full match
|
||||||
|
@ -54,7 +54,39 @@ pub fn parse_shortcode(input: &str) -> (String, HashMap<String, String>) {
|
||||||
if let Some(arg_list) = caps.get(2) {
|
if let Some(arg_list) = caps.get(2) {
|
||||||
for arg in arg_list.as_str().split(',') {
|
for arg in arg_list.as_str().split(',') {
|
||||||
let bits = arg.split('=').collect::<Vec<_>>();
|
let bits = arg.split('=').collect::<Vec<_>>();
|
||||||
args.insert(bits[0].trim().to_string(), bits[1].replace("\"", ""));
|
let arg_name = bits[0].trim().to_string();
|
||||||
|
let arg_val = bits[1].replace("\"", "");
|
||||||
|
|
||||||
|
// Regex captures will be str so we need to figure out if they are
|
||||||
|
// actually str or bool/number
|
||||||
|
if input.contains(&format!("{}=\"{}\"", arg_name, arg_val)) {
|
||||||
|
// that's a str, just add it
|
||||||
|
args.insert(arg_name, to_value(arg_val).unwrap());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.contains(&format!("{}=true", arg_name)) {
|
||||||
|
args.insert(arg_name, to_value(true).unwrap());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.contains(&format!("{}=false", arg_name)) {
|
||||||
|
args.insert(arg_name, to_value(false).unwrap());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not a string or a bool, a number then?
|
||||||
|
if arg_val.contains('.') {
|
||||||
|
if let Ok(float) = arg_val.parse::<f64>() {
|
||||||
|
args.insert(arg_name, to_value(float).unwrap());
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// must be an integer
|
||||||
|
if let Ok(int) = arg_val.parse::<i64>() {
|
||||||
|
args.insert(arg_name, to_value(int).unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +94,7 @@ pub fn parse_shortcode(input: &str) -> (String, HashMap<String, String>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders a shortcode or return an error
|
/// Renders a shortcode or return an error
|
||||||
pub fn render_simple_shortcode(tera: &Tera, name: &str, args: &HashMap<String, String>) -> Result<String> {
|
pub fn render_simple_shortcode(tera: &Tera, name: &str, args: &HashMap<String, Value>) -> Result<String> {
|
||||||
let mut context = Context::new();
|
let mut context = Context::new();
|
||||||
for (key, value) in args.iter() {
|
for (key, value) in args.iter() {
|
||||||
context.add(key, value);
|
context.add(key, value);
|
||||||
|
@ -117,7 +149,7 @@ mod tests {
|
||||||
let (name, args) = parse_shortcode(r#"{{ youtube(id="w7Ft2ymGmfc", autoplay=true) }}"#);
|
let (name, args) = parse_shortcode(r#"{{ youtube(id="w7Ft2ymGmfc", autoplay=true) }}"#);
|
||||||
assert_eq!(name, "youtube");
|
assert_eq!(name, "youtube");
|
||||||
assert_eq!(args["id"], "w7Ft2ymGmfc");
|
assert_eq!(args["id"], "w7Ft2ymGmfc");
|
||||||
assert_eq!(args["autoplay"], "true");
|
assert_eq!(args["autoplay"], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -125,6 +157,15 @@ mod tests {
|
||||||
let (name, args) = parse_shortcode(r#"{% youtube(id="w7Ft2ymGmfc", autoplay=true) %}"#);
|
let (name, args) = parse_shortcode(r#"{% youtube(id="w7Ft2ymGmfc", autoplay=true) %}"#);
|
||||||
assert_eq!(name, "youtube");
|
assert_eq!(name, "youtube");
|
||||||
assert_eq!(args["id"], "w7Ft2ymGmfc");
|
assert_eq!(args["id"], "w7Ft2ymGmfc");
|
||||||
assert_eq!(args["autoplay"], "true");
|
assert_eq!(args["autoplay"], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_parse_shortcode_number() {
|
||||||
|
let (name, args) = parse_shortcode(r#"{% test(int=42, float=42.0, autoplay=true) %}"#);
|
||||||
|
assert_eq!(name, "test");
|
||||||
|
assert_eq!(args["int"], 42);
|
||||||
|
assert_eq!(args["float"], 42.0);
|
||||||
|
assert_eq!(args["autoplay"], true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,15 @@ Lastly, a shortcode name (and thus the corresponding `.html` file) as well as th
|
||||||
can only contain numbers, letters and underscores, or in Regex terms the following: `[0-9A-Za-z_]`.
|
can only contain numbers, letters and underscores, or in Regex terms the following: `[0-9A-Za-z_]`.
|
||||||
While theoretically an argument name could be a number, it will not be possible to use it in the template in that case.
|
While theoretically an argument name could be a number, it will not be possible to use it in the template in that case.
|
||||||
|
|
||||||
|
Argument values can be of 4 types:
|
||||||
|
|
||||||
|
- string: surrounded by double quotes `"..."`
|
||||||
|
- bool: `true` or `false`
|
||||||
|
- float: a number with a `.` in it
|
||||||
|
- integer: a number without a `.` in it
|
||||||
|
|
||||||
|
Malformed values will be silently ignored.
|
||||||
|
|
||||||
### Shortcodes without body
|
### Shortcodes without body
|
||||||
|
|
||||||
On a new line, call the shortcode as if it was a Tera function in a variable block. All the examples below are valid
|
On a new line, call the shortcode as if it was a Tera function in a variable block. All the examples below are valid
|
||||||
|
|
Loading…
Reference in a new issue