use rumdl_lib::config::MarkdownFlavor;
use rumdl_lib::lint_context::LintContext;
use rumdl_lib::rule::Rule;
use rumdl_lib::rules::{
MD005ListIndent, MD007ULIndent, MD013LineLength, MD031BlanksAroundFences, MD042NoEmptyLinks, MD046CodeBlockStyle,
MD052ReferenceLinkImages,
};
#[test]
fn test_mkdocs_footnotes_integration() {
let content = r#"# Document with Footnotes
Here's some text with a footnote[^1] reference.
Another paragraph with a named footnote[^note].
[^1]: This is the first footnote definition.
It can span multiple lines with proper indentation.
Even include paragraphs.
[^note]: This is a named footnote.
Regular text after footnotes."#;
let rule_031 = MD031BlanksAroundFences::default();
let ctx = LintContext::new(content, MarkdownFlavor::MkDocs, None);
let warnings = rule_031.check(&ctx).unwrap();
assert_eq!(warnings.len(), 0, "Footnote definitions should not need blank lines");
let rule_042 = MD042NoEmptyLinks::default();
let warnings = rule_042.check(&ctx).unwrap();
assert_eq!(
warnings.len(),
0,
"Footnote references should not be flagged as empty links"
);
}
#[test]
fn test_mkdocs_tabs_integration() {
let content = r#"# Document with Tabs
Regular content here.
=== "Python"
```python
def hello():
print("Hello, World!")
```
Python is great for scripting.
=== "JavaScript"
```javascript
function hello() {
console.log("Hello, World!");
}
```
JavaScript runs in the browser.
=== "Rust"
```rust
fn main() {
println!("Hello, World!");
}
```
More content after tabs."#;
let rule_031 = MD031BlanksAroundFences::default();
let ctx = LintContext::new(content, MarkdownFlavor::MkDocs, None);
let warnings = rule_031.check(&ctx).unwrap();
assert!(warnings.len() <= 2, "Tab sections should be handled appropriately");
}
#[test]
fn test_mkdocstrings_autodoc_integration() {
let content = r#"# API Documentation
## Module Reference
::: mypackage.mymodule.MyClass
handler: python
options:
show_source: true
show_root_heading: true
members:
- method1
- method2
Regular documentation text.
::: another.module.Function
## Cross-References
See the [MyClass][] for more details.
The [configuration][mypackage.config.Config] is important.
You can also use [custom text][mymodule.utils.helper]."#;
let rule_052 = MD052ReferenceLinkImages::default();
let ctx = LintContext::new(content, MarkdownFlavor::MkDocs, None);
let warnings = rule_052.check(&ctx).unwrap();
assert!(
warnings.len() <= 3,
"Cross-references might be flagged if not explicitly handled"
);
}
#[test]
fn test_mkdocs_mixed_extensions() {
let content = r#"# Complex MkDocs Document
!!! note "Important"
This is an admonition with a footnote[^1].
## Content Tabs
=== "Tab 1"
Content in tab 1 with a snippet:
--8<-- "included.md"
=== "Tab 2"
Content in tab 2 with autodoc:
::: mymodule.MyClass
handler: python
## Regular Content
Some text with a footnote[^2] and a cross-reference to [MyClass][].
[^1]: First footnote in an admonition.
[^2]: Second footnote in regular text.
??? tip "Collapsible Tip"
This collapsible section has content."#;
let ctx = LintContext::new(content, MarkdownFlavor::MkDocs, None);
let rule_031 = MD031BlanksAroundFences::default();
let warnings = rule_031.check(&ctx).unwrap();
assert!(warnings.len() <= 10, "Mixed MkDocs features should be handled");
}
#[test]
fn test_standard_flavor_no_mkdocs_features() {
let content = r#"# Standard Markdown
[^1]: This looks like a footnote but isn't in standard flavor.
=== "Tab"
This looks like a tab but isn't.
::: module.Class
This looks like autodoc but isn't.
!!! note
This looks like an admonition but isn't."#;
let ctx = LintContext::new(content, MarkdownFlavor::Standard, None);
let rule_031 = MD031BlanksAroundFences::default();
let warnings = rule_031.check(&ctx).unwrap();
assert_eq!(warnings.len(), 0, "Standard flavor should not detect MkDocs features");
}
#[test]
fn test_footnotes_with_complex_content() {
let content = r#"# Document
Text with reference[^complex].
[^complex]: This footnote has:
- A list item
- Another item
```python
# Code in footnote
print("test")
```
More content.
Regular text."#;
let ctx = LintContext::new(content, MarkdownFlavor::MkDocs, None);
let rule_031 = MD031BlanksAroundFences::default();
let warnings = rule_031.check(&ctx).unwrap();
assert!(warnings.len() <= 2, "Complex footnote content should be handled");
}
#[test]
fn test_nested_tabs() {
let content = r#"# Nested Tabs
=== "Outer Tab 1"
Content in outer tab.
=== "Inner Tab A"
Nested content A.
=== "Inner Tab B"
Nested content B.
=== "Outer Tab 2"
Different content."#;
let ctx = LintContext::new(content, MarkdownFlavor::MkDocs, None);
let rule_031 = MD031BlanksAroundFences::default();
let warnings = rule_031.check(&ctx).unwrap();
assert!(warnings.len() <= 8, "Nested tabs should be handled");
}
#[test]
fn test_mkdocstrings_with_yaml_options() {
let content = r#"# API Documentation
::: toga.ScrollContainer
options:
members:
- window
- app
- content
show_source: true
show_root_heading: true
Regular text continues here."#;
let ctx = LintContext::new(content, MarkdownFlavor::MkDocs, None);
let rule_005 = MD005ListIndent::default();
let warnings = rule_005.check(&ctx).unwrap();
assert_eq!(
warnings.len(),
0,
"MD005 should not flag YAML lists in mkdocstrings options"
);
let rule_007 = MD007ULIndent::new(2);
let warnings = rule_007.check(&ctx).unwrap();
assert_eq!(
warnings.len(),
0,
"MD007 should not flag YAML lists in mkdocstrings options"
);
let rule_013 = MD013LineLength::new(80, false, false, false, false);
let warnings = rule_013.check(&ctx).unwrap();
assert_eq!(warnings.len(), 0, "MD013 should not flag mkdocstrings blocks");
let rule_046 = MD046CodeBlockStyle::new(rumdl_lib::rules::CodeBlockStyle::Fenced);
let warnings = rule_046.check(&ctx).unwrap();
assert_eq!(
warnings.len(),
0,
"MD046 should not flag YAML options as indented code blocks"
);
}
#[test]
fn test_mkdocstrings_deeply_nested_yaml() {
let content = r#"# API Documentation
::: mypackage.module.Class
handler: python
options:
show_source: true
show_root_heading: true
members:
- method1
- method2
- property1
filters:
- "!^_"
- "!^test_"
group_by_category: true
categories:
properties:
- property1
- property2
methods:
- method1
- method2
Regular documentation continues."#;
let ctx = LintContext::new(content, MarkdownFlavor::MkDocs, None);
let rule_005 = MD005ListIndent::default();
assert_eq!(rule_005.check(&ctx).unwrap().len(), 0);
let rule_007 = MD007ULIndent::new(2);
assert_eq!(rule_007.check(&ctx).unwrap().len(), 0);
let rule_046 = MD046CodeBlockStyle::new(rumdl_lib::rules::CodeBlockStyle::Fenced);
assert_eq!(rule_046.check(&ctx).unwrap().len(), 0);
}