added markdown with 'pulldown-cmark', added basic styling, render of the toc is still not completely done

This commit is contained in:
Mathieu David 2015-07-28 21:01:13 +02:00
parent 91c29ef81e
commit 4203b5b1c4
7 changed files with 182 additions and 11 deletions

View File

@ -7,3 +7,4 @@ authors = ["Mathieu David <mathieudavid@mathieudavid.org>"]
getopts = "*" getopts = "*"
handlebars = "*" handlebars = "*"
rustc-serialize = "*" rustc-serialize = "*"
pulldown-cmark = "*"

View File

@ -135,7 +135,7 @@ impl MDBook {
// Construct book // Construct book
fn parse_summary(&mut self) -> Result<(), Box<Error>> { fn parse_summary(&mut self) -> Result<(), Box<Error>> {
// 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"))); let book_items = try!(parse::construct_bookitems(&self.config.src().join("SUMMARY.md")));
for item in book_items { for item in book_items {

View File

@ -1,6 +1,6 @@
pub mod mdbook; pub mod mdbook;
pub mod bookitem; pub mod bookitem;
mod bookconfig; pub mod bookconfig;
pub use self::bookitem::{BookItem, BookItems}; pub use self::bookitem::{BookItem, BookItems};
pub use self::bookconfig::BookConfig; pub use self::bookconfig::BookConfig;

View File

@ -1,5 +1,6 @@
extern crate handlebars; extern crate handlebars;
extern crate rustc_serialize; extern crate rustc_serialize;
extern crate pulldown_cmark;
use renderer::Renderer; use renderer::Renderer;
use book::{BookItems, BookItem, BookConfig}; use book::{BookItems, BookItem, BookConfig};
@ -9,9 +10,13 @@ use std::path::{Path, PathBuf, Component};
use std::fs::{self, File, metadata}; use std::fs::{self, File, metadata};
use std::error::Error; use std::error::Error;
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::collections::BTreeMap;
use self::handlebars::Handlebars; use self::handlebars::Handlebars;
use self::rustc_serialize::json::{Json, ToJson}; use self::rustc_serialize::json::{Json, ToJson};
use std::collections::BTreeMap;
use self::pulldown_cmark::Parser;
use self::pulldown_cmark::html;
pub struct HtmlHandlebars; pub struct HtmlHandlebars;
@ -26,19 +31,46 @@ impl Renderer for HtmlHandlebars {
// Register template // Register template
try!(handlebars.register_template_string("index", t.to_owned())); 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 { for (_, item) in book {
if item.path != PathBuf::new() { 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)); let rendered = try!(handlebars.render("index", &data));
// Write to file
let mut file = try!(create_file(config.dest(), &item.path)); let mut file = try!(create_file(config.dest(), &item.path));
try!(file.write_all(&rendered.into_bytes())); 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(()) Ok(())
} }
} }
@ -114,7 +146,7 @@ fn create_file(working_directory: &Path, path: &Path) -> Result<File, Box<Error>
} }
fn make_data(book: BookItems, config: &BookConfig) -> Result<Json, Box<Error>> { fn make_data(book: BookItems, config: &BookConfig) -> Result<BTreeMap<String,Json>, Box<Error>> {
/* /*
Function to make the JSon data for the handlebars template: Function to make the JSon data for the handlebars template:
@ -149,5 +181,12 @@ fn make_data(book: BookItems, config: &BookConfig) -> Result<Json, Box<Error>> {
data.insert("chapters".to_string(), chapters.to_json()); 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
} }

View File

@ -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;
}

View File

@ -8,10 +8,30 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="book.css" media="screen" title="no title" charset="utf-8"> <link rel="stylesheet" href="book.css" media="screen" title="no title" charset="utf-8">
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
</head> </head>
<body> <body>
{{ chapters }} <div id="sidebar" class="sidebar">
<ul class="chapter">
{{#each chapters}}
<li><a href="{{ this.chapter.path }}">
<strong>{{ this.section }}</strong> {{ this.chapter.name }}
</a></li>
{{/each}}
</ul>
</div>
<div id="page-wrapper" class="page-wrapper">
<div id="menu-bar" class="menu-bar"></div>
<div id="page" class="page">
{{{ content }}}
</div>
</div>
<script src="book.js"></script> <script src="book.js"></script>
</body> </body>

View File

@ -4,12 +4,12 @@ pub fn get_index_hbs() -> &'static str {
index index
} }
pub fn get_css() -> &'static str { pub fn get_css() -> &'static [u8] {
let css = include_str!("book.css"); let css = include_bytes!("book.css");
css css
} }
pub fn get_js() -> &'static str { pub fn get_js() -> &'static [u8] {
let js = include_str!("book.js"); let js = include_bytes!("book.js");
js js
} }