Skip to content

Commit 864be6c

Browse files
authored
Merge pull request #207 from steveklabnik/gh204
Generate links at compile-time rather than use JS
2 parents f3fb1f1 + ec42e2f commit 864be6c

File tree

4 files changed

+39
-15
lines changed

4 files changed

+39
-15
lines changed

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ serde = "0.9"
2121
serde_json = "0.9"
2222
pulldown-cmark = "0.0.8"
2323
log = "0.3"
24-
env_logger = "0.3"
24+
env_logger = "0.4.0"
2525
toml = { version = "0.2", features = ["serde"] }
2626
open = "1.1"
27+
regex = "0.2.1"
2728

2829
# Watch feature
2930
notify = { version = "3.0", optional = true }

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ extern crate serde;
7474
extern crate serde_json;
7575
extern crate handlebars;
7676
extern crate pulldown_cmark;
77+
extern crate regex;
7778

7879
#[macro_use] extern crate log;
7980
pub mod book;

src/renderer/html_handlebars/hbs_renderer.rs

+36
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ use renderer::Renderer;
33
use book::MDBook;
44
use book::bookitem::BookItem;
55
use {utils, theme};
6+
use regex::{Regex, Captures};
67

8+
use std::ascii::AsciiExt;
79
use std::path::{Path, PathBuf};
810
use std::fs::{self, File};
911
use std::error::Error;
@@ -91,6 +93,9 @@ impl Renderer for HtmlHandlebars {
9193
// Render the handlebars template with the data
9294
debug!("[*]: Render template");
9395
let rendered = try!(handlebars.render("index", &data));
96+
97+
// create links for headers
98+
let rendered = build_header_links(rendered);
9499

95100
// Write to file
96101
let filename = Path::new(&ch.path).with_extension("html");
@@ -208,3 +213,34 @@ fn make_data(book: &MDBook) -> Result<serde_json::Map<String, serde_json::Value>
208213
debug!("[*]: JSON constructed");
209214
Ok(data)
210215
}
216+
217+
fn build_header_links(html: String) -> String {
218+
let regex = Regex::new(r"<h(\d)>(.*?)</h\d>").unwrap();
219+
220+
regex.replace_all(&html, |caps: &Captures| {
221+
let level = &caps[1];
222+
let text = &caps[2];
223+
let mut id = text.to_string();
224+
let repl_sub = vec!["<em>", "</em>", "<code>", "</code>",
225+
"<strong>", "</strong>",
226+
"&lt;", "&gt;", "&amp;", "&#39;", "&quot;"];
227+
for sub in repl_sub {
228+
id = id.replace(sub, "");
229+
}
230+
let id = id.chars().filter_map(|c| {
231+
if c.is_alphanumeric() || c == '-' || c == '_' {
232+
if c.is_ascii() {
233+
Some(c.to_ascii_lowercase())
234+
} else {
235+
Some(c)
236+
}
237+
} else if c.is_whitespace() && c.is_ascii() {
238+
Some('-')
239+
} else {
240+
None
241+
}
242+
}).collect::<String>();
243+
244+
format!("<a class=\"header\" href=\"#{id}\" name=\"{id}\"><h{level}>{text}</h{level}></a>", level=level, id=id, text=text)
245+
}).into_owned()
246+
}

src/theme/book.js

-14
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,6 @@ $( document ).ready(function() {
5555
var page_wrapper = $("#page-wrapper");
5656
var content = $("#content");
5757

58-
59-
// Add anchors for all content headers
60-
content.find("h1, h2, h3, h4, h5").wrap(function(){
61-
var wrapper = $("<a class=\"header\">");
62-
var header_name = $(this).text().trim().replace(/\W/g, '-')
63-
wrapper.attr("name", header_name);
64-
// Add so that when you click the link actually shows up in the url bar...
65-
// Remove any existing anchor then append the new one
66-
// ensuring eg. no spaces are present within it ie. they become %20
67-
wrapper.attr("href", $(location).attr('href').split("#")[0] + "#" + header_name );
68-
return wrapper;
69-
});
70-
71-
7258
// Toggle sidebar
7359
$("#sidebar-toggle").click(function(event){
7460
if ( html.hasClass("sidebar-hidden") ) {

0 commit comments

Comments
 (0)