Markdown-Checker 1.1.0__tar.gz → 1.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. markdown_checker-1.2.1/PKG-INFO +118 -0
  2. markdown_checker-1.2.1/README.md +88 -0
  3. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/docs/CONTRIBUTING.rst +8 -8
  4. markdown_checker-1.2.1/docs/api/checker.rst +10 -0
  5. markdown_checker-1.2.1/docs/api/checks.rst +45 -0
  6. markdown_checker-1.2.1/docs/api/cli.rst +10 -0
  7. markdown_checker-1.2.1/docs/api/main.rst +14 -0
  8. markdown_checker-1.2.1/docs/api/models.rst +39 -0
  9. markdown_checker-1.2.1/docs/api/patterns.rst +10 -0
  10. markdown_checker-1.2.1/docs/api/reports.rst +71 -0
  11. markdown_checker-1.2.1/docs/api/utils.rst +46 -0
  12. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/docs/conf.py +3 -0
  13. markdown_checker-1.2.1/docs/explanation/index.rst +12 -0
  14. markdown_checker-1.2.1/docs/explanation/link-detection.rst +53 -0
  15. markdown_checker-1.2.1/docs/explanation/url-checking.rst +78 -0
  16. markdown_checker-1.2.1/docs/howto/github-actions.rst +87 -0
  17. markdown_checker-1.2.1/docs/howto/index.rst +17 -0
  18. markdown_checker-1.2.1/docs/howto/pyproject-config.rst +63 -0
  19. markdown_checker-1.2.1/docs/howto/rate-limits.rst +73 -0
  20. markdown_checker-1.2.1/docs/howto/report-formats.rst +68 -0
  21. markdown_checker-1.2.1/docs/howto/select-files.rst +62 -0
  22. markdown_checker-1.2.1/docs/howto/shell-completions.rst +64 -0
  23. markdown_checker-1.2.1/docs/howto/skip-links.rst +53 -0
  24. markdown_checker-1.2.1/docs/index.rst +87 -0
  25. markdown_checker-1.2.1/docs/reference/checks.rst +105 -0
  26. markdown_checker-1.2.1/docs/reference/cli.rst +305 -0
  27. markdown_checker-1.2.1/docs/reference/configuration.rst +104 -0
  28. markdown_checker-1.2.1/docs/reference/exit-codes.rst +62 -0
  29. markdown_checker-1.2.1/docs/reference/index.rst +16 -0
  30. markdown_checker-1.2.1/docs/reference/report-formats.rst +95 -0
  31. markdown_checker-1.2.1/docs/tutorial.rst +135 -0
  32. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/pyproject.toml +3 -4
  33. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/__init__.py +1 -1
  34. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/checker.py +16 -6
  35. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/checks/__init__.py +3 -1
  36. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/checks/base.py +7 -0
  37. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/checks/broken_paths.py +8 -0
  38. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/checks/broken_urls.py +20 -4
  39. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/checks/locale.py +13 -1
  40. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/checks/tracking.py +18 -0
  41. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/cli.py +97 -51
  42. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/models/__init__.py +2 -0
  43. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/models/base.py +18 -1
  44. markdown_checker-1.2.1/src/markdown_checker/models/config.py +86 -0
  45. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/models/path.py +30 -12
  46. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/models/url.py +27 -4
  47. markdown_checker-1.2.1/src/markdown_checker/patterns.py +36 -0
  48. markdown_checker-1.2.1/src/markdown_checker/reports/__init__.py +38 -0
  49. markdown_checker-1.2.1/src/markdown_checker/reports/base.py +23 -0
  50. markdown_checker-1.2.1/src/markdown_checker/reports/model.py +135 -0
  51. markdown_checker-1.2.1/src/markdown_checker/reports/registry.py +35 -0
  52. markdown_checker-1.2.1/src/markdown_checker/reports/renderers/__init__.py +10 -0
  53. markdown_checker-1.2.1/src/markdown_checker/reports/renderers/annotations.py +39 -0
  54. markdown_checker-1.2.1/src/markdown_checker/reports/renderers/console.py +35 -0
  55. markdown_checker-1.2.1/src/markdown_checker/reports/renderers/json.py +48 -0
  56. markdown_checker-1.2.1/src/markdown_checker/reports/renderers/markdown.py +111 -0
  57. markdown_checker-1.2.1/src/markdown_checker/reports/writer.py +21 -0
  58. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/utils/__init__.py +11 -0
  59. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/utils/extract_links.py +25 -3
  60. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/utils/list_files.py +3 -1
  61. markdown_checker-1.2.1/src/markdown_checker/utils/pyproject_config.py +147 -0
  62. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/utils/spinner.py +23 -1
  63. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/utils/url_pipeline.py +1 -5
  64. markdown_checker-1.2.1/tests/checks/__init__.py +0 -0
  65. markdown_checker-1.2.1/tests/checks/test_base.py +56 -0
  66. markdown_checker-1.1.0/tests/test_checks_broken_urls.py → markdown_checker-1.2.1/tests/checks/test_broken_urls.py +0 -9
  67. markdown_checker-1.1.0/tests/test_checks_locale.py → markdown_checker-1.2.1/tests/checks/test_locale.py +0 -2
  68. markdown_checker-1.1.0/tests/test_checks_tracking.py → markdown_checker-1.2.1/tests/checks/test_tracking.py +0 -5
  69. markdown_checker-1.2.1/tests/models/__init__.py +0 -0
  70. markdown_checker-1.2.1/tests/models/test_config.py +70 -0
  71. markdown_checker-1.2.1/tests/models/test_models.py +20 -0
  72. markdown_checker-1.2.1/tests/reports/__init__.py +0 -0
  73. markdown_checker-1.2.1/tests/reports/conftest.py +36 -0
  74. markdown_checker-1.2.1/tests/reports/renderers/__init__.py +0 -0
  75. markdown_checker-1.2.1/tests/reports/renderers/test_annotations.py +35 -0
  76. markdown_checker-1.2.1/tests/reports/renderers/test_console.py +15 -0
  77. markdown_checker-1.2.1/tests/reports/renderers/test_json.py +27 -0
  78. markdown_checker-1.2.1/tests/reports/renderers/test_markdown.py +232 -0
  79. markdown_checker-1.2.1/tests/reports/renderers/test_renderers.py +17 -0
  80. markdown_checker-1.2.1/tests/reports/test_base.py +37 -0
  81. markdown_checker-1.2.1/tests/reports/test_model.py +77 -0
  82. markdown_checker-1.2.1/tests/reports/test_registry.py +42 -0
  83. markdown_checker-1.2.1/tests/reports/test_reports.py +28 -0
  84. markdown_checker-1.2.1/tests/reports/test_writer.py +22 -0
  85. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/tests/test_checker.py +0 -3
  86. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/tests/test_cli.py +88 -16
  87. markdown_checker-1.2.1/tests/test_markdown_checker.py +34 -0
  88. markdown_checker-1.2.1/tests/test_patterns.py +88 -0
  89. markdown_checker-1.2.1/tests/utils/__init__.py +0 -0
  90. markdown_checker-1.2.1/tests/utils/test_pyproject_config.py +173 -0
  91. markdown_checker-1.1.0/tests/test_utils_url_pipeline.py → markdown_checker-1.2.1/tests/utils/test_url_pipeline.py +2 -26
  92. markdown_checker-1.2.1/tests/utils/test_utils.py +22 -0
  93. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/uv.lock +0 -1
  94. markdown_checker-1.1.0/PKG-INFO +0 -127
  95. markdown_checker-1.1.0/README.md +0 -97
  96. markdown_checker-1.1.0/docs/advanced.rst +0 -439
  97. markdown_checker-1.1.0/docs/api/checker.rst +0 -7
  98. markdown_checker-1.1.0/docs/api/checks.rst +0 -42
  99. markdown_checker-1.1.0/docs/api/cli.rst +0 -7
  100. markdown_checker-1.1.0/docs/api/main.rst +0 -7
  101. markdown_checker-1.1.0/docs/api/models.rst +0 -34
  102. markdown_checker-1.1.0/docs/api/patterns.rst +0 -7
  103. markdown_checker-1.1.0/docs/api/reports.rst +0 -26
  104. markdown_checker-1.1.0/docs/api/utils.rst +0 -42
  105. markdown_checker-1.1.0/docs/automate.rst +0 -9
  106. markdown_checker-1.1.0/docs/index.rst +0 -71
  107. markdown_checker-1.1.0/docs/usage.rst +0 -73
  108. markdown_checker-1.1.0/src/markdown_checker/models/config.py +0 -36
  109. markdown_checker-1.1.0/src/markdown_checker/patterns.py +0 -27
  110. markdown_checker-1.1.0/src/markdown_checker/reports/__init__.py +0 -6
  111. markdown_checker-1.1.0/src/markdown_checker/reports/base.py +0 -31
  112. markdown_checker-1.1.0/src/markdown_checker/reports/format_output.py +0 -86
  113. markdown_checker-1.1.0/src/markdown_checker/reports/markdown.py +0 -65
  114. markdown_checker-1.1.0/tests/test_reports.py +0 -106
  115. markdown_checker-1.1.0/tests/test_utils_format_output.py +0 -139
  116. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/LICENSE +0 -0
  117. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/docs/CODE_OF_CONDUCT.rst +0 -0
  118. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/docs/changes.rst +0 -0
  119. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/docs/license.rst +0 -0
  120. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/py.typed +0 -0
  121. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/reports/templates/paths/broken.md +0 -0
  122. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/reports/templates/paths/tracking.md +0 -0
  123. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/reports/templates/urls/broken.md +0 -0
  124. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/reports/templates/urls/locale.md +0 -0
  125. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/reports/templates/urls/tracking.md +0 -0
  126. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/src/markdown_checker/utils/github_env.py +0 -0
  127. /markdown_checker-1.1.0/tests/test_checks_broken_paths.py → /markdown_checker-1.2.1/tests/checks/test_broken_paths.py +0 -0
  128. /markdown_checker-1.1.0/tests/test_checks_registry.py → /markdown_checker-1.2.1/tests/checks/test_checks.py +0 -0
  129. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/tests/conftest.py +0 -0
  130. /markdown_checker-1.1.0/tests/test_models_base.py → /markdown_checker-1.2.1/tests/models/test_base.py +0 -0
  131. /markdown_checker-1.1.0/tests/test_models_path.py → /markdown_checker-1.2.1/tests/models/test_path.py +0 -0
  132. /markdown_checker-1.1.0/tests/test_models_url.py → /markdown_checker-1.2.1/tests/models/test_url.py +0 -0
  133. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/tests/resources/sample1.md +0 -0
  134. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/tests/resources/sample2.md +0 -0
  135. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/tests/resources/sample3.md +0 -0
  136. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/tests/resources/sample4.md +0 -0
  137. {markdown_checker-1.1.0 → markdown_checker-1.2.1}/tests/smoke/test_cli_smoke.py +0 -0
  138. /markdown_checker-1.1.0/tests/test_utils_extract_links.py → /markdown_checker-1.2.1/tests/utils/test_extract_links.py +0 -0
  139. /markdown_checker-1.1.0/tests/test_utils_github_env.py → /markdown_checker-1.2.1/tests/utils/test_github_env.py +0 -0
  140. /markdown_checker-1.1.0/tests/test_utils_list_files.py → /markdown_checker-1.2.1/tests/utils/test_list_files.py +0 -0
  141. /markdown_checker-1.1.0/tests/test_utils_spinner.py → /markdown_checker-1.2.1/tests/utils/test_spinner.py +0 -0
