Skip to content

Commit

Permalink
Add bullet list style options
Browse files Browse the repository at this point in the history
This change adds a new option `--list-style` so users can choose which
character all bulleted lists use for their marker. The [commonmark
spec] supports three options for bullet markers: `-`, `*`, `+` which is
also now the case here. Previously, when comrak (or cmark-gfm) rendered
markdown, it would pick `-` which is now the default.

This also adds the ability to optionally provide custom ComrakOptions
when testing. If the defaults are fine, you can pass `None`.

[commonmark spec]: https://spec.commonmark.org/0.30/#bullet-list-marker
  • Loading branch information
edwardloveall committed Jul 8, 2022
1 parent e23a579 commit 3e493e0
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 8 deletions.
3 changes: 2 additions & 1 deletion src/cm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,8 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {

if entering {
if parent.list_type == ListType::Bullet {
write!(self, "- ").unwrap();
let bullet = char::from(self.options.render.list_style as u8);
write!(self, "{} ", bullet).unwrap();
} else {
self.write_all(&listmarker).unwrap();
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ pub use html::Anchorizer;
pub use parser::{
parse_document, parse_document_with_broken_link_callback, ComrakExtensionOptions,
ComrakOptions, ComrakParseOptions, ComrakPlugins, ComrakRenderOptions, ComrakRenderPlugins,
ListStyleType,
};
pub use typed_arena::Arena;

Expand Down
16 changes: 15 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extern crate xdg;

use comrak::{
Arena, ComrakExtensionOptions, ComrakOptions, ComrakParseOptions, ComrakPlugins,
ComrakRenderOptions,
ComrakRenderOptions, ListStyleType,
};

use comrak::adapters::SyntaxHighlighterAdapter;
Expand Down Expand Up @@ -161,6 +161,15 @@ if the file does not exist.\
.value_name("THEME")
.help("Syntax highlighting for codefence blocks. Choose a theme or 'none' for disabling.")
.default_value("base16-ocean.dark"),
)
.arg(
clap::Arg::with_name("list-style")
.long("list-style")
.takes_value(true)
.possible_values(&["dash", "plus", "star"])
.default_value("dash")
.value_name("LIST_STYLE")
.help("Specify bullet character for lists (-, +, *) in CommonMark ouput"),
);

let mut matches = app.clone().get_matches();
Expand Down Expand Up @@ -220,6 +229,11 @@ if the file does not exist.\
.unwrap_or(0),
unsafe_: matches.is_present("unsafe"),
escape: matches.is_present("escape"),
list_style: matches
.value_of("list-style")
.unwrap_or("dash")
.parse::<ListStyleType>()
.expect("unknown list style"),
},
};

Expand Down
55 changes: 54 additions & 1 deletion src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::cmp::min;
use std::collections::HashMap;
use std::fmt::{Debug, Formatter};
use std::mem;
use std::str;
use std::str::{self, FromStr};
use strings;
use typed_arena::Arena;

Expand Down Expand Up @@ -437,6 +437,29 @@ pub struct ComrakRenderOptions {
/// "<p>&lt;i&gt;italic text&lt;/i&gt;</p>\n");
/// ```
pub escape: bool,

/// Set the type of [bullet list marker](https://spec.commonmark.org/0.30/#bullet-list-marker) to use. Options are:
///
/// * `ListStyleType::Dash` to use `-` (default)
/// * `ListStyleType::Plus` to use `+`
/// * `ListStyleType::Star` to use `*`
///
/// ```rust
/// # use comrak::{markdown_to_commonmark, ComrakOptions, ListStyleType};
/// let mut options = ComrakOptions::default();
/// let input = "- one\n- two\n- three";
/// assert_eq!(markdown_to_commonmark(input, &options),
/// "- one\n- two\n- three\n"); // default is Dash
///
/// options.render.list_style = ListStyleType::Plus;
/// assert_eq!(markdown_to_commonmark(input, &options),
/// "+ one\n+ two\n+ three\n");
///
/// options.render.list_style = ListStyleType::Star;
/// assert_eq!(markdown_to_commonmark(input, &options),
/// "* one\n* two\n* three\n");
/// ```
pub list_style: ListStyleType,
}

