"#,
before = before,
classes = classes,
after = after)
}).into_owned()
}
fn add_playpen_pre(html: &str, playpen_config: &Playpen) -> String {
let regex = Regex::new(r##"((?s)]?class="([^"]+)".*?>(.*?)
)"##).unwrap();
regex.replace_all(html, |caps: &Captures| {
let text = &caps[1];
let classes = &caps[2];
let code = &caps[3];
if (classes.contains("language-rust") && !classes.contains("ignore")) ||
classes.contains("mdbook-runnable")
{
// wrap the contents in an external pre block
if playpen_config.editable && classes.contains("editable") ||
text.contains("fn main") || text.contains("quick_main!")
{
format!("{}
", text)
} else {
// we need to inject our own main
let (attrs, code) = partition_source(code);
format!("\n# \
#![allow(unused_variables)]\n\
{}#fn main() {{\n\
{}\
#}}
",
classes,
attrs,
code)
}
} else {
// not language-rust, so no-op
text.to_owned()
}
}).into_owned()
}
fn partition_source(s: &str) -> (String, String) {
let mut after_header = false;
let mut before = String::new();
let mut after = String::new();
for line in s.lines() {
let trimline = line.trim();
let header = trimline.chars().all(|c| c.is_whitespace()) || trimline.starts_with("#![");
if !header || after_header {
after_header = true;
after.push_str(line);
after.push_str("\n");
} else {
before.push_str(line);
before.push_str("\n");
}
}
(before, after)
}
struct RenderItemContext<'a> {
handlebars: &'a Handlebars,
destination: PathBuf,
data: serde_json::Map,
is_index: bool,
html_config: HtmlConfig,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn original_build_header_links() {
let inputs = vec![
(
"blah blah Foo
",
r##"blah blah "##,
),
(
"Foo
",
r##""##,
),
(
"Foo^bar
",
r##""##,
),
(
"",
r##""##,
),
(
"Hï
",
r##""##,
),
(
"Foo
Foo
",
r##""##,
),
];
for (src, should_be) in inputs {
let filepath = "./some_chapter/some_section.html";
let got = build_header_links(&src, filepath);
assert_eq!(got, should_be);
// This is redundant for most cases
let got = fix_anchor_links(&got, filepath);
assert_eq!(got, should_be);
}
}
}