diff --git a/Cargo.toml b/Cargo.toml index 93637fea..56d92739 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ authors = ["Mathieu David "] getopts = "*" handlebars = "*" rustc-serialize = "*" +pulldown-cmark = "*" diff --git a/src/book/mdbook.rs b/src/book/mdbook.rs index f7fefd9a..a81b43eb 100644 --- a/src/book/mdbook.rs +++ b/src/book/mdbook.rs @@ -135,7 +135,7 @@ impl MDBook { // Construct book fn parse_summary(&mut self) -> Result<(), Box> { - // When append becomes stale, use self.content.append() ... + // When append becomes stable, use self.content.append() ... let book_items = try!(parse::construct_bookitems(&self.config.src().join("SUMMARY.md"))); for item in book_items { diff --git a/src/book/mod.rs b/src/book/mod.rs index 64a119b0..9821c374 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -1,6 +1,6 @@ pub mod mdbook; pub mod bookitem; -mod bookconfig; +pub mod bookconfig; pub use self::bookitem::{BookItem, BookItems}; pub use self::bookconfig::BookConfig; diff --git a/src/renderer/html_handlebars.rs b/src/renderer/html_handlebars.rs index 5ce7c41a..3f10a956 100644 --- a/src/renderer/html_handlebars.rs +++ b/src/renderer/html_handlebars.rs @@ -1,5 +1,6 @@ extern crate handlebars; extern crate rustc_serialize; +extern crate pulldown_cmark; use renderer::Renderer; use book::{BookItems, BookItem, BookConfig}; @@ -9,9 +10,13 @@ use std::path::{Path, PathBuf, Component}; use std::fs::{self, File, metadata}; use std::error::Error; use std::io::{self, Read, Write}; +use std::collections::BTreeMap; + use self::handlebars::Handlebars; use self::rustc_serialize::json::{Json, ToJson}; -use std::collections::BTreeMap; + +use self::pulldown_cmark::Parser; +use self::pulldown_cmark::html; pub struct HtmlHandlebars; @@ -26,19 +31,46 @@ impl Renderer for HtmlHandlebars { // Register template try!(handlebars.register_template_string("index", t.to_owned())); - let data = try!(make_data(book.clone(), config)); + let mut data = try!(make_data(book.clone(), config)); + // Render a file for every entry in the book for (_, item) in book { if item.path != PathBuf::new() { + let path = config.src().join(&item.path); + println!("Open file: {:?}", path); + let mut f = try!(File::open(&path)); + let mut content: String = String::new(); + + try!(f.read_to_string(&mut content)); + + // Render markdown using the pulldown-cmark + content = render_html(&content); + + // Remove content from previous file and render content for this one + data.remove("content"); + data.insert("content".to_string(), content.to_json()); + + // Rendere the handlebars template with the data let rendered = try!(handlebars.render("index", &data)); + // Write to file let mut file = try!(create_file(config.dest(), &item.path)); try!(file.write_all(&rendered.into_bytes())); } } + // Copy static files (js, css, images, ...) + + // JavaScript + let mut js_file = try!(File::create(config.dest().join("book.js"))); + try!(js_file.write_all(theme::get_js())); + + // Css + let mut css_file = try!(File::create(config.dest().join("book.css"))); + try!(css_file.write_all(theme::get_css())); + Ok(()) } } @@ -114,7 +146,7 @@ fn create_file(working_directory: &Path, path: &Path) -> Result } -fn make_data(book: BookItems, config: &BookConfig) -> Result> { +fn make_data(book: BookItems, config: &BookConfig) -> Result, Box> { /* Function to make the JSon data for the handlebars template: @@ -149,5 +181,12 @@ fn make_data(book: BookItems, config: &BookConfig) -> Result> { data.insert("chapters".to_string(), chapters.to_json()); - Ok(data.to_json()) + Ok(data) +} + +fn render_html(text: &str) -> String { + let mut s = String::with_capacity(text.len() * 3 / 2); + let p = Parser::new(&text); + html::push_html(&mut s, p); + s } diff --git a/src/theme/book.css b/src/theme/book.css index e69de29b..4650e917 100644 --- a/src/theme/book.css +++ b/src/theme/book.css @@ -0,0 +1,111 @@ +html, body { + font-family: "Open Sans", sans-serif; +} + +@media only screen { + .sidebar { + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 300px; + overflow-y: auto; + border-right: 1px solid rgba(0, 0, 0, 0.07); + padding: 10px 10px; + font-size: 14px; + box-sizing: border-box; + -webkit-overflow-scrolling: touch; + background-color: #fafafa; + color: #364149; + } + + .page-wrapper { + position: absolute; + overflow-y: auto; + left: 310px; + right: 0; + top: 0; + bottom: 0; + box-sizing: border-box; + background: none repeat scroll 0 0 #FFF; + -webkit-overflow-scrolling: touch; + } +} + +@media only screen and (max-width: 1060px) { + .sidebar { + width: 100%; + margin-right: 0; + top: 40px; + } + .page-wrapper { + top: 40px; + left: 15px; + padding-right: 15px; + } + .mobile-hidden { + display: none; + } +} + +.page { + margin-left: auto; + margin-right:auto; + max-width: 750px; + padding-bottom: 50px; +} + +.chapter { + list-style: none outside none; + padding-left: 0; + line-height: 30px; +} + +.section { + list-style: none outside none; + padding-left: 20px; + line-height: 40px; +} + +.section li { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +.chapter li a { + color: #333; + padding: 5px 0; + text-decoration: none; +} + +.chapter li .active { + color: #008cff; +} + +.chapter li a:hover { + color: #008cff; + text-decoration: none; +} + +pre { + padding: 16px; + overflow: auto; + font-size: 85%; + line-height: 1.45; + background-color: #f7f7f7; + border: 0; + border-radius: 3px; +} + +.nav-previous-next { + margin-top: 60px; +} + +.left { + float: left; +} + +.right { + float: right; +} diff --git a/src/theme/index.hbs b/src/theme/index.hbs index 6f5e969e..72272ab3 100644 --- a/src/theme/index.hbs +++ b/src/theme/index.hbs @@ -8,10 +8,30 @@ + + - {{ chapters }} + + +
+ + + +
+ {{{ content }}} +
+ +
diff --git a/src/theme/mod.rs b/src/theme/mod.rs index f572aa84..cc880fb5 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -4,12 +4,12 @@ pub fn get_index_hbs() -> &'static str { index } -pub fn get_css() -> &'static str { - let css = include_str!("book.css"); +pub fn get_css() -> &'static [u8] { + let css = include_bytes!("book.css"); css } -pub fn get_js() -> &'static str { - let js = include_str!("book.js"); +pub fn get_js() -> &'static [u8] { + let js = include_bytes!("book.js"); js }