Skip to main content

oxc_markdown_parser/syntax/
mod.rs

1//! Grammar shared by the block and inline phases.
2//!
3//! Anything both phases (or the parser and its consumers) must agree on lives here exactly once:
4//! escape and entity decoding, label normalization, link-target productions,
5//! liquid delimiters, HTML tag grammar, Unicode character classes.
6//!
7//! `decode` and `label` are re-exported at the crate root as public API.
8
9pub mod decode;
10mod entities;
11pub mod html;
12pub mod label;
13pub mod link_target;
14pub mod liquid;
15pub mod unicode;
16
17/// Whether the backslash at `p` escapes the next byte
18/// (ASCII punctuation only; never a line ending).
19pub fn escapes_next(bytes: &[u8], p: usize) -> bool {
20    bytes.get(p + 1).is_some_and(u8::is_ascii_punctuation)
21}
22
23/// Length of the run of `marker` bytes at the start of `bytes`.
24pub fn run_len(bytes: &[u8], marker: u8) -> usize {
25    bytes.iter().take_while(|&&b| b == marker).count()
26}
27
28/// Skips spaces/tabs and up to `max_newlines` line endings.
29pub fn skip_ws(bytes: &[u8], mut p: usize, max_newlines: usize) -> usize {
30    let mut newlines = 0;
31    while let Some(&c) = bytes.get(p) {
32        match c {
33            b' ' | b'\t' => p += 1,
34            b'\n' if newlines < max_newlines => {
35                newlines += 1;
36                p += 1;
37            }
38            _ => break,
39        }
40    }
41    p
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn escapes_next_only_ascii_punctuation() {
50        assert!(escapes_next(br"\*", 0));
51        assert!(!escapes_next(br"\a", 0));
52        assert!(!escapes_next(b"\\\n", 0));
53        assert!(!escapes_next(br"\", 0), "nothing to escape at the end");
54    }
55
56    #[test]
57    fn skip_ws_caps_newlines() {
58        assert_eq!(skip_ws(b"  \t x", 0, 0), 4);
59        assert_eq!(skip_ws(b" \n x", 0, 0), 1);
60        assert_eq!(skip_ws(b" \n x", 0, 1), 3);
61        assert_eq!(skip_ws(b"\n\n x", 0, 1), 1);
62        assert_eq!(skip_ws(b"x", 0, 1), 0);
63    }
64}