rumdl_lib/rules/md057_existing_relative_links/md057_config.rs
1use crate::rule_config_serde::RuleConfig;
2use serde::{Deserialize, Serialize};
3
4/// How to handle absolute links (paths starting with /)
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
6#[serde(rename_all = "snake_case")]
7pub enum AbsoluteLinksOption {
8 /// Ignore absolute links (don't validate them) - this is the default
9 #[default]
10 Ignore,
11 /// Warn about absolute links (they can't be validated as local paths)
12 Warn,
13 /// Resolve absolute links relative to MkDocs docs_dir and validate
14 RelativeToDocs,
15 /// Resolve absolute links relative to one or more explicit root directories.
16 /// First match wins; reports broken only when all roots miss.
17 RelativeToRoots,
18}
19
20/// Configuration for MD057 (relative link validation)
21///
22/// This rule validates that relative links point to existing files.
23#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
24#[serde(default, rename_all = "kebab-case")]
25pub struct MD057Config {
26 /// How to handle absolute links (paths starting with /)
27 /// - "ignore" (default): Skip validation for absolute links
28 /// - "warn": Report a warning for absolute links
29 /// - "relative_to_docs": Resolve relative to MkDocs docs_dir and validate
30 /// - "relative_to_roots": Resolve relative to one or more configured root directories
31 #[serde(alias = "absolute_links")]
32 pub absolute_links: AbsoluteLinksOption,
33
34 /// Warn when relative links contain unnecessary path traversal.
35 /// When enabled, `../sub_dir/file.md` from within `sub_dir/` warns
36 /// and suggests the shorter equivalent `file.md`.
37 #[serde(alias = "compact_paths")]
38 pub compact_paths: bool,
39
40 /// Additional directories to search when a relative link is not found
41 /// relative to the file's directory.
42 ///
43 /// Paths are resolved relative to the project root (where `.rumdl.toml` or
44 /// `pyproject.toml` is found), or relative to the current working directory.
45 ///
46 /// For Obsidian users: the attachment folder is auto-detected from
47 /// `.obsidian/app.json` when `flavor = "obsidian"` is set, so this option
48 /// is typically not needed. Use it for custom setups or non-Obsidian tools.
49 ///
50 /// Example:
51 /// ```toml
52 /// [MD057]
53 /// search-paths = ["assets", "images", "attachments"]
54 /// ```
55 #[serde(alias = "search_paths")]
56 pub search_paths: Vec<String>,
57
58 /// Root directories used when `absolute-links = "relative_to_roots"`.
59 ///
60 /// Absolute links are resolved against each root in order; the first root
61 /// where the target file exists passes the check. A warning is emitted only
62 /// when none of the roots contain the target.
63 ///
64 /// Paths are resolved relative to the current working directory when not
65 /// absolute. Trailing slashes are normalized automatically.
66 ///
67 /// When `roots` is empty and `absolute-links = "relative_to_roots"`, the
68 /// rule emits a "not validated" warning for every absolute link, consistent
69 /// with the fallback behavior of `relative_to_docs` when no `mkdocs.yml` is
70 /// found.
71 ///
72 /// Example:
73 /// ```toml
74 /// [MD057]
75 /// absolute-links = "relative_to_roots"
76 /// roots = ["content/en", "content/zh-cn"]
77 /// ```
78 pub roots: Vec<String>,
79}
80
81impl RuleConfig for MD057Config {
82 const RULE_NAME: &'static str = "MD057";
83}