From 274c22c702d1fd3ba7390423c70edbaf921be1bc Mon Sep 17 00:00:00 2001 From: Kevin K Date: Fri, 20 Nov 2015 08:41:16 -0500 Subject: [PATCH 01/15] adds version for deps to make cargo installable --- Cargo.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cf348dd3..42d963a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,13 +14,13 @@ exclude = [ ] [dependencies] -clap = "*" -handlebars = "*" -rustc-serialize = "*" -pulldown-cmark = "*" +clap = "~1.5.3" +handlebars = "=0.11.2" +rustc-serialize = "~0.3.16" +pulldown-cmark = "~0.0.3" [dev-dependencies] -tempdir = "*" +tempdir = "~0.3.4" [features] default = ["output"] From d376b0663af3f4ce4ca86caee5836efc10cdf4f1 Mon Sep 17 00:00:00 2001 From: Mathieu David Date: Fri, 11 Dec 2015 22:17:05 +0100 Subject: [PATCH 02/15] Bumped version to 0.0.4 (after publishing 0.0.3 to crates.io) + updated README to use cargo install for the installation --- Cargo.toml | 2 +- README.md | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 42d963a5..e8b90d08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mdbook" -version = "0.0.3" +version = "0.0.4" authors = ["Mathieu David "] description = "create books from markdown files (like Gitbook)" documentation = "http://azerupi.github.io/mdBook/index.html" diff --git a/README.md b/README.md index 67963d95..ed5880e7 100644 --- a/README.md +++ b/README.md @@ -13,14 +13,10 @@ To have an idea of what a rendered book looks like,take a look at the [**Documen ## Installation ``` -git clone --depth=1 https://github.com/azerupi/mdBook.git -cd mdBook -cargo build --release +cargo install mdbook ``` -The executable `mdbook` will be in the `./target/release` folder, this should be added to the path. - -If you want to regenerate the css (stylesheet), make sure that you installed `stylus` and `nib` from `npm` because it is used to compile the stylesheets +If you want to regenerate the css (stylesheet), clone the git repo locally and make sure that you installed `stylus` and `nib` from `npm` because it is used to compile the stylesheets Install [node.js](https://nodejs.org/en/) From 4ca6693a482bd8b1db47850cee62c01a1e73d94e Mon Sep 17 00:00:00 2001 From: Mathieu David Date: Tue, 15 Dec 2015 18:58:34 +0100 Subject: [PATCH 03/15] Update handlebars from 0.11.x to 0.12.x --- Cargo.toml | 2 +- .../html_handlebars/helpers/navigation.rs | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e8b90d08..f39e23f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ exclude = [ [dependencies] clap = "~1.5.3" -handlebars = "=0.11.2" +handlebars = "~0.12.0" rustc-serialize = "~0.3.16" pulldown-cmark = "~0.0.3" diff --git a/src/renderer/html_handlebars/helpers/navigation.rs b/src/renderer/html_handlebars/helpers/navigation.rs index a693f9ca..8fa2f658 100644 --- a/src/renderer/html_handlebars/helpers/navigation.rs +++ b/src/renderer/html_handlebars/helpers/navigation.rs @@ -27,7 +27,7 @@ pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext // Decode json format let decoded: Vec> = match json::decode(&chapters.to_string()) { Ok(data) => data, - Err(_) => return Err(RenderError{ desc: "Could not decode the JSON data"}), + Err(_) => return Err(RenderError{ desc: "Could not decode the JSON data".to_owned()}), }; let mut previous: Option> = None; @@ -55,7 +55,7 @@ pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext }, None => { debug!("[*]: No title found for chapter"); - return Err(RenderError{ desc: "No title found for chapter in JSON data" }) + return Err(RenderError{ desc: "No title found for chapter in JSON data".to_owned() }) } }; @@ -68,10 +68,10 @@ pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext match path.to_str() { Some(p) => { previous_chapter.insert("link".to_owned(), p.to_json()); }, - None => return Err(RenderError{ desc: "Link could not be converted to str" }) + None => return Err(RenderError{ desc: "Link could not be converted to str".to_owned() }) } }, - None => return Err(RenderError{ desc: "No path found for chapter in JSON data" }) + None => return Err(RenderError{ desc: "No path found for chapter in JSON data".to_owned() }) } debug!("[*]: Inject in context"); @@ -84,7 +84,7 @@ pub fn previous(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext Some(t) => { try!(t.render(&updated_context, r, rc)); }, - None => return Err(RenderError{ desc: "Error with the handlebars template" }) + None => return Err(RenderError{ desc: "Error with the handlebars template".to_owned() }) } } @@ -124,7 +124,7 @@ pub fn next(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> // Decode json format let decoded: Vec> = match json::decode(&chapters.to_string()) { Ok(data) => data, - Err(_) => return Err(RenderError{ desc: "Could not decode the JSON data"}), + Err(_) => return Err(RenderError{ desc: "Could not decode the JSON data".to_owned() }), }; let mut previous: Option> = None; @@ -140,7 +140,7 @@ pub fn next(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> let previous_path = match previous.get("path") { Some(p) => p, - None => return Err(RenderError{ desc: "No path found for chapter in JSON data"}) + None => return Err(RenderError{ desc: "No path found for chapter in JSON data".to_owned() }) }; if previous_path == ¤t { @@ -155,7 +155,7 @@ pub fn next(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> debug!("[*]: Inserting title: {}", n); next_chapter.insert("title".to_owned(), n.to_json()); } - None => return Err(RenderError{ desc: "No title found for chapter in JSON data"}) + None => return Err(RenderError{ desc: "No title found for chapter in JSON data".to_owned() }) } @@ -164,7 +164,7 @@ pub fn next(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> match link.to_str() { Some(l) => { next_chapter.insert("link".to_owned(), l.to_json()); }, - None => return Err(RenderError{ desc: "Link could not converted to str"}) + None => return Err(RenderError{ desc: "Link could not converted to str".to_owned() }) } debug!("[*]: Inject in context"); @@ -178,7 +178,7 @@ pub fn next(c: &Context, _h: &Helper, r: &Handlebars, rc: &mut RenderContext) -> Some(t) => { try!(t.render(&updated_context, r, rc)); }, - None => return Err(RenderError{ desc: "Error with the handlebars template" }) + None => return Err(RenderError{ desc: "Error with the handlebars template".to_owned() }) } break From 6bcc592ed9c9d5f883c114b1f06f9563c7c31f52 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 15 Dec 2015 13:55:23 -0500 Subject: [PATCH 04/15] Implement 'mdbook test' Fixes #69 --- src/bin/mdbook.rs | 12 ++++++++++++ src/book/mdbook.rs | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/bin/mdbook.rs b/src/bin/mdbook.rs index 027fbb85..9d1db00a 100644 --- a/src/bin/mdbook.rs +++ b/src/bin/mdbook.rs @@ -33,6 +33,8 @@ fn main() { .arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when ommitted)'")) .subcommand(SubCommand::with_name("watch") .about("Watch the files for changes")) + .subcommand(SubCommand::with_name("test") + .about("Test that code samples compile")) .get_matches(); // Check which subcomamnd the user ran... @@ -40,6 +42,7 @@ fn main() { ("init", Some(sub_matches)) => init(sub_matches), ("build", Some(sub_matches)) => build(sub_matches), ("watch", _) => unimplemented!(), + ("test", Some(sub_matches)) => test(sub_matches), (_, _) => unreachable!() }; @@ -104,6 +107,15 @@ fn build(args: &ArgMatches) -> Result<(), Box> { Ok(()) } +fn test(args: &ArgMatches) -> Result<(), Box> { + let book_dir = get_book_dir(args); + let mut book = MDBook::new(&book_dir).read_config(); + + try!(book.test()); + + Ok(()) +} + fn get_book_dir(args: &ArgMatches) -> PathBuf { if let Some(dir) = args.value_of("dir") { // Check if path is relative from current dir, or absolute... diff --git a/src/book/mdbook.rs b/src/book/mdbook.rs index e2ee2581..02430414 100644 --- a/src/book/mdbook.rs +++ b/src/book/mdbook.rs @@ -1,7 +1,10 @@ use std::path::{Path, PathBuf}; use std::fs::{self, File}; -use std::io::Write; use std::error::Error; +use std::io; +use std::io::Write; +use std::io::ErrorKind; +use std::process::Command; use {BookConfig, BookItem, theme, parse, utils}; use book::BookItems; @@ -257,6 +260,39 @@ impl MDBook { self } + pub fn test(&mut self) -> Result<(), Box> { + // read in the chapters + try!(self.parse_summary()); + for item in self.iter() { + + match *item { + BookItem::Chapter(_, ref ch) => { + if ch.path != PathBuf::new() { + + let path = self.get_src().join(&ch.path); + + println!("[*]: Testing file: {:?}", path); + + let output_result = Command::new("rustdoc") + .arg(&path) + .arg("--test") + .output(); + let output = try!(output_result); + + if !output.status.success() { + return Err(Box::new(io::Error::new(ErrorKind::Other, format!( + "{}\n{}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr)))) as Box); + } + } + } + _ => {} + } + } + Ok(()) + } + pub fn set_dest(mut self, dest: &Path) -> Self { // Handle absolute and relative paths From f1cd9f54c243ac1da136c3cbddf6b6cf622deae7 Mon Sep 17 00:00:00 2001 From: Mathieu David Date: Thu, 17 Dec 2015 17:34:24 +0100 Subject: [PATCH 05/15] Fixes rust-lang/book#29 where the navigation arrow for next chapter was displayed on top of the scroll bar making it unusable --- src/theme/book.css | 2 +- src/theme/stylus/nav-icons.styl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/theme/book.css b/src/theme/book.css index 102b1762..c6e2546d 100644 --- a/src/theme/book.css +++ b/src/theme/book.css @@ -222,7 +222,7 @@ h3 { left: 0; } .next { - right: 0; + right: 15px; } .theme-popup { position: fixed; diff --git a/src/theme/stylus/nav-icons.styl b/src/theme/stylus/nav-icons.styl index 2ffb93f7..211db682 100644 --- a/src/theme/stylus/nav-icons.styl +++ b/src/theme/stylus/nav-icons.styl @@ -20,4 +20,4 @@ .mobile-nav-chapters { display: none } .nav-chapters:hover { text-decoration: none } .previous { left: 0 } -.next { right: 0 } +.next { right: 15px } From b1265862c76df34bc8feec18a3db74be3d7d82db Mon Sep 17 00:00:00 2001 From: mdinger Date: Tue, 22 Dec 2015 16:30:05 -0500 Subject: [PATCH 06/15] Generalize inline code to all themes --- src/theme/book.css | 32 +++++++++++++++++++++++++++++++ src/theme/highlight.css | 8 -------- src/theme/stylus/themes/base.styl | 8 ++++++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/theme/book.css b/src/theme/book.css index c6e2546d..93d4c9f0 100644 --- a/src/theme/book.css +++ b/src/theme/book.css @@ -270,9 +270,17 @@ h3 { } } .light { +/* Inline code */ color: #333; background-color: #fff; } +.light :not(pre) > .hljs { + display: inline-block; + vertical-align: middle; + padding: 0.1em 0.3em; + -webkit-border-radius: 3px; + border-radius: 3px; +} .light .sidebar { background-color: #fafafa; color: #364149; @@ -318,9 +326,17 @@ h3 { background-color: #e6e6e6; } .coal { +/* Inline code */ color: #98a3ad; background-color: #141617; } +.coal :not(pre) > .hljs { + display: inline-block; + vertical-align: middle; + padding: 0.1em 0.3em; + -webkit-border-radius: 3px; + border-radius: 3px; +} .coal .sidebar { background-color: #292c2f; color: #a1adb8; @@ -366,9 +382,17 @@ h3 { background-color: #1f2124; } .navy { +/* Inline code */ color: #bcbdd0; background-color: #161923; } +.navy :not(pre) > .hljs { + display: inline-block; + vertical-align: middle; + padding: 0.1em 0.3em; + -webkit-border-radius: 3px; + border-radius: 3px; +} .navy .sidebar { background-color: #282d3f; color: #c8c9db; @@ -414,9 +438,17 @@ h3 { background-color: #282e40; } .rust { +/* Inline code */ color: #262625; background-color: #e1e1db; } +.rust :not(pre) > .hljs { + display: inline-block; + vertical-align: middle; + padding: 0.1em 0.3em; + -webkit-border-radius: 3px; + border-radius: 3px; +} .rust .sidebar { background-color: #3b2e2a; color: #c8c9db; diff --git a/src/theme/highlight.css b/src/theme/highlight.css index 616dba0d..61681a2b 100644 --- a/src/theme/highlight.css +++ b/src/theme/highlight.css @@ -10,14 +10,6 @@ -webkit-text-size-adjust: none; } -/* Inline code */ -:not(pre) > .hljs { - display: inline-block; - vertical-align: middle; - padding: 0.1em 0.3em; - border-radius: 3px; -} - /* Atelier-Dune Comment */ .hljs-comment { diff --git a/src/theme/stylus/themes/base.styl b/src/theme/stylus/themes/base.styl index fdbcc9dc..e222fe4a 100644 --- a/src/theme/stylus/themes/base.styl +++ b/src/theme/stylus/themes/base.styl @@ -1,4 +1,12 @@ .{unquote($theme-name)} { + /* Inline code */ + :not(pre) > .hljs { + display: inline-block; + vertical-align: middle; + padding: 0.1em 0.3em; + border-radius: 3px; + } + color: $fg background-color: $bg From 1de00f9cd7be495195ea177c9c2515e708294f9b Mon Sep 17 00:00:00 2001 From: asolove Date: Sat, 26 Dec 2015 20:45:50 -0700 Subject: [PATCH 07/15] On page load, scroll sidebar to active section. --- src/theme/book.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/theme/book.js b/src/theme/book.js index 0754fee7..b07c9929 100644 --- a/src/theme/book.js +++ b/src/theme/book.js @@ -50,6 +50,13 @@ $( document ).ready(function() { }); + // Scroll sidebar to current active section + var activeSection = sidebar.find(".active"); + if(activeSection.length) { + sidebar.scrollTop(activeSection.offset().top); + } + + // Print button $("#print-button").click(function(){ var printWindow = window.open("print.html"); From 0ffd638904a43a12ef9d8f7672087251993c5f01 Mon Sep 17 00:00:00 2001 From: asolove Date: Sun, 27 Dec 2015 14:10:13 -0700 Subject: [PATCH 08/15] Add newlines back in to generated index.html files. --- src/renderer/html_handlebars/hbs_renderer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 6055b27f..3acb93cd 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -114,7 +114,7 @@ impl Renderer for HtmlHandlebars { // This could cause a problem when someone displays code containing // on the front page, however this case should be very very rare... - content = content.lines().filter(|line| !line.contains(" Date: Sun, 27 Dec 2015 14:24:42 -0700 Subject: [PATCH 09/15] Fix 0ffd638 with smarter way to join with linebreaks. --- src/renderer/html_handlebars/hbs_renderer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 3acb93cd..f45079cb 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -114,7 +114,7 @@ impl Renderer for HtmlHandlebars { // This could cause a problem when someone displays code containing // on the front page, however this case should be very very rare... - content = content.lines().filter(|line| !line.contains(" Date: Sun, 27 Dec 2015 15:17:59 -0700 Subject: [PATCH 10/15] Add anchors around all headers in the content. - Just uses the header's text as its anchor name. Spaces work. Scrolling to the anchor works even when the anchor is added after the dom loads. - Adjust theme css to only style links, not tags used as anchors. --- src/theme/book.css | 8 ++++---- src/theme/book.js | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/theme/book.css b/src/theme/book.css index 93d4c9f0..c73eb4a0 100644 --- a/src/theme/book.css +++ b/src/theme/book.css @@ -315,7 +315,7 @@ h3 { .light .mobile-nav-chapters { background-color: #fafafa; } -.light .content a { +.light .content a:link { color: #4183c4; } .light .theme-popup { @@ -371,7 +371,7 @@ h3 { .coal .mobile-nav-chapters { background-color: #292c2f; } -.coal .content a { +.coal .content a:link { color: #2b79a2; } .coal .theme-popup { @@ -427,7 +427,7 @@ h3 { .navy .mobile-nav-chapters { background-color: #282d3f; } -.navy .content a { +.navy .content a:link { color: #2b79a2; } .navy .theme-popup { @@ -483,7 +483,7 @@ h3 { .rust .mobile-nav-chapters { background-color: #3b2e2a; } -.rust .content a { +.rust .content a:link { color: #2b79a2; } .rust .theme-popup { diff --git a/src/theme/book.js b/src/theme/book.js index b07c9929..3a7ce712 100644 --- a/src/theme/book.js +++ b/src/theme/book.js @@ -28,6 +28,15 @@ $( document ).ready(function() { var html = $("html"); var sidebar = $("#sidebar"); var page_wrapper = $("#page-wrapper"); + var content = $("#content"); + + + // Add anchors for all content headers + content.find("h1, h2, h3, h4, h5").wrap(function(){ + var wrapper = $(""); + wrapper.attr("name", $(this).text()); + return wrapper; + }); // Toggle sidebar From 4dfa15cffa5ca8cb250a1e07a4dae47606960c79 Mon Sep 17 00:00:00 2001 From: asolove Date: Sun, 27 Dec 2015 21:13:31 -0700 Subject: [PATCH 11/15] Update .styl file. Ran the compile and it results in exactly what I did by hand, d'oh. --- src/theme/stylus/themes/base.styl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/theme/stylus/themes/base.styl b/src/theme/stylus/themes/base.styl index e222fe4a..b9a6d893 100644 --- a/src/theme/stylus/themes/base.styl +++ b/src/theme/stylus/themes/base.styl @@ -51,7 +51,7 @@ background-color: $sidebar-bg } - .content a { + .content a:link { color: $links } From 0dd6a17187d20af07a6dcac44b8a600127c2b522 Mon Sep 17 00:00:00 2001 From: Mathieu David Date: Mon, 28 Dec 2015 16:39:14 +0100 Subject: [PATCH 12/15] Fix some small things in javascript --- src/theme/book.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/theme/book.js b/src/theme/book.js index b07c9929..13aaed88 100644 --- a/src/theme/book.js +++ b/src/theme/book.js @@ -8,7 +8,7 @@ $( document ).ready(function() { // Set theme var theme = localStorage.getItem('theme'); - if (theme == null) { theme = 'light'; } + if (theme === null) { theme = 'light'; } set_theme(theme); @@ -84,7 +84,7 @@ $( document ).ready(function() { $('.theme').click(function(){ var theme = $(this).attr('id'); - set_theme(theme) + set_theme(theme); }); } From d6d0979ecfc31c76c58b6f6b8628d455f1a8a440 Mon Sep 17 00:00:00 2001 From: Mathieu David Date: Mon, 28 Dec 2015 23:52:05 +0100 Subject: [PATCH 13/15] The code on the lines prepended with a # are hidden, the space of the line remains because of the '\n' in
 tag

