Skip to content

Commit

Permalink
mod: broken link reference callback gets normalized and original.
Browse files Browse the repository at this point in the history
Fixes #143.
  • Loading branch information
kivikakk committed Jul 11, 2024
1 parent bd16259 commit c44bbcc
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 9 deletions.
7 changes: 4 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,10 @@ pub use html::format_document as format_html;
pub use html::format_document_with_plugins as format_html_with_plugins;
pub use html::Anchorizer;
pub use parser::{
parse_document, parse_document_with_broken_link_callback, ExtensionOptions,
ExtensionOptionsBuilder, ListStyleType, Options, ParseOptions, ParseOptionsBuilder, Plugins,
PluginsBuilder, RenderOptions, RenderOptionsBuilder, RenderPlugins, RenderPluginsBuilder,
parse_document, parse_document_with_broken_link_callback, BrokenLinkReference,
ExtensionOptions, ExtensionOptionsBuilder, ListStyleType, Options, ParseOptions,
ParseOptionsBuilder, Plugins, PluginsBuilder, RenderOptions, RenderOptionsBuilder,
RenderPlugins, RenderPluginsBuilder,
};
pub use typed_arena::Arena;
pub use xml::format_document as format_xml;
Expand Down
12 changes: 10 additions & 2 deletions src/parser/inlines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use crate::nodes::{
use crate::parser::autolink;
#[cfg(feature = "shortcodes")]
use crate::parser::shortcodes::NodeShortCode;
use crate::parser::{unwrap_into_2, unwrap_into_copy, AutolinkType, Callback, Options, Reference};
use crate::parser::{
unwrap_into_2, unwrap_into_copy, AutolinkType, BrokenLinkReference, Callback, Options,
Reference,
};
use crate::scanners;
use crate::strings::{self, is_blank, Case};
use std::cell::{Cell, RefCell};
Expand Down Expand Up @@ -1530,6 +1533,7 @@ impl<'a, 'r, 'o, 'd, 'i, 'c, 'subj> Subject<'a, 'r, 'o, 'd, 'i, 'c, 'subj> {
}

// Need to normalize both to lookup in refmap and to call callback
let unfolded_lab = lab.to_owned();
let lab = strings::normalize_label(&lab, Case::Fold);
let mut reff = if found_label {
self.refmap.lookup(&lab)
Expand All @@ -1540,7 +1544,11 @@ impl<'a, 'r, 'o, 'd, 'i, 'c, 'subj> Subject<'a, 'r, 'o, 'd, 'i, 'c, 'subj> {
// Attempt to use the provided broken link callback if a reference cannot be resolved
if reff.is_none() {
if let Some(ref mut callback) = self.callback {
reff = callback(&lab).map(|(url, title)| Reference { url, title });
reff = callback(BrokenLinkReference {
normalized: &lab,
original: &unfolded_lab,
})
.map(|(url, title)| Reference { url, title });
}
}

Expand Down
19 changes: 16 additions & 3 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub fn parse_document<'a>(
/// described in the [GFM spec](https://github.github.com/gfm/#matches).
///
/// ```
/// use comrak::{Arena, parse_document_with_broken_link_callback, format_html, Options};
/// use comrak::{Arena, parse_document_with_broken_link_callback, format_html, Options, BrokenLinkReference};
/// use comrak::nodes::{AstNode, NodeValue};
///
/// # fn main() -> std::io::Result<()> {
Expand All @@ -83,7 +83,7 @@ pub fn parse_document<'a>(
/// &arena,
/// "# Cool input!\nWow look at this cool [link][foo]. A [broken link] renders as text.",
/// &Options::default(),
/// Some(&mut |link_ref: &str| match link_ref {
/// Some(&mut |link_ref: BrokenLinkReference| match link_ref.normalized {
/// "foo" => Some((
/// "https://www.rust-lang.org/".to_string(),
/// "The Rust Language".to_string(),
Expand Down Expand Up @@ -122,7 +122,20 @@ pub fn parse_document_with_broken_link_callback<'a, 'c>(
parser.finish(linebuf)
}

type Callback<'c> = &'c mut dyn FnMut(&str) -> Option<(String, String)>;
type Callback<'c> = &'c mut dyn FnMut(BrokenLinkReference) -> Option<(String, String)>;

/// Struct to the broken link callback, containing details on the link reference
/// which failed to find a match.
#[derive(Debug)]
pub struct BrokenLinkReference<'l> {
/// The normalized reference link label. Unicode case folding is applied;
/// see <https://github.com/commonmark/commonmark-spec/issues/695> for a
/// discussion on the details of what this exactly means.
pub normalized: &'l str,

/// The original text in the link label.
pub original: &'l str,
}

pub struct Parser<'a, 'o, 'c> {
arena: &'a Arena<AstNode<'a>>,
Expand Down
6 changes: 5 additions & 1 deletion src/tests/api.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use parser::BrokenLinkReference;

use crate::{
adapters::{HeadingAdapter, HeadingMeta, SyntaxHighlighterAdapter},
nodes::Sourcepos,
Expand Down Expand Up @@ -31,7 +33,9 @@ fn exercise_full_api() {
&arena,
"document",
&default_options,
Some(&mut |_: &str| Some(("abc".to_string(), "xyz".to_string()))),
Some(&mut |blr: BrokenLinkReference| {
Some((blr.normalized.to_owned(), blr.original.to_owned()))
}),
);

let mut extension = ExtensionOptionsBuilder::default();
Expand Down

0 comments on commit c44bbcc

Please sign in to comment.