diff --git a/src/config.rs b/src/config.rs index 308f6dcf..f0aac90a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,7 +6,7 @@ use std::collections::HashMap; use toml::{Value as Toml, self}; use errors::{Result, ResultExt}; -use markdown::SETUP; +use rendering::highlighting::THEME_SET; #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -65,7 +65,7 @@ impl Config { match config.highlight_theme { Some(ref t) => { - if !SETUP.theme_set.themes.contains_key(t) { + if !THEME_SET.themes.contains_key(t) { bail!("Theme {} not available", t) } }, diff --git a/src/content/page.rs b/src/content/page.rs index 0883b432..caa9fdb5 100644 --- a/src/content/page.rs +++ b/src/content/page.rs @@ -11,7 +11,7 @@ use slug::slugify; use errors::{Result, ResultExt}; use config::Config; use front_matter::{PageFrontMatter, split_page_content}; -use markdown::markdown_to_html; +use rendering::markdown::markdown_to_html; use fs::{read_file}; use content::utils::{find_related_assets, get_reading_analytics}; use content::file_info::FileInfo; diff --git a/src/content/section.rs b/src/content/section.rs index 3d3f79b8..a8e41ef7 100644 --- a/src/content/section.rs +++ b/src/content/section.rs @@ -9,7 +9,7 @@ use config::Config; use front_matter::{SectionFrontMatter, split_section_content}; use errors::{Result, ResultExt}; use fs::{read_file}; -use markdown::markdown_to_html; +use rendering::markdown::markdown_to_html; use content::Page; use content::file_info::FileInfo; diff --git a/src/lib.rs b/src/lib.rs index cd217871..b72af67a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,7 @@ pub mod errors; mod front_matter; mod content; mod site; -mod markdown; +mod rendering; // Filters, Global Fns and default instance of Tera 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 content::{Page, Section, SortBy, sort_pages, populate_previous_and_next_pages}; pub use fs::{create_file}; -pub use markdown::markdown_to_html; diff --git a/src/rendering/highlighting.rs b/src/rendering/highlighting.rs new file mode 100644 index 00000000..ee2d95b8 --- /dev/null +++ b/src/rendering/highlighting.rs @@ -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")); +} diff --git a/src/markdown.rs b/src/rendering/markdown.rs similarity index 89% rename from src/markdown.rs rename to src/rendering/markdown.rs index 2905252c..bc93cdf3 100644 --- a/src/markdown.rs +++ b/src/rendering/markdown.rs @@ -8,19 +8,18 @@ use slug::slugify; use syntect::dumps::from_binary; use syntect::easy::HighlightLines; use syntect::parsing::SyntaxSet; -use syntect::highlighting::ThemeSet; use syntect::html::{start_coloured_html_snippet, styles_to_coloured_html, IncludeBackground}; use tera::{Tera, Context}; use config::Config; -use errors::{Result, ResultExt}; +use errors::{Result}; 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 pub struct Setup { pub syntax_set: SyntaxSet, - pub theme_set: ThemeSet, } unsafe impl Send for Setup {} @@ -30,75 +29,13 @@ lazy_static!{ static ref SHORTCODE_RE: Regex = Regex::new(r#"\{(?:%|\{)\s+([[:alnum:]]+?)\(([[:alnum:]]+?="?.+?"?)\)\s+(?:%|\})\}"#).unwrap(); pub static ref SETUP: Setup = Setup { 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 }, - 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, - body: String, -} - -impl ShortCode { - pub fn new(name: &str, args: HashMap) -> 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 { - 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) { - 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::>(); - 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) -> Result { - 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, tera: &Tera, config: &Config) -> Result { // 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, @@ -233,7 +170,7 @@ pub fn markdown_to_html(content: &str, permalinks: &HashMap, ter if !should_highlight { return Event::Html(Owned("
".to_owned()));
                 }
-                let theme = &SETUP.theme_set.themes[&highlight_theme];
+                let theme = &THEME_SET.themes[&highlight_theme];
                 let syntax = info
                     .split(' ')
                     .next()
diff --git a/src/rendering/mod.rs b/src/rendering/mod.rs
new file mode 100644
index 00000000..6263182d
--- /dev/null
+++ b/src/rendering/mod.rs
@@ -0,0 +1,3 @@
+pub mod highlighting;
+pub mod markdown;
+pub mod short_code;
diff --git a/src/rendering/short_code.rs b/src/rendering/short_code.rs
new file mode 100644
index 00000000..a78c30d7
--- /dev/null
+++ b/src/rendering/short_code.rs
@@ -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,
+    body: String,
+}
+
+impl ShortCode {
+    pub fn new(name: &str, args: HashMap) -> 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 {
+        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) {
+    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::>();
+        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) -> Result {
+    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))
+}