Integrating Ace #247
This commit is contained in:
parent
6601dbdd61
commit
16aa545c5b
|
@ -13,9 +13,9 @@ use errors::*;
|
|||
|
||||
use config::BookConfig;
|
||||
use config::tomlconfig::TomlConfig;
|
||||
use config::htmlconfig::HtmlConfig;
|
||||
use config::jsonconfig::JsonConfig;
|
||||
|
||||
|
||||
pub struct MDBook {
|
||||
config: BookConfig,
|
||||
|
||||
|
@ -496,6 +496,10 @@ impl MDBook {
|
|||
.get_additional_css()
|
||||
}
|
||||
|
||||
pub fn get_html_config(&self) -> &HtmlConfig {
|
||||
self.config.get_html_config()
|
||||
}
|
||||
|
||||
// Construct book
|
||||
fn parse_summary(&mut self) -> Result<()> {
|
||||
// When append becomes stable, use self.content.append() ...
|
||||
|
|
|
@ -112,7 +112,7 @@ impl BookConfig {
|
|||
self.get_mut_html_config()
|
||||
.fill_from_tomlconfig(root, tomlhtmlconfig);
|
||||
}
|
||||
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -213,7 +213,7 @@ impl BookConfig {
|
|||
self.authors.as_slice()
|
||||
}
|
||||
|
||||
pub fn set_html_config(&mut self, htmlconfig: HtmlConfig) -> &mut Self {
|
||||
pub fn set_html_config(&mut self, htmlconfig: HtmlConfig) -> &mut Self {
|
||||
self.html_config = htmlconfig;
|
||||
self
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::path::{PathBuf, Path};
|
||||
|
||||
use super::tomlconfig::TomlHtmlConfig;
|
||||
use super::playpenconfig::PlaypenConfig;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct HtmlConfig {
|
||||
|
@ -11,6 +12,7 @@ pub struct HtmlConfig {
|
|||
google_analytics: Option<String>,
|
||||
additional_css: Vec<PathBuf>,
|
||||
additional_js: Vec<PathBuf>,
|
||||
playpen: PlaypenConfig,
|
||||
}
|
||||
|
||||
impl HtmlConfig {
|
||||
|
@ -27,14 +29,16 @@ impl HtmlConfig {
|
|||
/// ```
|
||||
pub fn new<T: Into<PathBuf>>(root: T) -> Self {
|
||||
let root = root.into();
|
||||
let theme = root.join("theme");
|
||||
HtmlConfig {
|
||||
destination: root.clone().join("book"),
|
||||
theme: root.join("theme"),
|
||||
theme: theme.clone(),
|
||||
curly_quotes: false,
|
||||
mathjax_support: false,
|
||||
google_analytics: None,
|
||||
additional_css: Vec::new(),
|
||||
additional_js: Vec::new(),
|
||||
playpen: PlaypenConfig::new(theme),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,6 +85,10 @@ impl HtmlConfig {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(playpen) = tomlconfig.playpen {
|
||||
self.playpen.fill_from_tomlconfig(&self.theme, playpen);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -154,4 +162,12 @@ impl HtmlConfig {
|
|||
pub fn get_additional_js(&self) -> &[PathBuf] {
|
||||
&self.additional_js
|
||||
}
|
||||
|
||||
pub fn get_playpen_config(&self) -> &PlaypenConfig {
|
||||
&self.playpen
|
||||
}
|
||||
|
||||
pub fn get_mut_playpen_config(&mut self) -> &mut PlaypenConfig {
|
||||
&mut self.playpen
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
pub mod bookconfig;
|
||||
pub mod htmlconfig;
|
||||
pub mod playpenconfig;
|
||||
pub mod tomlconfig;
|
||||
pub mod jsonconfig;
|
||||
|
||||
// Re-export the config structs
|
||||
pub use self::bookconfig::BookConfig;
|
||||
pub use self::htmlconfig::HtmlConfig;
|
||||
pub use self::playpenconfig::PlaypenConfig;
|
||||
pub use self::tomlconfig::TomlConfig;
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
use std::path::{PathBuf, Path};
|
||||
|
||||
use super::tomlconfig::TomlPlaypenConfig;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct PlaypenConfig {
|
||||
editor: PathBuf,
|
||||
editable: bool,
|
||||
}
|
||||
|
||||
impl PlaypenConfig {
|
||||
/// Creates a new `PlaypenConfig` for playpen configuration.
|
||||
///
|
||||
/// ```
|
||||
/// # use std::path::PathBuf;
|
||||
/// # use mdbook::config::PlaypenConfig;
|
||||
/// #
|
||||
/// let editor = PathBuf::from("root/editor");
|
||||
/// let config = PlaypenConfig::new(PathBuf::from("root"));
|
||||
///
|
||||
/// assert_eq!(config.get_editor(), &editor);
|
||||
/// assert_eq!(config.is_editable(), false);
|
||||
/// ```
|
||||
pub fn new<T: Into<PathBuf>>(root: T) -> Self {
|
||||
PlaypenConfig {
|
||||
editor: root.into().join("editor"),
|
||||
editable: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fill_from_tomlconfig<T: Into<PathBuf>>(&mut self, root: T, tomlplaypenconfig: TomlPlaypenConfig) -> &mut Self {
|
||||
let root = root.into();
|
||||
|
||||
if let Some(editor) = tomlplaypenconfig.editor {
|
||||
if editor.is_relative() {
|
||||
self.editor = root.join(editor);
|
||||
} else {
|
||||
self.editor = editor;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(editable) = tomlplaypenconfig.editable {
|
||||
self.editable = editable;
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn is_editable(&self) -> bool {
|
||||
self.editable
|
||||
}
|
||||
|
||||
pub fn get_editor(&self) -> &Path {
|
||||
&self.editor
|
||||
}
|
||||
|
||||
pub fn set_editor<T: Into<PathBuf>>(&mut self, root: T, editor: T) -> &mut Self {
|
||||
let editor = editor.into();
|
||||
|
||||
if editor.is_relative() {
|
||||
self.editor = root.into().join(editor);
|
||||
} else {
|
||||
self.editor = editor;
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
|
@ -29,6 +29,13 @@ pub struct TomlHtmlConfig {
|
|||
pub mathjax_support: Option<bool>,
|
||||
pub additional_css: Option<Vec<PathBuf>>,
|
||||
pub additional_js: Option<Vec<PathBuf>>,
|
||||
pub playpen: Option<TomlPlaypenConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct TomlPlaypenConfig {
|
||||
pub editor: Option<PathBuf>,
|
||||
pub editable: Option<bool>,
|
||||
}
|
||||
|
||||
/// Returns a `TomlConfig` from a TOML string
|
||||
|
@ -52,5 +59,3 @@ impl TomlConfig {
|
|||
Ok(config)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,8 +3,9 @@ use preprocess;
|
|||
use renderer::Renderer;
|
||||
use book::MDBook;
|
||||
use book::bookitem::{BookItem, Chapter};
|
||||
use utils;
|
||||
use theme::{self, Theme};
|
||||
use config::PlaypenConfig;
|
||||
use {utils, theme};
|
||||
use theme::{Theme, playpen_editor};
|
||||
use errors::*;
|
||||
use regex::{Regex, Captures};
|
||||
|
||||
|
@ -19,7 +20,6 @@ use handlebars::Handlebars;
|
|||
|
||||
use serde_json;
|
||||
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct HtmlHandlebars;
|
||||
|
||||
|
@ -69,8 +69,11 @@ impl HtmlHandlebars {
|
|||
// Render the handlebars template with the data
|
||||
debug!("[*]: Render template");
|
||||
let rendered = ctx.handlebars.render("index", &ctx.data)?;
|
||||
|
||||
let filename = Path::new(&ch.path).with_extension("html");
|
||||
let rendered = self.post_process(rendered, filename.file_name().unwrap().to_str().unwrap_or(""));
|
||||
let rendered = self.post_process(rendered,
|
||||
filename.file_name().unwrap().to_str().unwrap_or(""),
|
||||
ctx.book.get_html_config().get_playpen_config());
|
||||
|
||||
// Write to file
|
||||
info!("[*] Creating {:?} ✓", filename.display());
|
||||
|
@ -116,11 +119,11 @@ impl HtmlHandlebars {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn post_process(&self, rendered: String, filename: &str) -> String {
|
||||
fn post_process(&self, rendered: String, filename: &str, playpen_config: &PlaypenConfig) -> String {
|
||||
let rendered = build_header_links(&rendered, filename);
|
||||
let rendered = fix_anchor_links(&rendered, filename);
|
||||
let rendered = fix_code_blocks(&rendered);
|
||||
let rendered = add_playpen_pre(&rendered);
|
||||
let rendered = add_playpen_pre(&rendered, playpen_config);
|
||||
|
||||
rendered
|
||||
}
|
||||
|
@ -171,6 +174,19 @@ impl HtmlHandlebars {
|
|||
theme::FONT_AWESOME_TTF,
|
||||
)?;
|
||||
|
||||
let playpen_config = book.get_html_config().get_playpen_config();
|
||||
|
||||
// Ace is a very large dependency, so only load it when requested
|
||||
if playpen_config.is_editable() {
|
||||
// Load the editor
|
||||
let editor = playpen_editor::PlaypenEditor::new(playpen_config.get_editor());
|
||||
book.write_file("editor.js", &editor.js)?;
|
||||
book.write_file("ace.js", &editor.ace_js)?;
|
||||
book.write_file("mode-rust.js", &editor.mode_rust_js)?;
|
||||
book.write_file("theme-dawn.js", &editor.theme_dawn_js)?;
|
||||
book.write_file("theme-tomorrow_night.js", &editor.theme_tomorrow_night_js)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -273,8 +289,10 @@ impl Renderer for HtmlHandlebars {
|
|||
debug!("[*]: Render template");
|
||||
|
||||
let rendered = handlebars.render("index", &data)?;
|
||||
let rendered = self.post_process(rendered, "print.html");
|
||||
|
||||
let rendered = self.post_process(rendered, "print.html",
|
||||
book.get_html_config().get_playpen_config());
|
||||
|
||||
book.write_file(
|
||||
Path::new("print").with_extension("html"),
|
||||
&rendered.into_bytes(),
|
||||
|
@ -354,6 +372,15 @@ fn make_data(book: &MDBook) -> Result<serde_json::Map<String, serde_json::Value>
|
|||
data.insert("additional_js".to_owned(), json!(js));
|
||||
}
|
||||
|
||||
if book.get_html_config().get_playpen_config().is_editable() {
|
||||
data.insert("playpens_editable".to_owned(), json!(true));
|
||||
data.insert("editor_js".to_owned(), json!("editor.js"));
|
||||
data.insert("ace_js".to_owned(), json!("ace.js"));
|
||||
data.insert("mode_rust_js".to_owned(), json!("mode-rust.js"));
|
||||
data.insert("theme_dawn_js".to_owned(), json!("theme-dawn.js"));
|
||||
data.insert("theme_tomorrow_night_js".to_owned(), json!("theme-tomorrow_night.js"));
|
||||
}
|
||||
|
||||
let mut chapters = vec![];
|
||||
|
||||
for item in book.iter() {
|
||||
|
@ -512,7 +539,7 @@ fn fix_code_blocks(html: &str) -> String {
|
|||
.into_owned()
|
||||
}
|
||||
|
||||
fn add_playpen_pre(html: &str) -> String {
|
||||
fn add_playpen_pre(html: &str, playpen_config: &PlaypenConfig) -> String {
|
||||
let regex = Regex::new(r##"((?s)<code[^>]?class="([^"]+)".*?>(.*?)</code>)"##).unwrap();
|
||||
regex
|
||||
.replace_all(html, |caps: &Captures| {
|
||||
|
@ -522,22 +549,18 @@ fn add_playpen_pre(html: &str) -> String {
|
|||
|
||||
if classes.contains("language-rust") && !classes.contains("ignore") {
|
||||
// wrap the contents in an external pre block
|
||||
|
||||
if text.contains("fn main") || text.contains("quick_main!") {
|
||||
if playpen_config.is_editable() &&
|
||||
classes.contains("editable") || text.contains("fn main") || text.contains("quick_main!") {
|
||||
format!("<pre class=\"playpen\">{}</pre>", text)
|
||||
} else {
|
||||
// we need to inject our own main
|
||||
let (attrs, code) = partition_source(code);
|
||||
format!(
|
||||
"<pre class=\"playpen\"><code class=\"{}\"># #![allow(unused_variables)]
|
||||
{}#fn main() {{
|
||||
\
|
||||
{}
|
||||
#}}</code></pre>",
|
||||
classes,
|
||||
attrs,
|
||||
code
|
||||
)
|
||||
|
||||
format!("<pre class=\"playpen\"><code class=\"{}\">\n# #![allow(unused_variables)]\n\
|
||||
{}#fn main() {{\n\
|
||||
{}\
|
||||
#}}</code></pre>",
|
||||
classes, attrs, code)
|
||||
}
|
||||
} else {
|
||||
// not language-rust, so no-op
|
||||
|
|
|
@ -936,6 +936,9 @@ table thead td {
|
|||
/* Force background to be printed in Chrome */
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
pre > .buttons {
|
||||
z-index: 2;
|
||||
}
|
||||
a,
|
||||
a:visited,
|
||||
a:active,
|
||||
|
|
|
@ -12,16 +12,25 @@ $( document ).ready(function() {
|
|||
|
||||
set_theme(theme);
|
||||
|
||||
|
||||
// Syntax highlighting Configuration
|
||||
hljs.configure({
|
||||
tabReplace: ' ', // 4 spaces
|
||||
languages: [], // Languages used for auto-detection
|
||||
});
|
||||
|
||||
if (window.ace) {
|
||||
// language-rust class needs to be removed for editable
|
||||
// blocks or highlightjs will capture events
|
||||
$('code.editable').removeClass('language-rust');
|
||||
|
||||
$('code').each(function(i, block) {
|
||||
hljs.highlightBlock(block);
|
||||
});
|
||||
$('code').not('.editable').each(function(i, block) {
|
||||
hljs.highlightBlock(block);
|
||||
});
|
||||
} else {
|
||||
$('code').each(function(i, block) {
|
||||
hljs.highlightBlock(block);
|
||||
});
|
||||
}
|
||||
|
||||
// Adding the hljs class gives code blocks the color css
|
||||
// even if highlighting doesn't apply
|
||||
|
@ -118,18 +127,32 @@ $( document ).ready(function() {
|
|||
});
|
||||
|
||||
function set_theme(theme) {
|
||||
let ace_theme;
|
||||
|
||||
if (theme == 'coal' || theme == 'navy') {
|
||||
$("[href='ayu-highlight.css']").prop('disabled', true);
|
||||
$("[href='tomorrow-night.css']").prop('disabled', false);
|
||||
$("[href='highlight.css']").prop('disabled', true);
|
||||
|
||||
ace_theme = "ace/theme/tomorrow_night";
|
||||
} else if (theme == 'ayu') {
|
||||
$("[href='ayu-highlight.css']").prop('disabled', false);
|
||||
$("[href='tomorrow-night.css']").prop('disabled', true);
|
||||
$("[href='highlight.css']").prop('disabled', true);
|
||||
|
||||
ace_theme = "ace/theme/tomorrow_night";
|
||||
} else {
|
||||
$("[href='ayu-highlight.css']").prop('disabled', true);
|
||||
$("[href='tomorrow-night.css']").prop('disabled', true);
|
||||
$("[href='highlight.css']").prop('disabled', false);
|
||||
|
||||
ace_theme = "ace/theme/dawn";
|
||||
}
|
||||
|
||||
if (window.ace && window.editors) {
|
||||
window.editors.forEach(function(editor) {
|
||||
editor.setTheme(ace_theme);
|
||||
});
|
||||
}
|
||||
|
||||
store.set('theme', theme);
|
||||
|
@ -187,7 +210,6 @@ $( document ).ready(function() {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
// Process playpen code blocks
|
||||
$(".playpen").each(function(block){
|
||||
var pre_block = $(this);
|
||||
|
@ -200,18 +222,37 @@ $( document ).ready(function() {
|
|||
buttons.prepend("<i class=\"fa fa-play play-button\"></i>");
|
||||
buttons.prepend("<i class=\"fa fa-copy clip-button\"><i class=\"tooltiptext\"></i></i>");
|
||||
|
||||
let code_block = pre_block.find("code").first();
|
||||
if (window.ace && code_block.hasClass("editable")) {
|
||||
buttons.prepend("<i class=\"fa fa-history reset-button\"></i>");
|
||||
}
|
||||
|
||||
buttons.find(".play-button").click(function(e){
|
||||
run_rust_code(pre_block);
|
||||
});
|
||||
buttons.find(".clip-button").mouseout(function(e){
|
||||
hideTooltip(e.currentTarget);
|
||||
});
|
||||
buttons.find(".reset-button").click(function() {
|
||||
if (!window.ace) { return; }
|
||||
let editor = window.ace.edit(code_block.get(0));
|
||||
editor.setValue(editor.originalCode);
|
||||
editor.clearSelection();
|
||||
});
|
||||
});
|
||||
|
||||
var clipboardSnippets = new Clipboard('.clip-button', {
|
||||
text: function(trigger) {
|
||||
hideTooltip(trigger);
|
||||
return $(trigger).parents(".playpen").find("code.language-rust.hljs")[0].textContent;
|
||||
let playpen = $(trigger).parents(".playpen");
|
||||
let code_block = playpen.find("code").first();
|
||||
|
||||
if (window.ace && code_block.hasClass("editable")) {
|
||||
let editor = window.ace.edit(code_block.get(0));
|
||||
return editor.getValue();
|
||||
} else {
|
||||
return code_block.get(0).textContent;
|
||||
}
|
||||
}
|
||||
});
|
||||
clipboardSnippets.on('success', function(e) {
|
||||
|
@ -221,7 +262,6 @@ $( document ).ready(function() {
|
|||
clipboardSnippets.on('error', function(e) {
|
||||
showTooltip(e.trigger, "Clipboard error!");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function hideTooltip(elem) {
|
||||
|
@ -260,7 +300,15 @@ function run_rust_code(code_block) {
|
|||
result_block = code_block.find(".result");
|
||||
}
|
||||
|
||||
var text = code_block.find(".language-rust").text();
|
||||
let text;
|
||||
|
||||
let inner_code_block = code_block.find("code").first();
|
||||
if (window.ace && inner_code_block.hasClass("editable")) {
|
||||
let editor = window.ace.edit(inner_code_block.get(0));
|
||||
text = editor.getValue();
|
||||
} else {
|
||||
text = inner_code_block.text();
|
||||
}
|
||||
|
||||
var params = {
|
||||
version: "stable",
|
||||
|
|
|
@ -146,8 +146,15 @@
|
|||
ga('create', '{{google_analytics}}', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#if playpens_editable}}
|
||||
<script src="{{ ace_js }}" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{ editor_js }}" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{ mode_rust_js }}" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{ theme_dawn_js }}" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{ theme_tomorrow_night_js }}" type="text/javascript" charset="utf-8"></script>
|
||||
{{/if}}
|
||||
|
||||
<script src="highlight.js"></script>
|
||||
<script src="book.js"></script>
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
pub mod playpen_editor;
|
||||
|
||||
use std::path::Path;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
||||
use errors::*;
|
||||
|
||||
|
||||
pub static INDEX: &'static [u8] = include_bytes!("index.hbs");
|
||||
pub static CSS: &'static [u8] = include_bytes!("book.css");
|
||||
pub static FAVICON: &'static [u8] = include_bytes!("favicon.png");
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
window.editors = [];
|
||||
(function(editors) {
|
||||
if (typeof(ace) === 'undefined' || !ace) {
|
||||
return;
|
||||
}
|
||||
|
||||
$(".editable").each(function() {
|
||||
let editor = ace.edit(this);
|
||||
editor.setOptions({
|
||||
highlightActiveLine: false,
|
||||
showPrintMargin: false,
|
||||
showLineNumbers: false,
|
||||
showGutter: false,
|
||||
maxLines: Infinity
|
||||
});
|
||||
|
||||
editor.$blockScrolling = Infinity;
|
||||
|
||||
editor.getSession().setMode("ace/mode/rust");
|
||||
|
||||
editor.originalCode = editor.getValue();
|
||||
|
||||
editors.push(editor);
|
||||
});
|
||||
})(window.editors);
|
|
@ -0,0 +1,71 @@
|
|||
use std::path::Path;
|
||||
|
||||
use theme::load_file_contents;
|
||||
|
||||
pub static JS: &'static [u8] = include_bytes!("editor.js");
|
||||
pub static ACE_JS: &'static [u8] = include_bytes!("ace.js");
|
||||
pub static MODE_RUST_JS: &'static [u8] = include_bytes!("mode-rust.js");
|
||||
pub static THEME_DAWN_JS: &'static [u8] = include_bytes!("theme-dawn.js");
|
||||
pub static THEME_TOMORROW_NIGHT_JS: &'static [u8] = include_bytes!("theme-tomorrow_night.js");
|
||||
|
||||
/// Integration of a JavaScript editor for playpens.
|
||||
/// Uses the Ace editor: https://ace.c9.io/.
|
||||
/// The Ace editor itself, the mode, and the theme files are the
|
||||
/// generated minified no conflict versions.
|
||||
///
|
||||
/// The `PlaypenEditor` struct should be used instead of the static variables because
|
||||
/// the `new()` method
|
||||
/// will look if the user has an editor directory in his source folder and use
|
||||
/// the users editor instead
|
||||
/// of the default.
|
||||
///
|
||||
/// You should exceptionnaly use the static variables only if you need the
|
||||
/// default editor even if the
|
||||
/// user has specified another editor.
|
||||
pub struct PlaypenEditor {
|
||||
pub js: Vec<u8>,
|
||||
pub ace_js: Vec<u8>,
|
||||
pub mode_rust_js: Vec<u8>,
|
||||
pub theme_dawn_js: Vec<u8>,
|
||||
pub theme_tomorrow_night_js: Vec<u8>,
|
||||
}
|
||||
|
||||
impl PlaypenEditor {
|
||||
pub fn new(src: &Path) -> Self {
|
||||
let mut editor = PlaypenEditor {
|
||||
js: JS.to_owned(),
|
||||
ace_js: ACE_JS.to_owned(),
|
||||
mode_rust_js: MODE_RUST_JS.to_owned(),
|
||||
theme_dawn_js: THEME_DAWN_JS.to_owned(),
|
||||
theme_tomorrow_night_js: THEME_TOMORROW_NIGHT_JS.to_owned(),
|
||||
};
|
||||
|
||||
// Check if the given path exists
|
||||
if !src.exists() || !src.is_dir() {
|
||||
return editor;
|
||||
}
|
||||
|
||||
// Check for individual files if they exist
|
||||
{
|
||||
let files = vec![
|
||||
(src.join("editor.js"), &mut editor.js),
|
||||
(src.join("ace.js"), &mut editor.ace_js),
|
||||
(src.join("mode-rust.js"), &mut editor.mode_rust_js),
|
||||
(src.join("theme-dawn.js"), &mut editor.theme_dawn_js),
|
||||
(src.join("theme-tomorrow_night.js"), &mut editor.theme_tomorrow_night_js),
|
||||
];
|
||||
|
||||
for (filename, dest) in files {
|
||||
if !filename.exists() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Err(e) = load_file_contents(&filename, dest) {
|
||||
warn!("Couldn't load custom file, {}: {}", filename.display(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
editor
|
||||
}
|
||||
}
|
|
@ -30,6 +30,10 @@
|
|||
-webkit-print-color-adjust: exact
|
||||
}
|
||||
|
||||
pre > .buttons {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
a, a:visited, a:active, a:hover {
|
||||
color: #4183c4
|
||||
text-decoration: none
|
||||
|
|
|
@ -59,7 +59,49 @@ fn from_toml_authors() {
|
|||
assert_eq!(config.get_authors(), &[String::from("John Doe"), String::from("Jane Doe")]);
|
||||
}
|
||||
|
||||
// Tests that the `output.html.destination` key is correctly parsed in the TOML config
|
||||
// Tests that the default `playpen` config is correct in the TOML config
|
||||
#[test]
|
||||
fn from_toml_playpen_default() {
|
||||
let toml = "";
|
||||
|
||||
let parsed = TomlConfig::from_toml(toml).expect("This should parse");
|
||||
let config = BookConfig::from_tomlconfig("root", parsed);
|
||||
|
||||
let playpenconfig = config.get_html_config().get_playpen_config();
|
||||
|
||||
assert_eq!(playpenconfig.get_editor(), PathBuf::from("root/theme/editor"));
|
||||
assert_eq!(playpenconfig.is_editable(), false);
|
||||
}
|
||||
|
||||
// Tests that the `playpen.editor` key is correctly parsed in the TOML config
|
||||
#[test]
|
||||
fn from_toml_playpen_editor() {
|
||||
let toml = r#"[output.html.playpen]
|
||||
editor = "editordir""#;
|
||||
|
||||
let parsed = TomlConfig::from_toml(toml).expect("This should parse");
|
||||
let config = BookConfig::from_tomlconfig("root", parsed);
|
||||
|
||||
let playpenconfig = config.get_html_config().get_playpen_config();
|
||||
|
||||
assert_eq!(playpenconfig.get_editor(), PathBuf::from("root/theme/editordir"));
|
||||
}
|
||||
|
||||
// Tests that the `playpen.editable` key is correctly parsed in the TOML config
|
||||
#[test]
|
||||
fn from_toml_playpen_editable() {
|
||||
let toml = r#"[output.html.playpen]
|
||||
editable = true"#;
|
||||
|
||||
let parsed = TomlConfig::from_toml(toml).expect("This should parse");
|
||||
let config = BookConfig::from_tomlconfig("root", parsed);
|
||||
|
||||
let playpenconfig = config.get_html_config().get_playpen_config();
|
||||
|
||||
assert_eq!(playpenconfig.is_editable(), true);
|
||||
}
|
||||
|
||||
// Tests that the `output.html.destination` key is correcly parsed in the TOML config
|
||||
#[test]
|
||||
fn from_toml_output_html_destination() {
|
||||
let toml = r#"[output.html]
|
||||
|
|
Loading…
Reference in New Issue