Skip to content

Commit

Permalink
Merge pull request #232 from kivikakk/xml-sourcepos
Browse files Browse the repository at this point in the history
xml, sourcepos
  • Loading branch information
kivikakk committed Mar 31, 2023
2 parents 93a9485 + 586f179 commit a11a4d4
Show file tree
Hide file tree
Showing 41 changed files with 3,517 additions and 1,823 deletions.
24 changes: 19 additions & 5 deletions examples/custom_headings.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use comrak::{
adapters::{HeadingAdapter, HeadingMeta},
markdown_to_html_with_plugins, ComrakOptions, ComrakPlugins,
markdown_to_html_with_plugins,
nodes::Sourcepos,
ComrakOptions, ComrakPlugins,
};
use std::io::{self, Write};

fn main() {
let adapter = CustomHeadingAdapter;
let options = ComrakOptions::default();
let mut options = ComrakOptions::default();
let mut plugins = ComrakPlugins::default();
plugins.render.heading_adapter = Some(&adapter);

Expand All @@ -25,21 +27,33 @@ fn main() {
&options,
&plugins
);
options.render.sourcepos = true;
print_html("# Here is a [link](/)", &options, &plugins);
}

struct CustomHeadingAdapter;

impl HeadingAdapter for CustomHeadingAdapter {
fn enter(&self, output: &mut dyn Write, heading: &HeadingMeta) -> io::Result<()> {
fn enter(
&self,
output: &mut dyn Write,
heading: &HeadingMeta,
sourcepos: Option<Sourcepos>,
) -> io::Result<()> {
let id = slug::slugify(&heading.content);

let search_include = !&heading.content.contains("hide");

write!(output, "<h{}", heading.level)?;

if let Some(sourcepos) = sourcepos {
write!(output, " data-sourcepos=\"{}\"", sourcepos)?;
}

write!(
output,
"<h{} id=\"{}\" data-search-include=\"{}\">",
heading.level, id, search_include
" id=\"{}\" data-search-include=\"{}\">",
id, search_include
)
}

Expand Down
6 changes: 6 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,9 @@ name = "quadratic"
path = "fuzz_targets/quadratic.rs"
test = false
doc = false

[[bin]]
name = "gfm_sourcepos"
path = "fuzz_targets/gfm_sourcepos.rs"
test = false
doc = false
1 change: 1 addition & 0 deletions fuzz/fuzz_targets/all_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ fuzz_target!(|s: &str| {
unsafe_: true,
escape: true,
list_style: ListStyleType::Star,
sourcepos: true,
},
},
);
Expand Down
32 changes: 32 additions & 0 deletions fuzz/fuzz_targets/gfm_sourcepos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#![no_main]

use libfuzzer_sys::fuzz_target;

use comrak::{markdown_to_html, ComrakExtensionOptions, ComrakOptions, ComrakRenderOptions};

// Note that what I'm targetting here isn't exactly the same
// as --gfm, but rather an approximation of what cmark-gfm
// options are routinely used by Commonmarker users.

fuzz_target!(|s: &str| {
markdown_to_html(
s,
&ComrakOptions {
extension: ComrakExtensionOptions {
strikethrough: true,
tagfilter: true,
table: true,
autolink: true,
..Default::default()
},
parse: Default::default(),
render: ComrakRenderOptions {
hardbreaks: true,
github_pre_lang: true,
unsafe_: true,
sourcepos: true,
..Default::default()
},
},
);
});
2 changes: 2 additions & 0 deletions fuzz/fuzz_targets/quadratic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ struct FuzzComrakRenderOptions {
unsafe_: bool,
escape: bool,
list_style: ListStyleType,
sourcepos: bool,
}

impl FuzzComrakRenderOptions {
Expand All @@ -249,6 +250,7 @@ impl FuzzComrakRenderOptions {
unsafe_: self.unsafe_,
escape: self.escape,
list_style: self.list_style,
sourcepos: self.sourcepos,
}
}
}
Expand Down
7 changes: 0 additions & 7 deletions proptest-regressions/tests.txt

This file was deleted.

13 changes: 10 additions & 3 deletions src/adapters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
use std::collections::HashMap;
use std::io::{self, Write};

use crate::nodes::Sourcepos;

