Pick highlighting theme from config
This commit is contained in:
parent
81596af366
commit
9af85ba3e4
|
@ -34,10 +34,5 @@ markdown -> HTML for the content
|
||||||
|
|
||||||
### Themes
|
### Themes
|
||||||
Gallery at https://tmtheme-editor.herokuapp.com/#!/editor/theme/Agola%20Dark
|
Gallery at https://tmtheme-editor.herokuapp.com/#!/editor/theme/Agola%20Dark
|
||||||
|
Make .themedump file:
|
||||||
# TODO:
|
`cargo run --example generate_themes themepack sublime_themes sublime_themes/all.themedump`
|
||||||
|
|
||||||
- find a way to add tests
|
|
||||||
- syntax highlighting
|
|
||||||
- pass a --config arg to the CLI to change from `config.toml`
|
|
||||||
- have verbosity levels with a `verbosity` config variable with a default
|
|
||||||
|
|
45
examples/generate_themes.rs
Normal file
45
examples/generate_themes.rs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
//! This program is mainly intended for generating the dumps that are compiled in to
|
||||||
|
//! syntect, not as a helpful example for beginners.
|
||||||
|
//! Although it is a valid example for serializing syntaxes, you probably won't need
|
||||||
|
//! to do this yourself unless you want to cache your own compiled grammars.
|
||||||
|
extern crate syntect;
|
||||||
|
use syntect::parsing::SyntaxSet;
|
||||||
|
use syntect::highlighting::ThemeSet;
|
||||||
|
use syntect::dumps::*;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
fn usage_and_exit() -> ! {
|
||||||
|
println!("USAGE: gendata synpack source-dir newlines.packdump nonewlines.packdump\n
|
||||||
|
gendata themepack source-dir themepack.themedump");
|
||||||
|
::std::process::exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
|
||||||
|
let mut a = env::args().skip(1);
|
||||||
|
match (a.next(), a.next(), a.next(), a.next()) {
|
||||||
|
(Some(ref cmd),
|
||||||
|
Some(ref package_dir),
|
||||||
|
Some(ref packpath_newlines),
|
||||||
|
Some(ref packpath_nonewlines)) if cmd == "synpack" => {
|
||||||
|
let mut ps = SyntaxSet::new();
|
||||||
|
ps.load_plain_text_syntax();
|
||||||
|
ps.load_syntaxes(package_dir, true).unwrap();
|
||||||
|
dump_to_file(&ps, packpath_newlines).unwrap();
|
||||||
|
|
||||||
|
ps = SyntaxSet::new();
|
||||||
|
ps.load_plain_text_syntax();
|
||||||
|
ps.load_syntaxes(package_dir, false).unwrap();
|
||||||
|
dump_to_file(&ps, packpath_nonewlines).unwrap();
|
||||||
|
|
||||||
|
}
|
||||||
|
(Some(ref s), Some(ref theme_dir), Some(ref packpath), None) if s == "themepack" => {
|
||||||
|
let ts = ThemeSet::load_from_folder(theme_dir).unwrap();
|
||||||
|
for (path, _) in &ts.themes {
|
||||||
|
println!("{:?}", path);
|
||||||
|
}
|
||||||
|
dump_to_file(&ts, packpath).unwrap();
|
||||||
|
}
|
||||||
|
_ => usage_and_exit(),
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +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;
|
||||||
|
|
||||||
|
|
||||||
// TO ADD:
|
// TO ADD:
|
||||||
|
@ -22,6 +23,8 @@ pub struct Config {
|
||||||
|
|
||||||
/// Whether to highlight all code blocks found in markdown files. Defaults to false
|
/// Whether to highlight all code blocks found in markdown files. Defaults to false
|
||||||
pub highlight_code: Option<bool>,
|
pub highlight_code: Option<bool>,
|
||||||
|
/// Which themes to use for code highlighting. See Readme for supported themes
|
||||||
|
pub highlight_theme: Option<String>,
|
||||||
/// Description of the site
|
/// Description of the site
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
/// The language used in the site. Defaults to "en"
|
/// The language used in the site. Defaults to "en"
|
||||||
|
@ -50,6 +53,15 @@ impl Config {
|
||||||
config.highlight_code = Some(false);
|
config.highlight_code = Some(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match config.highlight_theme {
|
||||||
|
Some(ref t) => {
|
||||||
|
if !SETUP.theme_set.themes.contains_key(t) {
|
||||||
|
bail!("Theme {} not available", t)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => config.highlight_theme = Some("base16-ocean-dark".to_string())
|
||||||
|
};
|
||||||
|
|
||||||
if config.generate_rss.is_none() {
|
if config.generate_rss.is_none() {
|
||||||
config.generate_rss = Some(false);
|
config.generate_rss = Some(false);
|
||||||
}
|
}
|
||||||
|
@ -84,6 +96,7 @@ impl Default for Config {
|
||||||
title: "".to_string(),
|
title: "".to_string(),
|
||||||
base_url: "http://a-website.com/".to_string(),
|
base_url: "http://a-website.com/".to_string(),
|
||||||
highlight_code: Some(true),
|
highlight_code: Some(true),
|
||||||
|
highlight_theme: Some("base16-ocean-dark".to_string()),
|
||||||
description: None,
|
description: None,
|
||||||
language_code: Some("en".to_string()),
|
language_code: Some("en".to_string()),
|
||||||
generate_rss: Some(false),
|
generate_rss: Some(false),
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::borrow::Cow::Owned;
|
||||||
use pulldown_cmark as cmark;
|
use pulldown_cmark as cmark;
|
||||||
use self::cmark::{Parser, Event, Tag};
|
use self::cmark::{Parser, Event, Tag};
|
||||||
|
|
||||||
|
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::highlighting::ThemeSet;
|
||||||
|
@ -10,18 +11,18 @@ use syntect::html::{start_coloured_html_snippet, styles_to_coloured_html, Includ
|
||||||
|
|
||||||
|
|
||||||
// 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
|
||||||
struct Setup {
|
pub struct Setup {
|
||||||
syntax_set: SyntaxSet,
|
syntax_set: SyntaxSet,
|
||||||
theme_set: ThemeSet,
|
pub theme_set: ThemeSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Setup {}
|
unsafe impl Send for Setup {}
|
||||||
unsafe impl Sync for Setup {}
|
unsafe impl Sync for Setup {}
|
||||||
|
|
||||||
lazy_static!{
|
lazy_static!{
|
||||||
static ref SETUP: Setup = Setup {
|
pub static ref SETUP: Setup = Setup {
|
||||||
syntax_set: SyntaxSet::load_defaults_newlines(),
|
syntax_set: SyntaxSet::load_defaults_newlines(),
|
||||||
theme_set: ThemeSet::load_defaults()
|
theme_set: from_binary(include_bytes!("../sublime_themes/all.themedump"))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,13 +31,15 @@ struct CodeHighlightingParser<'a> {
|
||||||
// The block we're currently highlighting
|
// The block we're currently highlighting
|
||||||
highlighter: Option<HighlightLines<'a>>,
|
highlighter: Option<HighlightLines<'a>>,
|
||||||
parser: Parser<'a>,
|
parser: Parser<'a>,
|
||||||
|
theme: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CodeHighlightingParser<'a> {
|
impl<'a> CodeHighlightingParser<'a> {
|
||||||
pub fn new(parser: Parser<'a>) -> CodeHighlightingParser<'a> {
|
pub fn new(parser: Parser<'a>, theme: &'a str) -> CodeHighlightingParser<'a> {
|
||||||
CodeHighlightingParser {
|
CodeHighlightingParser {
|
||||||
highlighter: None,
|
highlighter: None,
|
||||||
parser: parser,
|
parser: parser,
|
||||||
|
theme: theme,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,15 +70,16 @@ impl<'a> Iterator for CodeHighlightingParser<'a> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Event::Start(Tag::CodeBlock(ref info)) => {
|
Event::Start(Tag::CodeBlock(ref info)) => {
|
||||||
|
let theme = &SETUP.theme_set.themes[self.theme];
|
||||||
let syntax = info
|
let syntax = info
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.next()
|
.next()
|
||||||
.and_then(|lang| SETUP.syntax_set.find_syntax_by_token(lang))
|
.and_then(|lang| SETUP.syntax_set.find_syntax_by_token(lang))
|
||||||
.unwrap_or_else(|| SETUP.syntax_set.find_syntax_plain_text());
|
.unwrap_or_else(|| SETUP.syntax_set.find_syntax_plain_text());
|
||||||
self.highlighter = Some(
|
self.highlighter = Some(
|
||||||
HighlightLines::new(syntax, &SETUP.theme_set.themes["base16-ocean.dark"])
|
HighlightLines::new(syntax, &theme)
|
||||||
);
|
);
|
||||||
let snippet = start_coloured_html_snippet(&SETUP.theme_set.themes["base16-ocean.dark"]);
|
let snippet = start_coloured_html_snippet(&theme);
|
||||||
Some(Event::Html(Owned(snippet)))
|
Some(Event::Html(Owned(snippet)))
|
||||||
},
|
},
|
||||||
Event::End(Tag::CodeBlock(_)) => {
|
Event::End(Tag::CodeBlock(_)) => {
|
||||||
|
@ -89,10 +93,10 @@ impl<'a> Iterator for CodeHighlightingParser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn markdown_to_html(content: &str, highlight_code: bool) -> String {
|
pub fn markdown_to_html(content: &str, highlight_code: bool, highlight_theme: &str) -> String {
|
||||||
let mut html = String::new();
|
let mut html = String::new();
|
||||||
if highlight_code {
|
if highlight_code {
|
||||||
let parser = CodeHighlightingParser::new(Parser::new(content));
|
let parser = CodeHighlightingParser::new(Parser::new(content), highlight_theme);
|
||||||
cmark::html::push_html(&mut html, parser);
|
cmark::html::push_html(&mut html, parser);
|
||||||
} else {
|
} else {
|
||||||
let parser = Parser::new(content);
|
let parser = Parser::new(content);
|
||||||
|
@ -108,13 +112,13 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_markdown_to_html_simple() {
|
fn test_markdown_to_html_simple() {
|
||||||
let res = markdown_to_html("# hello", true);
|
let res = markdown_to_html("# hello", true, "base16-ocean-dark");
|
||||||
assert_eq!(res, "<h1>hello</h1>\n");
|
assert_eq!(res, "<h1>hello</h1>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_markdown_to_html_code_block_highlighting_off() {
|
fn test_markdown_to_html_code_block_highlighting_off() {
|
||||||
let res = markdown_to_html("```\n$ gutenberg server\n```", false);
|
let res = markdown_to_html("```\n$ gutenberg server\n```", false, "base16-ocean-dark");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res,
|
res,
|
||||||
"<pre><code>$ gutenberg server\n</code></pre>\n"
|
"<pre><code>$ gutenberg server\n</code></pre>\n"
|
||||||
|
@ -123,7 +127,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_markdown_to_html_code_block_no_lang() {
|
fn test_markdown_to_html_code_block_no_lang() {
|
||||||
let res = markdown_to_html("```\n$ gutenberg server\n$ ping\n```", true);
|
let res = markdown_to_html("```\n$ gutenberg server\n$ ping\n```", true, "base16-ocean-dark");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res,
|
res,
|
||||||
"<pre style=\"background-color:#2b303b\">\n<span style=\"background-color:#2b303b;color:#c0c5ce;\">$ gutenberg server\n</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">$ ping\n</span></pre>"
|
"<pre style=\"background-color:#2b303b\">\n<span style=\"background-color:#2b303b;color:#c0c5ce;\">$ gutenberg server\n</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">$ ping\n</span></pre>"
|
||||||
|
@ -132,7 +136,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_markdown_to_html_code_block_with_lang() {
|
fn test_markdown_to_html_code_block_with_lang() {
|
||||||
let res = markdown_to_html("```python\nlist.append(1)\n```", true);
|
let res = markdown_to_html("```python\nlist.append(1)\n```", true, "base16-ocean-dark");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res,
|
res,
|
||||||
"<pre style=\"background-color:#2b303b\">\n<span style=\"background-color:#2b303b;color:#c0c5ce;\">list</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">.</span><span style=\"background-color:#2b303b;color:#bf616a;\">append</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">(</span><span style=\"background-color:#2b303b;color:#d08770;\">1</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">)</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">\n</span></pre>"
|
"<pre style=\"background-color:#2b303b\">\n<span style=\"background-color:#2b303b;color:#c0c5ce;\">list</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">.</span><span style=\"background-color:#2b303b;color:#bf616a;\">append</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">(</span><span style=\"background-color:#2b303b;color:#d08770;\">1</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">)</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">\n</span></pre>"
|
||||||
|
@ -140,7 +144,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_markdown_to_html_code_block_with_unknown_lang() {
|
fn test_markdown_to_html_code_block_with_unknown_lang() {
|
||||||
let res = markdown_to_html("```yolo\nlist.append(1)\n```", true);
|
let res = markdown_to_html("```yolo\nlist.append(1)\n```", true, "base16-ocean-dark");
|
||||||
// defaults to plain text
|
// defaults to plain text
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res,
|
res,
|
||||||
|
|
|
@ -132,12 +132,13 @@ impl Page {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
page.content = markdown_to_html(&page.raw_content, should_highlight);
|
let highlight_theme = config.highlight_theme.clone().unwrap();
|
||||||
|
page.content = markdown_to_html(&page.raw_content, should_highlight, &highlight_theme);
|
||||||
|
|
||||||
if page.raw_content.contains("<!-- more -->") {
|
if page.raw_content.contains("<!-- more -->") {
|
||||||
page.summary = {
|
page.summary = {
|
||||||
let summary = page.raw_content.splitn(2, "<!-- more -->").collect::<Vec<&str>>()[0];
|
let summary = page.raw_content.splitn(2, "<!-- more -->").collect::<Vec<&str>>()[0];
|
||||||
markdown_to_html(summary, should_highlight)
|
markdown_to_html(summary, should_highlight, &highlight_theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
BIN
sublime_themes/all.themedump
Normal file
BIN
sublime_themes/all.themedump
Normal file
Binary file not shown.
Loading…
Reference in a new issue