use crate::syntax::run_len;
#[expect(clippy::cast_possible_truncation)] pub fn directive_fence_open(tail: &str) -> Option<u32> {
let run = run_len(tail.as_bytes(), b':');
if run < 3 {
return None;
}
tail[run..]
.trim_start_matches([' ', '\t'])
.starts_with(|c: char| c.is_alphanumeric() || matches!(c, '_' | '{' | '['))
.then_some(run as u32)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fence_open() {
assert_eq!(directive_fence_open(":::note"), Some(3));
assert_eq!(directive_fence_open(":::日本"), Some(3));
assert_eq!(directive_fence_open("::::my-note[Label]{#id .cls} "), Some(4));
assert_eq!(directive_fence_open("::: tip Custom Title"), Some(3), "markdown-it-container");
assert_eq!(directive_fence_open(":::tip Custom Title"), Some(3));
assert_eq!(directive_fence_open("::: {.class}"), Some(3), "Pandoc fenced div");
assert_eq!(directive_fence_open(":::_x"), Some(3));
assert_eq!(directive_fence_open("::x"), None);
assert_eq!(directive_fence_open(":::"), None, "a closing fence is not an opener");
assert_eq!(directive_fence_open("::: "), None);
assert_eq!(directive_fence_open(":::)"), None, "an emoticon is not an opener");
assert_eq!(directive_fence_open("::: -x"), None);
}
}