/// Implement this adapter for creating a plugin for custom syntax highlighting of codefence blocks.
pub trait SyntaxHighlighterAdapter {
/// Generates a syntax highlighted HTML output.
Expand Down Expand Up @@ -56,9 +58,14 @@ pub struct HeadingMeta {
/// defines what's rendered after it. Both methods provide access to a [`HeadingMeta`] struct and
/// leave the AST content of the heading unchanged.
pub trait HeadingAdapter {
/// Called prior to rendering
fn enter(&self, output: &mut dyn Write, heading: &HeadingMeta) -> io::Result<()>;
/// Render the opening tag.
fn enter(
&self,
output: &mut dyn Write,
heading: &HeadingMeta,
sourcepos: Option<Sourcepos>,
) -> io::Result<()>;

/// Close tags.
/// Render the closing tag.
fn exit(&self, output: &mut dyn Write, heading: &HeadingMeta) -> io::Result<()>;
}
41 changes: 25 additions & 16 deletions src/cm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,22 +277,28 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
None => return false,
};

if let NodeValue::Item(..) = tmp.data.borrow().value {
if let NodeValue::List(ref nl) = tmp.parent().unwrap().data.borrow().value {
return nl.tight;
match tmp.data.borrow().value {
NodeValue::Item(..) | NodeValue::TaskItem(..) => {
if let NodeValue::List(ref nl) = tmp.parent().unwrap().data.borrow().value {
return nl.tight;
}
return false;
}
return false;
_ => {}
}

let parent = match tmp.parent() {
Some(parent) => parent,
None => return false,
};

if let NodeValue::Item(..) = parent.data.borrow().value {
if let NodeValue::List(ref nl) = parent.parent().unwrap().data.borrow().value {
return nl.tight;
match parent.data.borrow().value {
NodeValue::Item(..) | NodeValue::TaskItem(..) => {
if let NodeValue::List(ref nl) = parent.parent().unwrap().data.borrow().value {
return nl.tight;
}
}
_ => {}
}

false
Expand All @@ -302,8 +308,10 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
self.node = node;
let allow_wrap = self.options.render.width > 0 && !self.options.render.hardbreaks;

if !(matches!(node.data.borrow().value, NodeValue::Item(..))
&& node.previous_sibling().is_none()
if !(matches!(
node.data.borrow().value,
NodeValue::Item(..) | NodeValue::TaskItem(..)
) && node.previous_sibling().is_none()
&& entering)
{
self.in_tight_list_item = self.get_in_tight_list_item(node);
Expand Down Expand Up @@ -337,7 +345,7 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
}
NodeValue::Strong => self.format_strong(),
NodeValue::Emph => self.format_emph(node),
NodeValue::TaskItem { symbol } => self.format_task_item(symbol, entering),
NodeValue::TaskItem(symbol) => self.format_task_item(symbol, node, entering),
NodeValue::Strikethrough => self.format_strikethrough(),
NodeValue::Superscript => self.format_superscript(),
NodeValue::Link(ref nl) => return self.format_link(node, nl, entering),
Expand Down Expand Up @@ -465,7 +473,10 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
let first_in_list_item = node.previous_sibling().is_none()
&& match node.parent() {
Some(parent) => {
matches!(parent.data.borrow().value, NodeValue::Item(..))
matches!(
parent.data.borrow().value,
NodeValue::Item(..) | NodeValue::TaskItem(..)
)
}
_ => false,
};
Expand Down Expand Up @@ -612,7 +623,8 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
self.write_all(&[emph_delim]).unwrap();
}

fn format_task_item(&mut self, symbol: Option<char>, entering: bool) {
fn format_task_item(&mut self, symbol: Option<char>, node: &'a AstNode<'a>, entering: bool) {
self.format_item(node, entering);
if entering {
write!(self, "[{}] ", symbol.unwrap_or(' ')).unwrap();
}
Expand Down Expand Up @@ -667,10 +679,7 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
fn format_shortcode(&mut self, ne: &NodeShortCode, entering: bool) {
if entering {
write!(self, ":").unwrap();
} else {
if let Some(shortcode) = ne.shortcode() {
self.output(shortcode.as_bytes(), false, Escaping::Literal);
}
self.output(ne.shortcode().as_bytes(), false, Escaping::Literal);
write!(self, ":").unwrap();
}
}
Expand Down
Loading

0 comments on commit a11a4d4

Please sign in to comment.