Move Playground and comma/space class normalization into a pulldown-cmark filter

This avoids scanning over all the HTML with a regex, so it should be faster.
This commit is contained in:
Michael Howell 2021-09-17 15:25:44 -07:00
parent 14250259ef
commit 1fe86a5a0c
3 changed files with 383 additions and 95 deletions

View File

@ -62,6 +62,8 @@ impl HtmlHandlebars {
&content, &content,
ctx.html_config.curly_quotes, ctx.html_config.curly_quotes,
self.syntaxes.borrow().as_ref().unwrap(), self.syntaxes.borrow().as_ref().unwrap(),
&ctx.html_config.playground,
ctx.edition,
); );
let fixed_content = utils::render_markdown_with_path( let fixed_content = utils::render_markdown_with_path(
@ -69,6 +71,8 @@ impl HtmlHandlebars {
ctx.html_config.curly_quotes, ctx.html_config.curly_quotes,
Some(&path), Some(&path),
self.syntaxes.borrow().as_ref().unwrap(), self.syntaxes.borrow().as_ref().unwrap(),
&ctx.html_config.playground,
ctx.edition,
); );
if !ctx.is_index && ctx.html_config.print.page_break { if !ctx.is_index && ctx.html_config.print.page_break {
// Add page break between chapters // Add page break between chapters
@ -121,7 +125,7 @@ impl HtmlHandlebars {
debug!("Render template"); debug!("Render template");
let rendered = ctx.handlebars.render("index", &ctx.data)?; let rendered = ctx.handlebars.render("index", &ctx.data)?;
let rendered = self.post_process(rendered, &ctx.html_config.playground, ctx.edition); let rendered = self.post_process(rendered);
// Write to file // Write to file
debug!("Creating {}", filepath.display()); debug!("Creating {}", filepath.display());
@ -132,8 +136,7 @@ impl HtmlHandlebars {
ctx.data.insert("path_to_root".to_owned(), json!("")); ctx.data.insert("path_to_root".to_owned(), json!(""));
ctx.data.insert("is_index".to_owned(), json!(true)); ctx.data.insert("is_index".to_owned(), json!(true));
let rendered_index = ctx.handlebars.render("index", &ctx.data)?; let rendered_index = ctx.handlebars.render("index", &ctx.data)?;
let rendered_index = let rendered_index = self.post_process(rendered_index);
self.post_process(rendered_index, &ctx.html_config.playground, ctx.edition);
debug!("Creating index.html from {}", ctx_path); debug!("Creating index.html from {}", ctx_path);
utils::fs::write_file(&ctx.destination, "index.html", rendered_index.as_bytes())?; utils::fs::write_file(&ctx.destination, "index.html", rendered_index.as_bytes())?;
} }
@ -171,6 +174,8 @@ impl HtmlHandlebars {
&content_404, &content_404,
html_config.curly_quotes, html_config.curly_quotes,
self.syntaxes.borrow().as_ref().unwrap(), self.syntaxes.borrow().as_ref().unwrap(),
&html_config.playground,
ctx.config.rust.edition,
); );
let mut data_404 = data.clone(); let mut data_404 = data.clone();
@ -197,8 +202,7 @@ impl HtmlHandlebars {
data_404.insert("title".to_owned(), json!(title)); data_404.insert("title".to_owned(), json!(title));
let rendered = handlebars.render("index", &data_404)?; let rendered = handlebars.render("index", &data_404)?;
let rendered = let rendered = self.post_process(rendered);
self.post_process(rendered, &html_config.playground, ctx.config.rust.edition);
let output_file = get_404_output_file(&html_config.input_404); let output_file = get_404_output_file(&html_config.input_404);
utils::fs::write_file(destination, output_file, rendered.as_bytes())?; utils::fs::write_file(destination, output_file, rendered.as_bytes())?;
debug!("Creating 404.html ✓"); debug!("Creating 404.html ✓");
@ -206,15 +210,8 @@ impl HtmlHandlebars {
} }
#[cfg_attr(feature = "cargo-clippy", allow(clippy::let_and_return))] #[cfg_attr(feature = "cargo-clippy", allow(clippy::let_and_return))]
fn post_process( fn post_process(&self, rendered: String) -> String {
&self,
rendered: String,
playground_config: &Playground,
edition: Option<RustEdition>,
) -> String {
let rendered = build_header_links(&rendered); let rendered = build_header_links(&rendered);
let rendered = fix_code_blocks(&rendered);
let rendered = add_playground_pre(&rendered, playground_config, edition);
rendered rendered
} }
@ -595,8 +592,7 @@ impl Renderer for HtmlHandlebars {
debug!("Render template"); debug!("Render template");
let rendered = handlebars.render("index", &data)?; let rendered = handlebars.render("index", &data)?;
let rendered = let rendered = self.post_process(rendered);
self.post_process(rendered, &html_config.playground, ctx.config.rust.edition);
utils::fs::write_file(destination, "print.html", rendered.as_bytes())?; utils::fs::write_file(destination, "print.html", rendered.as_bytes())?;
debug!("Creating print.html ✓"); debug!("Creating print.html ✓");
@ -1000,6 +996,10 @@ fn partition_source(s: &str) -> (String, String) {
(before, after) (before, after)
} }
lazy_static! {
static ref BORING_LINES_REGEX: Regex = Regex::new(r"^(\s*)#(.?)(.*)$").unwrap();
}
struct RenderItemContext<'a> { struct RenderItemContext<'a> {
handlebars: &'a Handlebars<'a>, handlebars: &'a Handlebars<'a>,
destination: PathBuf, destination: PathBuf,

View File

@ -86,10 +86,8 @@ impl<'a> HtmlGenerator<'a> {
if did_boringify { if did_boringify {
// Since the boring scope is preceded only by a Pop operation, // Since the boring scope is preceded only by a Pop operation,
// it must be the first match on the line for <span class=""> // it must be the first match on the line for <span class="">
formatted_line = formatted_line.replace( formatted_line =
r#"<span class="">"#, formatted_line.replace(r#"<span class="">"#, r#"<span class="boring">"#);
r#"<span class="boring">"#,
);
} }
self.open_spans += delta; self.open_spans += delta;
self.html.push_str(&formatted_line); self.html.push_str(&formatted_line);

View File

@ -7,6 +7,7 @@ pub(crate) mod toml_ext;
use crate::errors::Error; use crate::errors::Error;
use regex::Regex; use regex::Regex;
use crate::config::{Playground, RustEdition};
use pulldown_cmark::{html, CodeBlockKind, CowStr, Event, Options, Parser, Tag}; use pulldown_cmark::{html, CodeBlockKind, CowStr, Event, Options, Parser, Tag};
use syntect::html::ClassStyle; use syntect::html::ClassStyle;
use syntect::parsing::SyntaxReference; use syntect::parsing::SyntaxReference;
@ -184,8 +185,21 @@ fn adjust_links<'a>(event: Event<'a>, path: Option<&Path>) -> Event<'a> {
} }
/// Wrapper around the pulldown-cmark parser for rendering markdown to HTML. /// Wrapper around the pulldown-cmark parser for rendering markdown to HTML.
pub fn render_markdown(text: &str, curly_quotes: bool, syntaxes: &SyntaxSet) -> String { pub fn render_markdown(
render_markdown_with_path(text, curly_quotes, None, syntaxes) text: &str,
curly_quotes: bool,
syntaxes: &SyntaxSet,
playground_config: &Playground,
default_edition: Option<RustEdition>,
) -> String {
render_markdown_with_path(
text,
curly_quotes,
None,
syntaxes,
playground_config,
default_edition,
)
} }
pub fn new_cmark_parser(text: &str, curly_quotes: bool) -> Parser<'_, '_> { pub fn new_cmark_parser(text: &str, curly_quotes: bool) -> Parser<'_, '_> {
@ -205,18 +219,20 @@ pub fn render_markdown_with_path(
curly_quotes: bool, curly_quotes: bool,
path: Option<&Path>, path: Option<&Path>,
syntaxes: &SyntaxSet, syntaxes: &SyntaxSet,
playground_config: &Playground,
default_edition: Option<RustEdition>,
) -> String { ) -> String {
let mut s = String::with_capacity(text.len() * 3 / 2); let mut s = String::with_capacity(text.len() * 3 / 2);
let p = new_cmark_parser(text, curly_quotes); let p = new_cmark_parser(text, curly_quotes);
let mut highlighter = SyntaxHighlighter::default(); let mut highlighter = SyntaxHighlighter::new(playground_config, default_edition);
let events = p let events = p
.map(clean_codeblock_headers) .map(clean_codeblock_headers)
.map(|event| highlighter.highlight(syntaxes, event))
.map(|event| adjust_links(event, path)) .map(|event| adjust_links(event, path))
.flat_map(|event| { .flat_map(|event| {
let (a, b) = wrap_tables(event); let (a, b) = wrap_tables(event);
a.into_iter().chain(b) a.into_iter().chain(b)
}); })
.map(|event| highlighter.highlight(syntaxes, event));
html::push_html(&mut s, events); html::push_html(&mut s, events);
s s
@ -234,20 +250,40 @@ fn wrap_tables(event: Event<'_>) -> (Option<Event<'_>>, Option<Event<'_>>) {
} }
} }
#[derive(Default)]
struct SyntaxHighlighter<'a> { struct SyntaxHighlighter<'a> {
highlight: bool, highlight: bool,
is_rust: bool, is_rust: bool,
is_playground: bool,
is_editable: bool,
syntax: Option<&'a SyntaxReference>, syntax: Option<&'a SyntaxReference>,
playground_config: &'a Playground,
default_edition: Option<RustEdition>,
} }
impl<'a> SyntaxHighlighter<'a> { impl<'a> SyntaxHighlighter<'a> {
fn new(playground_config: &'a Playground, default_edition: Option<RustEdition>) -> Self {
SyntaxHighlighter {
highlight: false,
is_rust: false,
is_playground: false,
is_editable: false,
syntax: None,
playground_config,
default_edition,
}
}
fn highlight<'b>(&mut self, syntaxes: &'a SyntaxSet, event: Event<'b>) -> Event<'b> { fn highlight<'b>(&mut self, syntaxes: &'a SyntaxSet, event: Event<'b>) -> Event<'b> {
match event { match event {
Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(ref info))) => { Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(ref info))) => {
self.highlight = true; self.highlight = true;
let lang_name = info.split(',').next(); let mut classes: Vec<_> = info
if let Some(name) = lang_name { .replace(",", " ")
.split(' ')
.map(String::from)
.filter(|x| !x.is_empty())
.collect();
if let Some(name) = classes.first() {
// If we're given an empty name, or it is marked as // If we're given an empty name, or it is marked as
// plaintext, we shouldn't highlight it. // plaintext, we shouldn't highlight it.
if name.is_empty() if name.is_empty()
@ -270,19 +306,64 @@ impl<'a> SyntaxHighlighter<'a> {
self.is_rust = true; self.is_rust = true;
} }
} }
event if self.is_rust {
let ignore = classes.iter().find(|&x| x == "ignore").is_some();
let noplayground = classes.iter().find(|&x| x == "noplayground").is_some();
let noplaypen = classes.iter().find(|&x| x == "noplaypen").is_some();
let mdbook_runnable =
classes.iter().find(|&x| x == "mdbook-runnable").is_some();
// Enable playground
if (!ignore && !noplayground && !noplaypen) || mdbook_runnable {
self.is_editable = classes.iter().find(|&x| x == "editable").is_some();
let contains_e2015 =
classes.iter().find(|&x| x == "edition2015").is_some();
let contains_e2018 =
classes.iter().find(|&x| x == "edition2018").is_some();
let contains_e2021 =
classes.iter().find(|&x| x == "edition2021").is_some();
// if the user forced edition, we should not overwrite it
if !contains_e2015 && !contains_e2018 && !contains_e2021 {
match self.default_edition {
Some(RustEdition::E2015) => {
classes.push("edition2015".to_owned())
}
Some(RustEdition::E2018) => {
classes.push("edition2018".to_owned())
}
Some(RustEdition::E2021) => {
classes.push("edition2021".to_owned())
}
None => {}
}
}
self.is_playground = true;
return Event::Html(CowStr::from(format!(
r#"<pre class="playground"><code class="language-{}">"#,
classes.join(" ")
)));
}
}
} else { } else {
// We also don't perform auto-detection of languages, so we // We also don't perform auto-detection of languages, so we
// shouldn't highlight code blocks without lang tags. // shouldn't highlight code blocks without lang tags.
self.highlight = false; self.highlight = false;
event }
if classes.is_empty() {
Event::Html(CowStr::from("<pre><code>"))
} else {
Event::Html(CowStr::from(format!(
r#"<pre><code class="language-{}">"#,
classes.join(" ")
)))
} }
} }
Event::End(Tag::CodeBlock(CodeBlockKind::Fenced(_))) => { Event::End(Tag::CodeBlock(CodeBlockKind::Fenced(_))) => {
self.highlight = false; self.highlight = false;
self.is_rust = false; self.is_rust = false;
self.syntax = None; self.syntax = None;
event self.is_playground = false;
self.is_editable = false;
Event::Html(CowStr::from("</code></pre>"))
} }
Event::Text(ref code) if self.highlight => { Event::Text(ref code) if self.highlight => {
let mut gen = highlight::HtmlGenerator::new( let mut gen = highlight::HtmlGenerator::new(
@ -290,9 +371,19 @@ impl<'a> SyntaxHighlighter<'a> {
syntaxes, syntaxes,
ClassStyle::SpacedPrefixed { prefix: "syn-" }, ClassStyle::SpacedPrefixed { prefix: "syn-" },
); );
let needs_wrapped = self.is_rust
&& !(self.playground_config.editable && self.is_editable)
&& !code.contains("fn main")
&& !code.contains("quick_main!");
if needs_wrapped {
gen.parse_line("# fn main() {\n", self.is_rust);
}
for line in LinesWithEndings::from(code) { for line in LinesWithEndings::from(code) {
gen.parse_line(line, self.is_rust); gen.parse_line(line, self.is_rust);
} }
if needs_wrapped {
gen.parse_line("# }\n", self.is_rust);
}
Event::Html(CowStr::from(gen.finalize())) Event::Html(CowStr::from(gen.finalize()))
} }
_ => event, _ => event,
@ -300,41 +391,6 @@ impl<'a> SyntaxHighlighter<'a> {
} }
} }
struct EventQuoteConverter {
enabled: bool,
convert_text: bool,
}
impl EventQuoteConverter {
fn new(enabled: bool) -> Self {
EventQuoteConverter {
enabled,
convert_text: true,
}
}
fn convert<'a>(&mut self, event: Event<'a>) -> Event<'a> {
if !self.enabled {
return event;
}
match event {
Event::Start(Tag::CodeBlock(_)) => {
self.convert_text = false;
event
}
Event::End(Tag::CodeBlock(_)) => {
self.convert_text = true;
event
}
Event::Text(ref text) if self.convert_text => {
Event::Text(CowStr::from(convert_quotes_to_curly(text)))
}
_ => event,
}
}
}
fn clean_codeblock_headers(event: Event<'_>) -> Event<'_> { fn clean_codeblock_headers(event: Event<'_>) -> Event<'_> {
match event { match event {
Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(ref info))) => { Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(ref info))) => {
@ -389,6 +445,7 @@ mod tests {
} }
use super::super::render_markdown; use super::super::render_markdown;
use crate::config::{Playground, RustEdition};
#[test] #[test]
fn preserves_external_links() { fn preserves_external_links() {
@ -396,7 +453,9 @@ mod tests {
render_markdown( render_markdown(
"[example](https://www.rust-lang.org/)", "[example](https://www.rust-lang.org/)",
false, false,
&default_syntaxes() &default_syntaxes(),
&Playground::default(),
None,
), ),
"<p><a href=\"https://www.rust-lang.org/\">example</a></p>\n" "<p><a href=\"https://www.rust-lang.org/\">example</a></p>\n"
); );
@ -405,14 +464,22 @@ mod tests {
#[test] #[test]
fn it_can_adjust_markdown_links() { fn it_can_adjust_markdown_links() {
assert_eq!( assert_eq!(
render_markdown("[example](example.md)", false, &default_syntaxes()), render_markdown(
"[example](example.md)",
false,
&default_syntaxes(),
&Playground::default(),
None,
),
"<p><a href=\"example.html\">example</a></p>\n" "<p><a href=\"example.html\">example</a></p>\n"
); );
assert_eq!( assert_eq!(
render_markdown( render_markdown(
"[example_anchor](example.md#anchor)", "[example_anchor](example.md#anchor)",
false, false,
&default_syntaxes() &default_syntaxes(),
&Playground::default(),
None,
), ),
"<p><a href=\"example.html#anchor\">example_anchor</a></p>\n" "<p><a href=\"example.html#anchor\">example_anchor</a></p>\n"
); );
@ -422,7 +489,9 @@ mod tests {
render_markdown( render_markdown(
"[phantom data](foo.html#phantomdata)", "[phantom data](foo.html#phantomdata)",
false, false,
&default_syntaxes() &default_syntaxes(),
&Playground::default(),
None,
), ),
"<p><a href=\"foo.html#phantomdata\">phantom data</a></p>\n" "<p><a href=\"foo.html#phantomdata\">phantom data</a></p>\n"
); );
@ -441,13 +510,28 @@ mod tests {
</tbody></table> </tbody></table>
</div> </div>
"#.trim(); "#.trim();
assert_eq!(render_markdown(src, false), out); assert_eq!(
render_markdown(
src,
false,
&default_syntaxes(),
&Playground::default(),
None,
),
out
);
} }
#[test] #[test]
fn it_can_keep_quotes_straight() { fn it_can_keep_quotes_straight() {
assert_eq!( assert_eq!(
render_markdown("'one'", false, &default_syntaxes()), render_markdown(
"'one'",
false,
&default_syntaxes(),
&Playground::default(),
None,
),
"<p>'one'</p>\n" "<p>'one'</p>\n"
); );
} }
@ -465,7 +549,16 @@ mod tests {
</code></pre> </code></pre>
<p><code>'three'</code> four</p> <p><code>'three'</code> four</p>
"#; "#;
assert_eq!(render_markdown(input, true, &default_syntaxes()), expected); assert_eq!(
render_markdown(
input,
true,
&default_syntaxes(),
&Playground::default(),
None,
),
expected
);
} }
#[test] #[test]
@ -481,7 +574,7 @@ more text with spaces
"#; "#;
let expected = r#"<p>some text with spaces</p> let expected = r#"<p>some text with spaces</p>
<pre><code class="language-rust"><span class="syn-source syn-rust"><span class="syn-meta syn-function syn-rust"><span class="syn-meta syn-function syn-rust"><span class="syn-storage syn-type syn-function syn-rust">fn</span> </span><span class="syn-entity syn-name syn-function syn-rust">main</span></span><span class="syn-meta syn-function syn-rust"><span class="syn-meta syn-function syn-parameters syn-rust"><span class="syn-punctuation syn-section syn-parameters syn-begin syn-rust">(</span></span><span class="syn-meta syn-function syn-rust"><span class="syn-meta syn-function syn-parameters syn-rust"><span class="syn-punctuation syn-section syn-parameters syn-end syn-rust">)</span></span></span></span><span class="syn-meta syn-function syn-rust"> </span><span class="syn-meta syn-function syn-rust"><span class="syn-meta syn-block syn-rust"><span class="syn-punctuation syn-section syn-block syn-begin syn-rust">{</span> <pre class="playground"><code class="language-rust"><span class="syn-source syn-rust"><span class="syn-meta syn-function syn-rust"><span class="syn-meta syn-function syn-rust"><span class="syn-storage syn-type syn-function syn-rust">fn</span> </span><span class="syn-entity syn-name syn-function syn-rust">main</span></span><span class="syn-meta syn-function syn-rust"><span class="syn-meta syn-function syn-parameters syn-rust"><span class="syn-punctuation syn-section syn-parameters syn-begin syn-rust">(</span></span><span class="syn-meta syn-function syn-rust"><span class="syn-meta syn-function syn-parameters syn-rust"><span class="syn-punctuation syn-section syn-parameters syn-end syn-rust">)</span></span></span></span><span class="syn-meta syn-function syn-rust"> </span><span class="syn-meta syn-function syn-rust"><span class="syn-meta syn-block syn-rust"><span class="syn-punctuation syn-section syn-block syn-begin syn-rust">{</span>
<span class="syn-comment syn-line syn-double-slash syn-rust"><span class="syn-punctuation syn-definition syn-comment syn-rust">//</span> code inside is unchanged <span class="syn-comment syn-line syn-double-slash syn-rust"><span class="syn-punctuation syn-definition syn-comment syn-rust">//</span> code inside is unchanged
</span> </span>
@ -490,8 +583,26 @@ more text with spaces
</span></code></pre> </span></code></pre>
<p>more text with spaces</p> <p>more text with spaces</p>
"#; "#;
assert_eq!(render_markdown(input, false, &default_syntaxes()), expected); assert_eq!(
assert_eq!(render_markdown(input, true, &default_syntaxes()), expected); render_markdown(
input,
false,
&default_syntaxes(),
&Playground::default(),
None,
),
expected
);
assert_eq!(
render_markdown(
input,
true,
&default_syntaxes(),
&Playground::default(),
None,
),
expected
);
} }
#[test] #[test]
@ -501,10 +612,27 @@ more text with spaces
``` ```
"#; "#;
let expected = r#"<pre><code class="language-rust,no_run,should_panic,property_3"></code></pre> let expected = r#"<pre class="playground"><code class="language-rust no_run should_panic property_3"></code></pre>"#;
"#; assert_eq!(
assert_eq!(render_markdown(input, false, &default_syntaxes()), expected); render_markdown(
assert_eq!(render_markdown(input, true, &default_syntaxes()), expected); input,
false,
&default_syntaxes(),
&Playground::default(),
None,
),
expected
);
assert_eq!(
render_markdown(
input,
true,
&default_syntaxes(),
&Playground::default(),
None,
),
expected
);
} }
#[test] #[test]
@ -514,10 +642,27 @@ more text with spaces
``` ```
"#; "#;
let expected = r#"<pre><code class="language-rust,,,,,no_run,,,should_panic,,,,property_3"></code></pre> let expected = r#"<pre class="playground"><code class="language-rust no_run should_panic property_3"></code></pre>"#;
"#; assert_eq!(
assert_eq!(render_markdown(input, false, &default_syntaxes()), expected); render_markdown(
assert_eq!(render_markdown(input, true, &default_syntaxes()), expected); input,
false,
&default_syntaxes(),
&Playground::default(),
None,
),
expected
);
assert_eq!(
render_markdown(
input,
true,
&default_syntaxes(),
&Playground::default(),
None,
),
expected
);
} }
#[test] #[test]
@ -527,19 +672,164 @@ more text with spaces
``` ```
"#; "#;
let expected = r#"<pre><code class="language-rust"></code></pre> let expected = r#"<pre class="playground"><code class="language-rust"></code></pre>"#;
"#; assert_eq!(
assert_eq!(render_markdown(input, false, &default_syntaxes()), expected); render_markdown(
assert_eq!(render_markdown(input, true, &default_syntaxes()), expected); input,
false,
&default_syntaxes(),
&Playground::default(),
None,
),
expected
);
assert_eq!(
render_markdown(
input,
true,
&default_syntaxes(),
&Playground::default(),
None,
),
expected
);
}
// FIXME: Why are we doing this twice? It seems to be the same // These HTML strings get very, very long.
// input and assertions. // What I do is copy them out of here,
let input = r#" // paste them into a document.write() call in the JavaScript console,
```rust // and then I can read the HTML in the DOM inspector to see if it looks right.
``` #[test]
"#; fn add_playground() {
assert_eq!(render_markdown(input, false, &default_syntaxes()), expected); let inputs = [
assert_eq!(render_markdown(input, true, &default_syntaxes()), expected); ("```rust\nx()\n```",
"<pre class=\"playground\"><code class=\"language-rust\"><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span>\n</span></span></span></span><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-support syn-function syn-rust\">x</span><span class=\"syn-meta syn-group syn-rust\"><span class=\"syn-punctuation syn-section syn-group syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-group syn-rust\"><span class=\"syn-punctuation syn-section syn-group syn-end syn-rust\">)</span></span>\n\n</span></span></span><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n</span></span><span class=\"syn-source syn-rust\"></span></code></pre>"),
("```rust\nfn main() {}\n```",
"<pre class=\"playground\"><code class=\"language-rust\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span></span><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n\n</span></code></pre>"),
("```rust editable\nlet s = \"foo\n # bar\n\";\n```",
"<pre class=\"playground\"><code class=\"language-rust editable\"><span class=\"syn-source syn-rust\"><span class=\"syn-storage syn-type syn-rust\">let</span> s <span class=\"syn-keyword syn-operator syn-assignment syn-rust\">=</span> <span class=\"syn-string syn-quoted syn-double syn-rust\"><span class=\"syn-punctuation syn-definition syn-string syn-begin syn-rust\">&quot;</span>foo\n\n</span></span><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-string syn-quoted syn-double syn-rust\"> bar\n</span></span></span><span class=\"syn-source syn-rust\"><span class=\"syn-string syn-quoted syn-double syn-rust\"><span class=\"syn-punctuation syn-definition syn-string syn-end syn-rust\">&quot;</span></span><span class=\"syn-punctuation syn-terminator syn-rust\">;</span>\n\n</span></code></pre>"),
("```rust editable\nlet s = \"foo\n ## bar\n\";\n```",
"<pre class=\"playground\"><code class=\"language-rust editable\"><span class=\"syn-source syn-rust\"><span class=\"syn-storage syn-type syn-rust\">let</span> s <span class=\"syn-keyword syn-operator syn-assignment syn-rust\">=</span> <span class=\"syn-string syn-quoted syn-double syn-rust\"><span class=\"syn-punctuation syn-definition syn-string syn-begin syn-rust\">&quot;</span>foo\n\n</span></span><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-string syn-quoted syn-double syn-rust\"> # bar\n</span></span></span><span class=\"syn-source syn-rust\"><span class=\"syn-string syn-quoted syn-double syn-rust\"><span class=\"syn-punctuation syn-definition syn-string syn-end syn-rust\">&quot;</span></span><span class=\"syn-punctuation syn-terminator syn-rust\">;</span>\n\n</span></code></pre>"),
("```rust editable\nlet s = \"foo\n # bar\n#\n\";\n```",
"<pre class=\"playground\"><code class=\"language-rust editable\"><span class=\"syn-source syn-rust\"><span class=\"syn-storage syn-type syn-rust\">let</span> s <span class=\"syn-keyword syn-operator syn-assignment syn-rust\">=</span> <span class=\"syn-string syn-quoted syn-double syn-rust\"><span class=\"syn-punctuation syn-definition syn-string syn-begin syn-rust\">&quot;</span>foo\n\n</span></span><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-string syn-quoted syn-double syn-rust\"> bar\n</span></span></span><span class=\"syn-source syn-rust\"><span class=\"syn-string syn-quoted syn-double syn-rust\"></span></span><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-string syn-quoted syn-double syn-rust\">\n</span></span></span><span class=\"syn-source syn-rust\"><span class=\"syn-string syn-quoted syn-double syn-rust\"><span class=\"syn-punctuation syn-definition syn-string syn-end syn-rust\">&quot;</span></span><span class=\"syn-punctuation syn-terminator syn-rust\">;</span>\n\n</span></code></pre>"),
("```rust ignore\nlet s = \"foo\n # bar\n\";\n```",
"<pre><code class=\"language-rust ignore\"><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span>\n</span></span></span></span><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-storage syn-type syn-rust\">let</span> s <span class=\"syn-keyword syn-operator syn-assignment syn-rust\">=</span> <span class=\"syn-string syn-quoted syn-double syn-rust\"><span class=\"syn-punctuation syn-definition syn-string syn-begin syn-rust\">&quot;</span>foo\n\n</span></span></span></span><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-string syn-quoted syn-double syn-rust\"> bar\n</span></span></span></span></span><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-string syn-quoted syn-double syn-rust\"><span class=\"syn-punctuation syn-definition syn-string syn-end syn-rust\">&quot;</span></span><span class=\"syn-punctuation syn-terminator syn-rust\">;</span>\n\n</span></span></span><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n</span></span><span class=\"syn-source syn-rust\"></span></code></pre>"),
("```rust editable\n#![no_std]\nlet s = \"foo\";\n #[some_attr]\n```",
"<pre class=\"playground\"><code class=\"language-rust editable\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-annotation syn-rust\"><span class=\"syn-punctuation syn-definition syn-annotation syn-rust\">#!</span><span class=\"syn-punctuation syn-section syn-group syn-begin syn-rust\">[</span><span class=\"syn-variable syn-annotation syn-rust\">no_std</span><span class=\"syn-punctuation syn-section syn-group syn-end syn-rust\">]</span></span>\n\n<span class=\"syn-storage syn-type syn-rust\">let</span> s <span class=\"syn-keyword syn-operator syn-assignment syn-rust\">=</span> <span class=\"syn-string syn-quoted syn-double syn-rust\"><span class=\"syn-punctuation syn-definition syn-string syn-begin syn-rust\">&quot;</span>foo<span class=\"syn-punctuation syn-definition syn-string syn-end syn-rust\">&quot;</span></span><span class=\"syn-punctuation syn-terminator syn-rust\">;</span>\n\n <span class=\"syn-meta syn-annotation syn-rust\"><span class=\"syn-punctuation syn-definition syn-annotation syn-rust\">#</span><span class=\"syn-punctuation syn-section syn-group syn-begin syn-rust\">[</span><span class=\"syn-variable syn-annotation syn-rust\">some_attr</span><span class=\"syn-punctuation syn-section syn-group syn-end syn-rust\">]</span></span>\n\n</span></code></pre>"),
];
for (src, should_be) in &inputs {
let got = render_markdown(
src,
false,
&default_syntaxes(),
&Playground {
editable: true,
..Playground::default()
},
None,
);
assert_eq!(&*got, *should_be);
}
}
#[test]
fn add_playground_edition2015() {
let inputs = [
("```rust\nx()\n```",
"<pre class=\"playground\"><code class=\"language-rust edition2015\"><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span>\n</span></span></span></span><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-support syn-function syn-rust\">x</span><span class=\"syn-meta syn-group syn-rust\"><span class=\"syn-punctuation syn-section syn-group syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-group syn-rust\"><span class=\"syn-punctuation syn-section syn-group syn-end syn-rust\">)</span></span>\n\n</span></span></span><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n</span></span><span class=\"syn-source syn-rust\"></span></code></pre>"),
("```rust\nfn main() {}\n```",
"<pre class=\"playground\"><code class=\"language-rust edition2015\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span></span><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n\n</span></code></pre>"),
("```rust edition2015\nfn main() {}\n```",
"<pre class=\"playground\"><code class=\"language-rust edition2015\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span></span><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n\n</span></code></pre>"),
("```rust edition2018\nfn main() {}\n```",
"<pre class=\"playground\"><code class=\"language-rust edition2018\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span></span><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n\n</span></code></pre>"),
];
for (src, should_be) in &inputs {
let got = render_markdown(
src,
false,
&default_syntaxes(),
&Playground {
editable: true,
..Playground::default()
},
Some(RustEdition::E2015),
);
assert_eq!(&*got, *should_be);
}
}
#[test]
fn add_playground_edition2018() {
let inputs = [
("```rust\nx()\n```",
"<pre class=\"playground\"><code class=\"language-rust edition2018\"><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span>\n</span></span></span></span><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-support syn-function syn-rust\">x</span><span class=\"syn-meta syn-group syn-rust\"><span class=\"syn-punctuation syn-section syn-group syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-group syn-rust\"><span class=\"syn-punctuation syn-section syn-group syn-end syn-rust\">)</span></span>\n\n</span></span></span><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n</span></span><span class=\"syn-source syn-rust\"></span></code></pre>"),
("```rust\nfn main() {}\n```",
"<pre class=\"playground\"><code class=\"language-rust edition2018\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span></span><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n\n</span></code></pre>"),
("```rust edition2015\nfn main() {}\n```",
"<pre class=\"playground\"><code class=\"language-rust edition2015\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span></span><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n\n</span></code></pre>"),
("```rust edition2018\nfn main() {}\n```",
"<pre class=\"playground\"><code class=\"language-rust edition2018\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span></span><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n\n</span></code></pre>"),
];
for (src, should_be) in &inputs {
let got = render_markdown(
src,
false,
&default_syntaxes(),
&Playground {
editable: true,
..Playground::default()
},
Some(RustEdition::E2018),
);
assert_eq!(&*got, *should_be);
}
}
#[test]
fn add_playground_edition2021() {
let inputs = [
("```rust\nx()\n```",
"<pre class=\"playground\"><code class=\"language-rust edition2021\"><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span>\n</span></span></span></span><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-support syn-function syn-rust\">x</span><span class=\"syn-meta syn-group syn-rust\"><span class=\"syn-punctuation syn-section syn-group syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-group syn-rust\"><span class=\"syn-punctuation syn-section syn-group syn-end syn-rust\">)</span></span>\n\n</span></span></span><span class=\"boring\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n</span></span><span class=\"syn-source syn-rust\"></span></code></pre>"),
("```rust\nfn main() {}\n```",
"<pre class=\"playground\"><code class=\"language-rust edition2021\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span></span><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n\n</span></code></pre>"),
("```rust edition2015\nfn main() {}\n```",
"<pre class=\"playground\"><code class=\"language-rust edition2015\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span></span><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n\n</span></code></pre>"),
("```rust edition2018\nfn main() {}\n```",
"<pre class=\"playground\"><code class=\"language-rust edition2018\"><span class=\"syn-source syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-storage syn-type syn-function syn-rust\">fn</span> </span><span class=\"syn-entity syn-name syn-function syn-rust\">main</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-begin syn-rust\">(</span></span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-function syn-parameters syn-rust\"><span class=\"syn-punctuation syn-section syn-parameters syn-end syn-rust\">)</span></span></span></span><span class=\"syn-meta syn-function syn-rust\"> </span><span class=\"syn-meta syn-function syn-rust\"><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-begin syn-rust\">{</span></span><span class=\"syn-meta syn-block syn-rust\"><span class=\"syn-punctuation syn-section syn-block syn-end syn-rust\">}</span></span></span>\n\n</span></code></pre>"),
];
for (src, should_be) in &inputs {
let got = render_markdown(
src,
false,
&default_syntaxes(),
&Playground {
editable: true,
..Playground::default()
},
Some(RustEdition::E2021),
);
assert_eq!(&*got, *should_be);
}
}
#[test]
fn no_add_playground_to_other_languages() {
let inputs = [
("```html,testhtml\n<p>\n```",
"<pre><code class=\"language-html testhtml\"><span class=\"syn-text syn-html syn-basic\"><span class=\"syn-meta syn-tag syn-block syn-any syn-html\"><span class=\"syn-punctuation syn-definition syn-tag syn-begin syn-html\">&lt;</span><span class=\"syn-entity syn-name syn-tag syn-block syn-any syn-html\">p</span><span class=\"syn-punctuation syn-definition syn-tag syn-end syn-html\">&gt;</span></span>\n</span></code></pre>"),
("```js es7\nf()\n```",
"<pre><code class=\"language-js es7\"><span class=\"syn-source syn-js\"><span class=\"syn-meta syn-function-call syn-without-arguments syn-js\"><span class=\"syn-variable syn-function syn-js\">f</span><span class=\"syn-meta syn-group syn-braces syn-round syn-function syn-arguments syn-js\">()</span></span>\n</span></code></pre>"),
];
for (src, should_be) in &inputs {
let got = render_markdown(
src,
false,
&default_syntaxes(),
&Playground {
editable: true,
..Playground::default()
},
Some(RustEdition::E2021),
);
assert_eq!(&*got, *should_be);
}
} }
} }