parent
e40e97711f
commit
d67211bfd6
|
@ -12,6 +12,7 @@ to the public directory
|
||||||
- Update Tera: now has `break` and `continue` in loops
|
- Update Tera: now has `break` and `continue` in loops
|
||||||
- Gutenberg now creates an anchor link at the position of the `<!-- more -->` tag if you
|
- Gutenberg now creates an anchor link at the position of the `<!-- more -->` tag if you
|
||||||
want to link directly to it
|
want to link directly to it
|
||||||
|
- Fix many shortcode parsing issues
|
||||||
|
|
||||||
## 0.3.2 (2018-03-05)
|
## 0.3.2 (2018-03-05)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,15 @@ use tera::{Tera, Context, Value, to_value};
|
||||||
use errors::{Result, ResultExt};
|
use errors::{Result, ResultExt};
|
||||||
|
|
||||||
lazy_static!{
|
lazy_static!{
|
||||||
pub static ref SHORTCODE_RE: Regex = Regex::new(r#"\{(?:%|\{)\s+([[:word:]]+?)\(([[:word:]]+?="?.+?"?)?\)\s+(?:%|\})\}"#).unwrap();
|
// Does this look like a shortcode?
|
||||||
|
pub static ref SHORTCODE_RE: Regex = Regex::new(
|
||||||
|
r#"\{(?:%|\{)\s+(\w+?)\((\w+?="?(?:.|\n)+?"?)?\)\s+(?:%|\})\}"#
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
// Parse the shortcode args with capture groups named after their type
|
||||||
|
pub static ref SHORTCODE_ARGS_RE: Regex = Regex::new(
|
||||||
|
r#"(?P<name>\w+)=\s*((?P<str>".*?")|(?P<float>[-+]?[0-9]+\.[0-9]+)|(?P<int>[-+]?[0-9]+)|(?P<bool>true|false))"#
|
||||||
|
).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A shortcode that has a body
|
/// A shortcode that has a body
|
||||||
|
@ -52,41 +60,28 @@ pub fn parse_shortcode(input: &str) -> (String, HashMap<String, Value>) {
|
||||||
let name = &caps[1];
|
let name = &caps[1];
|
||||||
|
|
||||||
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_cap in SHORTCODE_ARGS_RE.captures_iter(arg_list.as_str()) {
|
||||||
let bits = arg.split('=').collect::<Vec<_>>();
|
let arg_name = arg_cap["name"].trim().to_string();
|
||||||
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
|
if let Some(arg_val) = arg_cap.name("str") {
|
||||||
// actually str or bool/number
|
args.insert(arg_name, to_value(arg_val.as_str().replace("\"", "")).unwrap());
|
||||||
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.contains(&format!("{}=true", arg_name)) {
|
if let Some(arg_val) = arg_cap.name("int") {
|
||||||
args.insert(arg_name, to_value(true).unwrap());
|
args.insert(arg_name, to_value(arg_val.as_str().parse::<i64>().unwrap()).unwrap());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.contains(&format!("{}=false", arg_name)) {
|
if let Some(arg_val) = arg_cap.name("float") {
|
||||||
args.insert(arg_name, to_value(false).unwrap());
|
args.insert(arg_name, to_value(arg_val.as_str().parse::<f64>().unwrap()).unwrap());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not a string or a bool, a number then?
|
if let Some(arg_val) = arg_cap.name("bool") {
|
||||||
if arg_val.contains('.') {
|
args.insert(arg_name, to_value(arg_val.as_str() == "true").unwrap());
|
||||||
if let Ok(float) = arg_val.parse::<f64>() {
|
|
||||||
args.insert(arg_name, to_value(float).unwrap());
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// must be an integer
|
|
||||||
if let Ok(int) = arg_val.parse::<i64>() {
|
|
||||||
args.insert(arg_name, to_value(int).unwrap());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,6 +117,10 @@ mod tests {
|
||||||
"{% basic() %}",
|
"{% basic() %}",
|
||||||
"{% quo_te(author=\"Bob\") %}",
|
"{% quo_te(author=\"Bob\") %}",
|
||||||
"{{ quo_te(author=\"Bob\") }}",
|
"{{ quo_te(author=\"Bob\") }}",
|
||||||
|
// https://github.com/Keats/gutenberg/issues/229
|
||||||
|
r#"{{ youtube(id="dQw4w9WgXcQ",
|
||||||
|
|
||||||
|
autoplay=true) }}"#,
|
||||||
];
|
];
|
||||||
|
|
||||||
for i in inputs {
|
for i in inputs {
|
||||||
|
@ -130,6 +129,15 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/Keats/gutenberg/issues/228
|
||||||
|
#[test]
|
||||||
|
fn doesnt_panic_on_invalid_shortcode() {
|
||||||
|
let (name, args) = parse_shortcode(r#"{{ youtube(id="dQw4w9WgXcQ", autoplay) }}"#);
|
||||||
|
assert_eq!(name, "youtube");
|
||||||
|
assert_eq!(args["id"], "dQw4w9WgXcQ");
|
||||||
|
assert!(args.get("autoplay").is_none());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_parse_simple_shortcode_no_arg() {
|
fn can_parse_simple_shortcode_no_arg() {
|
||||||
let (name, args) = parse_shortcode(r#"{{ basic() }}"#);
|
let (name, args) = parse_shortcode(r#"{{ basic() }}"#);
|
||||||
|
@ -162,10 +170,21 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_parse_shortcode_number() {
|
fn can_parse_shortcode_number() {
|
||||||
let (name, args) = parse_shortcode(r#"{% test(int=42, float=42.0, autoplay=true) %}"#);
|
let (name, args) = parse_shortcode(r#"{% test(int=42, float=42.0, autoplay=false) %}"#);
|
||||||
assert_eq!(name, "test");
|
assert_eq!(name, "test");
|
||||||
assert_eq!(args["int"], 42);
|
assert_eq!(args["int"], 42);
|
||||||
assert_eq!(args["float"], 42.0);
|
assert_eq!(args["float"], 42.0);
|
||||||
assert_eq!(args["autoplay"], true);
|
assert_eq!(args["autoplay"], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/Keats/gutenberg/issues/249
|
||||||
|
#[test]
|
||||||
|
fn can_parse_shortcode_with_comma_in_it() {
|
||||||
|
let (name, args) = parse_shortcode(
|
||||||
|
r#"{% quote(author="C++ Standard Core Language Defect Reports and Accepted Issues, Revision 82, delete and user-written deallocation function", href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#348") %}"#
|
||||||
|
);
|
||||||
|
assert_eq!(name, "quote");
|
||||||
|
assert_eq!(args["author"], "C++ Standard Core Language Defect Reports and Accepted Issues, Revision 82, delete and user-written deallocation function");
|
||||||
|
assert_eq!(args["href"], "http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#348");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue