Skip to content

Commit

Permalink
Merge pull request #444 from kivikakk/experimental-inline-sourcepos
Browse files Browse the repository at this point in the history
Restore inline sourcepos as experimental.
  • Loading branch information
kivikakk authored Jul 12, 2024
2 parents ae113bf + 1dc3fed commit 0de8251
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 38 deletions.
130 changes: 96 additions & 34 deletions src/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -725,31 +725,43 @@ impl<'o, 'c: 'o> HtmlFormatter<'o, 'c> {
}
}
NodeValue::Text(ref literal) => {
// No sourcepos.
// Nowhere to put sourcepos.
if entering {
self.escape(literal.as_bytes())?;
}
}
NodeValue::LineBreak => {
// No sourcepos.
// Unreliable sourcepos.
if entering {
self.output.write_all(b"<br />\n")?;
self.output.write_all(b"<br")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output.write_all(b" />\n")?;
}
}
NodeValue::SoftBreak => {
// No sourcepos.
// Unreliable sourcepos.
if entering {
if self.options.render.hardbreaks {
self.output.write_all(b"<br />\n")?;
self.output.write_all(b"<br")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output.write_all(b" />\n")?;
} else {
self.output.write_all(b"\n")?;
}
}
}
NodeValue::Code(NodeCode { ref literal, .. }) => {
// No sourcepos.
// Unreliable sourcepos.
if entering {
self.output.write_all(b"<code>")?;
self.output.write_all(b"<code")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output.write_all(b">")?;
self.escape(literal.as_bytes())?;
self.output.write_all(b"</code>")?;
}
Expand All @@ -771,47 +783,67 @@ impl<'o, 'c: 'o> HtmlFormatter<'o, 'c> {
}
}
NodeValue::Strong => {
// No sourcepos.
// Unreliable sourcepos.
let parent_node = node.parent();
if !self.options.render.gfm_quirks
|| (parent_node.is_none()
|| !matches!(parent_node.unwrap().data.borrow().value, NodeValue::Strong))
{
if entering {
self.output.write_all(b"<strong>")?;
self.output.write_all(b"<strong")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output.write_all(b">")?;
} else {
self.output.write_all(b"</strong>")?;
}
}
}
NodeValue::Emph => {
// No sourcepos.
// Unreliable sourcepos.
if entering {
self.output.write_all(b"<em>")?;
self.output.write_all(b"<em")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output.write_all(b">")?;
} else {
self.output.write_all(b"</em>")?;
}
}
NodeValue::Strikethrough => {
// No sourcepos.
// Unreliable sourcepos.
if entering {
self.output.write_all(b"<del>")?;
self.output.write_all(b"<del")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output.write_all(b">")?;
} else {
self.output.write_all(b"</del>")?;
}
}
NodeValue::Superscript => {
// No sourcepos.
// Unreliable sourcepos.
if entering {
self.output.write_all(b"<sup>")?;
self.output.write_all(b"<sup")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output.write_all(b">")?;
} else {
self.output.write_all(b"</sup>")?;
}
}
NodeValue::Link(ref nl) => {
// No sourcepos.
// Unreliable sourcepos.
if entering {
self.output.write_all(b"<a href=\"")?;
self.output.write_all(b"<a")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output.write_all(b" href=\"")?;
let url = nl.url.as_bytes();
if self.options.render.unsafe_ || !dangerous_url(url) {
self.escape_href(url)?;
Expand All @@ -826,9 +858,13 @@ impl<'o, 'c: 'o> HtmlFormatter<'o, 'c> {
}
}
NodeValue::Image(ref nl) => {
// No sourcepos.
// Unreliable sourcepos.
if entering {
self.output.write_all(b"<img src=\"")?;
self.output.write_all(b"<img")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output.write_all(b" src=\"")?;
let url = nl.url.as_bytes();
if self.options.render.unsafe_ || !dangerous_url(url) {
self.escape_href(url)?;
Expand All @@ -845,6 +881,7 @@ impl<'o, 'c: 'o> HtmlFormatter<'o, 'c> {
}
#[cfg(feature = "shortcodes")]
NodeValue::ShortCode(ref nsc) => {
// Nowhere to put sourcepos.
if entering {
self.output.write_all(nsc.emoji.as_bytes())?;
}
Expand Down Expand Up @@ -941,14 +978,17 @@ impl<'o, 'c: 'o> HtmlFormatter<'o, 'c> {
}
}
NodeValue::FootnoteDefinition(ref nfd) => {
// No sourcepos.
if entering {
if self.footnote_ix == 0 {
self.output.write_all(b"<section")?;
self.render_sourcepos(node)?;
self.output
.write_all(b"<section class=\"footnotes\" data-footnotes>\n<ol>\n")?;
.write_all(b" class=\"footnotes\" data-footnotes>\n<ol>\n")?;
}
self.footnote_ix += 1;
self.output.write_all(b"<li id=\"fn-")?;
self.output.write_all(b"<li")?;
self.render_sourcepos(node)?;
self.output.write_all(b" id=\"fn-")?;
self.escape_href(nfd.name.as_bytes())?;
self.output.write_all(b"\">")?;
} else {
Expand All @@ -959,14 +999,19 @@ impl<'o, 'c: 'o> HtmlFormatter<'o, 'c> {
}
}
NodeValue::FootnoteReference(ref nfr) => {
// No sourcepos.
// Unreliable sourcepos.
if entering {
let mut ref_id = format!("fnref-{}", nfr.name);
if nfr.ref_num > 1 {
ref_id = format!("{}-{}", ref_id, nfr.ref_num);
}

self.output.write_all(b"<sup")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output
.write_all(b"<sup class=\"footnote-ref\"><a href=\"#fn-")?;
.write_all(b" class=\"footnote-ref\"><a href=\"#fn-")?;
self.escape_href(nfr.name.as_bytes())?;
self.output.write_all(b"\" id=\"")?;
self.escape_href(ref_id.as_bytes())?;
Expand Down Expand Up @@ -1004,10 +1049,14 @@ impl<'o, 'c: 'o> HtmlFormatter<'o, 'c> {
}
}
NodeValue::Escaped => {
// No sourcepos.
// Unreliable sourcepos.
if self.options.render.escaped_char_spans {
if entering {
self.output.write_all(b"<span data-escaped-char>")?;
self.output.write_all(b"<span data-escaped-char")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output.write_all(b">")?;
} else {
self.output.write_all(b"</span>")?;
}
Expand All @@ -1024,9 +1073,13 @@ impl<'o, 'c: 'o> HtmlFormatter<'o, 'c> {
}
}
NodeValue::WikiLink(ref nl) => {
// No sourcepos.
// Unreliable sourcepos.
if entering {
self.output.write_all(b"<a href=\"")?;
self.output.write_all(b"<a")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output.write_all(b" href=\"")?;
let url = nl.url.as_bytes();
if self.options.render.unsafe_ || !dangerous_url(url) {
self.escape_href(url)?;
Expand All @@ -1038,23 +1091,31 @@ impl<'o, 'c: 'o> HtmlFormatter<'o, 'c> {
}
}
NodeValue::Underline => {
// No sourcepos.
// Unreliable sourcepos.
if entering {
self.output.write_all(b"<u>")?;
self.output.write_all(b"<u")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output.write_all(b">")?;
} else {
self.output.write_all(b"</u>")?;
}
}
NodeValue::SpoileredText => {
// No sourcepos.
// Unreliable sourcepos.
if entering {
self.output.write_all(b"<span class=\"spoiler\">")?;
self.output.write_all(b"<span")?;
if self.options.render.experimental_inline_sourcepos {
self.render_sourcepos(node)?;
}
self.output.write_all(b" class=\"spoiler\">")?;
} else {
self.output.write_all(b"</span>")?;
}
}
NodeValue::EscapedTag(ref net) => {
// No sourcepos.
// Nowhere to put sourcepos.
self.output.write_all(net.as_bytes())?;
}
}
Expand Down Expand Up @@ -1114,7 +1175,8 @@ impl<'o, 'c: 'o> HtmlFormatter<'o, 'c> {

tag_attributes.push((String::from("data-math-style"), String::from(style_attr)));

if self.options.render.sourcepos {
// Unreliable sourcepos.
if self.options.render.experimental_inline_sourcepos && self.options.render.sourcepos {
let ast = node.data.borrow();
tag_attributes.push(("data-sourcepos".to_string(), ast.sourcepos.to_string()));
}
Expand Down
24 changes: 20 additions & 4 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,19 +761,35 @@ pub struct RenderOptions {
/// extensions. The description lists extension still has issues; see
/// <https://github.com/kivikakk/comrak/blob/3bb6d4ce/src/tests/description_lists.rs#L60-L125>.
///
/// Sourcepos information is **not** reliable for inlines. See
/// <https://github.com/kivikakk/comrak/pull/439> for a discussion.
/// Sourcepos information is **not** reliable for inlines, and is not
/// included in HTML without also setting [`experimental_inline_sourcepos`].
/// See <https://github.com/kivikakk/comrak/pull/439> for a discussion.
///
/// ```rust
/// # use comrak::{markdown_to_commonmark_xml, Options};
/// let mut options = Options::default();
/// options.render.sourcepos = true;
/// let input = "Hello *world*!";
/// let input = "## Hello world!";
/// let xml = markdown_to_commonmark_xml(input, &options);
/// assert!(xml.contains("<emph sourcepos=\"1:7-1:13\">"));
/// assert!(xml.contains("<text sourcepos=\"1:4-1:15\" xml:space=\"preserve\">"));
/// ```
pub sourcepos: bool,

/// Include inline sourcepos in HTML output, which is known to have issues.
/// See <https://github.com/kivikakk/comrak/pull/439> for a discussion.
/// ```rust
/// # use comrak::{markdown_to_html, Options};
/// let mut options = Options::default();
/// options.render.sourcepos = true;
/// let input = "Hello *world*!";
/// assert_eq!(markdown_to_html(input, &options),
/// "<p data-sourcepos=\"1:1-1:14\">Hello <em>world</em>!</p>\n");
/// options.render.experimental_inline_sourcepos = true;
/// assert_eq!(markdown_to_html(input, &options),
/// "<p data-sourcepos=\"1:1-1:14\">Hello <em data-sourcepos=\"1:7-1:13\">world</em>!</p>\n");
/// ```
pub experimental_inline_sourcepos: bool,

/// Wrap escaped characters in a `<span>` to allow any
/// post-processing to recognize them.
///
Expand Down

0 comments on commit 0de8251

Please sign in to comment.