Skip to content

Commit

Permalink
Add boolean to tell if it's an indented code block or not (#416)
Browse files Browse the repository at this point in the history
* Add codeblock kind in Tag:CodeBlock

* Add tests for new syntax

* Fix size tests

* Only keep the syntax

* Re-export CodeBlockKind
  • Loading branch information
GuillaumeGomez authored and marcusklaas committed Dec 18, 2019
1 parent ac3b283 commit e10b680
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 17 deletions.
21 changes: 13 additions & 8 deletions src/html.rs
Expand Up @@ -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 {
Expand Down Expand Up @@ -254,13 +254,18 @@ where
if !self.end_newline {
self.write_newline()?;
}
let lang = info.split(' ').next().unwrap();
if lang.is_empty() {
self.write("<pre><code>")
} else {
self.write("<pre><code class=\"language-")?;
escape_html(&mut self.writer, lang)?;
self.write("\">")
match info {
CodeBlockKind::Fenced(info) => {
let lang = info.split(' ').next().unwrap();
if lang.is_empty() {
self.write("<pre><code>")
} else {
self.write("<pre><code class=\"language-")?;
escape_html(&mut self.writer, lang)?;
self.write("\">")
}
}
CodeBlockKind::Indented => self.write("<pre><code>"),
}
}
Tag::List(Some(1)) => {
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Expand Up @@ -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};
76 changes: 68 additions & 8 deletions src/parse.rs
Expand Up @@ -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> {
Expand All @@ -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.
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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')' {
Expand Down Expand Up @@ -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')' {
Expand Down Expand Up @@ -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);
}
}

0 comments on commit e10b680

Please sign in to comment.