@@ -6,7 +6,7 @@ use std::collections::HashMap; | |||||
use toml::{Value as Toml, self}; | use toml::{Value as Toml, self}; | ||||
use errors::{Result, ResultExt}; | use errors::{Result, ResultExt}; | ||||
use markdown::SETUP; | |||||
use rendering::highlighting::THEME_SET; | |||||
#[derive(Debug, PartialEq, Serialize, Deserialize)] | #[derive(Debug, PartialEq, Serialize, Deserialize)] | ||||
@@ -65,7 +65,7 @@ impl Config { | |||||
match config.highlight_theme { | match config.highlight_theme { | ||||
Some(ref t) => { | Some(ref t) => { | ||||
if !SETUP.theme_set.themes.contains_key(t) { | |||||
if !THEME_SET.themes.contains_key(t) { | |||||
bail!("Theme {} not available", t) | bail!("Theme {} not available", t) | ||||
} | } | ||||
}, | }, | ||||
@@ -11,7 +11,7 @@ use slug::slugify; | |||||
use errors::{Result, ResultExt}; | use errors::{Result, ResultExt}; | ||||
use config::Config; | use config::Config; | ||||
use front_matter::{PageFrontMatter, split_page_content}; | use front_matter::{PageFrontMatter, split_page_content}; | ||||
use markdown::markdown_to_html; | |||||
use rendering::markdown::markdown_to_html; | |||||
use fs::{read_file}; | use fs::{read_file}; | ||||
use content::utils::{find_related_assets, get_reading_analytics}; | use content::utils::{find_related_assets, get_reading_analytics}; | ||||
use content::file_info::FileInfo; | use content::file_info::FileInfo; | ||||
@@ -9,7 +9,7 @@ use config::Config; | |||||
use front_matter::{SectionFrontMatter, split_section_content}; | use front_matter::{SectionFrontMatter, split_section_content}; | ||||
use errors::{Result, ResultExt}; | use errors::{Result, ResultExt}; | ||||
use fs::{read_file}; | use fs::{read_file}; | ||||
use markdown::markdown_to_html; | |||||
use rendering::markdown::markdown_to_html; | |||||
use content::Page; | use content::Page; | ||||
use content::file_info::FileInfo; | use content::file_info::FileInfo; | ||||
@@ -25,7 +25,7 @@ pub mod errors; | |||||
mod front_matter; | mod front_matter; | ||||
mod content; | mod content; | ||||
mod site; | mod site; | ||||
mod markdown; | |||||
mod rendering; | |||||
// Filters, Global Fns and default instance of Tera | // Filters, Global Fns and default instance of Tera | ||||
mod templates; | mod templates; | ||||
@@ -34,4 +34,3 @@ pub use config::{Config, get_config}; | |||||
pub use front_matter::{PageFrontMatter, SectionFrontMatter, split_page_content, split_section_content}; | pub use front_matter::{PageFrontMatter, SectionFrontMatter, split_page_content, split_section_content}; | ||||
pub use content::{Page, Section, SortBy, sort_pages, populate_previous_and_next_pages}; | pub use content::{Page, Section, SortBy, sort_pages, populate_previous_and_next_pages}; | ||||
pub use fs::{create_file}; | pub use fs::{create_file}; | ||||
pub use markdown::markdown_to_html; |
@@ -0,0 +1,6 @@ | |||||
use syntect::dumps::from_binary; | |||||
use syntect::highlighting::ThemeSet; | |||||
lazy_static!{ | |||||
pub static ref THEME_SET: ThemeSet = from_binary(include_bytes!("../../sublime_themes/all.themedump")); | |||||
} |
@@ -8,19 +8,18 @@ use slug::slugify; | |||||
use syntect::dumps::from_binary; | use syntect::dumps::from_binary; | ||||
use syntect::easy::HighlightLines; | use syntect::easy::HighlightLines; | ||||
use syntect::parsing::SyntaxSet; | use syntect::parsing::SyntaxSet; | ||||
use syntect::highlighting::ThemeSet; | |||||
use syntect::html::{start_coloured_html_snippet, styles_to_coloured_html, IncludeBackground}; | use syntect::html::{start_coloured_html_snippet, styles_to_coloured_html, IncludeBackground}; | ||||
use tera::{Tera, Context}; | use tera::{Tera, Context}; | ||||
use config::Config; | use config::Config; | ||||
use errors::{Result, ResultExt}; | |||||
use errors::{Result}; | |||||
use site::resolve_internal_link; | use site::resolve_internal_link; | ||||
use rendering::highlighting::THEME_SET; | |||||
use rendering::short_code::{ShortCode, parse_shortcode, render_simple_shortcode}; | |||||
// We need to put those in a struct to impl Send and sync | // We need to put those in a struct to impl Send and sync | ||||
pub struct Setup { | pub struct Setup { | ||||
pub syntax_set: SyntaxSet, | pub syntax_set: SyntaxSet, | ||||
pub theme_set: ThemeSet, | |||||
} | } | ||||
unsafe impl Send for Setup {} | unsafe impl Send for Setup {} | ||||
@@ -30,75 +29,13 @@ lazy_static!{ | |||||
static ref SHORTCODE_RE: Regex = Regex::new(r#"\{(?:%|\{)\s+([[:alnum:]]+?)\(([[:alnum:]]+?="?.+?"?)\)\s+(?:%|\})\}"#).unwrap(); | static ref SHORTCODE_RE: Regex = Regex::new(r#"\{(?:%|\{)\s+([[:alnum:]]+?)\(([[:alnum:]]+?="?.+?"?)\)\s+(?:%|\})\}"#).unwrap(); | ||||
pub static ref SETUP: Setup = Setup { | pub static ref SETUP: Setup = Setup { | ||||
syntax_set: { | syntax_set: { | ||||
let mut ps: SyntaxSet = from_binary(include_bytes!("../sublime_syntaxes/newlines.packdump")); | |||||
let mut ps: SyntaxSet = from_binary(include_bytes!("../../sublime_syntaxes/newlines.packdump")); | |||||
ps.link_syntaxes(); | ps.link_syntaxes(); | ||||
ps | ps | ||||
}, | }, | ||||
theme_set: from_binary(include_bytes!("../sublime_themes/all.themedump")) | |||||
}; | }; | ||||
} | } | ||||
/// A shortcode that has a body | |||||
/// Called by having some content like {% ... %} body {% end %} | |||||
/// We need the struct to hold the data while we're processing the markdown | |||||
#[derive(Debug)] | |||||
struct ShortCode { | |||||
name: String, | |||||
args: HashMap<String, String>, | |||||
body: String, | |||||
} | |||||
impl ShortCode { | |||||
pub fn new(name: &str, args: HashMap<String, String>) -> ShortCode { | |||||
ShortCode { | |||||
name: name.to_string(), | |||||
args: args, | |||||
body: String::new(), | |||||
} | |||||
} | |||||
pub fn append(&mut self, text: &str) { | |||||
self.body.push_str(text) | |||||
} | |||||
pub fn render(&self, tera: &Tera) -> Result<String> { | |||||
let mut context = Context::new(); | |||||
for (key, value) in &self.args { | |||||
context.add(key, value); | |||||
} | |||||
context.add("body", &self.body); | |||||
let tpl_name = format!("shortcodes/{}.html", self.name); | |||||
tera.render(&tpl_name, &context) | |||||
.chain_err(|| format!("Failed to render {} shortcode", self.name)) | |||||
} | |||||
} | |||||
/// Parse a shortcode without a body | |||||
fn parse_shortcode(input: &str) -> (String, HashMap<String, String>) { | |||||
let mut args = HashMap::new(); | |||||
let caps = SHORTCODE_RE.captures(input).unwrap(); | |||||
// caps[0] is the full match | |||||
let name = &caps[1]; | |||||
let arg_list = &caps[2]; | |||||
for arg in arg_list.split(',') { | |||||
let bits = arg.split('=').collect::<Vec<_>>(); | |||||
args.insert(bits[0].trim().to_string(), bits[1].replace("\"", "")); | |||||
} | |||||
(name.to_string(), args) | |||||
} | |||||
/// Renders a shortcode or return an error | |||||
fn render_simple_shortcode(tera: &Tera, name: &str, args: &HashMap<String, String>) -> Result<String> { | |||||
let mut context = Context::new(); | |||||
for (key, value) in args.iter() { | |||||
context.add(key, value); | |||||
} | |||||
let tpl_name = format!("shortcodes/{}.html", name); | |||||
tera.render(&tpl_name, &context).chain_err(|| format!("Failed to render {} shortcode", name)) | |||||
} | |||||
pub fn markdown_to_html(content: &str, permalinks: &HashMap<String, String>, tera: &Tera, config: &Config) -> Result<String> { | pub fn markdown_to_html(content: &str, permalinks: &HashMap<String, String>, tera: &Tera, config: &Config) -> Result<String> { | ||||
// We try to be smart about highlighting code as it can be time-consuming | // We try to be smart about highlighting code as it can be time-consuming | ||||
// If the global config disables it, then we do nothing. However, | // If the global config disables it, then we do nothing. However, | ||||
@@ -233,7 +170,7 @@ pub fn markdown_to_html(content: &str, permalinks: &HashMap<String, String>, ter | |||||
if !should_highlight { | if !should_highlight { | ||||
return Event::Html(Owned("<pre><code>".to_owned())); | return Event::Html(Owned("<pre><code>".to_owned())); | ||||
} | } | ||||
let theme = &SETUP.theme_set.themes[&highlight_theme]; | |||||
let theme = &THEME_SET.themes[&highlight_theme]; | |||||
let syntax = info | let syntax = info | ||||
.split(' ') | .split(' ') | ||||
.next() | .next() |
@@ -0,0 +1,3 @@ | |||||
pub mod highlighting; | |||||
pub mod markdown; | |||||
pub mod short_code; |
@@ -0,0 +1,71 @@ | |||||
use std::collections::HashMap; | |||||
use regex::Regex; | |||||
use tera::{Tera, Context}; | |||||
use errors::{Result, ResultExt}; | |||||
lazy_static!{ | |||||
static ref SHORTCODE_RE: Regex = Regex::new(r#"\{(?:%|\{)\s+([[:alnum:]]+?)\(([[:alnum:]]+?="?.+?"?)\)\s+(?:%|\})\}"#).unwrap(); | |||||
} | |||||
/// A shortcode that has a body | |||||
/// Called by having some content like {% ... %} body {% end %} | |||||
/// We need the struct to hold the data while we're processing the markdown | |||||
#[derive(Debug)] | |||||
pub struct ShortCode { | |||||
name: String, | |||||
args: HashMap<String, String>, | |||||
body: String, | |||||
} | |||||
impl ShortCode { | |||||
pub fn new(name: &str, args: HashMap<String, String>) -> ShortCode { | |||||
ShortCode { | |||||
name: name.to_string(), | |||||
args: args, | |||||
body: String::new(), | |||||
} | |||||
} | |||||
pub fn append(&mut self, text: &str) { | |||||
self.body.push_str(text) | |||||
} | |||||
pub fn render(&self, tera: &Tera) -> Result<String> { | |||||
let mut context = Context::new(); | |||||
for (key, value) in &self.args { | |||||
context.add(key, value); | |||||
} | |||||
context.add("body", &self.body); | |||||
let tpl_name = format!("shortcodes/{}.html", self.name); | |||||
tera.render(&tpl_name, &context) | |||||
.chain_err(|| format!("Failed to render {} shortcode", self.name)) | |||||
} | |||||
} | |||||
/// Parse a shortcode without a body | |||||
pub fn parse_shortcode(input: &str) -> (String, HashMap<String, String>) { | |||||
let mut args = HashMap::new(); | |||||
let caps = SHORTCODE_RE.captures(input).unwrap(); | |||||
// caps[0] is the full match | |||||
let name = &caps[1]; | |||||
let arg_list = &caps[2]; | |||||
for arg in arg_list.split(',') { | |||||
let bits = arg.split('=').collect::<Vec<_>>(); | |||||
args.insert(bits[0].trim().to_string(), bits[1].replace("\"", "")); | |||||
} | |||||
(name.to_string(), args) | |||||
} | |||||
/// Renders a shortcode or return an error | |||||
pub fn render_simple_shortcode(tera: &Tera, name: &str, args: &HashMap<String, String>) -> Result<String> { | |||||
let mut context = Context::new(); | |||||
for (key, value) in args.iter() { | |||||
context.add(key, value); | |||||
} | |||||
let tpl_name = format!("shortcodes/{}.html", name); | |||||
tera.render(&tpl_name, &context).chain_err(|| format!("Failed to render {} shortcode", name)) | |||||
} |