Markdown parser fork with extended syntax for personal use.
at hack 152 lines 4.5 kB view raw
1use crate::construct::partial_space_or_tab_eol::{space_or_tab_eol_with_options, Options}; 2use crate::event::{Content, Link, Name}; 3use crate::state::{Name as StateName, State}; 4use crate::subtokenize::link; 5use crate::tokenizer::Tokenizer; 6use crate::util::constant::LINK_REFERENCE_SIZE_MAX; 7 8/// Start of label. 9/// 10/// ```markdown 11/// > | [a] 12/// ^ 13/// ``` 14pub fn start(tokenizer: &mut Tokenizer) -> State { 15 State::Retry(StateName::WikilinkLabelAtBreak) 16} 17 18/// In label, at something, before something else. 19/// 20/// ```markdown 21/// > | [a] 22/// ^ 23/// ``` 24pub fn at_break(tokenizer: &mut Tokenizer) -> State { 25 if tokenizer.tokenize_state.size > LINK_REFERENCE_SIZE_MAX || matches!(tokenizer.current, None) 26 { 27 State::Retry(StateName::WikilinkLabelNok) 28 } else { 29 match tokenizer.current { 30 Some(b'\n') => { 31 tokenizer.attempt( 32 State::Next(StateName::WikilinkLabelEolAfter), 33 State::Next(StateName::WikilinkLabelNok), 34 ); 35 State::Retry(space_or_tab_eol_with_options( 36 tokenizer, 37 Options { 38 content: Some(Content::String), 39 connect: tokenizer.tokenize_state.connect, 40 }, 41 )) 42 } 43 44 Some(b']') if tokenizer.tokenize_state.size_b == 1 => { 45 tokenizer.tokenize_state.size_b = 0; 46 State::Retry(StateName::WikilinkEnd) 47 } 48 _ => { 49 tokenizer.enter_link( 50 Name::Data, 51 Link { 52 previous: None, 53 next: None, 54 content: Content::String, 55 }, 56 ); 57 58 if tokenizer.tokenize_state.connect { 59 let index = tokenizer.events.len() - 1; 60 link(&mut tokenizer.events, index); 61 } else { 62 tokenizer.tokenize_state.connect = true; 63 } 64 65 State::Retry(StateName::WikilinkLabelInside) 66 } 67 } 68 } 69} 70 71/// In label, after whitespace. 72/// 73/// ```markdown 74/// | [a␊ 75/// > | b] 76/// ^ 77/// ``` 78pub fn eol_after(tokenizer: &mut Tokenizer) -> State { 79 tokenizer.tokenize_state.connect = true; 80 State::Retry(StateName::WikilinkLabelAtBreak) 81} 82 83/// In label, on something disallowed. 84/// 85/// ```markdown 86/// > | [] 87/// ^ 88/// ``` 89pub fn nok(tokenizer: &mut Tokenizer) -> State { 90 tokenizer.tokenize_state.connect = false; 91 tokenizer.tokenize_state.seen = false; 92 tokenizer.tokenize_state.size = 0; 93 State::Nok 94} 95 96/// In label, in text. 97/// 98/// ```markdown 99/// > | [a] 100/// ^ 101/// ``` 102pub fn inside(tokenizer: &mut Tokenizer) -> State { 103 match tokenizer.current { 104 None | Some(b'\n') => { 105 tokenizer.exit(Name::Data); 106 State::Retry(StateName::WikilinkLabelAtBreak) 107 } 108 Some(b']') => { 109 tokenizer.exit(Name::Data); 110 tokenizer.consume(); 111 tokenizer.tokenize_state.size += 1; 112 tokenizer.tokenize_state.size_b = 1; 113 tokenizer.tokenize_state.seen = false; // ?? 114 115 State::Next(StateName::WikilinkLabelAtBreak) 116 } 117 Some(byte) => { 118 if tokenizer.tokenize_state.size > LINK_REFERENCE_SIZE_MAX { 119 tokenizer.exit(Name::Data); 120 State::Retry(StateName::WikilinkLabelAtBreak) 121 } else { 122 tokenizer.consume(); 123 tokenizer.tokenize_state.size += 1; 124 if !tokenizer.tokenize_state.seen && !matches!(byte, b'\t' | b' ') { 125 tokenizer.tokenize_state.seen = true; 126 } 127 State::Next(if matches!(byte, b'\\') { 128 StateName::WikilinkLabelEscape 129 } else { 130 StateName::WikilinkLabelInside 131 }) 132 } 133 } 134 } 135} 136 137/// After `\`, at a special character. 138/// 139/// ```markdown 140/// > | [a\*a] 141/// ^ 142/// ``` 143pub fn escape(tokenizer: &mut Tokenizer) -> State { 144 match tokenizer.current { 145 Some(b'[' | b'\\' | b']') => { 146 tokenizer.consume(); 147 tokenizer.tokenize_state.size += 1; 148 State::Next(StateName::WikilinkLabelInside) 149 } 150 _ => State::Retry(StateName::WikilinkLabelInside), 151 } 152}