---
 src/theme/book.js | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/src/theme/book.js b/src/theme/book.js
index 04368f76..862cb324 100644
--- a/src/theme/book.js
+++ b/src/theme/book.js
@@ -112,4 +112,21 @@ $( document ).ready(function() {
 
         $('body').removeClass().addClass(theme);
     }
+
+
+    // Hide Rust code lines prepended with a specific character
+    var hiding_character = "#";
+
+    $("code.language-rust").each(function(i, block){
+        var lines = $(this).html().split("\n");
+
+        for(var n = 0; n < lines.length; n++){
+            if($.trim(lines[n])[0] == hiding_character){
+                lines[n] = "" + lines[n] + ""
+            }
+        }
+        $(this).html(lines.join());
+    });
+
+
 });

From 0620ef1f472e8242bfa411dba207d15b46a1e29f Mon Sep 17 00:00:00 2001
From: Mathieu David 
Date: Tue, 29 Dec 2015 12:26:32 +0100
Subject: [PATCH 14/15] Hides rust code lines prepended with #

---
 src/theme/book.css            |  3 +++
 src/theme/book.js             | 11 +++++++++--
 src/theme/stylus/general.styl |  4 ++++
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/theme/book.css b/src/theme/book.css
index c73eb4a0..df72378b 100644
--- a/src/theme/book.css
+++ b/src/theme/book.css
@@ -9,6 +9,9 @@ body {
 .right {
   float: right;
 }
+.hidden {
+  display: none;
+}
 h2,
 h3 {
   margin-top: 2.5em;
diff --git a/src/theme/book.js b/src/theme/book.js
index 862cb324..b4809118 100644
--- a/src/theme/book.js
+++ b/src/theme/book.js
@@ -119,13 +119,20 @@ $( document ).ready(function() {
 
     $("code.language-rust").each(function(i, block){
         var lines = $(this).html().split("\n");
+        var first_non_hidden_line = false;
 
         for(var n = 0; n < lines.length; n++){
             if($.trim(lines[n])[0] == hiding_character){
-                lines[n] = "" + lines[n] + ""
+                lines[n] = "" + lines[n] + "";
+            }
+            else if(first_non_hidden_line) {
+                lines[n] = "\n" + lines[n];
+            }
+            else {
+                first_non_hidden_line = true;
             }
         }
-        $(this).html(lines.join());
+        $(this).html(lines.join(""));
     });
 
 
diff --git a/src/theme/stylus/general.styl b/src/theme/stylus/general.styl
index 13f616f6..e798e8e0 100644
--- a/src/theme/stylus/general.styl
+++ b/src/theme/stylus/general.styl
@@ -11,4 +11,8 @@ html, body {
     float: right
 }
 
+.hidden {
+    display: none;
+}
+
 h2, h3 { margin-top: 2.5em }

From 71213f40dafdfe70da8b49e33fd9bd5c2ee79712 Mon Sep 17 00:00:00 2001
From: Mathieu David 
Date: Tue, 29 Dec 2015 13:08:25 +0100
Subject: [PATCH 15/15] Add expand/collapse button to show and hide the hidden
 code lines

---
 src/theme/book.css                | 52 +++++++++++++++++++++++++++++++
 src/theme/book.js                 | 28 ++++++++++++++++-
 src/theme/stylus/themes/base.styl | 16 ++++++++++
 3 files changed, 95 insertions(+), 1 deletion(-)

diff --git a/src/theme/book.css b/src/theme/book.css
index df72378b..108e39e0 100644
--- a/src/theme/book.css
+++ b/src/theme/book.css
@@ -284,6 +284,19 @@ h3 {
   -webkit-border-radius: 3px;
   border-radius: 3px;
 }
+.light pre {
+  position: relative;
+}
+.light pre > i {
+  position: absolute;
+  right: 5px;
+  top: 5px;
+  color: #364149;
+  cursor: pointer;
+}
+.light pre > i :hover {
+  color: #008cff;
+}
 .light .sidebar {
   background-color: #fafafa;
   color: #364149;
@@ -340,6 +353,19 @@ h3 {
   -webkit-border-radius: 3px;
   border-radius: 3px;
 }
+.coal pre {
+  position: relative;
+}
+.coal pre > i {
+  position: absolute;
+  right: 5px;
+  top: 5px;
+  color: #a1adb8;
+  cursor: pointer;
+}
+.coal pre > i :hover {
+  color: #3473ad;
+}
 .coal .sidebar {
   background-color: #292c2f;
   color: #a1adb8;
@@ -396,6 +422,19 @@ h3 {
   -webkit-border-radius: 3px;
   border-radius: 3px;
 }
+.navy pre {
+  position: relative;
+}
+.navy pre > i {
+  position: absolute;
+  right: 5px;
+  top: 5px;
+  color: #c8c9db;
+  cursor: pointer;
+}
+.navy pre > i :hover {
+  color: #2b79a2;
+}
 .navy .sidebar {
   background-color: #282d3f;
   color: #c8c9db;
@@ -452,6 +491,19 @@ h3 {
   -webkit-border-radius: 3px;
   border-radius: 3px;
 }
+.rust pre {
+  position: relative;
+}
+.rust pre > i {
+  position: absolute;
+  right: 5px;
+  top: 5px;
+  color: #c8c9db;
+  cursor: pointer;
+}
+.rust pre > i :hover {
+  color: #e69f67;
+}
 .rust .sidebar {
   background-color: #3b2e2a;
   color: #c8c9db;
diff --git a/src/theme/book.js b/src/theme/book.js
index b4809118..58d8eed9 100644
--- a/src/theme/book.js
+++ b/src/theme/book.js
@@ -118,12 +118,21 @@ $( document ).ready(function() {
     var hiding_character = "#";
 
     $("code.language-rust").each(function(i, block){
+
+        // hide lines
         var lines = $(this).html().split("\n");
         var first_non_hidden_line = false;
+        var lines_hidden = false;
 
         for(var n = 0; n < lines.length; n++){
             if($.trim(lines[n])[0] == hiding_character){
-                lines[n] = "" + lines[n] + "";
+                if(first_non_hidden_line){
+                    lines[n] = "" + "\n" + lines[n].substr(1) + "";
+                }
+                else {
+                    lines[n] = "" + lines[n].substr(1) + "\n"  +  "";
+                }
+                lines_hidden = true;
             }
             else if(first_non_hidden_line) {
                 lines[n] = "\n" + lines[n];
@@ -133,6 +142,23 @@ $( document ).ready(function() {
             }
         }
         $(this).html(lines.join(""));
+
+        // If no lines were hidden, return
+        if(!lines_hidden) { return; }
+
+        // add expand button
+        $(this).parent().prepend("");
+
+        $(this).parent().find("i").click(function(e){
+            if( $(this).hasClass("fa-expand") ) {
+                $(this).removeClass("fa-expand").addClass("fa-compress");
+                $(this).parent().find("span.hidden").removeClass("hidden").addClass("unhidden");
+            }
+            else {
+                $(this).removeClass("fa-compress").addClass("fa-expand");
+                $(this).parent().find("span.unhidden").removeClass("unhidden").addClass("hidden");
+            }
+        });
     });
 
 
diff --git a/src/theme/stylus/themes/base.styl b/src/theme/stylus/themes/base.styl
index b9a6d893..0a87b587 100644
--- a/src/theme/stylus/themes/base.styl
+++ b/src/theme/stylus/themes/base.styl
@@ -7,6 +7,22 @@
         border-radius: 3px;
     }
 
+    pre {
+        position: relative;
+    }
+    pre > i {
+        position: absolute;
+        right: 5px;
+        top: 5px;
+
+        color: $sidebar-fg;
+        cursor: pointer;
+
+        :hover {
+            color: $sidebar-active;
+        }
+    }
+
     color: $fg
     background-color: $bg