mirror of
https://github.com/rust-lang/mdBook.git
synced 2025-12-28 17:21:52 -05:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cba988f009 | ||
|
|
9602acce80 | ||
|
|
65d7e86024 | ||
|
|
b5ec813d2f | ||
|
|
41735b4579 | ||
|
|
9cb232058b | ||
|
|
ef402c16e8 | ||
|
|
df5472ab5a | ||
|
|
d768963c30 | ||
|
|
8e7ec6e1fd | ||
|
|
80f01d70c6 | ||
|
|
40f275bf21 | ||
|
|
af8300c0b4 | ||
|
|
793a88260c | ||
|
|
1ec776244d | ||
|
|
4af107b0ca | ||
|
|
35e2807138 | ||
|
|
1632d2e339 | ||
|
|
7c3932cef9 | ||
|
|
ed1a216121 | ||
|
|
f814e96459 | ||
|
|
a7272e0ff5 | ||
|
|
1cf4774737 | ||
|
|
c6a5d12002 | ||
|
|
b120ce7397 | ||
|
|
c7916c4818 | ||
|
|
56f597b90c | ||
|
|
c5f9625feb | ||
|
|
79f00eeea3 | ||
|
|
677fa42458 |
4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[attr]rust text eol=lf whitespace=tab-in-indent,trailing-space,tabwidth=4
|
||||
|
||||
* text=auto eol=lf
|
||||
*.rs rust
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mdbook"
|
||||
version = "0.0.17"
|
||||
version = "0.0.19"
|
||||
authors = ["Mathieu David <mathieudavid@mathieudavid.org>"]
|
||||
description = "create books from markdown files (like Gitbook)"
|
||||
documentation = "http://azerupi.github.io/mdBook/index.html"
|
||||
|
||||
@@ -72,7 +72,7 @@ There are multiple ways to install mdBook.
|
||||
|
||||
## Usage
|
||||
|
||||
mdBook will primaraly be used as a command line tool, even though it exposes all its functionality as a Rust crate for integration in other projects.
|
||||
mdBook will primarily be used as a command line tool, even though it exposes all its functionality as a Rust crate for integration in other projects.
|
||||
|
||||
Here are the main commands you will want to run. For a more exhaustive explanation, check out the [documentation](http://azerupi.github.io/mdBook/).
|
||||
|
||||
@@ -88,7 +88,7 @@ Here are the main commands you will want to run. For a more exhaustive explanati
|
||||
└── SUMMARY.md
|
||||
```
|
||||
|
||||
`book` and `src` are both directories. `src` contains the markdown files that will be used to render the ouput to the `book` directory.
|
||||
`book` and `src` are both directories. `src` contains the markdown files that will be used to render the output to the `book` directory.
|
||||
|
||||
Please, take a look at the [**Documentation**](http://azerupi.github.io/mdBook/cli/init.html) for more information and some neat tricks.
|
||||
|
||||
@@ -102,7 +102,7 @@ Here are the main commands you will want to run. For a more exhaustive explanati
|
||||
|
||||
- `mdbook serve`
|
||||
|
||||
Does the same thing as `mdbook watch` but additionally serves the book at `http://localhost:3000` (port is changeable) and reloads the browser when a change occures.
|
||||
Does the same thing as `mdbook watch` but additionally serves the book at `http://localhost:3000` (port is changeable) and reloads the browser when a change occurs.
|
||||
|
||||
### As a library
|
||||
|
||||
|
||||
@@ -37,6 +37,20 @@ pub struct MDBook {
|
||||
impl MDBook {
|
||||
/// Create a new `MDBook` struct with root directory `root`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # extern crate mdbook;
|
||||
/// # use mdbook::MDBook;
|
||||
/// # use std::path::Path;
|
||||
/// # fn main() {
|
||||
/// let book = MDBook::new(Path::new("root_dir"));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// In this example, `root_dir` will be the root directory of our book and is specified in function
|
||||
/// of the current working directory by using a relative path instead of an absolute path.
|
||||
///
|
||||
/// Default directory paths:
|
||||
///
|
||||
/// - source: `root/src`
|
||||
@@ -286,18 +300,6 @@ impl MDBook {
|
||||
/// Parses the `book.json` file (if it exists) to extract the configuration parameters.
|
||||
/// The `book.json` file should be in the root directory of the book.
|
||||
/// The root directory is the one specified when creating a new `MDBook`
|
||||
///
|
||||
/// ```no_run
|
||||
/// # extern crate mdbook;
|
||||
/// # use mdbook::MDBook;
|
||||
/// # use std::path::Path;
|
||||
/// # fn main() {
|
||||
/// let mut book = MDBook::new(Path::new("root_dir"));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// In this example, `root_dir` will be the root directory of our book and is specified in function
|
||||
/// of the current working directory by using a relative path instead of an absolute path.
|
||||
|
||||
pub fn read_config(mut self) -> Self {
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ use std::fs::{self, File};
|
||||
use std::error::Error;
|
||||
use std::io::{self, Read};
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use handlebars::Handlebars;
|
||||
|
||||
@@ -97,12 +98,11 @@ impl Renderer for HtmlHandlebars {
|
||||
|
||||
let filename = Path::new(&ch.path).with_extension("html");
|
||||
|
||||
// create links for headers and fix anchors
|
||||
// Do several kinds of post-processing
|
||||
let rendered = build_header_links(rendered, filename.to_str().unwrap_or(""));
|
||||
let rendered = fix_anchor_links(rendered, filename.to_str().unwrap_or(""));
|
||||
|
||||
// fix code blocks
|
||||
let rendered = fix_code_blocks(rendered);
|
||||
let rendered = add_playpen_pre(rendered);
|
||||
|
||||
// Write to file
|
||||
info!("[*] Creating {:?} ✓", filename.display());
|
||||
@@ -146,11 +146,12 @@ impl Renderer for HtmlHandlebars {
|
||||
debug!("[*]: Render template");
|
||||
|
||||
let rendered = try!(handlebars.render("index", &data));
|
||||
|
||||
// do several kinds of post-processing
|
||||
let rendered = build_header_links(rendered, "print.html");
|
||||
let rendered = fix_anchor_links(rendered, "print.html");
|
||||
|
||||
// fix code blocks
|
||||
let rendered = fix_code_blocks(rendered);
|
||||
let rendered = add_playpen_pre(rendered);
|
||||
|
||||
try!(book.write_file(Path::new("print").with_extension("html"), &rendered.into_bytes()));
|
||||
info!("[*] Creating print.html ✓");
|
||||
@@ -229,6 +230,7 @@ fn make_data(book: &MDBook) -> Result<serde_json::Map<String, serde_json::Value>
|
||||
|
||||
fn build_header_links(html: String, filename: &str) -> String {
|
||||
let regex = Regex::new(r"<h(\d)>(.*?)</h\d>").unwrap();
|
||||
let mut id_counter = HashMap::new();
|
||||
|
||||
regex.replace_all(&html, |caps: &Captures| {
|
||||
let level = &caps[1];
|
||||
@@ -254,7 +256,16 @@ fn build_header_links(html: String, filename: &str) -> String {
|
||||
}
|
||||
}).collect::<String>();
|
||||
|
||||
format!("<a class=\"header\" href=\"{filename}#{id}\" name=\"{id}\"><h{level}>{text}</h{level}></a>",
|
||||
let id_count = *id_counter.get(&id).unwrap_or(&0);
|
||||
id_counter.insert(id.clone(), id_count + 1);
|
||||
|
||||
let id = if id_count > 0 {
|
||||
format!("{}-{}", id, id_count)
|
||||
} else {
|
||||
id
|
||||
};
|
||||
|
||||
format!("<a class=\"header\" href=\"{filename}#{id}\" id=\"{id}\"><h{level}>{text}</h{level}></a>",
|
||||
level=level, id=id, text=text, filename=filename)
|
||||
}).into_owned()
|
||||
}
|
||||
@@ -292,3 +303,52 @@ fn fix_code_blocks(html: String) -> String {
|
||||
format!("<code{before}class=\"{classes}\"{after}>", before=before, classes=classes, after=after)
|
||||
}).into_owned()
|
||||
}
|
||||
|
||||
fn add_playpen_pre(html: String) -> String {
|
||||
let regex = Regex::new(r##"((?s)<code[^>]?class="([^"]+)".*?>(.*?)</code>)"##).unwrap();
|
||||
regex.replace_all(&html, |caps: &Captures| {
|
||||
let text = &caps[1];
|
||||
let classes = &caps[2];
|
||||
let code = &caps[3];
|
||||
|
||||
if classes.contains("language-rust") && !classes.contains("ignore") {
|
||||
// wrap the contents in an external pre block
|
||||
|
||||
if text.contains("fn main") {
|
||||
format!("<pre class=\"playpen\">{}</pre>", text)
|
||||
} else {
|
||||
// we need to inject our own main
|
||||
let (attrs, code) = partition_source(code);
|
||||
format!("<pre class=\"playpen\"><code class=\"{}\"># #![allow(unused_variables)]
|
||||
{}#fn main() {{
|
||||
{}
|
||||
#}}</code></pre>", classes, attrs, code)
|
||||
}
|
||||
} else {
|
||||
// not language-rust, so no-op
|
||||
format!("{}", text)
|
||||
}
|
||||
}).into_owned()
|
||||
}
|
||||
|
||||
fn partition_source(s: &str) -> (String, String) {
|
||||
let mut after_header = false;
|
||||
let mut before = String::new();
|
||||
let mut after = String::new();
|
||||
|
||||
for line in s.lines() {
|
||||
let trimline = line.trim();
|
||||
let header = trimline.chars().all(|c| c.is_whitespace()) ||
|
||||
trimline.starts_with("#![");
|
||||
if !header || after_header {
|
||||
after_header = true;
|
||||
after.push_str(line);
|
||||
after.push_str("\n");
|
||||
} else {
|
||||
before.push_str(line);
|
||||
before.push_str("\n");
|
||||
}
|
||||
}
|
||||
|
||||
(before, after)
|
||||
}
|
||||
@@ -35,7 +35,7 @@ pub fn render_playpen(s: &str, path: &Path) -> String {
|
||||
continue;
|
||||
};
|
||||
|
||||
let replacement = String::new() + "<pre class=\"playpen\"><code class=\"language-rust\">" + &file_content +
|
||||
let replacement = String::new() + "<pre><code class=\"language-rust\">" + &file_content +
|
||||
"</code></pre>";
|
||||
|
||||
replaced.push_str(&s[previous_end_index..playpen.start_index]);
|
||||
|
||||
@@ -33,7 +33,7 @@ impl HelperDef for RenderToc {
|
||||
}
|
||||
|
||||
let level = if let Some(s) = item.get("section") {
|
||||
s.len() / 2
|
||||
s.matches(".").count()
|
||||
} else {
|
||||
1
|
||||
};
|
||||
|
||||
@@ -3,6 +3,10 @@ body {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
color: #333;
|
||||
}
|
||||
code {
|
||||
font-family: "Source Code Pro", "Menlo", "DejaVu Sans Mono", monospace;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
.left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ $( document ).ready(function() {
|
||||
};
|
||||
|
||||
$(document).on('keydown', function (e) {
|
||||
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; }
|
||||
switch (e.keyCode) {
|
||||
case KEY_CODES.NEXT_KEY:
|
||||
e.preventDefault();
|
||||
@@ -207,6 +208,18 @@ function run_rust_code(code_block) {
|
||||
result_block = code_block.find(".result");
|
||||
}
|
||||
|
||||
let text = code_block.find(".language-rust").text();
|
||||
|
||||
let params = {
|
||||
version: "stable",
|
||||
optimize: "0",
|
||||
code: text,
|
||||
};
|
||||
|
||||
if(text.includes("#![feature")) {
|
||||
params.version = "nightly";
|
||||
}
|
||||
|
||||
result_block.text("Running...");
|
||||
|
||||
$.ajax({
|
||||
@@ -215,7 +228,7 @@ function run_rust_code(code_block) {
|
||||
crossDomain: true,
|
||||
dataType: "json",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({version: "stable", optimize: "0", code: code_block.find(".language-rust").text() }),
|
||||
data: JSON.stringify(params),
|
||||
success: function(response){
|
||||
result_block.text(response.result);
|
||||
}
|
||||
|
||||
@@ -12,96 +12,59 @@
|
||||
|
||||
|
||||
/* Atelier-Dune Comment */
|
||||
.hljs-comment {
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #AAA;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Red */
|
||||
.hljs-variable,
|
||||
|
||||
.hljs-template-variable,
|
||||
.hljs-attribute,
|
||||
.hljs-tag,
|
||||
.hljs-regexp,
|
||||
.hljs-name,
|
||||
.ruby .hljs-constant,
|
||||
.xml .hljs-tag .hljs-title,
|
||||
.xml .hljs-pi,
|
||||
.xml .hljs-doctype,
|
||||
.html .hljs-doctype,
|
||||
.css .hljs-id,
|
||||
.css .hljs-class,
|
||||
.css .hljs-pseudo {
|
||||
.hljs-regexp,
|
||||
.hljs-link,
|
||||
.hljs-name,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #d73737;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Orange */
|
||||
.hljs-number,
|
||||
.hljs-preprocessor,
|
||||
.hljs-meta,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name,
|
||||
.hljs-literal,
|
||||
.hljs-params,
|
||||
.hljs-attribute,
|
||||
.hljs-constant {
|
||||
.hljs-type,
|
||||
.hljs-params {
|
||||
color: #b65611;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Yellow */
|
||||
.ruby .hljs-class .hljs-title,
|
||||
.css .hljs-rule .hljs-attribute {
|
||||
color: #ae9513;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Green */
|
||||
.hljs-string,
|
||||
.hljs-value,
|
||||
.hljs-inheritance,
|
||||
.ruby .hljs-symbol,
|
||||
.xml .hljs-cdata {
|
||||
color: #2a9292;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Aqua */
|
||||
.hljs-title,
|
||||
.css .hljs-hexcolor {
|
||||
color: #1fad83;
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #60ac39;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Blue */
|
||||
.hljs-function,
|
||||
.python .hljs-decorator,
|
||||
.python .hljs-title,
|
||||
.ruby .hljs-function .hljs-title,
|
||||
.ruby .hljs-title .hljs-keyword,
|
||||
.perl .hljs-sub,
|
||||
.javascript .hljs-title,
|
||||
.coffeescript .hljs-title {
|
||||
.hljs-title,
|
||||
.hljs-section {
|
||||
color: #6684e1;
|
||||
}
|
||||
|
||||
/* Atelier-Dune Purple */
|
||||
.hljs-keyword,
|
||||
.javascript .hljs-function {
|
||||
.hljs-selector-tag {
|
||||
color: #b854d4;
|
||||
}
|
||||
|
||||
.coffeescript .javascript,
|
||||
.javascript .xml,
|
||||
.tex .hljs-formula,
|
||||
.xml .javascript,
|
||||
.xml .vbscript,
|
||||
.xml .css,
|
||||
.xml .hljs-cdata {
|
||||
opacity: 0.5;
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* markdown */
|
||||
.hljs-header {
|
||||
color: #A30000;
|
||||
}
|
||||
|
||||
.hljs-link_label {
|
||||
color: #33CCCC;
|
||||
}
|
||||
|
||||
.hljs-link_url {
|
||||
color: #CC66FF;
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -10,7 +10,8 @@
|
||||
<base href="{{ path_to_root }}">
|
||||
|
||||
<link rel="stylesheet" href="book.css">
|
||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
|
||||
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
|
||||
|
||||
<link rel="shortcut icon" href="{{ favicon }}">
|
||||
|
||||
|
||||
@@ -3,6 +3,11 @@ html, body {
|
||||
color: #333
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: "Source Code Pro", "Menlo", "DejaVu Sans Mono", monospace;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
.left {
|
||||
float: left
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user