Skip to content

Commit

Permalink
Merge pull request #192 from vojtechkral/code-num-backticks
Browse files Browse the repository at this point in the history
Add the NodeCode struct to expose number of backticks from inline code spans
  • Loading branch information
kivikakk committed Jul 15, 2021
2 parents 38beddb + 7284d7f commit 7b1f19f
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 14 deletions.
4 changes: 2 additions & 2 deletions examples/headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
extern crate comrak;

use comrak::{
nodes::{AstNode, NodeValue},
nodes::{AstNode, NodeCode, NodeValue},
parse_document, Arena, ComrakOptions,
};

Expand Down Expand Up @@ -40,7 +40,7 @@ fn get_document_title(document: &str) -> String {

fn collect_text<'a>(node: &'a AstNode<'a>, output: &mut Vec<u8>) {
match node.data.borrow().value {
NodeValue::Text(ref literal) | NodeValue::Code(ref literal) => {
NodeValue::Text(ref literal) | NodeValue::Code(NodeCode { ref literal, .. }) => {
output.extend_from_slice(literal)
}
NodeValue::LineBreak | NodeValue::SoftBreak => output.push(b' '),
Expand Down
10 changes: 9 additions & 1 deletion examples/s-expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,19 @@ fn iter_nodes<'a, W: Write>(
match &node.data.borrow().value {
Text(t) => write!(writer, "{:?}", String::from_utf8_lossy(&t))?,
value => {
try_node_inline!(value, Code);
try_node_inline!(value, FootnoteDefinition);
try_node_inline!(value, FootnoteReference);
try_node_inline!(value, HtmlInline);

if let Code(code) = value {
return write!(
writer,
"Code({:?}, {})",
String::from_utf8_lossy(&code.literal),
code.num_backticks
);
}

let has_blocks = node.children().any(|c| c.data.borrow().value.block());

write!(writer, "({:?}", value)?;
Expand Down
2 changes: 1 addition & 1 deletion src/cm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
NodeValue::Text(ref literal) => self.format_text(literal, allow_wrap, entering),
NodeValue::LineBreak => self.format_line_break(entering),
NodeValue::SoftBreak => self.format_soft_break(allow_wrap, entering),
NodeValue::Code(ref literal) => self.format_code(literal, allow_wrap, entering),
NodeValue::Code(ref code) => self.format_code(&code.literal, allow_wrap, entering),
NodeValue::HtmlInline(ref literal) => self.format_html_inline(literal, entering),
NodeValue::Strong => self.format_strong(),
NodeValue::Emph => self.format_emph(node),
Expand Down
8 changes: 4 additions & 4 deletions src/html.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ctype::isspace;
use nodes::{AstNode, ListType, NodeValue, TableAlignment};
use nodes::{AstNode, ListType, NodeCode, NodeValue, TableAlignment};
use parser::ComrakOptions;
use regex::Regex;
use scanners;
Expand Down Expand Up @@ -338,7 +338,7 @@ impl<'o> HtmlFormatter<'o> {
if plain {
match node.data.borrow().value {
NodeValue::Text(ref literal)
| NodeValue::Code(ref literal)
| NodeValue::Code(NodeCode { ref literal, .. })
| NodeValue::HtmlInline(ref literal) => {
self.escape(literal)?;
}
Expand Down Expand Up @@ -369,7 +369,7 @@ impl<'o> HtmlFormatter<'o> {

fn collect_text<'a>(&self, node: &'a AstNode<'a>, output: &mut Vec<u8>) {
match node.data.borrow().value {
NodeValue::Text(ref literal) | NodeValue::Code(ref literal) => {
NodeValue::Text(ref literal) | NodeValue::Code(NodeCode { ref literal, .. }) => {
output.extend_from_slice(literal)
}
NodeValue::LineBreak | NodeValue::SoftBreak => output.push(b' '),
Expand Down Expand Up @@ -563,7 +563,7 @@ impl<'o> HtmlFormatter<'o> {
}
}
}
NodeValue::Code(ref literal) => {
NodeValue::Code(NodeCode { ref literal, .. }) => {
if entering {
self.output.write_all(b"<code>")?;
self.escape(literal)?;
Expand Down
15 changes: 14 additions & 1 deletion src/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ pub enum NodeValue {
LineBreak,

/// **Inline**. A [code span](https://github.github.com/gfm/#code-spans).
Code(Vec<u8>),
Code(NodeCode),

/// **Inline**. [Raw HTML](https://github.github.com/gfm/#raw-html) contained inline.
HtmlInline(Vec<u8>),
Expand Down Expand Up @@ -160,6 +160,19 @@ pub enum TableAlignment {
Right,
}

/// An inline [code span](https://github.github.com/gfm/#code-spans).
#[derive(Debug, Clone)]
pub struct NodeCode {
/// The URL for the link destination or image source.
pub num_backticks: usize,

/// The content of the inline code span.
/// As the contents are not interpreted as Markdown at all,
/// they are contained within this structure,
/// rather than inserted into a child inline of any kind.
pub literal: Vec<u8>,
}

/// The details of a link's destination, or an image's source.
#[derive(Debug, Clone)]
pub struct NodeLink {
Expand Down
8 changes: 6 additions & 2 deletions src/parser/inlines.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use arena_tree::Node;
use ctype::{ispunct, isspace};
use entity;
use nodes::{Ast, AstNode, NodeLink, NodeValue};
use nodes::{Ast, AstNode, NodeCode, NodeLink, NodeValue};
use parser::{unwrap_into_2, unwrap_into_copy, AutolinkType, Callback, ComrakOptions, Reference};
use scanners;
use std::cell::{Cell, RefCell};
Expand Down Expand Up @@ -518,7 +518,11 @@ impl<'a, 'r, 'o, 'd, 'i, 'c, 'subj> Subject<'a, 'r, 'o, 'd, 'i, 'c, 'subj> {
Some(endpos) => {
let buf = &self.input[startpos..endpos - openticks];
let buf = strings::normalize_code(buf);
make_inline(self.arena, NodeValue::Code(buf))
let code = NodeCode {
num_backticks: openticks,
literal: buf,
};
make_inline(self.arena, NodeValue::Code(code))
}
}
}
Expand Down
41 changes: 38 additions & 3 deletions src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::nodes::{AstNode, NodeCode, NodeValue};
use cm;
use html;
use propfuzz::prelude::*;
Expand Down Expand Up @@ -95,6 +96,18 @@ macro_rules! html_opts {
};
}

fn asssert_node_eq<'a>(node: &'a AstNode<'a>, location: &[usize], expected: &NodeValue) {
let node = location
.iter()
.fold(node, |node, &n| node.children().nth(n).unwrap());

let data = node.data.borrow();
let actual = format!("{:?}", data.value);
let expected = format!("{:?}", expected);

compare_strs(&actual, &expected, "ast comparison");
}

#[test]
fn basic() {
html(
Expand Down Expand Up @@ -310,6 +323,27 @@ fn backticks() {
);
}

#[test]
fn backticks_num() {
let input = "Some `code1`. More ``` code2 ```.\n";

let arena = Arena::new();
let options = ComrakOptions::default();
let root = parse_document(&arena, input, &options);

let code1 = NodeValue::Code(NodeCode {
num_backticks: 1,
literal: b"code1".to_vec(),
});
asssert_node_eq(root, &[0, 1], &code1);

let code2 = NodeValue::Code(NodeCode {
num_backticks: 3,
literal: b"code2".to_vec(),
});
asssert_node_eq(root, &[0, 3], &code2);
}

#[test]
fn backslashes() {
html(
Expand Down Expand Up @@ -1065,9 +1099,9 @@ fn exercise_full_api() {

let _: String = ::Anchorizer::new().anchorize("header".to_string());

let _: &::nodes::AstNode = ::parse_document(&arena, "document", &default_options);
let _: &AstNode = ::parse_document(&arena, "document", &default_options);

let _: &::nodes::AstNode = ::parse_document_with_broken_link_callback(
let _: &AstNode = ::parse_document_with_broken_link_callback(
&arena,
"document",
&default_options,
Expand Down Expand Up @@ -1168,7 +1202,8 @@ fn exercise_full_api() {
::nodes::NodeValue::SoftBreak => {}
::nodes::NodeValue::LineBreak => {}
::nodes::NodeValue::Code(code) => {
let _: &Vec<u8> = code;
let _: usize = code.num_backticks;
let _: Vec<u8> = code.literal;
}
::nodes::NodeValue::HtmlInline(html) => {
let _: &Vec<u8> = html;
Expand Down

0 comments on commit 7b1f19f

Please sign in to comment.