Add an option to convert to curly quotes when rendering to HTML
This commit is contained in:
parent
29708db467
commit
193f014a5b
|
@ -66,6 +66,7 @@ The following configuration options are available:
|
||||||
- **destination:** By default, the HTML book will be rendered in the `root/book` directory, but this option lets you specify another
|
- **destination:** By default, the HTML book will be rendered in the `root/book` directory, but this option lets you specify another
|
||||||
destination fodler.
|
destination fodler.
|
||||||
- **theme:** mdBook comes with a default theme and all the resource files needed for it. But if this option is set, mdBook will selectively overwrite the theme files with the ones found in the specified folder.
|
- **theme:** mdBook comes with a default theme and all the resource files needed for it. But if this option is set, mdBook will selectively overwrite the theme files with the ones found in the specified folder.
|
||||||
|
- **curly-quotes:** Convert straight quotes to curly quotes, except for those that occur in code blocks and code spans. Defaults to `false`.
|
||||||
- **google-analytics:** If you use Google Analytics, this option lets you enable it by simply specifying your ID in the configuration file.
|
- **google-analytics:** If you use Google Analytics, this option lets you enable it by simply specifying your ID in the configuration file.
|
||||||
- **additional-css:** If you need to slightly change the appearance of your book without overwriting the whole style, you can specify a set of stylesheets that will be loaded after the default ones where you can surgically change the style.
|
- **additional-css:** If you need to slightly change the appearance of your book without overwriting the whole style, you can specify a set of stylesheets that will be loaded after the default ones where you can surgically change the style.
|
||||||
|
|
||||||
|
@ -78,6 +79,7 @@ description = "The example book covers examples."
|
||||||
[output.html]
|
[output.html]
|
||||||
destination = "my-book" # the output files will be generated in `root/my-book` instead of `root/book`
|
destination = "my-book" # the output files will be generated in `root/my-book` instead of `root/book`
|
||||||
theme = "my-theme"
|
theme = "my-theme"
|
||||||
|
curly-quotes = true
|
||||||
google-analytics = "123456"
|
google-analytics = "123456"
|
||||||
additional-css = ["custom.css", "custom2.css"]
|
additional-css = ["custom.css", "custom2.css"]
|
||||||
```
|
```
|
||||||
|
|
|
@ -64,16 +64,19 @@ fn main() {
|
||||||
.arg_from_usage("-o, --open 'Open the compiled book in a web browser'")
|
.arg_from_usage("-o, --open 'Open the compiled book in a web browser'")
|
||||||
.arg_from_usage("-d, --dest-dir=[dest-dir] 'The output directory for your book{n}(Defaults to ./book when omitted)'")
|
.arg_from_usage("-d, --dest-dir=[dest-dir] 'The output directory for your book{n}(Defaults to ./book when omitted)'")
|
||||||
.arg_from_usage("--no-create 'Will not create non-existent files linked from SUMMARY.md'")
|
.arg_from_usage("--no-create 'Will not create non-existent files linked from SUMMARY.md'")
|
||||||
|
.arg_from_usage("--curly-quotes 'Convert straight quotes to curly quotes, except for those that occur in code blocks and code spans'")
|
||||||
.arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when omitted)'"))
|
.arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when omitted)'"))
|
||||||
.subcommand(SubCommand::with_name("watch")
|
.subcommand(SubCommand::with_name("watch")
|
||||||
.about("Watch the files for changes")
|
.about("Watch the files for changes")
|
||||||
.arg_from_usage("-o, --open 'Open the compiled book in a web browser'")
|
.arg_from_usage("-o, --open 'Open the compiled book in a web browser'")
|
||||||
.arg_from_usage("-d, --dest-dir=[dest-dir] 'The output directory for your book{n}(Defaults to ./book when omitted)'")
|
.arg_from_usage("-d, --dest-dir=[dest-dir] 'The output directory for your book{n}(Defaults to ./book when omitted)'")
|
||||||
|
.arg_from_usage("--curly-quotes 'Convert straight quotes to curly quotes, except for those that occur in code blocks and code spans'")
|
||||||
.arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when omitted)'"))
|
.arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when omitted)'"))
|
||||||
.subcommand(SubCommand::with_name("serve")
|
.subcommand(SubCommand::with_name("serve")
|
||||||
.about("Serve the book at http://localhost:3000. Rebuild and reload on change.")
|
.about("Serve the book at http://localhost:3000. Rebuild and reload on change.")
|
||||||
.arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when omitted)'")
|
.arg_from_usage("[dir] 'A directory for your book{n}(Defaults to Current Directory when omitted)'")
|
||||||
.arg_from_usage("-d, --dest-dir=[dest-dir] 'The output directory for your book{n}(Defaults to ./book when omitted)'")
|
.arg_from_usage("-d, --dest-dir=[dest-dir] 'The output directory for your book{n}(Defaults to ./book when omitted)'")
|
||||||
|
.arg_from_usage("--curly-quotes 'Convert straight quotes to curly quotes, except for those that occur in code blocks and code spans'")
|
||||||
.arg_from_usage("-p, --port=[port] 'Use another port{n}(Defaults to 3000)'")
|
.arg_from_usage("-p, --port=[port] 'Use another port{n}(Defaults to 3000)'")
|
||||||
.arg_from_usage("-w, --websocket-port=[ws-port] 'Use another port for the websocket connection (livereload){n}(Defaults to 3001)'")
|
.arg_from_usage("-w, --websocket-port=[ws-port] 'Use another port for the websocket connection (livereload){n}(Defaults to 3001)'")
|
||||||
.arg_from_usage("-i, --interface=[interface] 'Interface to listen on{n}(Defaults to localhost)'")
|
.arg_from_usage("-i, --interface=[interface] 'Interface to listen on{n}(Defaults to localhost)'")
|
||||||
|
@ -181,6 +184,10 @@ fn build(args: &ArgMatches) -> Result<(), Box<Error>> {
|
||||||
book.create_missing = false;
|
book.create_missing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if args.is_present("curly-quotes") {
|
||||||
|
book = book.with_curly_quotes(true);
|
||||||
|
}
|
||||||
|
|
||||||
book.build()?;
|
book.build()?;
|
||||||
|
|
||||||
if let Some(d) = book.get_destination() {
|
if let Some(d) = book.get_destination() {
|
||||||
|
@ -204,6 +211,10 @@ fn watch(args: &ArgMatches) -> Result<(), Box<Error>> {
|
||||||
None => book,
|
None => book,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if args.is_present("curly-quotes") {
|
||||||
|
book = book.with_curly_quotes(true);
|
||||||
|
}
|
||||||
|
|
||||||
if args.is_present("open") {
|
if args.is_present("open") {
|
||||||
book.build()?;
|
book.build()?;
|
||||||
if let Some(d) = book.get_destination() {
|
if let Some(d) = book.get_destination() {
|
||||||
|
@ -241,6 +252,10 @@ fn serve(args: &ArgMatches) -> Result<(), Box<Error>> {
|
||||||
std::process::exit(2);
|
std::process::exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if args.is_present("curly-quotes") {
|
||||||
|
book = book.with_curly_quotes(true);
|
||||||
|
}
|
||||||
|
|
||||||
let port = args.value_of("port").unwrap_or("3000");
|
let port = args.value_of("port").unwrap_or("3000");
|
||||||
let ws_port = args.value_of("websocket-port").unwrap_or("3001");
|
let ws_port = args.value_of("websocket-port").unwrap_or("3001");
|
||||||
let interface = args.value_of("interface").unwrap_or("localhost");
|
let interface = args.value_of("interface").unwrap_or("localhost");
|
||||||
|
|
|
@ -479,6 +479,23 @@ impl MDBook {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_curly_quotes(mut self, curly_quotes: bool) -> Self {
|
||||||
|
if let Some(htmlconfig) = self.config.get_mut_html_config() {
|
||||||
|
htmlconfig.set_curly_quotes(curly_quotes);
|
||||||
|
} else {
|
||||||
|
error!("There is no HTML renderer set...");
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_curly_quotes(&self) -> bool {
|
||||||
|
if let Some(htmlconfig) = self.config.get_html_config() {
|
||||||
|
return htmlconfig.get_curly_quotes();
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_google_analytics_id(&self) -> Option<String> {
|
pub fn get_google_analytics_id(&self) -> Option<String> {
|
||||||
if let Some(htmlconfig) = self.config.get_html_config() {
|
if let Some(htmlconfig) = self.config.get_html_config() {
|
||||||
return htmlconfig.get_google_analytics_id();
|
return htmlconfig.get_google_analytics_id();
|
||||||
|
|
|
@ -159,6 +159,12 @@ impl BookConfig {
|
||||||
htmlconfig.set_theme(&root, &d);
|
htmlconfig.set_theme(&root, &d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(curly_quotes) = jsonconfig.curly_quotes {
|
||||||
|
if let Some(htmlconfig) = self.get_mut_html_config() {
|
||||||
|
htmlconfig.set_curly_quotes(curly_quotes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use super::tomlconfig::TomlHtmlConfig;
|
||||||
pub struct HtmlConfig {
|
pub struct HtmlConfig {
|
||||||
destination: PathBuf,
|
destination: PathBuf,
|
||||||
theme: Option<PathBuf>,
|
theme: Option<PathBuf>,
|
||||||
|
curly_quotes: bool,
|
||||||
google_analytics: Option<String>,
|
google_analytics: Option<String>,
|
||||||
additional_css: Vec<PathBuf>,
|
additional_css: Vec<PathBuf>,
|
||||||
additional_js: Vec<PathBuf>,
|
additional_js: Vec<PathBuf>,
|
||||||
|
@ -27,6 +28,7 @@ impl HtmlConfig {
|
||||||
HtmlConfig {
|
HtmlConfig {
|
||||||
destination: root.into().join("book"),
|
destination: root.into().join("book"),
|
||||||
theme: None,
|
theme: None,
|
||||||
|
curly_quotes: false,
|
||||||
google_analytics: None,
|
google_analytics: None,
|
||||||
additional_css: Vec::new(),
|
additional_css: Vec::new(),
|
||||||
additional_js: Vec::new(),
|
additional_js: Vec::new(),
|
||||||
|
@ -52,6 +54,10 @@ impl HtmlConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(curly_quotes) = tomlconfig.curly_quotes {
|
||||||
|
self.curly_quotes = curly_quotes;
|
||||||
|
}
|
||||||
|
|
||||||
if tomlconfig.google_analytics.is_some() {
|
if tomlconfig.google_analytics.is_some() {
|
||||||
self.google_analytics = tomlconfig.google_analytics;
|
self.google_analytics = tomlconfig.google_analytics;
|
||||||
}
|
}
|
||||||
|
@ -110,6 +116,14 @@ impl HtmlConfig {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_curly_quotes(&self) -> bool {
|
||||||
|
self.curly_quotes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_curly_quotes(&mut self, curly_quotes: bool) {
|
||||||
|
self.curly_quotes = curly_quotes;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_google_analytics_id(&self) -> Option<String> {
|
pub fn get_google_analytics_id(&self) -> Option<String> {
|
||||||
self.google_analytics.clone()
|
self.google_analytics.clone()
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ pub struct JsonConfig {
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
|
||||||
pub theme_path: Option<PathBuf>,
|
pub theme_path: Option<PathBuf>,
|
||||||
|
pub curly_quotes: Option<bool>,
|
||||||
pub google_analytics: Option<String>,
|
pub google_analytics: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ pub struct TomlHtmlConfig {
|
||||||
pub destination: Option<PathBuf>,
|
pub destination: Option<PathBuf>,
|
||||||
pub theme: Option<PathBuf>,
|
pub theme: Option<PathBuf>,
|
||||||
pub google_analytics: Option<String>,
|
pub google_analytics: Option<String>,
|
||||||
|
pub curly_quotes: Option<bool>,
|
||||||
pub additional_css: Option<Vec<PathBuf>>,
|
pub additional_css: Option<Vec<PathBuf>>,
|
||||||
pub additional_js: Option<Vec<PathBuf>>,
|
pub additional_js: Option<Vec<PathBuf>>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ impl Renderer for HtmlHandlebars {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render markdown using the pulldown-cmark crate
|
// Render markdown using the pulldown-cmark crate
|
||||||
content = utils::render_markdown(&content);
|
content = utils::render_markdown(&content, book.get_curly_quotes());
|
||||||
print_content.push_str(&content);
|
print_content.push_str(&content);
|
||||||
|
|
||||||
// Update the context with data for this file
|
// Update the context with data for this file
|
||||||
|
|
108
src/utils/mod.rs
108
src/utils/mod.rs
|
@ -1,13 +1,14 @@
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
|
|
||||||
use pulldown_cmark::{Parser, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES};
|
use pulldown_cmark::{Parser, Event, Tag, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES};
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// Wrapper around the pulldown-cmark parser and renderer to render markdown
|
/// Wrapper around the pulldown-cmark parser and renderer to render markdown
|
||||||
|
|
||||||
pub fn render_markdown(text: &str) -> String {
|
pub fn render_markdown(text: &str, curly_quotes: bool) -> String {
|
||||||
let mut s = String::with_capacity(text.len() * 3 / 2);
|
let mut s = String::with_capacity(text.len() * 3 / 2);
|
||||||
|
|
||||||
let mut opts = Options::empty();
|
let mut opts = Options::empty();
|
||||||
|
@ -15,6 +16,107 @@ pub fn render_markdown(text: &str) -> String {
|
||||||
opts.insert(OPTION_ENABLE_FOOTNOTES);
|
opts.insert(OPTION_ENABLE_FOOTNOTES);
|
||||||
|
|
||||||
let p = Parser::new_ext(text, opts);
|
let p = Parser::new_ext(text, opts);
|
||||||
html::push_html(&mut s, p);
|
let mut converter = EventQuoteConverter::new(curly_quotes);
|
||||||
|
let events = p.map(|event| converter.convert(event));
|
||||||
|
html::push_html(&mut s, events);
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct EventQuoteConverter {
|
||||||
|
enabled: bool,
|
||||||
|
convert_text: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventQuoteConverter {
|
||||||
|
fn new(enabled: bool) -> Self {
|
||||||
|
EventQuoteConverter { enabled: enabled, convert_text: true }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert<'a>(&mut self, event: Event<'a>) -> Event<'a> {
|
||||||
|
if !self.enabled {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
match event {
|
||||||
|
Event::Start(Tag::CodeBlock(_)) |
|
||||||
|
Event::Start(Tag::Code) => {
|
||||||
|
self.convert_text = false;
|
||||||
|
event
|
||||||
|
},
|
||||||
|
Event::End(Tag::CodeBlock(_)) |
|
||||||
|
Event::End(Tag::Code) => {
|
||||||
|
self.convert_text = true;
|
||||||
|
event
|
||||||
|
},
|
||||||
|
Event::Text(ref text) if self.convert_text => Event::Text(Cow::from(convert_quotes_to_curly(text))),
|
||||||
|
_ => event,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_quotes_to_curly(original_text: &str) -> String {
|
||||||
|
// We'll consider the start to be "whitespace".
|
||||||
|
let mut preceded_by_whitespace = true;
|
||||||
|
|
||||||
|
original_text
|
||||||
|
.chars()
|
||||||
|
.map(|original_char| {
|
||||||
|
let converted_char = match original_char {
|
||||||
|
'\'' => if preceded_by_whitespace { '‘' } else { '’' },
|
||||||
|
'"' => if preceded_by_whitespace { '“' } else { '”' },
|
||||||
|
_ => original_char,
|
||||||
|
};
|
||||||
|
|
||||||
|
preceded_by_whitespace = original_char.is_whitespace();
|
||||||
|
|
||||||
|
converted_char
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
mod render_markdown {
|
||||||
|
use super::super::render_markdown;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_can_keep_quotes_straight() {
|
||||||
|
assert_eq!(render_markdown("'one'", false), "<p>'one'</p>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_can_make_quotes_curly_except_when_they_are_in_code() {
|
||||||
|
let input = r#"
|
||||||
|
'one'
|
||||||
|
```
|
||||||
|
'two'
|
||||||
|
```
|
||||||
|
`'three'` 'four'"#;
|
||||||
|
let expected = r#"<p>‘one’</p>
|
||||||
|
<pre><code>'two'
|
||||||
|
</code></pre>
|
||||||
|
<p><code>'three'</code> ‘four’</p>
|
||||||
|
"#;
|
||||||
|
assert_eq!(render_markdown(input, true), expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod convert_quotes_to_curly {
|
||||||
|
use super::super::convert_quotes_to_curly;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_converts_single_quotes() {
|
||||||
|
assert_eq!(convert_quotes_to_curly("'one', 'two'"), "‘one’, ‘two’");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_converts_double_quotes() {
|
||||||
|
assert_eq!(convert_quotes_to_curly(r#""one", "two""#), "“one”, “two”");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_treats_tab_as_whitespace() {
|
||||||
|
assert_eq!(convert_quotes_to_curly("\t'one'"), "\t‘one’");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use mdbook::config::jsonconfig::JsonConfig;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
// Tests that the `title` key is correcly parsed in the TOML config
|
// Tests that the `src` key is correctly parsed in the JSON config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_json_source() {
|
fn from_json_source() {
|
||||||
let json = r#"{
|
let json = r#"{
|
||||||
|
@ -17,7 +17,7 @@ fn from_json_source() {
|
||||||
assert_eq!(config.get_source(), PathBuf::from("root/source"));
|
assert_eq!(config.get_source(), PathBuf::from("root/source"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the `title` key is correcly parsed in the TOML config
|
// Tests that the `title` key is correctly parsed in the JSON config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_json_title() {
|
fn from_json_title() {
|
||||||
let json = r#"{
|
let json = r#"{
|
||||||
|
@ -30,7 +30,7 @@ fn from_json_title() {
|
||||||
assert_eq!(config.get_title(), "Some title");
|
assert_eq!(config.get_title(), "Some title");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the `description` key is correcly parsed in the TOML config
|
// Tests that the `description` key is correctly parsed in the JSON config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_json_description() {
|
fn from_json_description() {
|
||||||
let json = r#"{
|
let json = r#"{
|
||||||
|
@ -43,7 +43,7 @@ fn from_json_description() {
|
||||||
assert_eq!(config.get_description(), "This is a description");
|
assert_eq!(config.get_description(), "This is a description");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the `author` key is correcly parsed in the TOML config
|
// Tests that the `author` key is correctly parsed in the JSON config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_json_author() {
|
fn from_json_author() {
|
||||||
let json = r#"{
|
let json = r#"{
|
||||||
|
@ -56,7 +56,7 @@ fn from_json_author() {
|
||||||
assert_eq!(config.get_authors(), &[String::from("John Doe")]);
|
assert_eq!(config.get_authors(), &[String::from("John Doe")]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the `output.html.destination` key is correcly parsed in the TOML config
|
// Tests that the `dest` key is correctly parsed in the JSON config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_json_destination() {
|
fn from_json_destination() {
|
||||||
let json = r#"{
|
let json = r#"{
|
||||||
|
@ -71,7 +71,7 @@ fn from_json_destination() {
|
||||||
assert_eq!(htmlconfig.get_destination(), PathBuf::from("root/htmlbook"));
|
assert_eq!(htmlconfig.get_destination(), PathBuf::from("root/htmlbook"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the `output.html.theme` key is correcly parsed in the TOML config
|
// Tests that the `theme_path` key is correctly parsed in the JSON config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_json_output_html_theme() {
|
fn from_json_output_html_theme() {
|
||||||
let json = r#"{
|
let json = r#"{
|
||||||
|
@ -84,4 +84,19 @@ fn from_json_output_html_theme() {
|
||||||
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig");
|
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig");
|
||||||
|
|
||||||
assert_eq!(htmlconfig.get_theme().expect("the theme key was provided"), &PathBuf::from("root/theme"));
|
assert_eq!(htmlconfig.get_theme().expect("the theme key was provided"), &PathBuf::from("root/theme"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that the `curly_quotes` key is correctly parsed in the JSON config
|
||||||
|
#[test]
|
||||||
|
fn from_json_output_html_curly_quotes() {
|
||||||
|
let json = r#"{
|
||||||
|
"curly_quotes": true
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
let parsed = JsonConfig::from_json(&json).expect("This should parse");
|
||||||
|
let config = BookConfig::from_jsonconfig("root", parsed);
|
||||||
|
|
||||||
|
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig");
|
||||||
|
|
||||||
|
assert_eq!(htmlconfig.get_curly_quotes(), true);
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use mdbook::config::tomlconfig::TomlConfig;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
// Tests that the `title` key is correcly parsed in the TOML config
|
// Tests that the `source` key is correctly parsed in the TOML config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_toml_source() {
|
fn from_toml_source() {
|
||||||
let toml = r#"source = "source""#;
|
let toml = r#"source = "source""#;
|
||||||
|
@ -15,7 +15,7 @@ fn from_toml_source() {
|
||||||
assert_eq!(config.get_source(), PathBuf::from("root/source"));
|
assert_eq!(config.get_source(), PathBuf::from("root/source"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the `title` key is correcly parsed in the TOML config
|
// Tests that the `title` key is correctly parsed in the TOML config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_toml_title() {
|
fn from_toml_title() {
|
||||||
let toml = r#"title = "Some title""#;
|
let toml = r#"title = "Some title""#;
|
||||||
|
@ -26,7 +26,7 @@ fn from_toml_title() {
|
||||||
assert_eq!(config.get_title(), "Some title");
|
assert_eq!(config.get_title(), "Some title");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the `description` key is correcly parsed in the TOML config
|
// Tests that the `description` key is correctly parsed in the TOML config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_toml_description() {
|
fn from_toml_description() {
|
||||||
let toml = r#"description = "This is a description""#;
|
let toml = r#"description = "This is a description""#;
|
||||||
|
@ -37,7 +37,7 @@ fn from_toml_description() {
|
||||||
assert_eq!(config.get_description(), "This is a description");
|
assert_eq!(config.get_description(), "This is a description");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the `author` key is correcly parsed in the TOML config
|
// Tests that the `author` key is correctly parsed in the TOML config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_toml_author() {
|
fn from_toml_author() {
|
||||||
let toml = r#"author = "John Doe""#;
|
let toml = r#"author = "John Doe""#;
|
||||||
|
@ -48,7 +48,7 @@ fn from_toml_author() {
|
||||||
assert_eq!(config.get_authors(), &[String::from("John Doe")]);
|
assert_eq!(config.get_authors(), &[String::from("John Doe")]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the `authors` key is correcly parsed in the TOML config
|
// Tests that the `authors` key is correctly parsed in the TOML config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_toml_authors() {
|
fn from_toml_authors() {
|
||||||
let toml = r#"authors = ["John Doe", "Jane Doe"]"#;
|
let toml = r#"authors = ["John Doe", "Jane Doe"]"#;
|
||||||
|
@ -59,7 +59,7 @@ fn from_toml_authors() {
|
||||||
assert_eq!(config.get_authors(), &[String::from("John Doe"), String::from("Jane Doe")]);
|
assert_eq!(config.get_authors(), &[String::from("John Doe"), String::from("Jane Doe")]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the `output.html.destination` key is correcly parsed in the TOML config
|
// Tests that the `output.html.destination` key is correctly parsed in the TOML config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_toml_output_html_destination() {
|
fn from_toml_output_html_destination() {
|
||||||
let toml = r#"[output.html]
|
let toml = r#"[output.html]
|
||||||
|
@ -73,7 +73,7 @@ fn from_toml_output_html_destination() {
|
||||||
assert_eq!(htmlconfig.get_destination(), PathBuf::from("root/htmlbook"));
|
assert_eq!(htmlconfig.get_destination(), PathBuf::from("root/htmlbook"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the `output.html.theme` key is correcly parsed in the TOML config
|
// Tests that the `output.html.theme` key is correctly parsed in the TOML config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_toml_output_html_theme() {
|
fn from_toml_output_html_theme() {
|
||||||
let toml = r#"[output.html]
|
let toml = r#"[output.html]
|
||||||
|
@ -87,7 +87,21 @@ fn from_toml_output_html_theme() {
|
||||||
assert_eq!(htmlconfig.get_theme().expect("the theme key was provided"), &PathBuf::from("root/theme"));
|
assert_eq!(htmlconfig.get_theme().expect("the theme key was provided"), &PathBuf::from("root/theme"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the `output.html.google-analytics` key is correcly parsed in the TOML config
|
// Tests that the `output.html.curly-quotes` key is correctly parsed in the TOML config
|
||||||
|
#[test]
|
||||||
|
fn from_toml_output_html_curly_quotes() {
|
||||||
|
let toml = r#"[output.html]
|
||||||
|
curly-quotes = true"#;
|
||||||
|
|
||||||
|
let parsed = TomlConfig::from_toml(&toml).expect("This should parse");
|
||||||
|
let config = BookConfig::from_tomlconfig("root", parsed);
|
||||||
|
|
||||||
|
let htmlconfig = config.get_html_config().expect("There should be an HtmlConfig");
|
||||||
|
|
||||||
|
assert_eq!(htmlconfig.get_curly_quotes(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests that the `output.html.google-analytics` key is correctly parsed in the TOML config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_toml_output_html_google_analytics() {
|
fn from_toml_output_html_google_analytics() {
|
||||||
let toml = r#"[output.html]
|
let toml = r#"[output.html]
|
||||||
|
@ -101,8 +115,7 @@ fn from_toml_output_html_google_analytics() {
|
||||||
assert_eq!(htmlconfig.get_google_analytics_id().expect("the google-analytics key was provided"), String::from("123456"));
|
assert_eq!(htmlconfig.get_google_analytics_id().expect("the google-analytics key was provided"), String::from("123456"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that the `output.html.additional-css` key is correctly parsed in the TOML config
|
||||||
// Tests that the `output.html.additional-css` key is correcly parsed in the TOML config
|
|
||||||
#[test]
|
#[test]
|
||||||
fn from_toml_output_html_additional_stylesheet() {
|
fn from_toml_output_html_additional_stylesheet() {
|
||||||
let toml = r#"[output.html]
|
let toml = r#"[output.html]
|
||||||
|
@ -116,7 +129,7 @@ fn from_toml_output_html_additional_stylesheet() {
|
||||||
assert_eq!(htmlconfig.get_additional_css(), &[PathBuf::from("root/custom.css"), PathBuf::from("root/two/custom.css")]);
|
assert_eq!(htmlconfig.get_additional_css(), &[PathBuf::from("root/custom.css"), PathBuf::from("root/two/custom.css")]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the `output.html.additional-js` key is correcly parsed in the TOML config
|
// Tests that the `output.html.additional-js` key is correctly parsed in the TOML config
|
||||||
#[test]
|
#[test]
|
||||||
fn from_toml_output_html_additional_scripts() {
|
fn from_toml_output_html_additional_scripts() {
|
||||||
let toml = r#"[output.html]
|
let toml = r#"[output.html]
|
||||||
|
|
Loading…
Reference in New Issue