Skip to content

Commit 3bb6d4c

Browse files
authored
Merge pull request #438 from kivikakk/broken-link-callback-cleanup
broken reflink callback updates & big cleanup.
2 parents bd16259 + 433e15e commit 3bb6d4c

File tree

12 files changed

+267
-164
lines changed

12 files changed

+267
-164
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ fn replace_text(document: &str, orig_string: &str, replacement: &str) -> String
193193
for node in root.descendants() {
194194
if let NodeValue::Text(ref mut text) = node.data.borrow_mut().value {
195195
// If the node is a text node, perform the string replacement.
196-
*text = text.replace(orig_string, replacement)
196+
*text = text.replace(orig_string, replacement);
197197
}
198198
}
199199

fuzz/fuzz_targets/all_options.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
use libfuzzer_sys::fuzz_target;
44

55
use comrak::{
6-
markdown_to_html, ExtensionOptions, Options, ParseOptions,
7-
RenderOptions, ListStyleType,
6+
markdown_to_html, BrokenLinkReference, ExtensionOptions, ListStyleType, Options, ParseOptions,
7+
RenderOptions, ResolvedReference,
88
};
9+
use std::sync::{Arc, Mutex};
910

1011
fuzz_target!(|s: &str| {
1112
let mut extension = ExtensionOptions::default();
@@ -18,22 +19,29 @@ fuzz_target!(|s: &str| {
1819
extension.header_ids = Some("user-content-".to_string());
1920
extension.footnotes = true;
2021
extension.description_lists = true;
22+
extension.front_matter_delimiter = Some("---".to_string());
2123
extension.multiline_block_quotes = true;
2224
extension.math_dollars = true;
2325
extension.math_code = true;
24-
extension.front_matter_delimiter = Some("---".to_string());
2526
extension.shortcodes = true;
2627
extension.wikilinks_title_after_pipe = true;
2728
extension.wikilinks_title_before_pipe = true;
2829
extension.underline = true;
2930
extension.spoiler = true;
3031
extension.greentext = true;
31-
32+
3233
let mut parse = ParseOptions::default();
3334
parse.smart = true;
3435
parse.default_info_string = Some("rust".to_string());
3536
parse.relaxed_tasklist_matching = true;
3637
parse.relaxed_autolinks = true;
38+
let mut cb = |link_ref: BrokenLinkReference| {
39+
Some(ResolvedReference {
40+
url: link_ref.normalized.to_string(),
41+
title: link_ref.original.to_string(),
42+
})
43+
};
44+
parse.broken_link_callback = Some(Arc::new(Mutex::new(&mut cb)));
3745

3846
let mut render = RenderOptions::default();
3947
render.hardbreaks = true;
@@ -47,9 +55,15 @@ fuzz_target!(|s: &str| {
4755
render.escaped_char_spans = true;
4856
render.ignore_setext = true;
4957
render.ignore_empty_links = true;
58+
render.gfm_quirks = true;
59+
render.prefer_fenced = true;
5060

5161
markdown_to_html(
5262
s,
53-
&Options { extension, parse, render },
63+
&Options {
64+
extension,
65+
parse,
66+
render,
67+
},
5468
);
5569
});

fuzz/fuzz_targets/cli_default.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22

33
use libfuzzer_sys::fuzz_target;
44

5-
use comrak::{
6-
markdown_to_html_with_plugins, plugins::syntect::SyntectAdapter, Plugins,
7-
};
5+
use comrak::{markdown_to_html_with_plugins, plugins::syntect::SyntectAdapter, Plugins};
86

97
// Note that we end up fuzzing Syntect here.
108

fuzz/fuzz_targets/quadratic.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
#![feature(int_roundings)]
33
#![no_main]
44
use comrak::{
5-
markdown_to_html, markdown_to_commonmark, markdown_to_commonmark_xml,
6-
ExtensionOptions, Options, ParseOptions,
7-
RenderOptions, ListStyleType,
5+
markdown_to_commonmark, markdown_to_commonmark_xml, markdown_to_html, ExtensionOptions,
6+
ListStyleType, Options, ParseOptions, RenderOptions,
87
};
98
use libfuzzer_sys::arbitrary::{self, Arbitrary};
109
use libfuzzer_sys::fuzz_target;
@@ -297,18 +296,10 @@ fn fuzz_one_input(input: &Input, num_bytes: usize) -> (usize, Duration, f64) {
297296
let duration_per_byte = duration.as_secs_f64() / (byte_length as f64);
298297

299298
if DEBUG {
300-
println!(
301-
"do_one: {} bytes, duration = {:?}",
302-
byte_length,
303-
duration
304-
);
299+
println!("do_one: {} bytes, duration = {:?}", byte_length, duration);
305300
}
306301

307-
(
308-
byte_length,
309-
duration,
310-
duration_per_byte
311-
)
302+
(byte_length, duration, duration_per_byte)
312303
}
313304

314305
/// The maximum number of steps to run in the main fuzzing loop below.

src/cm.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ pub fn format_document_with_plugins<'a>(
4747
Ok(())
4848
}
4949

50-
struct CommonMarkFormatter<'a, 'o> {
50+
struct CommonMarkFormatter<'a, 'o, 'c> {
5151
node: &'a AstNode<'a>,
52-
options: &'o Options,
52+
options: &'o Options<'c>,
5353
v: Vec<u8>,
5454
prefix: Vec<u8>,
5555
column: usize,
@@ -72,7 +72,7 @@ enum Escaping {
7272
Title,
7373
}
7474

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

86-
impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
87-
fn new(node: &'a AstNode<'a>, options: &'o Options) -> Self {
86+
impl<'a, 'o, 'c> CommonMarkFormatter<'a, 'o, 'c> {
87+
fn new(node: &'a AstNode<'a>, options: &'o Options<'c>) -> Self {
8888
CommonMarkFormatter {
8989
node,
9090
options,

src/html.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -63,25 +63,24 @@ impl<'w> Write for WriteWithLast<'w> {
6363
}
6464
}
6565

66-
/// Converts header Strings to canonical, unique, but still human-readable, anchors.
66+
/// Converts header strings to canonical, unique, but still human-readable,
67+
/// anchors.
6768
///
68-
/// To guarantee uniqueness, an anchorizer keeps track of the anchors
69-
/// it has returned. So, for example, to parse several MarkDown
70-
/// files, use a new anchorizer per file.
69+
/// To guarantee uniqueness, an anchorizer keeps track of the anchors it has
70+
/// returned; use one per output file.
7171
///
7272
/// ## Example
7373
///
7474
/// ```
75-
/// use comrak::Anchorizer;
76-
///
75+
/// # use comrak::Anchorizer;
7776
/// let mut anchorizer = Anchorizer::new();
78-
///
7977
/// // First "stuff" is unsuffixed.
8078
/// assert_eq!("stuff".to_string(), anchorizer.anchorize("Stuff".to_string()));
8179
/// // Second "stuff" has "-1" appended to make it unique.
8280
/// assert_eq!("stuff-1".to_string(), anchorizer.anchorize("Stuff".to_string()));
8381
/// ```
8482
#[derive(Debug, Default)]
83+
#[doc(hidden)]
8584
pub struct Anchorizer(HashSet<String>);
8685

8786
impl Anchorizer {
@@ -96,12 +95,9 @@ impl Anchorizer {
9695
/// resultant anchor unique.
9796
///
9897
/// ```
99-
/// use comrak::Anchorizer;
100-
///
98+
/// # use comrak::Anchorizer;
10199
/// let mut anchorizer = Anchorizer::new();
102-
///
103100
/// let source = "Ticks aren't in";
104-
///
105101
/// assert_eq!("ticks-arent-in".to_string(), anchorizer.anchorize(source.to_string()));
106102
/// ```
107103
pub fn anchorize(&mut self, header: String) -> String {
@@ -130,9 +126,9 @@ impl Anchorizer {
130126
}
131127
}
132128

133-
struct HtmlFormatter<'o> {
129+
struct HtmlFormatter<'o, 'c> {
134130
output: &'o mut WriteWithLast<'o>,
135-
options: &'o Options,
131+
options: &'o Options<'c>,
136132
anchorizer: Anchorizer,
137133
footnote_ix: u32,
138134
written_footnote_ix: u32,
@@ -365,8 +361,12 @@ where
365361
Ok(())
366362
}
367363

368-
impl<'o> HtmlFormatter<'o> {
369-
fn new(options: &'o Options, output: &'o mut WriteWithLast<'o>, plugins: &'o Plugins) -> Self {
364+
impl<'o, 'c: 'o> HtmlFormatter<'o, 'c> {
365+
fn new(
366+
options: &'o Options<'c>,
367+
output: &'o mut WriteWithLast<'o>,
368+
plugins: &'o Plugins,
369+
) -> Self {
370370
HtmlFormatter {
371371
options,
372372
output,

src/lib.rs

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
//! A 100% [CommonMark](http://commonmark.org/) and [GFM](https://github.github.com/gfm/)
2-
//! compatible Markdown parser. Source repository is at <https://github.com/kivikakk/comrak>.
2+
//! compatible Markdown parser.
33
//!
4-
//! The design is based on [cmark-gfm](https://github.com/github/cmark-gfm), so
5-
//! familiarity with that will help.
4+
//! Source repository and detailed `README` is at <https://github.com/kivikakk/comrak>.
65
//!
76
//! You can use `comrak::markdown_to_html` directly:
87
//!
@@ -20,41 +19,28 @@
2019
//! use comrak::nodes::{AstNode, NodeValue};
2120
//!
2221
//! # fn main() {
23-
//! // The returned nodes are created in the supplied Arena, and are bound by its lifetime.
2422
//! let arena = Arena::new();
2523
//!
2624
//! let root = parse_document(
2725
//! &arena,
28-
//! "This is my input.\n\n1. Also my input.\n2. Certainly my input.\n",
26+
//! "This is my input.\n\n1. Also [my](#) input.\n2. Certainly *my* input.\n",
2927
//! &Options::default());
3028
//!
31-
//! fn iter_nodes<'a, F>(node: &'a AstNode<'a>, f: &F)
32-
//! where F : Fn(&'a AstNode<'a>) {
33-
//! f(node);
34-
//! for c in node.children() {
35-
//! iter_nodes(c, f);
29+
//! for node in root.descendants() {
30+
//! if let NodeValue::Text(ref mut text) = node.data.borrow_mut().value {
31+
//! *text = text.replace("my", "your");
3632
//! }
3733
//! }
3834
//!
39-
//! iter_nodes(root, &|node| {
40-
//! match &mut node.data.borrow_mut().value {
41-
//! &mut NodeValue::Text(ref mut text) => {
42-
//! let orig = std::mem::replace(text, String::new());
43-
//! *text = orig.replace("my", "your");
44-
//! }
45-
//! _ => (),
46-
//! }
47-
//! });
48-
//!
4935
//! let mut html = vec![];
5036
//! format_html(root, &Options::default(), &mut html).unwrap();
5137
//!
5238
//! assert_eq!(
5339
//! String::from_utf8(html).unwrap(),
5440
//! "<p>This is your input.</p>\n\
5541
//! <ol>\n\
56-
//! <li>Also your input.</li>\n\
57-
//! <li>Certainly your input.</li>\n\
42+
//! <li>Also <a href=\"#\">your</a> input.</li>\n\
43+
//! <li>Certainly <em>your</em> input.</li>\n\
5844
//! </ol>\n");
5945
//! # }
6046
//! ```
@@ -98,11 +84,15 @@ pub use cm::format_document as format_commonmark;
9884
pub use cm::format_document_with_plugins as format_commonmark_with_plugins;
9985
pub use html::format_document as format_html;
10086
pub use html::format_document_with_plugins as format_html_with_plugins;
87+
#[doc(inline)]
10188
pub use html::Anchorizer;
89+
#[allow(deprecated)]
90+
pub use parser::parse_document_with_broken_link_callback;
10291
pub use parser::{
103-
parse_document, parse_document_with_broken_link_callback, ExtensionOptions,
92+
parse_document, BrokenLinkCallback, BrokenLinkReference, ExtensionOptions,
10493
ExtensionOptionsBuilder, ListStyleType, Options, ParseOptions, ParseOptionsBuilder, Plugins,
10594
PluginsBuilder, RenderOptions, RenderOptionsBuilder, RenderPlugins, RenderPluginsBuilder,
95+
ResolvedReference,
10696
};
10797
pub use typed_arena::Arena;
10898
pub use xml::format_document as format_xml;
@@ -111,9 +101,9 @@ pub use xml::format_document_with_plugins as format_xml_with_plugins;
111101
/// Legacy naming of [`ExtensionOptions`]
112102
pub type ComrakExtensionOptions = ExtensionOptions;
113103
/// Legacy naming of [`Options`]
114-
pub type ComrakOptions = Options;
104+
pub type ComrakOptions<'c> = Options<'c>;
115105
/// Legacy naming of [`ParseOptions`]
116-
pub type ComrakParseOptions = ParseOptions;
106+
pub type ComrakParseOptions<'c> = ParseOptions<'c>;
117107
/// Legacy naming of [`Plugins`]
118108
pub type ComrakPlugins<'a> = Plugins<'a>;
119109
/// Legacy naming of [`RenderOptions`]

0 commit comments

Comments
 (0)