@@ -0,0 +1,118 @@
1
+ Metadata-Version: 2.4
2
+ Name: markdown-checker
3
+ Version: 1.2.1
4
+ Summary: A markdown link validation reporting tool.
5
+ Author-email: John Aziz <johnaziz269@gmail.com>
6
+ Maintainer-email: John Aziz <johnaziz269@gmail.com>
7
+ Requires-Python: >=3.11
8
+ Description-Content-Type: text/markdown
9
+ License-Expression: MIT
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Environment :: Console
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Typing :: Typed
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Classifier: Topic :: Software Development :: Quality Assurance
21
+ License-File: LICENSE
22
+ Requires-Dist: click>=8.3.1
23
+ Requires-Dist: httpx2>=2.0.0
24
+ Project-URL: Contributing, https://github.com/john0isaac/markdown-checker/pulls
25
+ Project-URL: Documentation, https://markdown-checker.readthedocs.io/en/latest/
26
+ Project-URL: Homepage, https://github.com/john0isaac/markdown-checker
27
+ Project-URL: Issues, https://github.com/john0isaac/markdown-checker/issues
28
+ Project-URL: Releases, https://github.com/john0isaac/markdown-checker/releases
29
+
30
+ [![PyPi](https://img.shields.io/pypi/v/markdown-checker)](https://pypi.org/project/markdown-checker/)
31
+ [![Documentation Status](https://readthedocs.org/projects/markdown-checker/badge/?version=latest)](https://markdown-checker.readthedocs.io/en/latest/?badge=latest)
32
+ [![Downloads](https://img.shields.io/pypi/dm/markdown-checker)](https://pypi.org/project/markdown-checker/)
33
+
34
+ [![GitHub issues](https://img.shields.io/badge/issue_tracking-github-blue.svg)](https://github.com/john0isaac/markdown-checker/issues)
35
+ [![Contributing](https://img.shields.io/badge/PR-Welcome-%23FF8300.svg?)](https://github.com/john0isaac/markdown-checker/pulls)
36
+
37
+ markdown-checker is a markdown link validation reporting tool for `.md` and
38
+ `.ipynb` files. It flags broken relative paths, broken web URLs, missing
39
+ locale segments, and missing tracking IDs, then writes the findings as a
40
+ report your CI can post back to a pull request.
41
+
42
+ ## Features
43
+
44
+ - Five built-in checks: broken relative paths, broken web URLs, locale
45
+ segments in URLs, and tracking IDs on URLs and paths.
46
+ - Concurrent URL checking with cross-file deduplication, per-host rate
47
+ pacing, and `Retry-After`/429 handling, so large repositories don't
48
+ trip host rate limits.
49
+ - Four report formats: `markdown`, `json`, `github-annotations`, and
50
+ `console`.
51
+ - Error vs. warning severity - rate-limited or unverifiable links are
52
+ reported but never fail your CI.
53
+ - Configuration via a `[tool.markdown-checker]` table in `pyproject.toml`,
54
+ so you don't have to repeat flags in every command or workflow file.
55
+
56
+ ## Installation
57
+
58
+ ```bash
59
+ pip install markdown-checker
60
+ ```
61
+
62
+ ## Quickstart
63
+
64
+ ```bash
65
+ markdown-checker . -f check_broken_paths
66
+ ```
67
+
68
+ ```text
69
+ 🔍 Checked 42 links in 10 files.
70
+ All files are compliant with the guidelines. 🎉
71
+ ```
72
+
73
+ When issues are found, a `comment.md` report is written and the command
74
+ exits with a non-zero status:
75
+
76
+ ```text
77
+ 🔍 Checked 42 links in 10 files.
78
+ 😭 Found 1 issues in the following files:
79
+ File 'docs/index.md', line 5
80
+ ./missing.md is broken.
81
+ ```
82
+
83
+ ## Using `markdown-checker` in GitHub Actions
84
+
85
+ Run this tool within a GitHub workflow using the
86
+ [action-check-markdown](https://github.com/marketplace/actions/check-markdown)
87
+ GitHub Action, which posts the report as a pull request comment:
88
+
89
+ ```yaml
90
+ - uses: john0isaac/action-check-markdown@v1.2.0
91
+ with:
92
+ github-token: ${{ secrets.GITHUB_TOKEN }}
93
+ command: check_broken_paths
94
+ directory: ./
95
+ guide-url: "https://github.com/<owner>/<repo>/blob/main/CONTRIBUTING.md"
96
+ ```
97
+
98
+ See the [GitHub Actions how-to](https://markdown-checker.readthedocs.io/en/latest/howto/github-actions/)
99
+ for the full workflow, including running `check_broken_urls` (not yet
100
+ supported by the wrapper action) directly as a step.
101
+
102
+ ## Documentation
103
+
104
+ - [Tutorial](https://markdown-checker.readthedocs.io/en/latest/tutorial/) - install and run your first check.
105
+ - [How-to guides](https://markdown-checker.readthedocs.io/en/latest/howto/) - configuration, rate limiting, report formats, CI.
106
+ - [CLI reference](https://markdown-checker.readthedocs.io/en/latest/reference/cli/) - every command-line option.
107
+ - [API reference](https://markdown-checker.readthedocs.io/en/latest/api/) - for programmatic use.
108
+ - [Full documentation](https://markdown-checker.readthedocs.io/en/latest/).
109
+
110
+ ## Contributing
111
+
112
+ Contributions are welcome - see the
113
+ [Contributing guide](https://markdown-checker.readthedocs.io/en/latest/CONTRIBUTING/).
114
+
115
+ ## License
116
+
117
+ [MIT](https://github.com/john0isaac/markdown-checker/blob/main/LICENSE)
118
+
@@ -0,0 +1,88 @@
1
+ [![PyPi](https://img.shields.io/pypi/v/markdown-checker)](https://pypi.org/project/markdown-checker/)
2
+ [![Documentation Status](https://readthedocs.org/projects/markdown-checker/badge/?version=latest)](https://markdown-checker.readthedocs.io/en/latest/?badge=latest)
3
+ [![Downloads](https://img.shields.io/pypi/dm/markdown-checker)](https://pypi.org/project/markdown-checker/)
4
+
5
+ [![GitHub issues](https://img.shields.io/badge/issue_tracking-github-blue.svg)](https://github.com/john0isaac/markdown-checker/issues)
6
+ [![Contributing](https://img.shields.io/badge/PR-Welcome-%23FF8300.svg?)](https://github.com/john0isaac/markdown-checker/pulls)
7
+
8
+ markdown-checker is a markdown link validation reporting tool for `.md` and
9
+ `.ipynb` files. It flags broken relative paths, broken web URLs, missing
10
+ locale segments, and missing tracking IDs, then writes the findings as a
11
+ report your CI can post back to a pull request.
12
+
13
+ ## Features
14
+
15
+ - Five built-in checks: broken relative paths, broken web URLs, locale
16
+ segments in URLs, and tracking IDs on URLs and paths.
17
+ - Concurrent URL checking with cross-file deduplication, per-host rate
18
+ pacing, and `Retry-After`/429 handling, so large repositories don't
19
+ trip host rate limits.
20
+ - Four report formats: `markdown`, `json`, `github-annotations`, and
21
+ `console`.
22
+ - Error vs. warning severity - rate-limited or unverifiable links are
23
+ reported but never fail your CI.
24
+ - Configuration via a `[tool.markdown-checker]` table in `pyproject.toml`,
25
+ so you don't have to repeat flags in every command or workflow file.
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ pip install markdown-checker
31
+ ```
32
+
33
+ ## Quickstart
34
+
35
+ ```bash
36
+ markdown-checker . -f check_broken_paths
37
+ ```
38
+
39
+ ```text
40
+ 🔍 Checked 42 links in 10 files.
41
+ All files are compliant with the guidelines. 🎉
42
+ ```
43
+
44
+ When issues are found, a `comment.md` report is written and the command
45
+ exits with a non-zero status:
46
+
47
+ ```text
48
+ 🔍 Checked 42 links in 10 files.
49
+ 😭 Found 1 issues in the following files:
50
+ File 'docs/index.md', line 5
51
+ ./missing.md is broken.
52
+ ```
53
+
54
+ ## Using `markdown-checker` in GitHub Actions
55
+
56
+ Run this tool within a GitHub workflow using the
57
+ [action-check-markdown](https://github.com/marketplace/actions/check-markdown)
58
+ GitHub Action, which posts the report as a pull request comment:
59
+
60
+ ```yaml
61
+ - uses: john0isaac/action-check-markdown@v1.2.0
62
+ with:
63
+ github-token: ${{ secrets.GITHUB_TOKEN }}
64
+ command: check_broken_paths
65
+ directory: ./
66
+ guide-url: "https://github.com/<owner>/<repo>/blob/main/CONTRIBUTING.md"
67
+ ```
68
+
69
+ See the [GitHub Actions how-to](https://markdown-checker.readthedocs.io/en/latest/howto/github-actions/)
70
+ for the full workflow, including running `check_broken_urls` (not yet
71
+ supported by the wrapper action) directly as a step.
72
+
73
+ ## Documentation
74
+
75
+ - [Tutorial](https://markdown-checker.readthedocs.io/en/latest/tutorial/) - install and run your first check.
76
+ - [How-to guides](https://markdown-checker.readthedocs.io/en/latest/howto/) - configuration, rate limiting, report formats, CI.
77
+ - [CLI reference](https://markdown-checker.readthedocs.io/en/latest/reference/cli/) - every command-line option.
78
+ - [API reference](https://markdown-checker.readthedocs.io/en/latest/api/) - for programmatic use.
79
+ - [Full documentation](https://markdown-checker.readthedocs.io/en/latest/).
80
+
81
+ ## Contributing
82
+
83
+ Contributions are welcome - see the
84
+ [Contributing guide](https://markdown-checker.readthedocs.io/en/latest/CONTRIBUTING/).
85
+
86
+ ## License
87
+
88
+ [MIT](https://github.com/john0isaac/markdown-checker/blob/main/LICENSE)
@@ -16,13 +16,13 @@ Install all dependencies and the package in editable mode:
16
16
 
17
17
  .. code-block:: shell
18
18
 
19
- uv sync
19
+ uv sync
20
20
 
21
21
  Activate the virtual environment:
22
22
 
23
23
  .. code-block:: shell
24
24
 
25
- source .venv/bin/activate
25
+ source .venv/bin/activate
26
26
 
27
27
  Any changes you make to the source will take effect immediately.
28
28
 
@@ -39,13 +39,13 @@ These are the most common commands you will use:
39
39
  These are some more specific commands if you need them:
40
40
 
41
41
  - ``tox parallel``: Run all test environments that will be run in CI, in
42
- parallel. Python versions that are not installed are skipped.
42
+ parallel. Python versions that are not installed are skipped.
43
43
  - ``pre-commit``: Run the linter and formatter tools. Only staged files are
44
- checked, and this runs automatically before each commit.
44
+ checked, and this runs automatically before each commit.
45
45
  - ``pre-commit run --all-files``: Run the pre-commit hooks against all files,
46
- including unchanged and unstaged files.
46
+ including unchanged and unstaged files.
47
47
  - ``tox run -e py3.11``: Run unit tests with a specific Python version. The
48
- version must be installed.
48
+ version must be installed.
49
49
  - ``tox run -e style``: Run all pre-commit hooks on all files via tox.
50
50
  - ``tox run -e typing``: Run all typing checks.
51
51
  - ``tox run -e docs``: Build the documentation in strict mode.
@@ -56,5 +56,5 @@ These are some more specific commands if you need them:
56
56
 
57
57
  .. tip::
58
58
 
59
- ``tox run`` and ``tox parallel`` can be shortened to ``tox r`` and
60
- ``tox p``.
59
+ ``tox run`` and ``tox parallel`` can be shortened to ``tox r`` and
60
+ ``tox p``.
@@ -0,0 +1,10 @@
1
+ Checker
2
+ =======
3
+
4
+ Runs a named check across a set of files and aggregates the results; used
5
+ internally by the CLI (:doc:`cli`).
6
+
7
+ .. automodule:: markdown_checker.checker
8
+ :members:
9
+ :undoc-members:
10
+ :show-inheritance:
@@ -0,0 +1,45 @@
1
+ Checks
2
+ ======
3
+
4
+ The five built-in checks and their shared base class. See
5
+ :doc:`../reference/checks` for what each one flags.
6
+
7
+ Base
8
+ ----
9
+
10
+ .. automodule:: markdown_checker.checks.base
11
+ :members:
12
+ :undoc-members:
13
+ :show-inheritance:
14
+
15
+ Broken Paths
16
+ ------------
17
+
18
+ .. automodule:: markdown_checker.checks.broken_paths
19
+ :members:
20
+ :undoc-members:
21
+ :show-inheritance:
22
+
23
+ Broken URLs
24
+ -----------
25
+
26
+ .. automodule:: markdown_checker.checks.broken_urls
27
+ :members:
28
+ :undoc-members:
29
+ :show-inheritance:
30
+
31
+ Locale
32
+ ------
33
+
34
+ .. automodule:: markdown_checker.checks.locale
35
+ :members:
36
+ :undoc-members:
37
+ :show-inheritance:
38
+
39
+ Tracking
40
+ --------
41
+
42
+ .. automodule:: markdown_checker.checks.tracking
43
+ :members:
44
+ :undoc-members:
45
+ :show-inheritance:
@@ -0,0 +1,10 @@
1
+ CLI
2
+ ===
3
+
4
+ The ``markdown-checker`` command-line entry point. See
5
+ :doc:`../reference/cli` for a user-facing option reference.
6
+
7
+ .. automodule:: markdown_checker.cli
8
+ :members:
9
+ :undoc-members:
10
+ :show-inheritance:
@@ -0,0 +1,14 @@
1
+ Main
2
+ ====
3
+
4
+ Top-level package exports: :class:`~markdown_checker.models.Config`,
5
+ :class:`~markdown_checker.models.MarkdownPath`,
6
+ :class:`~markdown_checker.models.MarkdownURL`,
7
+ :class:`~markdown_checker.models.MarkdownLinkBase`, ``main``, and
8
+ ``__version__``. Documented canonically under :doc:`models`, :doc:`cli`,
9
+ and :doc:`checker`; shown here without indexing to avoid duplicate targets.
10
+
11
+ .. automodule:: markdown_checker
12
+ :members:
13
+ :undoc-members:
14
+ :noindex:
@@ -0,0 +1,39 @@
1
+ Models
2
+ ======
3
+
4
+ Data models shared by the checks: extracted links (:class:`MarkdownPath
5
+ <markdown_checker.models.path.MarkdownPath>`,
6
+ :class:`MarkdownURL <markdown_checker.models.url.MarkdownURL>`) and runtime
7
+ configuration (:class:`Config <markdown_checker.models.config.Config>`).
8
+
9
+ Base
10
+ ----
11
+
12
+ .. automodule:: markdown_checker.models.base
13
+ :members:
14
+ :undoc-members:
15
+ :show-inheritance:
16
+
17
+ Config
18
+ ------
19
+
20
+ .. automodule:: markdown_checker.models.config
21
+ :members:
22
+ :undoc-members:
23
+ :show-inheritance:
24
+
25
+ Path
26
+ ----
27
+
28
+ .. automodule:: markdown_checker.models.path
29
+ :members:
30
+ :undoc-members:
31
+ :show-inheritance:
32
+
33
+ URL
34
+ ---
35
+
36
+ .. automodule:: markdown_checker.models.url
37
+ :members:
38
+ :undoc-members:
39
+ :show-inheritance:
@@ -0,0 +1,10 @@
1
+ Patterns
2
+ ========
3
+
4
+ Compiled regular expressions used across the package for link/scheme/fence/
5
+ locale/tracking matching.
6
+
7
+ .. automodule:: markdown_checker.patterns
8
+ :members:
9
+ :undoc-members:
10
+ :show-inheritance:
@@ -0,0 +1,71 @@
1
+ Reports
2
+ =======
3
+
4
+ The format-agnostic report model, the renderer contract and
5
+ implementations, and the writer that emits rendered reports. See
6
+ :doc:`../reference/report-formats` for the user-facing shape of each format.
7
+
8
+ Base
9
+ ----
10
+
11
+ .. automodule:: markdown_checker.reports.base
12
+ :members:
13
+ :undoc-members:
14
+ :show-inheritance:
15
+
16
+ Model
17
+ ------
18
+
19
+ .. automodule:: markdown_checker.reports.model
20
+ :members:
21
+ :undoc-members:
22
+ :show-inheritance:
23
+
24
+ Registry
25
+ --------
26
+
27
+ .. automodule:: markdown_checker.reports.registry
28
+ :members:
29
+ :undoc-members:
30
+ :show-inheritance:
31
+
32
+
33
+ Writer
34
+ ------
35
+
36
+ .. automodule:: markdown_checker.reports.writer
37
+ :members:
38
+ :undoc-members:
39
+ :show-inheritance:
40
+
41
+ Markdown Renderer
42
+ ------------------
43
+
44
+ .. automodule:: markdown_checker.reports.renderers.markdown
45
+ :members:
46
+ :undoc-members:
47
+ :show-inheritance:
48
+
49
+ JSON Renderer
50
+ -------------
51
+
52
+ .. automodule:: markdown_checker.reports.renderers.json
53
+ :members:
54
+ :undoc-members:
55
+ :show-inheritance:
56
+
57
+ GitHub Annotations Renderer
58
+ ----------------------------
59
+
60
+ .. automodule:: markdown_checker.reports.renderers.annotations
61
+ :members:
62
+ :undoc-members:
63
+ :show-inheritance:
64
+
65
+ Console Renderer
66
+ -----------------
67
+
68
+ .. automodule:: markdown_checker.reports.renderers.console
69
+ :members:
70
+ :undoc-members:
71
+ :show-inheritance:
@@ -0,0 +1,46 @@
1
+ Utilities
2
+ =========
3
+
4
+ Standalone helpers: link extraction, file listing, the concurrent
5
+ URL-checking pipeline, GitHub Actions environment detection, pyproject.toml
6
+ config loading, and the CLI spinner.
7
+
8
+ Extract Links
9
+ -------------
10
+
11
+ .. automodule:: markdown_checker.utils.extract_links
12
+ :members:
13
+ :undoc-members:
14
+ :show-inheritance:
15
+
16
+ GitHub Environment
17
+ -------------------
18
+
19
+ .. automodule:: markdown_checker.utils.github_env
20
+ :members:
21
+ :undoc-members:
22
+ :show-inheritance:
23
+
24
+ List Files
25
+ ----------
26
+
27
+ .. automodule:: markdown_checker.utils.list_files
28
+ :members:
29
+ :undoc-members:
30
+ :show-inheritance:
31
+
32
+ Spinner
33
+ -------
34
+
35
+ .. automodule:: markdown_checker.utils.spinner
36
+ :members:
37
+ :undoc-members:
38
+ :show-inheritance:
39
+
40
+ URL Pipeline
41
+ ------------
42
+
43
+ .. automodule:: markdown_checker.utils.url_pipeline
44
+ :members:
45
+ :undoc-members:
46
+ :show-inheritance:
@@ -24,6 +24,9 @@ extensions = [
24
24
  autodoc_member_order = "bysource"
25
25
  autodoc_typehints = "description"
26
26
  autodoc_preserve_defaults = True
27
+ autodoc_default_options = {
28
+ "no-value": True,
29
+ }
27
30
  napoleon_google_docstring = True
28
31
  napoleon_numpy_docstring = False
29
32
  napoleon_use_rtype = False
@@ -0,0 +1,12 @@
1
+ Explanation
2
+ ============
3
+
4
+ Background and design discussion for understanding *why* markdown-checker
5
+ behaves the way it does, rather than step-by-step instructions. For tasks,
6
+ see :doc:`../howto/index`; for exact facts, see :doc:`../reference/index`.
7
+
8
+ .. toctree::
9
+ :maxdepth: 1
10
+
11
+ url-checking
12
+ link-detection
@@ -0,0 +1,53 @@
1
+ How Link Detection Works
2
+ ===========================
3
+
4
+ Every check starts from the same extraction step: reading a markdown file
5
+ line by line and pulling out link destinations. This page explains what
6
+ counts as a checkable link and what's deliberately excluded.
7
+
8
+ What's matched
9
+ -----------------
10
+
11
+ Only the destination of an inline Markdown link is considered - the part
12
+ inside parentheses in ``[text](destination)``, or inside angle brackets in
13
+ ``[text](<destination>)``. Reference-style links (``[text][ref]`` with a
14
+ separate ``[ref]: destination`` definition) are not currently matched.
15
+
16
+ Code fences are skipped entirely: lines between an opening and matching
17
+ closing fence (three or more backtick or tilde characters) are ignored, so
18
+ example links inside a code sample are never checked.
19
+
20
+ How a destination is classified
21
+ ------------------------------------
22
+
23
+ Each matched destination falls into one of three buckets:
24
+
25
+ - **URL**: starts with ``http://`` or ``https://`` (protocol-relative
26
+ ``//host/...`` links are treated as ``https://``). Handled by
27
+ ``check_broken_urls``, ``check_urls_locale``, and ``check_urls_tracking``.
28
+ - **Ignored**: starts with another URI scheme (e.g. ``mailto:``, ``tel:``),
29
+ or is a bare same-page anchor (``#section``). These can't be meaningfully
30
+ checked as either a URL or a local file, so no check ever sees them.
31
+ - **Path**: anything else - this includes root-relative paths
32
+ (``/docs/usage.md``), explicitly relative paths (``./img.png``,
33
+ ``../docs/usage.md``), and bare relative paths with no prefix
34
+ (``docs/usage.md``). All of these are treated identically and handled by
35
+ ``check_broken_paths`` and ``check_paths_tracking``.
36
+
37
+ Fragments on paths
38
+ ----------------------
39
+
40
+ A path may carry a trailing ``?query`` and/or ``#anchor`` - for example
41
+ ``docs/usage.md#configuration``. Both checks that operate on paths strip
42
+ this fragment before resolving the file, so only the ``docs/usage.md``
43
+ part needs to exist on disk; the anchor itself is never validated against
44
+ the target file's headings.
45
+
46
+ Resolving a path to a file
47
+ --------------------------------
48
+
49
+ ``check_broken_paths`` tries to resolve a path relative to the markdown
50
+ file it was found in first (e.g. ``../img.png`` in ``docs/usage.md``
51
+ resolves against ``docs/``), then falls back to resolving it as an
52
+ absolute or current-working-directory-relative path. A path is reported as
53
+ broken only if neither resolution finds an existing file.
@@ -0,0 +1,78 @@
1
+ How URL Checking Works
2
+ ========================
3
+
4
+ ``check_broken_urls`` (and the other URL-based checks) can end up sending
5
+ thousands of requests across a large repository. This page explains the
6
+ pipeline that makes that practical without hammering any single host, and
7
+ why some failures are reported as warnings rather than errors.
8
+
9
+ The life of a URL
10
+ --------------------
11
+
12
+ 1. **Extraction.** Every markdown link destination is extracted per file
13
+ (see :doc:`link-detection`) and classified as a URL if it starts with
14
+ ``http://``/``https://`` (protocol-relative ``//host/...`` links are
15
+ normalized to ``https://``).
16
+
17
+ 2. **Normalization and dedupe.** Before checking, each URL is normalized
18
+ (scheme and host lowercased, trailing slash and fragment dropped; the
19
+ query string is kept). If the same normalized URL appears in fifty
20
+ files, it is only ever requested once - every other occurrence shares
21
+ the same in-flight result.
22
+
23
+ 3. **Per-host queueing and pacing.** Requests are grouped by host and paced
24
+ with a minimum delay between two requests to the same host
25
+ (``--per-host-delay``), so a link-heavy file doesn't burst a host with
26
+ many simultaneous requests just because it happens to link to it
27
+ repeatedly.
28
+
29
+ 4. **The request itself.** Each URL is checked with a ``HEAD`` request
30
+ first; if that isn't a success, a ``GET`` is attempted as a fallback,
31
+ since some servers reject ``HEAD`` but allow ``GET``. A successful
32
+ (``2xx``) response on either is treated as ``alive``.
33
+
34
+ 5. **Hard-failure retries.** If neither request succeeds and there's no
35
+ rate-limit or auth signal, the attempt is retried with exponential
36
+ backoff up to ``--retries`` times before being reported as ``broken``.
37
+
38
+ 6. **Rate limiting and auth errors return immediately.** A ``429`` (or any
39
+ non-success response carrying ``Retry-After``) is reported as
40
+ ``rate_limited`` right away - it is *not* retried in place. Likewise, a
41
+ ``401``/``403`` response is reported as ``unverifiable`` immediately:
42
+ the server is reachable but blocking automated access, and retrying
43
+ won't change that. Retrying either case would only generate more
44
+ traffic against a host that's already unhappy with us.
45
+
46
+ 7. **Host circuit breaker.** When a host produces two rate-limited
47
+ responses in a row, it's treated as persistently throttled: every other
48
+ URL already queued for that host is resolved as ``rate_limited``
49
+ without spending a network request on each, and the host is blocked
50
+ from new requests until its ``Retry-After`` window elapses.
51
+
52
+ 8. **Backpressure.** The number of URL checks in flight at once is bounded
53
+ (``max_pending`` in the underlying configuration), so checking a huge
54
+ repository doesn't grow memory unboundedly - submitting more work simply
55
+ waits for a slot to free up.
56
+
57
+ Why warnings don't fail the build
58
+ -------------------------------------
59
+
60
+ ``rate_limited``, ``unverifiable``, and ``transient_error`` all mean the
61
+ checker *couldn't determine* whether the link is actually broken - the host
62
+ is either throttling, blocking bots, or momentarily unreachable. Treating
63
+ these the same as a confirmed ``404`` would make CI fail on
64
+ infrastructure noise rather than real broken links, so they're reported as
65
+ warnings instead: visible, but never blocking. Only ``broken`` (a
66
+ confirmed non-2xx response with no rate-limit/auth signal) is an
67
+ error. See :doc:`../reference/exit-codes` for the full status table.
68
+
69
+ Overlapping file processing
70
+ -------------------------------
71
+
72
+ Separately from URL-level concurrency, files themselves are processed
73
+ through an adaptive window: a file's links are submitted for checking as
74
+ soon as they're extracted, without waiting for earlier files' checks to
75
+ finish first. This overlaps link extraction and I/O wait time across
76
+ files, while still bounding how many files can be "in flight"
77
+ simultaneously so memory use stays predictable regardless of how many
78
+ links a single file happens to contain.