PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
Functions | Variables
check_markdown_links Namespace Reference

Functions

argparse.Namespace parse_args ()
 Parse command-line arguments.
 
 iter_markdown_files (Path repo_root, str docs_dir, str examples_dir, bool include_readme)
 Yield markdown files from configured roots.
 
bool should_skip_link (str target)
 Perform should skip link.
 
str normalize_target (str raw_target)
 Normalize target.
 
int main ()
 Entry point for this script.
 

Variables

 LINK_PATTERN = re.compile(r"!\[[^\]]*\]\‍(([^)\s]+)(?:\s+\"[^\"]*\")?\‍)|\[[^\]]*\]\‍(([^)\s]+)(?:\s+\"[^\"]*\")?\‍)")
 

Detailed Description

Basic local markdown link checker for README, docs, and example guides.

Function Documentation

◆ parse_args()

argparse.Namespace check_markdown_links.parse_args ( )

Parse command-line arguments.

Returns
Value returned by parse_args().

Definition at line 13 of file check_markdown_links.py.

13def parse_args() -> argparse.Namespace:
14 """!
15 @brief Parse command-line arguments.
16 @return Value returned by `parse_args()`.
17 """
18 parser = argparse.ArgumentParser(
19 description=(
20 "Check local markdown links for README.md plus docs/examples trees.\n"
21 "HTTP(S), mailto, and in-page anchor links are skipped."
22 ),
23 formatter_class=argparse.RawTextHelpFormatter,
24 epilog=(
25 "Examples:\n"
26 " python3 scripts/check_markdown_links.py\n"
27 " python3 scripts/check_markdown_links.py --repo-root . --docs-dir docs --examples-dir examples\n"
28 " python3 scripts/check_markdown_links.py --no-readme"
29 ),
30 )
31 parser.add_argument(
32 "--repo-root",
33 type=Path,
34 default=Path(__file__).resolve().parents[1],
35 help="Repository root directory (default: parent of this script).",
36 )
37 parser.add_argument(
38 "--docs-dir",
39 default="docs",
40 help="Docs subtree under repo root to scan recursively for *.md (default: docs).",
41 )
42 parser.add_argument(
43 "--examples-dir",
44 default="examples",
45 help="Examples subtree under repo root to scan recursively for *.md (default: examples).",
46 )
47 parser.add_argument(
48 "--no-readme",
49 action="store_true",
50 help="Skip README.md in scan set.",
51 )
52 return parser.parse_args()
53
54
Here is the caller graph for this function:

◆ iter_markdown_files()

check_markdown_links.iter_markdown_files ( Path  repo_root,
str  docs_dir,
str  examples_dir,
bool  include_readme 
)

Yield markdown files from configured roots.

Parameters
[in]repo_rootArgument passed to iter_markdown_files().
[in]docs_dirArgument passed to iter_markdown_files().
[in]examples_dirArgument passed to iter_markdown_files().
[in]include_readmeArgument passed to iter_markdown_files().

Definition at line 55 of file check_markdown_links.py.

55def iter_markdown_files(repo_root: Path, docs_dir: str, examples_dir: str, include_readme: bool):
56 """!
57 @brief Yield markdown files from configured roots.
58 @param[in] repo_root Argument passed to `iter_markdown_files()`.
59 @param[in] docs_dir Argument passed to `iter_markdown_files()`.
60 @param[in] examples_dir Argument passed to `iter_markdown_files()`.
61 @param[in] include_readme Argument passed to `iter_markdown_files()`.
62 """
63 if include_readme:
64 yield repo_root / "README.md"
65
66 docs_root = repo_root / docs_dir
67 examples_root = repo_root / examples_dir
68
69 for md in sorted(docs_root.rglob("*.md")):
70 if "docs_build" in md.parts:
71 continue
72 yield md
73 for md in sorted(examples_root.rglob("*.md")):
74 yield md
75
76
Here is the caller graph for this function:

◆ should_skip_link()

bool check_markdown_links.should_skip_link ( str  target)

Perform should skip link.

Parameters
[in]targetArgument passed to should_skip_link().
Returns
Value returned by should_skip_link().

Definition at line 77 of file check_markdown_links.py.

77def should_skip_link(target: str) -> bool:
78 """!
79 @brief Perform should skip link.
80 @param[in] target Argument passed to `should_skip_link()`.
81 @return Value returned by `should_skip_link()`.
82 """
83 lower = target.lower()
84 return (
85 lower.startswith("http://")
86 or lower.startswith("https://")
87 or lower.startswith("mailto:")
88 or lower.startswith("#")
89 )
90
91
Here is the caller graph for this function:

◆ normalize_target()

str check_markdown_links.normalize_target ( str  raw_target)

Normalize target.

Parameters
[in]raw_targetArgument passed to normalize_target().
Returns
Value returned by normalize_target().

Definition at line 92 of file check_markdown_links.py.

92def normalize_target(raw_target: str) -> str:
93 """!
94 @brief Normalize target.
95 @param[in] raw_target Argument passed to `normalize_target()`.
96 @return Value returned by `normalize_target()`.
97 """
98 cleaned = raw_target.strip().strip("<>").split("#", 1)[0].split("?", 1)[0]
99 return cleaned
100
101
Here is the caller graph for this function:

◆ main()

int check_markdown_links.main ( )

Entry point for this script.

Returns
Value returned by main().

Definition at line 102 of file check_markdown_links.py.

102def main() -> int:
103 """!
104 @brief Entry point for this script.
105 @return Value returned by `main()`.
106 """
107 args = parse_args()
108 repo_root = args.repo_root.resolve()
109 failures = []
110
111 for md_file in iter_markdown_files(
112 repo_root,
113 docs_dir=args.docs_dir,
114 examples_dir=args.examples_dir,
115 include_readme=not args.no_readme,
116 ):
117 if not md_file.is_file():
118 failures.append((str(md_file), "<file>", "Markdown file not found"))
119 continue
120 content = md_file.read_text(encoding="utf-8", errors="replace")
121 for match in LINK_PATTERN.findall(content):
122 target = match[0] or match[1]
123 if should_skip_link(target):
124 continue
125 normalized = normalize_target(target)
126 if not normalized:
127 continue
128 resolved = (md_file.parent / normalized).resolve()
129 try:
130 exists = resolved.exists()
131 except OSError as exc:
132 failures.append((str(md_file.relative_to(repo_root)), target, f"{resolved} ({exc})"))
133 continue
134 if not exists:
135 failures.append((str(md_file.relative_to(repo_root)), target, str(resolved)))
136
137 if failures:
138 print("Broken markdown links detected:")
139 for src, target, resolved in failures:
140 print(f" - {src}: '{target}' -> missing '{resolved}'")
141 return 1
142
143 scope = []
144 if not args.no_readme:
145 scope.append("README.md")
146 scope.append(f"{args.docs_dir}/**/*.md")
147 scope.append(f"{args.examples_dir}/**/*.md")
148 print(f"Markdown link check passed for {', '.join(scope)}")
149 return 0
150
151
int main(int argc, char **argv)
Entry point for the postprocessor executable.
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ LINK_PATTERN

check_markdown_links.LINK_PATTERN = re.compile(r"!\[[^\]]*\]\‍(([^)\s]+)(?:\s+\"[^\"]*\")?\‍)|\[[^\]]*\]\‍(([^)\s]+)(?:\s+\"[^\"]*\")?\‍)")

Definition at line 10 of file check_markdown_links.py.