Skip to content

Commit

Permalink
Formatting chars can be escaped with \
Browse files Browse the repository at this point in the history
It's a breaking change. It's possible to compile without
the "escaping" feature to keep the old behaviour.
  • Loading branch information
Canop committed Feb 15, 2021
1 parent c650e67 commit f19b772
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 48 deletions.
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "minimad"
version = "0.6.9"
version = "0.7.0"
authors = ["dystroy <denys.seguret@gmail.com>"]
repository = "https://github.com/Canop/minimad"
description = "light Markdown parser"
Expand All @@ -12,3 +12,7 @@ readme = "README.md"

[dependencies]
lazy_static = "1"

[features]
escaping = []
default = ["escaping"]
45 changes: 45 additions & 0 deletions src/header.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use {
crate::*,
std::cmp,
};

/// count the number of '#' at start. Return 0 if they're
/// not followed by a ' ' or if they're too many
pub fn header_level(src: &str) -> usize {
let src = src.as_bytes();
let mut l: usize = src.len();
if l > 2 {
l = cmp::min(src.len() - 1, MAX_HEADER_DEPTH + 1);
for i in 0..l {
match src[i] {
b'#' => {}
b' ' => {
return i;
}
_ => {
return 0;
}
}
}
}
0
}

#[test]
fn header_level_count() {
assert_eq!(header_level(""), 0);
assert_eq!(header_level("#"), 0);
assert_eq!(header_level("# "), 0); // we don't allow empty headers
assert_eq!(header_level("# A"), 1);
assert_eq!(header_level(" "), 0);
assert_eq!(header_level("test"), 0);
assert_eq!(header_level("###b"), 0);
assert_eq!(header_level("###"), 0);
assert_eq!(header_level("### b"), 3);
assert_eq!(header_level(" a b"), 0);
assert_eq!(header_level("# titre"), 1);
assert_eq!(header_level("#### *titre*"), 4);
assert_eq!(header_level("######## a b"), 8);
assert_eq!(header_level("######### a b"), 0); // too deep
}

4 changes: 3 additions & 1 deletion src/inline_template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,12 @@ macro_rules! mad_inline {
#[allow(unused_mut)]
#[allow(unused_variables)]
let mut arg_idx = 0;
#[allow(unused_mut)]
let mut composite = TEMPLATE.raw_composite();
$(
TEMPLATE.apply(&mut composite, arg_idx, $value);
arg_idx += 1;
#[allow(unused_assignments)] // rustc bug
{ arg_idx += 1; }
)*
composite
}};
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ assert_eq!(
pub mod clean;
mod composite;
mod compound;
mod header;
mod inline_template;
mod line;
mod line_parser;
Expand All @@ -46,6 +47,7 @@ mod text_template;
pub use {
composite::{Composite, CompositeStyle},
compound::{Alignment, Compound},
header::header_level,
inline_template::InlineTemplate,
line::Line,
line::MAX_HEADER_DEPTH,
Expand Down
104 changes: 58 additions & 46 deletions src/line_parser.rs
Original file line number Diff line number Diff line change
@@ -1,48 +1,6 @@
use crate::composite::{Composite, CompositeStyle};
use crate::compound::Compound;
use crate::line::*;
use crate::tbl::TableRow;
use std::cmp;

/// count the number of '#' at start. Return 0 if they're
/// not followed by a ' ' or if they're too many
fn header_level(src: &str) -> usize {
let src = src.as_bytes();
let mut l: usize = src.len();
if l > 2 {
l = cmp::min(src.len() - 1, MAX_HEADER_DEPTH + 1);
for i in 0..l {
match src[i] {
b'#' => {}
b' ' => {
return i;
}
_ => {
return 0;
}
}
}
}
0
}

#[test]
fn header_level_count() {
assert_eq!(header_level(""), 0);
assert_eq!(header_level("#"), 0);
assert_eq!(header_level("# "), 0); // we don't allow empty headers
assert_eq!(header_level("# A"), 1);
assert_eq!(header_level(" "), 0);
assert_eq!(header_level("test"), 0);
assert_eq!(header_level("###b"), 0);
assert_eq!(header_level("###"), 0);
assert_eq!(header_level("### b"), 3);
assert_eq!(header_level(" a b"), 0);
assert_eq!(header_level("# titre"), 1);
assert_eq!(header_level("#### *titre*"), 4);
assert_eq!(header_level("######## a b"), 8);
assert_eq!(header_level("######### a b"), 0); // too deep
}
use {
crate::*,
};

/// The structure parsing a line or part of a line.
/// A LineParser initialized from a markdown string exposes 2 main methods:
Expand Down Expand Up @@ -96,14 +54,31 @@ impl<'s> LineParser<'s> {
let mut compounds = Vec::new();
let mut after_first_star = false;
let mut after_first_tilde = false;
let mut after_antislash = false;

for (idx, char) in self.src.char_indices().skip(self.idx) {
if self.code {
// only one thing matters: whether we're closing the inline code
if char == '`' {
self.close_compound(idx, 1, &mut compounds);
self.code = false;
}
} else if after_first_star {
after_antislash = false;
after_first_star = false;
continue;
}

#[cfg(feature="escaping")]
if after_antislash {
after_antislash = false;
continue;
} else if char=='\\' {
self.close_compound(idx, 1, &mut compounds);
after_antislash = true;
continue;
}

if after_first_star {
match char {
'*' => {
// this is the second star
Expand Down Expand Up @@ -402,6 +377,43 @@ mod tests {
);
}

#[test]
fn escapes() {
assert_eq!(
Line::from(
"no \\*italic\\* here"
),
Line::new_paragraph(vec![
Compound::raw_str("no "),
Compound::raw_str("*italic"),
Compound::raw_str("* here"),
])
);
assert_eq!(
Line::from(
"*italic\\*and\\*still\\*italic*"
),
Line::new_paragraph(vec![
Compound::raw_str("italic").italic(),
Compound::raw_str("*and").italic(),
Compound::raw_str("*still").italic(),
Compound::raw_str("*italic").italic(),
])
);
assert_eq!(
Line::from("\\**Italic then **bold\\\\ and \\`italic `and some *code*`** and italic*\\*"),
Line::new_paragraph(vec![
Compound::raw_str("*"),
Compound::raw_str("Italic then ").italic(),
Compound::raw_str("bold").bold().italic(),
Compound::raw_str("\\ and ").bold().italic(),
Compound::raw_str("`italic ").bold().italic(),
Compound::raw_str("and some *code*").bold().italic().code(),
Compound::raw_str(" and italic*").italic(),
])
);
}

#[test]
fn code_fence() {
assert_eq!(Line::from("```"), Line::new_code_fence(vec![]),);
Expand Down

0 comments on commit f19b772

Please sign in to comment.