Skip to content

Commit

Permalink
Merge pull request #438 from kivikakk/broken-link-callback-cleanup
Browse files Browse the repository at this point in the history
broken reflink callback updates & big cleanup.
  • Loading branch information
kivikakk committed Jul 11, 2024
2 parents bd16259 + 433e15e commit 3bb6d4c
Show file tree
Hide file tree
Showing 12 changed files with 267 additions and 164 deletions.
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

0 comments on commit 3bb6d4c

Please sign in to comment.