diff --git a/src/html.rs b/src/html.rs index 8a3cc5c1..6edf7215 100644 --- a/src/html.rs +++ b/src/html.rs @@ -26,7 +26,7 @@ use std::io::{self, ErrorKind, Write}; use crate::escape::{escape_href, escape_html}; use crate::parse::Event::*; -use crate::parse::{Alignment, Event, LinkType, Tag}; +use crate::parse::{Alignment, CodeBlockKind, Event, LinkType, Tag}; use crate::strings::CowStr; enum TableState { @@ -254,13 +254,18 @@ where if !self.end_newline { self.write_newline()?; } - let lang = info.split(' ').next().unwrap(); - if lang.is_empty() { - self.write("
")
- } else {
- self.write("")
+ match info {
+ CodeBlockKind::Fenced(info) => {
+ let lang = info.split(' ').next().unwrap();
+ if lang.is_empty() {
+ self.write("")
+ } else {
+ self.write("")
+ }
+ }
+ CodeBlockKind::Indented => self.write(""),
}
}
Tag::List(Some(1)) => {
diff --git a/src/lib.rs b/src/lib.rs
index 18b8d85d..229e1f03 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -70,5 +70,5 @@ mod tree;
#[cfg(all(target_arch = "x86_64", feature = "simd"))]
mod simd;
-pub use crate::parse::{Alignment, Event, LinkType, OffsetIter, Options, Parser, Tag};
+pub use crate::parse::{Alignment, CodeBlockKind, Event, LinkType, OffsetIter, Options, Parser, Tag};
pub use crate::strings::{CowStr, InlineStr};
diff --git a/src/parse.rs b/src/parse.rs
index 9801b536..83a81dc8 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -38,6 +38,30 @@ use crate::tree::{Tree, TreeIndex, TreePointer};
// https://spec.commonmark.org/0.29/#link-destination
const LINK_MAX_NESTED_PARENS: usize = 5;
+/// Codeblock kind.
+#[derive(Clone, Debug, PartialEq)]
+pub enum CodeBlockKind<'a> {
+ Indented,
+ /// The value contained in the tag describes the language of the code, which may be empty.
+ Fenced(CowStr<'a>),
+}
+
+impl<'a> CodeBlockKind<'a> {
+ pub fn is_indented(&self) -> bool {
+ match *self {
+ CodeBlockKind::Indented => true,
+ _ => false,
+ }
+ }
+
+ pub fn is_fenced(&self) -> bool {
+ match *self {
+ CodeBlockKind::Fenced(_) => true,
+ _ => false,
+ }
+ }
+}
+
/// Tags for elements that can contain other elements.
#[derive(Clone, Debug, PartialEq)]
pub enum Tag<'a> {
@@ -48,9 +72,8 @@ pub enum Tag<'a> {
Heading(u32),
BlockQuote,
- /// A code block. The value contained in the tag describes the language of the code,
- /// which may be empty.
- CodeBlock(CowStr<'a>),
+ /// A code block.
+ CodeBlock(CodeBlockKind<'a>),
/// A list. If the list is ordered the field indicates the number of the first item.
/// Contains only list items.
@@ -1015,7 +1038,9 @@ impl<'a> FirstPass<'a> {
self.tree.append(Item {
start: start_ix,
end: 0, // will get set later
- body: ItemBody::FencedCodeBlock(self.allocs.allocate_cow(info_string)),
+ body: ItemBody::FencedCodeBlock(
+ self.allocs.allocate_cow(info_string),
+ ),
});
self.tree.push();
loop {
@@ -2676,8 +2701,10 @@ fn item_to_tag<'a>(item: &Item, allocs: &Allocations<'a>) -> Tag<'a> {
Tag::Image(*link_type, url.clone(), title.clone())
}
ItemBody::Heading(level) => Tag::Heading(level),
- ItemBody::FencedCodeBlock(cow_ix) => Tag::CodeBlock(allocs[cow_ix].clone()),
- ItemBody::IndentCodeBlock => Tag::CodeBlock("".into()),
+ ItemBody::FencedCodeBlock(cow_ix) => {
+ Tag::CodeBlock(CodeBlockKind::Fenced(allocs[cow_ix].clone()))
+ }
+ ItemBody::IndentCodeBlock => Tag::CodeBlock(CodeBlockKind::Indented),
ItemBody::BlockQuote => Tag::BlockQuote,
ItemBody::List(_, c, listitem_start) => {
if c == b'.' || c == b')' {
@@ -2723,8 +2750,10 @@ fn item_to_event<'a>(item: Item, text: &'a str, allocs: &Allocations<'a>) -> Eve
Tag::Image(*link_type, url.clone(), title.clone())
}
ItemBody::Heading(level) => Tag::Heading(level),
- ItemBody::FencedCodeBlock(cow_ix) => Tag::CodeBlock(allocs[cow_ix].clone()),
- ItemBody::IndentCodeBlock => Tag::CodeBlock("".into()),
+ ItemBody::FencedCodeBlock(cow_ix) => {
+ Tag::CodeBlock(CodeBlockKind::Fenced(allocs[cow_ix].clone()))
+ }
+ ItemBody::IndentCodeBlock => Tag::CodeBlock(CodeBlockKind::Indented),
ItemBody::BlockQuote => Tag::BlockQuote,
ItemBody::List(_, c, listitem_start) => {
if c == b'.' || c == b')' {
@@ -3031,4 +3060,35 @@ mod test {
}
assert!(link_tag_count > 0);
}
+
+ #[test]
+ fn code_block_kind_check_fenced() {
+ let parser = Parser::new("hello\n```test\ntadam\n```");
+ let mut found = 0;
+ for (ev, _range) in parser.into_offset_iter() {
+ match ev {
+ Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(syntax))) => {
+ assert_eq!(syntax.as_ref(), "test");
+ found += 1;
+ }
+ _ => {}
+ }
+ }
+ assert_eq!(found, 1);
+ }
+
+ #[test]
+ fn code_block_kind_check_indented() {
+ let parser = Parser::new("hello\n\n ```test\n tadam\nhello");
+ let mut found = 0;
+ for (ev, _range) in parser.into_offset_iter() {
+ match ev {
+ Event::Start(Tag::CodeBlock(CodeBlockKind::Indented)) => {
+ found += 1;
+ }
+ _ => {}
+ }
+ }
+ assert_eq!(found, 1);
+ }
}