markdown_it/plugins/cmark/inline/
escape.rs1use crate::parser::inline::{InlineRule, InlineState, TextSpecial};
8use crate::plugins::cmark::inline::newline::Hardbreak;
9use crate::{MarkdownIt, Node};
10
11pub fn add(md: &mut MarkdownIt) {
12 md.inline.add_rule::<EscapeScanner>();
13}
14
15#[doc(hidden)]
16pub struct EscapeScanner;
17impl InlineRule for EscapeScanner {
18 const MARKER: char = '\\';
19
20 fn run(state: &mut InlineState) -> Option<(Node, usize)> {
21 let mut chars = state.src[state.pos..state.pos_max].chars();
22 if chars.next().unwrap() != '\\' { return None; }
23
24 match chars.next() {
25 Some('\n') => {
26 let mut len = 2;
28 while let Some(' ' | '\t') = chars.next() {
29 len += 1;
30 }
31 Some((Node::new(Hardbreak), len))
32 }
33 Some(chr) => {
34 let start = state.pos;
35 let end = state.pos + 1 + chr.len_utf8();
36
37 let mut orig_str = "\\".to_owned();
38 orig_str.push(chr);
39
40 let content_str = match chr {
41 '\\' | '!' | '"' | '#' | '$' | '%' | '&' | '\'' | '(' | ')' |
42 '*' | '+' | ',' | '.' | '/' | ':' | ';' | '<' | '=' | '>' | '?' |
43 '@' | '[' | ']' | '^' | '_' | '`' | '{' | '|' | '}' | '~' | '-' => chr.into(),
44 _ => orig_str.clone()
45 };
46
47 let node = Node::new(TextSpecial {
48 content: content_str,
49 markup: orig_str,
50 info: "escape",
51 });
52 Some((node, end - start))
53 }
54 None => None
55 }
56 }
57}