Skip to content

Commit

Permalink
smarter URL title quoting
Browse files Browse the repository at this point in the history
  • Loading branch information
yshavit authored Jun 24, 2024
1 parent f75bf73 commit 1b12a07
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 13 deletions.
100 changes: 91 additions & 9 deletions src/fmt_md.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,15 +583,7 @@ impl<'a> MdWriterState<'a> {
{
let Some(title) = title else { return };
out.write_char(' ');
// TODO pick which quoting char to use (single, double, or paren) depending on title
out.write_char('"');
for ch in title.chars() {
if ch == '"' {
out.write_char('\\');
}
out.write_char(ch);
}
out.write_char('"');
TitleQuote::find_best_strategy(title).escape_to(title, out);
}

fn line_to_string<E>(&mut self, line: &'a [E]) -> String
Expand All @@ -604,6 +596,53 @@ impl<'a> MdWriterState<'a> {
}
}

enum TitleQuote {
Double,
Single,
Paren,
}

impl TitleQuote {
pub fn find_best_strategy(text: &str) -> Self {
[Self::Double, Self::Single, Self::Paren]
.into_iter()
.find(|strategy| !strategy.has_conflicts(text))
.unwrap_or(TitleQuote::Double)
}

fn get_surround_chars(&self) -> (char, char) {
match self {
TitleQuote::Double => ('"', '"'),
TitleQuote::Single => ('\'', '\''),
TitleQuote::Paren => ('(', ')'),
}
}

fn get_conflict_char_fn(surrounds: (char, char)) -> impl Fn(char) -> bool {
let (open, close) = surrounds;
move |ch| ch == open || ch == close
}

fn has_conflicts(&self, text: &str) -> bool {
text.chars().any(Self::get_conflict_char_fn(self.get_surround_chars()))
}

fn escape_to<W: SimpleWrite>(&self, text: &str, out: &mut Output<W>) {
let surrounds = self.get_surround_chars();
let conflict_char_fn = Self::get_conflict_char_fn(surrounds);
let (open, close) = surrounds;

out.write_char(open);
for ch in text.chars() {
if conflict_char_fn(ch) {
out.write_char('\\');
}
out.write_char(ch);
}
out.write_char(close);
}
}

enum DefinitionsToWrite {
// simple enum-set-like definition
Links,
Expand Down Expand Up @@ -676,6 +715,49 @@ pub mod tests {
Table(_),
});

mod title_quoting {
use super::*;
use crate::fmt_md::TitleQuote;

crate::variants_checker!(TITLE_QUOTING_CHECKER = TitleQuote { Double, Single, Paren });

#[test]
fn bareword_uses_double() {
check("foo", "\"foo\"");
}

#[test]
fn has_double_quotes() {
check("foo\"bar", "'foo\"bar'");
}

#[test]
fn has_double_quotes_and_singles() {
check("foo'\"bar", "(foo'\"bar)");
}

#[test]
fn has_only_single_quotes() {
check("foo'bar", "\"foo'bar\"");
}

#[test]
fn has_all_delimiters() {
check("foo('\")bar", "\"foo('\\\")bar\"");
}

fn check(input: &str, expected: &str) {
let strategy = TitleQuote::find_best_strategy(input);
TITLE_QUOTING_CHECKER.see(&strategy);

// +1 to give room for some quotes
let mut writer = Output::new(String::with_capacity(input.len() + 4));
strategy.escape_to(input, &mut writer);
let actual = writer.take_underlying().unwrap();
assert_eq!(&actual, expected);
}
}

#[test]
fn empty() {
check_render(vec![], indoc! {r#""#});
Expand Down
4 changes: 0 additions & 4 deletions src/select/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,3 @@ impl MdqRefSelector {
}
}
}

/*
*/

0 comments on commit 1b12a07

Please sign in to comment.