diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs
index 91f75676..f13f39a1 100644
--- a/src/renderer/html_handlebars/hbs_renderer.rs
+++ b/src/renderer/html_handlebars/hbs_renderer.rs
@@ -6,7 +6,6 @@ use crate::renderer::{RenderContext, Renderer};
use crate::theme::{self, playpen_editor, Theme};
use crate::utils;
-use std::borrow::Cow;
use std::collections::BTreeMap;
use std::collections::HashMap;
use std::fs;
@@ -585,7 +584,6 @@ fn fix_code_blocks(html: &str) -> String {
}
fn add_playpen_pre(html: &str, playpen_config: &Playpen) -> String {
- let boring_line_regex = Regex::new(r"^(\s*)#(#|.)(.*)$").unwrap();
let regex = Regex::new(r##"((?s)]?class="([^"]+)".*?>(.*?))"##).unwrap();
regex
.replace_all(html, |caps: &Captures<'_>| {
@@ -599,45 +597,21 @@ fn add_playpen_pre(html: &str, playpen_config: &Playpen) -> String {
|| classes.contains("mdbook-runnable")
{
// wrap the contents in an external pre block
- format!("
{}",
- classes,
- {
- let content: Cow{}", text)
+ } else {
+ // we need to inject our own main
+ let (attrs, code) = partition_source(code);
- format!("\n# #![allow(unused_variables)]\n{}#fn main() {{\n{}#}}",
- attrs, code
- ).into()
- };
- let mut prev_line_hidden = false;
- let mut result = String::with_capacity(content.len());
- for line in content.lines() {
- if let Some(caps) = boring_line_regex.captures(line) {
- if !prev_line_hidden && &caps[2] != "#" {
- result += "";
- prev_line_hidden = true;
- }
- result += &caps[1];
- if &caps[2] != " " { result += &caps[2]; }
- result += &caps[3];
- } else {
- if prev_line_hidden {
- result += "";
- prev_line_hidden = false;
- }
- result += line;
- }
- result += "\n";
- }
- result
- }
- )
+ format!(
+ "\n# \
+ #![allow(unused_variables)]\n{}#fn main() {{\n{}#}}",
+ classes, attrs, code
+ )
+ }
} else {
// not language-rust, so no-op
text.to_owned()
@@ -713,22 +687,4 @@ mod tests {
assert_eq!(got, should_be);
}
}
-
- #[test]
- fn add_playpen() {
- let inputs = [
- ("x()",
- "\n#![allow(unused_variables)]\nfn main() {\nx()\n}\n"),
- ("fn main() {}",
- "fn main() {}\n"),
- ("let s = \"foo\n # bar\n\";",
- "let s = \"foo\n bar\n\";\n"),
- ("let s = \"foo\n ## bar\n\";",
- "let s = \"foo\n # bar\n\";\n"),
- ];
- for (src, should_be) in &inputs {
- let got = add_playpen_pre(src, &Playpen { editable: true, ..Playpen::default() });
- assert_eq!(&*got, *should_be);
- }
- }
}
diff --git a/src/theme/book.js b/src/theme/book.js
index 2c2ade22..263e8ad0 100644
--- a/src/theme/book.js
+++ b/src/theme/book.js
@@ -161,34 +161,72 @@ function playpen_text(playpen) {
Array.from(document.querySelectorAll("code.language-rust")).forEach(function (block) {
- var lines = Array.from(block.querySelectorAll('.boring'));
+ var code_block = block;
+ var pre_block = block.parentNode;
+ // hide lines
+ var lines = code_block.innerHTML.split("\n");
+ var first_non_hidden_line = false;
+ var lines_hidden = false;
+ var trimmed_line = "";
+
+ for (var n = 0; n < lines.length; n++) {
+ trimmed_line = lines[n].trim();
+ if (trimmed_line[0] == hiding_character && trimmed_line[1] != hiding_character) {
+ if (first_non_hidden_line) {
+ lines[n] = "" + "\n" + lines[n].replace(/(\s*)# ?/, "$1") + "";
+ }
+ else {
+ lines[n] = "" + lines[n].replace(/(\s*)# ?/, "$1") + "\n" + "";
+ }
+ lines_hidden = true;
+ }
+ else if (first_non_hidden_line) {
+ lines[n] = "\n" + lines[n];
+ }
+ else {
+ first_non_hidden_line = true;
+ }
+ if (trimmed_line[0] == hiding_character && trimmed_line[1] == hiding_character) {
+ lines[n] = lines[n].replace("##", "#")
+ }
+ }
+ code_block.innerHTML = lines.join("");
+
// If no lines were hidden, return
- if (!lines.length) { return; }
- block.classList.add("hide-boring");
+ if (!lines_hidden) { return; }
var buttons = document.createElement('div');
buttons.className = 'buttons';
buttons.innerHTML = "";
// add expand button
- var pre_block = block.parentNode;
pre_block.insertBefore(buttons, pre_block.firstChild);
pre_block.querySelector('.buttons').addEventListener('click', function (e) {
if (e.target.classList.contains('fa-expand')) {
+ var lines = pre_block.querySelectorAll('span.hidden');
+
e.target.classList.remove('fa-expand');
e.target.classList.add('fa-compress');
e.target.title = 'Hide lines';
e.target.setAttribute('aria-label', e.target.title);
- block.classList.remove('hide-boring');
+ Array.from(lines).forEach(function (line) {
+ line.classList.remove('hidden');
+ line.classList.add('unhidden');
+ });
} else if (e.target.classList.contains('fa-compress')) {
+ var lines = pre_block.querySelectorAll('span.unhidden');
+
e.target.classList.remove('fa-compress');
e.target.classList.add('fa-expand');
e.target.title = 'Show hidden lines';
e.target.setAttribute('aria-label', e.target.title);
- block.classList.add('hide-boring');
+ Array.from(lines).forEach(function (line) {
+ line.classList.remove('unhidden');
+ line.classList.add('hidden');
+ });
}
});
});
diff --git a/src/theme/css/general.css b/src/theme/css/general.css
index 2f1a0083..b45f90fb 100644
--- a/src/theme/css/general.css
+++ b/src/theme/css/general.css
@@ -22,9 +22,8 @@ code {
.left { float: left; }
.right { float: right; }
-.boring { opacity: 0.6; }
-.hide-boring .boring { display: none; }
.hidden { display: none; }
+.play-button.hidden { display: none; }
h2, h3 { margin-top: 2.5em; }
h4, h5 { margin-top: 2em; }