Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

broken reflink callback updates & big cleanup. #438

Merged
merged 6 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ fn replace_text(document: &str, orig_string: &str, replacement: &str) -> String
for node in root.descendants() {
if let NodeValue::Text(ref mut text) = node.data.borrow_mut().value {
// If the node is a text node, perform the string replacement.
*text = text.replace(orig_string, replacement)
*text = text.replace(orig_string, replacement);
}
}

Expand Down
24 changes: 19 additions & 5 deletions fuzz/fuzz_targets/all_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
use libfuzzer_sys::fuzz_target;

use comrak::{
markdown_to_html, ExtensionOptions, Options, ParseOptions,
RenderOptions, ListStyleType,
markdown_to_html, BrokenLinkReference, ExtensionOptions, ListStyleType, Options, ParseOptions,
RenderOptions, ResolvedReference,
};
use std::sync::{Arc, Mutex};

fuzz_target!(|s: &str| {
let mut extension = ExtensionOptions::default();
Expand All @@ -18,22 +19,29 @@ fuzz_target!(|s: &str| {
extension.header_ids = Some("user-content-".to_string());
extension.footnotes = true;
extension.description_lists = true;
extension.front_matter_delimiter = Some("---".to_string());
extension.multiline_block_quotes = true;
extension.math_dollars = true;
extension.math_code = true;
extension.front_matter_delimiter = Some("---".to_string());
extension.shortcodes = true;
extension.wikilinks_title_after_pipe = true;
extension.wikilinks_title_before_pipe = true;
extension.underline = true;
extension.spoiler = true;
extension.greentext = true;

let mut parse = ParseOptions::default();
parse.smart = true;
parse.default_info_string = Some("rust".to_string());
parse.relaxed_tasklist_matching = true;
parse.relaxed_autolinks = true;
let mut cb = |link_ref: BrokenLinkReference| {
Some(ResolvedReference {
url: link_ref.normalized.to_string(),
title: link_ref.original.to_string(),
})
};
parse.broken_link_callback = Some(Arc::new(Mutex::new(&mut cb)));

let mut render = RenderOptions::default();
render.hardbreaks = true;
Expand All @@ -47,9 +55,15 @@ fuzz_target!(|s: &str| {
render.escaped_char_spans = true;
render.ignore_setext = true;
render.ignore_empty_links = true;
render.gfm_quirks = true;
render.prefer_fenced = true;

markdown_to_html(
s,
&Options { extension, parse, render },
&Options {
extension,
parse,
render,
},
);
});
4 changes: 1 addition & 3 deletions fuzz/fuzz_targets/cli_default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

use libfuzzer_sys::fuzz_target;

use comrak::{
markdown_to_html_with_plugins, plugins::syntect::SyntectAdapter, Plugins,
};
use comrak::{markdown_to_html_with_plugins, plugins::syntect::SyntectAdapter, Plugins};

// Note that we end up fuzzing Syntect here.

Expand Down
17 changes: 4 additions & 13 deletions fuzz/fuzz_targets/quadratic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
#![feature(int_roundings)]
#![no_main]
use comrak::{
markdown_to_html, markdown_to_commonmark, markdown_to_commonmark_xml,
ExtensionOptions, Options, ParseOptions,
RenderOptions, ListStyleType,
markdown_to_commonmark, markdown_to_commonmark_xml, markdown_to_html, ExtensionOptions,
ListStyleType, Options, ParseOptions, RenderOptions,
};
use libfuzzer_sys::arbitrary::{self, Arbitrary};
use libfuzzer_sys::fuzz_target;
Expand Down Expand Up @@ -297,18 +296,10 @@ fn fuzz_one_input(input: &Input, num_bytes: usize) -> (usize, Duration, f64) {
let duration_per_byte = duration.as_secs_f64() / (byte_length as f64);

if DEBUG {
println!(
"do_one: {} bytes, duration = {:?}",
byte_length,
duration
);
println!("do_one: {} bytes, duration = {:?}", byte_length, duration);
}

(
byte_length,
duration,
duration_per_byte
)
(byte_length, duration, duration_per_byte)
}

/// The maximum number of steps to run in the main fuzzing loop below.
Expand Down
10 changes: 5 additions & 5 deletions src/cm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ pub fn format_document_with_plugins<'a>(
Ok(())
}

struct CommonMarkFormatter<'a, 'o> {
struct CommonMarkFormatter<'a, 'o, 'c> {
node: &'a AstNode<'a>,
options: &'o Options,
options: &'o Options<'c>,
v: Vec<u8>,
prefix: Vec<u8>,
column: usize,
Expand All @@ -72,7 +72,7 @@ enum Escaping {
Title,
}

impl<'a, 'o> Write for CommonMarkFormatter<'a, 'o> {
impl<'a, 'o, 'c> Write for CommonMarkFormatter<'a, 'o, 'c> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.output(buf, false, Escaping::Literal);
Ok(buf.len())
Expand All @@ -83,8 +83,8 @@ impl<'a, 'o> Write for CommonMarkFormatter<'a, 'o> {
}
}

impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
fn new(node: &'a AstNode<'a>, options: &'o Options) -> Self {
impl<'a, 'o, 'c> CommonMarkFormatter<'a, 'o, 'c> {
fn new(node: &'a AstNode<'a>, options: &'o Options<'c>) -> Self {
CommonMarkFormatter {
node,
options,
Expand Down
30 changes: 15 additions & 15 deletions src/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,25 +63,24 @@ impl<'w> Write for WriteWithLast<'w> {
}
}

/// Converts header Strings to canonical, unique, but still human-readable, anchors.
/// Converts header strings to canonical, unique, but still human-readable,
/// anchors.
///
/// To guarantee uniqueness, an anchorizer keeps track of the anchors
/// it has returned. So, for example, to parse several MarkDown
/// files, use a new anchorizer per file.
/// To guarantee uniqueness, an anchorizer keeps track of the anchors it has
/// returned; use one per output file.
///
/// ## Example
///
/// ```
/// use comrak::Anchorizer;
///
/// # use comrak::Anchorizer;
/// let mut anchorizer = Anchorizer::new();
///
/// // First "stuff" is unsuffixed.
/// assert_eq!("stuff".to_string(), anchorizer.anchorize("Stuff".to_string()));
/// // Second "stuff" has "-1" appended to make it unique.
/// assert_eq!("stuff-1".to_string(), anchorizer.anchorize("Stuff".to_string()));
/// ```
#[derive(Debug, Default)]
#[doc(hidden)]
pub struct Anchorizer(HashSet<String>);

impl Anchorizer {
Expand All @@ -96,12 +95,9 @@ impl Anchorizer {
/// resultant anchor unique.
///
/// ```
/// use comrak::Anchorizer;
///
/// # use comrak::Anchorizer;
/// let mut anchorizer = Anchorizer::new();
///
/// let source = "Ticks aren't in";
///
/// assert_eq!("ticks-arent-in".to_string(), anchorizer.anchorize(source.to_string()));
/// ```
pub fn anchorize(&mut self, header: String) -> String {
Expand Down Expand Up @@ -130,9 +126,9 @@ impl Anchorizer {
}
}

struct HtmlFormatter<'o> {
struct HtmlFormatter<'o, 'c> {
output: &'o mut WriteWithLast<'o>,
options: &'o Options,
options: &'o Options<'c>,
anchorizer: Anchorizer,
footnote_ix: u32,
written_footnote_ix: u32,
Expand Down Expand Up @@ -365,8 +361,12 @@ where
Ok(())
}

impl<'o> HtmlFormatter<'o> {
fn new(options: &'o Options, output: &'o mut WriteWithLast<'o>, plugins: &'o Plugins) -> Self {
impl<'o, 'c: 'o> HtmlFormatter<'o, 'c> {
fn new(
options: &'o Options<'c>,
output: &'o mut WriteWithLast<'o>,
plugins: &'o Plugins,
) -> Self {
HtmlFormatter {
options,
output,
Expand Down
40 changes: 15 additions & 25 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! A 100% [CommonMark](http://commonmark.org/) and [GFM](https://github.github.com/gfm/)
//! compatible Markdown parser. Source repository is at <https://github.com/kivikakk/comrak>.
//! compatible Markdown parser.
//!
//! The design is based on [cmark-gfm](https://github.com/github/cmark-gfm), so
//! familiarity with that will help.
//! Source repository and detailed `README` is at <https://github.com/kivikakk/comrak>.
//!
//! You can use `comrak::markdown_to_html` directly:
//!
Expand All @@ -20,41 +19,28 @@
//! use comrak::nodes::{AstNode, NodeValue};
//!
//! # fn main() {
//! // The returned nodes are created in the supplied Arena, and are bound by its lifetime.
//! let arena = Arena::new();
//!
//! let root = parse_document(
//! &arena,
//! "This is my input.\n\n1. Also my input.\n2. Certainly my input.\n",
//! "This is my input.\n\n1. Also [my](#) input.\n2. Certainly *my* input.\n",
//! &Options::default());
//!
//! fn iter_nodes<'a, F>(node: &'a AstNode<'a>, f: &F)
//! where F : Fn(&'a AstNode<'a>) {
//! f(node);
//! for c in node.children() {
//! iter_nodes(c, f);
//! for node in root.descendants() {
//! if let NodeValue::Text(ref mut text) = node.data.borrow_mut().value {
//! *text = text.replace("my", "your");
//! }
//! }
//!
//! iter_nodes(root, &|node| {
//! match &mut node.data.borrow_mut().value {
//! &mut NodeValue::Text(ref mut text) => {
//! let orig = std::mem::replace(text, String::new());
//! *text = orig.replace("my", "your");
//! }
//! _ => (),
//! }
//! });
//!
//! let mut html = vec![];
//! format_html(root, &Options::default(), &mut html).unwrap();
//!
//! assert_eq!(
//! String::from_utf8(html).unwrap(),
//! "<p>This is your input.</p>\n\
//! <ol>\n\
//! <li>Also your input.</li>\n\
//! <li>Certainly your input.</li>\n\
//! <li>Also <a href=\"#\">your</a> input.</li>\n\
//! <li>Certainly <em>your</em> input.</li>\n\
//! </ol>\n");
//! # }
//! ```
Expand Down Expand Up @@ -98,11 +84,15 @@ pub use cm::format_document as format_commonmark;
pub use cm::format_document_with_plugins as format_commonmark_with_plugins;
pub use html::format_document as format_html;
pub use html::format_document_with_plugins as format_html_with_plugins;
#[doc(inline)]
pub use html::Anchorizer;
#[allow(deprecated)]
pub use parser::parse_document_with_broken_link_callback;
pub use parser::{
parse_document, parse_document_with_broken_link_callback, ExtensionOptions,
parse_document, BrokenLinkCallback, BrokenLinkReference, ExtensionOptions,
ExtensionOptionsBuilder, ListStyleType, Options, ParseOptions, ParseOptionsBuilder, Plugins,
PluginsBuilder, RenderOptions, RenderOptionsBuilder, RenderPlugins, RenderPluginsBuilder,
ResolvedReference,
};
pub use typed_arena::Arena;
pub use xml::format_document as format_xml;
Expand All @@ -111,9 +101,9 @@ pub use xml::format_document_with_plugins as format_xml_with_plugins;
/// Legacy naming of [`ExtensionOptions`]
pub type ComrakExtensionOptions = ExtensionOptions;
/// Legacy naming of [`Options`]
pub type ComrakOptions = Options;
pub type ComrakOptions<'c> = Options<'c>;
/// Legacy naming of [`ParseOptions`]
pub type ComrakParseOptions = ParseOptions;
pub type ComrakParseOptions<'c> = ParseOptions<'c>;
/// Legacy naming of [`Plugins`]
pub type ComrakPlugins<'a> = Plugins<'a>;
/// Legacy naming of [`RenderOptions`]
Expand Down
Loading