use pulldown cmarks curly quotes
This commit is contained in:
parent
1be69af553
commit
1c0983b811
|
@ -85,7 +85,7 @@ fn render_item(
|
||||||
.with_context(|| "Could not convert HTML path to str")?;
|
.with_context(|| "Could not convert HTML path to str")?;
|
||||||
let anchor_base = utils::fs::normalize_path(filepath);
|
let anchor_base = utils::fs::normalize_path(filepath);
|
||||||
|
|
||||||
let mut p = utils::new_cmark_parser(&chapter.content).peekable();
|
let mut p = utils::new_cmark_parser(&chapter.content, false).peekable();
|
||||||
|
|
||||||
let mut in_heading = false;
|
let mut in_heading = false;
|
||||||
let max_section_depth = u32::from(search_config.heading_split_level);
|
let max_section_depth = u32::from(search_config.heading_split_level);
|
||||||
|
|
|
@ -168,64 +168,29 @@ pub fn render_markdown(text: &str, curly_quotes: bool) -> String {
|
||||||
render_markdown_with_path(text, curly_quotes, None)
|
render_markdown_with_path(text, curly_quotes, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_cmark_parser(text: &str) -> Parser<'_> {
|
pub fn new_cmark_parser(text: &str, curly_quotes: bool) -> Parser<'_> {
|
||||||
let mut opts = Options::empty();
|
let mut opts = Options::empty();
|
||||||
opts.insert(Options::ENABLE_TABLES);
|
opts.insert(Options::ENABLE_TABLES);
|
||||||
opts.insert(Options::ENABLE_FOOTNOTES);
|
opts.insert(Options::ENABLE_FOOTNOTES);
|
||||||
opts.insert(Options::ENABLE_STRIKETHROUGH);
|
opts.insert(Options::ENABLE_STRIKETHROUGH);
|
||||||
opts.insert(Options::ENABLE_TASKLISTS);
|
opts.insert(Options::ENABLE_TASKLISTS);
|
||||||
|
if curly_quotes {
|
||||||
opts.insert(Options::ENABLE_SMART_PUNCTUATION);
|
opts.insert(Options::ENABLE_SMART_PUNCTUATION);
|
||||||
|
}
|
||||||
Parser::new_ext(text, opts)
|
Parser::new_ext(text, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_markdown_with_path(text: &str, curly_quotes: bool, path: Option<&Path>) -> String {
|
pub fn render_markdown_with_path(text: &str, curly_quotes: bool, path: Option<&Path>) -> String {
|
||||||
let mut s = String::with_capacity(text.len() * 3 / 2);
|
let mut s = String::with_capacity(text.len() * 3 / 2);
|
||||||
let p = new_cmark_parser(text);
|
let p = new_cmark_parser(text, curly_quotes);
|
||||||
let mut converter = EventQuoteConverter::new(curly_quotes);
|
|
||||||
let events = p
|
let events = p
|
||||||
.map(clean_codeblock_headers)
|
.map(clean_codeblock_headers)
|
||||||
.map(|event| adjust_links(event, path))
|
.map(|event| adjust_links(event, path));
|
||||||
.map(|event| converter.convert(event));
|
|
||||||
|
|
||||||
html::push_html(&mut s, events);
|
html::push_html(&mut s, events);
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EventQuoteConverter {
|
|
||||||
enabled: bool,
|
|
||||||
convert_text: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EventQuoteConverter {
|
|
||||||
fn new(enabled: bool) -> Self {
|
|
||||||
EventQuoteConverter {
|
|
||||||
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(_)) => {
|
|
||||||
self.convert_text = false;
|
|
||||||
event
|
|
||||||
}
|
|
||||||
Event::End(Tag::CodeBlock(_)) => {
|
|
||||||
self.convert_text = true;
|
|
||||||
event
|
|
||||||
}
|
|
||||||
Event::Text(ref text) if self.convert_text => {
|
|
||||||
Event::Text(CowStr::from(convert_quotes_to_curly(text)))
|
|
||||||
}
|
|
||||||
_ => event,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clean_codeblock_headers(event: Event<'_>) -> Event<'_> {
|
fn clean_codeblock_headers(event: Event<'_>) -> Event<'_> {
|
||||||
match event {
|
match event {
|
||||||
Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(ref info))) => {
|
Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(ref info))) => {
|
||||||
|
@ -244,38 +209,6 @@ fn clean_codeblock_headers(event: Event<'_>) -> 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()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Prints a "backtrace" of some `Error`.
|
/// Prints a "backtrace" of some `Error`.
|
||||||
pub fn log_backtrace(e: &Error) {
|
pub fn log_backtrace(e: &Error) {
|
||||||
error!("Error: {}", e);
|
error!("Error: {}", e);
|
||||||
|
@ -451,23 +384,4 @@ more text with spaces
|
||||||
assert_eq!(normalize_id(""), "");
|
assert_eq!(normalize_id(""), "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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’");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue