diff --git a/components/config/src/lib.rs b/components/config/src/lib.rs index 40b4ff1..8643485 100644 --- a/components/config/src/lib.rs +++ b/components/config/src/lib.rs @@ -107,6 +107,9 @@ pub struct Config { /// Whether to check all external links for validity pub check_external_links: bool, + /// A list of directories containing extra syntax definitions to load. + pub extra_syntaxes: Vec, + /// All user params set in [extra] in the config pub extra: HashMap, @@ -233,6 +236,7 @@ impl Default for Config { ignored_content: Vec::new(), ignored_content_globset: None, translations: HashMap::new(), + extra_syntaxes: Vec::new(), extra: HashMap::new(), build_timestamp: Some(1), } diff --git a/components/highlighting/src/lib.rs b/components/highlighting/src/lib.rs index f814279..2f66cf3 100644 --- a/components/highlighting/src/lib.rs +++ b/components/highlighting/src/lib.rs @@ -2,16 +2,20 @@ extern crate lazy_static; extern crate syntect; +use std::cell::RefCell; + +use syntect::LoadingError; use syntect::dumps::from_binary; use syntect::parsing::SyntaxSet; use syntect::highlighting::{ThemeSet, Theme}; use syntect::easy::HighlightLines; thread_local! { - pub static SYNTAX_SET: SyntaxSet = { + /// A pair of the set and whether extras have been added to it. + pub static SYNTAX_SET: RefCell<(SyntaxSet, bool)> = { let mut ss: SyntaxSet = from_binary(include_bytes!("../../../sublime_syntaxes/newlines.packdump")); ss.link_syntaxes(); - ss + RefCell::new((ss, false)) }; } @@ -19,14 +23,22 @@ lazy_static! { pub static ref THEME_SET: ThemeSet = from_binary(include_bytes!("../../../sublime_themes/all.themedump")); } +pub fn get_highlighter<'a>(theme: &'a Theme, info: &str, extra_syntaxes: &[String]) -> Result, LoadingError> { + SYNTAX_SET.with(|rc| { + let (ss, extras_added) = &mut *rc.borrow_mut(); + if !*extras_added { + for dir in extra_syntaxes { + ss.load_syntaxes(dir, true)?; + } + ss.link_syntaxes(); + *extras_added = true; + } -pub fn get_highlighter<'a>(theme: &'a Theme, info: &str) -> HighlightLines<'a> { - SYNTAX_SET.with(|ss| { let syntax = info .split(' ') .next() .and_then(|lang| ss.find_syntax_by_token(lang)) .unwrap_or_else(|| ss.find_syntax_plain_text()); - HighlightLines::new(syntax, theme) + Ok(HighlightLines::new(syntax, theme)) }) } diff --git a/components/rendering/src/markdown.rs b/components/rendering/src/markdown.rs index 60ea672..648e3b6 100644 --- a/components/rendering/src/markdown.rs +++ b/components/rendering/src/markdown.rs @@ -97,7 +97,13 @@ pub fn markdown_to_html(content: &str, context: &RenderContext) -> Result<(Strin } let theme = &THEME_SET.themes[&context.config.highlight_theme]; - highlighter = Some(get_highlighter(&theme, info)); + match get_highlighter(&theme, info, &context.config.extra_syntaxes) { + Ok(h) => highlighter = Some(h), + Err(err) => { + error = Some(format!("Could not load syntax: {}", err).into()); + return Event::Html(Owned(String::new())); + } + } let snippet = start_coloured_html_snippet(theme); Event::Html(Owned(snippet)) }