Skip to main content

rumdl_lib/utils/
mkdocs_definition_lists.rs

1//! MkDocs/Python-Markdown Definition Lists extension support
2//!
3//! This module provides support for the Python-Markdown Definition Lists extension,
4//! which allows creating definition lists with terms and their definitions.
5//!
6//! ## Syntax
7//!
8//! ```markdown
9//! Term 1
10//! :   Definition for term 1
11//!
12//! Term 2
13//! :   Definition for term 2
14//!     Continuation of the definition
15//!
16//! Term with multiple definitions
17//! :   First definition
18//! :   Second definition
19//! ```
20//!
21//! ## Format Requirements
22//!
23//! - Term appears on its own line (no leading whitespace required for the term)
24//! - Definition starts with `:` followed by whitespace (typically 3 spaces after `:`)
25//! - Multiple definitions for a term use separate `:` lines
26//! - Continuation lines are indented (typically 4 spaces)
27//!
28//! ## MkDocs Material Specifics
29//!
30//! MkDocs Material supports definition lists via the Python-Markdown Definition Lists extension,
31//! which is enabled by default in the Material theme.
32//!
33//! ## References
34//!
35//! - [Python-Markdown Definition Lists](https://python-markdown.github.io/extensions/definition_lists/)
36//! - [MkDocs Material - Lists](https://squidfunk.github.io/mkdocs-material/reference/lists/#using-definition-lists)
37
38/// Check if a line is a definition (starts with `:` followed by whitespace)
39///
40/// Reexported from utils::mod.rs for compatibility
41#[inline]
42pub fn is_definition_line(line: &str) -> bool {
43    crate::utils::is_definition_list_item(line)
44}
45
46/// Check if a line could be a term (precedes a definition)
47///
48/// A term line is a non-empty line that:
49/// - Doesn't start with whitespace (or has consistent indentation for nested terms)
50/// - Is followed by a definition line (checked by caller)
51/// - Is not a definition line itself
52/// - Is not a blank line
53#[inline]
54pub fn could_be_term_line(line: &str) -> bool {
55    let trimmed = line.trim();
56    !trimmed.is_empty() && !is_definition_line(line) && !line.starts_with(' ')
57}
58
59/// Check if a line is a definition continuation (indented after a definition)
60///
61/// Continuation lines are typically indented 4 spaces
62#[inline]
63pub fn is_definition_continuation(line: &str) -> bool {
64    // Continuation is indented (at least 4 spaces) and not a new definition
65    line.starts_with("    ") && !line.trim_start().starts_with(':')
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71
72    #[test]
73    fn test_is_definition_line() {
74        assert!(is_definition_line(":   Definition text"));
75        assert!(is_definition_line(": Definition text"));
76        assert!(is_definition_line(":\tDefinition text"));
77        assert!(is_definition_line(":    Long definition"));
78
79        assert!(!is_definition_line("Term"));
80        assert!(!is_definition_line("  Term"));
81        assert!(!is_definition_line(""));
82        assert!(!is_definition_line(":NoSpace")); // No space after colon
83    }
84
85    #[test]
86    fn test_could_be_term_line() {
87        assert!(could_be_term_line("Term"));
88        assert!(could_be_term_line("Multi Word Term"));
89        assert!(could_be_term_line("Term with special chars: like this"));
90
91        assert!(!could_be_term_line("")); // Empty
92        assert!(!could_be_term_line("   ")); // Blank
93        assert!(!could_be_term_line(":   Definition")); // Definition
94        assert!(!could_be_term_line(" Term")); // Leading space
95    }
96
97    #[test]
98    fn test_is_definition_continuation() {
99        assert!(is_definition_continuation("    Continuation text"));
100        assert!(is_definition_continuation("    More continuation"));
101
102        assert!(!is_definition_continuation(":   New definition"));
103        assert!(!is_definition_continuation("No indent"));
104        assert!(!is_definition_continuation("  Only 2 spaces"));
105    }
106}