| 1 | use markdown_it::parser::block::{BlockRule, BlockState}; |
| 2 | use markdown_it::Node; |
| 3 | |
| 4 | use crate::plugin::{get_line_raw, RawBlock}; |
| 5 | |
| 6 | /// Parse line comments (//) and HTML comments (<!--) |
| 7 | pub(crate) struct Rule; |
| 8 | |
| 9 | impl BlockRule for Rule { |
| 10 | fn run(state: &mut BlockState) -> Option<(Node, usize)> { |
| 11 | if state.line >= state.line_max { |
| 12 | return None; |
| 13 | } |
| 14 | |
| 15 | let line = get_line_raw(state, state.line); |
| 16 | |
| 17 | if !line.starts_with("//") && !line.starts_with("<!--") { |
| 18 | return None; |
| 19 | } |
| 20 | |
| 21 | let (end_line, is_closed) = if line.starts_with("//") { |
| 22 | (state.line, true) |
| 23 | } else { |
| 24 | find_html_comment_end(state, state.line) |
| 25 | }; |
| 26 | |
| 27 | if !is_closed { |
| 28 | return None; |
| 29 | } |
| 30 | |
| 31 | let mut content_lines = Vec::new(); |
| 32 | for line_idx in state.line..=end_line { |
| 33 | content_lines.push(get_line_raw(state, line_idx).to_string()); |
| 34 | } |
| 35 | |
| 36 | let mut content = content_lines.join("\n"); |
| 37 | content.push('\n'); |
| 38 | |
| 39 | Some((Node::new(RawBlock { content }), end_line - state.line + 1)) |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | /// Find the end line of an HTML comment and whether it's properly closed |
| 44 | fn find_html_comment_end(state: &BlockState, start_line: usize) -> (usize, bool) { |
| 45 | for line_idx in start_line..state.line_max { |
| 46 | let line = get_line_raw(state, line_idx); |
| 47 | if line.contains("-->") { |
| 48 | return (line_idx, true); |
| 49 | } |
| 50 | } |
| 51 | // Comment never closed |
| 52 | (state.line_max - 1, false) |
| 53 | } |