Browse Source

Pick highlighting theme from config

index-subcmd
Vincent Prouillet 7 years ago
parent
commit
9af85ba3e4
6 changed files with 81 additions and 23 deletions
  1. +2
    -7
      README.md
  2. +45
    -0
      examples/generate_themes.rs
  3. +13
    -0
      src/config.rs
  4. +18
    -14
      src/markdown.rs
  5. +3
    -2
      src/page.rs
  6. BIN
      sublime_themes/all.themedump

+ 2
- 7
README.md View File

@@ -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

# TODO:

- 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
Make .themedump file:
`cargo run --example generate_themes themepack sublime_themes sublime_themes/all.themedump`

+ 45
- 0
examples/generate_themes.rs View 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(),
}
}

+ 13
- 0
src/config.rs View File

@@ -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),


+ 18
- 14
src/markdown.rs View File

@@ -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,


+ 3
- 2
src/page.rs View File

@@ -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 View File


Loading…
Cancel
Save