#[derive(Default, Debug)]
Expand Down Expand Up @@ -1891,3 +1914,33 @@ pub enum AutolinkType {
URI,
Email,
}

#[derive(Debug, Clone, Copy)]
/// Options for bulleted list redering in markdown. See `link_style` in [ComrakRenderOptions] for more details.
pub enum ListStyleType {
/// The `-` character
Dash = 45,
/// The `+` character
Plus = 43,
/// The `*` character
Star = 42,
}

impl Default for ListStyleType {
fn default() -> Self {
ListStyleType::Dash
}
}

impl FromStr for ListStyleType {
type Err = ();

fn from_str(input: &str) -> Result<ListStyleType, Self::Err> {
match input {
"dash" => Ok(ListStyleType::Dash),
"plus" => Ok(ListStyleType::Plus),
"star" => Ok(ListStyleType::Star),
_ => Err(()),
}
}
}
39 changes: 34 additions & 5 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ fn fuzz_doesnt_crash(md: String) {
width: 80,
unsafe_: true,
escape: false,
list_style: ::ListStyleType::Dash,
},
};

Expand All @@ -62,12 +63,12 @@ fn compare_strs(output: &str, expected: &str, kind: &str) {
}

#[track_caller]
fn commonmark(input: &str, expected: &str) {
fn commonmark(input: &str, expected: &str, opts: Option<&::ComrakOptions>) {
let arena = ::Arena::new();
let mut options = ::ComrakOptions::default();
options.render.width = 72;
let defaults = ::ComrakOptions::default();
let options = opts.unwrap_or(&defaults);

let root = ::parse_document(&arena, input, &options);
let root = ::parse_document(&arena, input, options);
let mut output = vec![];
cm::format_document(root, &options, &mut output).unwrap();
compare_strs(&String::from_utf8(output).unwrap(), expected, "regular");
Expand Down Expand Up @@ -253,6 +254,31 @@ fn lists() {
);
}

#[test]
fn markdown_list_bullets() {
let dash = concat!("- a\n");
let plus = concat!("+ a\n");
let star = concat!("* a\n");
let mut dash_opts = ::ComrakOptions::default();
dash_opts.render.list_style = ::ListStyleType::Dash;
let mut plus_opts = ::ComrakOptions::default();
plus_opts.render.list_style = ::ListStyleType::Plus;
let mut star_opts = ::ComrakOptions::default();
star_opts.render.list_style = ::ListStyleType::Star;

commonmark(dash, dash, Some(&dash_opts));
commonmark(plus, dash, Some(&dash_opts));
commonmark(star, dash, Some(&dash_opts));

commonmark(dash, plus, Some(&plus_opts));
commonmark(plus, plus, Some(&plus_opts));
commonmark(star, plus, Some(&plus_opts));

commonmark(dash, star, Some(&star_opts));
commonmark(plus, star, Some(&star_opts));
commonmark(star, star, Some(&star_opts));
}

#[test]
fn thematic_breaks() {
html(
Expand All @@ -263,6 +289,8 @@ fn thematic_breaks() {

#[test]
fn width_breaks() {
let mut options = ::ComrakOptions::default();
options.render.width = 72;
let input = concat!(
"this should break because it has breakable characters. break right here newline\n",
"\n",
Expand All @@ -279,7 +307,7 @@ fn width_breaks() {
"a-long-line-that-won't-break-because-there-is-no-character-it-can-break-on\n"
);

commonmark(input, output);
commonmark(input, output, Some(&options));
}

#[test]
Expand Down Expand Up @@ -1272,6 +1300,7 @@ fn exercise_full_api<'a>() {
width: 123456,
unsafe_: false,
escape: false,
list_style: ::ListStyleType::Dash,
},
};

Expand Down

0 comments on commit 3e493e0

Please sign in to comment.