rumdl 0.0.128__tar.gz → 0.0.130__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.

Potentially problematic release.


This version of rumdl might be problematic. Click here for more details.

Files changed (420) hide show
  1. {rumdl-0.0.128 → rumdl-0.0.130}/CHANGELOG.md +30 -1
  2. {rumdl-0.0.128 → rumdl-0.0.130}/Cargo.lock +5 -5
  3. {rumdl-0.0.128 → rumdl-0.0.130}/Cargo.toml +1 -1
  4. {rumdl-0.0.128 → rumdl-0.0.130}/PKG-INFO +1 -1
  5. {rumdl-0.0.128 → rumdl-0.0.130}/src/lint_context.rs +43 -8
  6. {rumdl-0.0.128 → rumdl-0.0.130}/src/markdownlint_config.rs +30 -14
  7. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md009_trailing_spaces.rs +34 -44
  8. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md011_no_reversed_links.rs +44 -0
  9. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md024_no_duplicate_heading.rs +20 -0
  10. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md027_multiple_spaces_blockquote.rs +11 -6
  11. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md028_no_blanks_blockquote.rs +1 -1
  12. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md031_blanks_around_fences.rs +65 -0
  13. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md033_no_inline_html.rs +19 -1
  14. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md034_no_bare_urls.rs +15 -0
  15. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md040_fenced_code_language.rs +26 -4
  16. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md046_code_block_style.rs +142 -14
  17. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md052_reference_links_images.rs +162 -6
  18. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md053_link_image_reference_definitions.rs +23 -125
  19. rumdl-0.0.130/src/utils/mkdocs_admonitions.rs +268 -0
  20. rumdl-0.0.130/src/utils/mkdocs_common.rs +214 -0
  21. rumdl-0.0.130/src/utils/mkdocs_critic.rs +163 -0
  22. rumdl-0.0.130/src/utils/mkdocs_footnotes.rs +147 -0
  23. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/mkdocs_patterns.rs +0 -6
  24. rumdl-0.0.130/src/utils/mkdocs_snippets.rs +346 -0
  25. rumdl-0.0.130/src/utils/mkdocs_tabs.rs +227 -0
  26. rumdl-0.0.130/src/utils/mkdocs_test_utils.rs +216 -0
  27. rumdl-0.0.130/src/utils/mkdocstrings_refs.rs +221 -0
  28. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/mod.rs +8 -0
  29. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/skip_context.rs +67 -0
  30. {rumdl-0.0.128 → rumdl-0.0.130}/tests/markdownlint_config_test.rs +48 -0
  31. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md009_test.rs +3 -3
  32. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md053_additional_test.rs +8 -125
  33. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md053_test.rs +5 -20
  34. rumdl-0.0.130/tests/rules/mkdocs_admonitions_test.rs +198 -0
  35. rumdl-0.0.130/tests/rules/mkdocs_edge_cases_test.rs +543 -0
  36. rumdl-0.0.130/tests/rules/mkdocs_extensions_test.rs +258 -0
  37. rumdl-0.0.130/tests/rules/mkdocs_snippets_test.rs +152 -0
  38. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/mod.rs +4 -0
  39. {rumdl-0.0.128 → rumdl-0.0.130}/.config/nextest.toml +0 -0
  40. {rumdl-0.0.128 → rumdl-0.0.130}/.mise.toml +0 -0
  41. {rumdl-0.0.128 → rumdl-0.0.130}/.pre-commit-config.yaml +0 -0
  42. {rumdl-0.0.128 → rumdl-0.0.130}/.rumdl.toml +0 -0
  43. {rumdl-0.0.128 → rumdl-0.0.130}/.rustfmt.toml +0 -0
  44. {rumdl-0.0.128 → rumdl-0.0.130}/LICENSE +0 -0
  45. {rumdl-0.0.128 → rumdl-0.0.130}/MANIFEST.in +0 -0
  46. {rumdl-0.0.128 → rumdl-0.0.130}/Makefile +0 -0
  47. {rumdl-0.0.128 → rumdl-0.0.130}/README.md +0 -0
  48. {rumdl-0.0.128 → rumdl-0.0.130}/assets/logo.png +0 -0
  49. {rumdl-0.0.128 → rumdl-0.0.130}/benches/fix_performance.rs +0 -0
  50. {rumdl-0.0.128 → rumdl-0.0.130}/benches/range_performance.rs +0 -0
  51. {rumdl-0.0.128 → rumdl-0.0.130}/benches/range_utils_benchmark.rs +0 -0
  52. {rumdl-0.0.128 → rumdl-0.0.130}/benches/rule_performance.rs +0 -0
  53. {rumdl-0.0.128 → rumdl-0.0.130}/benches/simple_fix_bench.rs +0 -0
  54. {rumdl-0.0.128 → rumdl-0.0.130}/benchmark/bin/bench_lint_context.rs +0 -0
  55. {rumdl-0.0.128 → rumdl-0.0.130}/benchmark/bin/benchmark.rs +0 -0
  56. {rumdl-0.0.128 → rumdl-0.0.130}/benchmark/bin/benchmark_rule.rs +0 -0
  57. {rumdl-0.0.128 → rumdl-0.0.130}/benchmark/bin/file_parallel_benchmark.rs +0 -0
  58. {rumdl-0.0.128 → rumdl-0.0.130}/benchmark/bin/measure_code_span_performance.rs +0 -0
  59. {rumdl-0.0.128 → rumdl-0.0.130}/docs/RULES.md +0 -0
  60. {rumdl-0.0.128 → rumdl-0.0.130}/docs/global-settings.md +0 -0
  61. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md001.md +0 -0
  62. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md002.md +0 -0
  63. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md003.md +0 -0
  64. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md004.md +0 -0
  65. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md005.md +0 -0
  66. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md006.md +0 -0
  67. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md007.md +0 -0
  68. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md009.md +0 -0
  69. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md010.md +0 -0
  70. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md011.md +0 -0
  71. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md012.md +0 -0
  72. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md013.md +0 -0
  73. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md014.md +0 -0
  74. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md018.md +0 -0
  75. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md019.md +0 -0
  76. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md020.md +0 -0
  77. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md021.md +0 -0
  78. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md022.md +0 -0
  79. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md023.md +0 -0
  80. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md024.md +0 -0
  81. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md025.md +0 -0
  82. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md026.md +0 -0
  83. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md027.md +0 -0
  84. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md028.md +0 -0
  85. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md029.md +0 -0
  86. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md030.md +0 -0
  87. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md031.md +0 -0
  88. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md032.md +0 -0
  89. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md033.md +0 -0
  90. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md034.md +0 -0
  91. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md035.md +0 -0
  92. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md036.md +0 -0
  93. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md037.md +0 -0
  94. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md038.md +0 -0
  95. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md039.md +0 -0
  96. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md040.md +0 -0
  97. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md041.md +0 -0
  98. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md042.md +0 -0
  99. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md043.md +0 -0
  100. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md044.md +0 -0
  101. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md045.md +0 -0
  102. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md046.md +0 -0
  103. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md047.md +0 -0
  104. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md048.md +0 -0
  105. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md049.md +0 -0
  106. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md050.md +0 -0
  107. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md051.md +0 -0
  108. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md052.md +0 -0
  109. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md053.md +0 -0
  110. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md054.md +0 -0
  111. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md055.md +0 -0
  112. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md056.md +0 -0
  113. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md057.md +0 -0
  114. {rumdl-0.0.128 → rumdl-0.0.130}/docs/md058.md +0 -0
  115. {rumdl-0.0.128 → rumdl-0.0.130}/docs/vscode-extension.md +0 -0
  116. {rumdl-0.0.128 → rumdl-0.0.130}/parity_check.py +0 -0
  117. {rumdl-0.0.128 → rumdl-0.0.130}/pyproject.toml +0 -0
  118. {rumdl-0.0.128 → rumdl-0.0.130}/python/MANIFEST.in +0 -0
  119. {rumdl-0.0.128 → rumdl-0.0.130}/python/PYTHON-README.md +0 -0
  120. {rumdl-0.0.128 → rumdl-0.0.130}/python/rumdl/__init__.py +0 -0
  121. {rumdl-0.0.128 → rumdl-0.0.130}/python/rumdl/__main__.py +0 -0
  122. {rumdl-0.0.128 → rumdl-0.0.130}/python/rumdl/py.typed +0 -0
  123. {rumdl-0.0.128 → rumdl-0.0.130}/rumdl.toml.example +0 -0
  124. {rumdl-0.0.128 → rumdl-0.0.130}/rust-toolchain.toml +0 -0
  125. {rumdl-0.0.128 → rumdl-0.0.130}/scripts/extract-changelog.sh +0 -0
  126. {rumdl-0.0.128 → rumdl-0.0.130}/scripts/generate-downloads-table.sh +0 -0
  127. {rumdl-0.0.128 → rumdl-0.0.130}/scripts/pre-release.sh +0 -0
  128. {rumdl-0.0.128 → rumdl-0.0.130}/scripts/prepare-release.sh +0 -0
  129. {rumdl-0.0.128 → rumdl-0.0.130}/scripts/setup-pre-commit.sh +0 -0
  130. {rumdl-0.0.128 → rumdl-0.0.130}/scripts/update-pre-commit-docs.sh +0 -0
  131. {rumdl-0.0.128 → rumdl-0.0.130}/src/config.rs +0 -0
  132. {rumdl-0.0.128 → rumdl-0.0.130}/src/exit_codes.rs +0 -0
  133. {rumdl-0.0.128 → rumdl-0.0.130}/src/inline_config.rs +0 -0
  134. {rumdl-0.0.128 → rumdl-0.0.130}/src/lib.rs +0 -0
  135. {rumdl-0.0.128 → rumdl-0.0.130}/src/lsp/mod.rs +0 -0
  136. {rumdl-0.0.128 → rumdl-0.0.130}/src/lsp/server.rs +0 -0
  137. {rumdl-0.0.128 → rumdl-0.0.130}/src/lsp/types.rs +0 -0
  138. {rumdl-0.0.128 → rumdl-0.0.130}/src/main.rs +0 -0
  139. {rumdl-0.0.128 → rumdl-0.0.130}/src/output/formatters/azure.rs +0 -0
  140. {rumdl-0.0.128 → rumdl-0.0.130}/src/output/formatters/concise.rs +0 -0
  141. {rumdl-0.0.128 → rumdl-0.0.130}/src/output/formatters/github.rs +0 -0
  142. {rumdl-0.0.128 → rumdl-0.0.130}/src/output/formatters/gitlab.rs +0 -0
  143. {rumdl-0.0.128 → rumdl-0.0.130}/src/output/formatters/grouped.rs +0 -0
  144. {rumdl-0.0.128 → rumdl-0.0.130}/src/output/formatters/json.rs +0 -0
  145. {rumdl-0.0.128 → rumdl-0.0.130}/src/output/formatters/json_lines.rs +0 -0
  146. {rumdl-0.0.128 → rumdl-0.0.130}/src/output/formatters/junit.rs +0 -0
  147. {rumdl-0.0.128 → rumdl-0.0.130}/src/output/formatters/mod.rs +0 -0
  148. {rumdl-0.0.128 → rumdl-0.0.130}/src/output/formatters/pylint.rs +0 -0
  149. {rumdl-0.0.128 → rumdl-0.0.130}/src/output/formatters/sarif.rs +0 -0
  150. {rumdl-0.0.128 → rumdl-0.0.130}/src/output/formatters/text.rs +0 -0
  151. {rumdl-0.0.128 → rumdl-0.0.130}/src/output/mod.rs +0 -0
  152. {rumdl-0.0.128 → rumdl-0.0.130}/src/parallel.rs +0 -0
  153. {rumdl-0.0.128 → rumdl-0.0.130}/src/performance.rs +0 -0
  154. {rumdl-0.0.128 → rumdl-0.0.130}/src/profiling.rs +0 -0
  155. {rumdl-0.0.128 → rumdl-0.0.130}/src/python.rs +0 -0
  156. {rumdl-0.0.128 → rumdl-0.0.130}/src/rule.rs +0 -0
  157. {rumdl-0.0.128 → rumdl-0.0.130}/src/rule_config.rs +0 -0
  158. {rumdl-0.0.128 → rumdl-0.0.130}/src/rule_config_serde.rs +0 -0
  159. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/blockquote_utils.rs +0 -0
  160. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/code_block_utils.rs +0 -0
  161. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/code_fence_utils.rs +0 -0
  162. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/emphasis_style.rs +0 -0
  163. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/front_matter_utils.rs +0 -0
  164. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/heading_utils.rs +0 -0
  165. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/list_utils.rs +0 -0
  166. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md001_heading_increment.rs +0 -0
  167. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md002_first_heading_h1/md002_config.rs +0 -0
  168. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md002_first_heading_h1.rs +0 -0
  169. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md003_heading_style/md003_config.rs +0 -0
  170. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md003_heading_style.rs +0 -0
  171. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md004_unordered_list_style/md004_config.rs +0 -0
  172. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md004_unordered_list_style.rs +0 -0
  173. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md005_list_indent.rs +0 -0
  174. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md006_start_bullets.rs +0 -0
  175. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md007_ul_indent/md007_config.rs +0 -0
  176. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md007_ul_indent.rs +0 -0
  177. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md009_trailing_spaces/md009_config.rs +0 -0
  178. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md010_no_hard_tabs/md010_config.rs +0 -0
  179. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md010_no_hard_tabs.rs +0 -0
  180. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md012_no_multiple_blanks/md012_config.rs +0 -0
  181. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md012_no_multiple_blanks.rs +0 -0
  182. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md013_line_length/md013_config.rs +0 -0
  183. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md013_line_length.rs +0 -0
  184. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md014_commands_show_output/md014_config.rs +0 -0
  185. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md014_commands_show_output.rs +0 -0
  186. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md018_no_missing_space_atx.rs +0 -0
  187. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md019_no_multiple_space_atx.rs +0 -0
  188. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md020_no_missing_space_closed_atx.rs +0 -0
  189. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
  190. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md022_blanks_around_headings/md022_config.rs +0 -0
  191. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md022_blanks_around_headings.rs +0 -0
  192. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md023_heading_start_left.rs +0 -0
  193. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md024_no_duplicate_heading/md024_config.rs +0 -0
  194. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md025_single_title/md025_config.rs +0 -0
  195. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md025_single_title.rs +0 -0
  196. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md026_no_trailing_punctuation/md026_config.rs +0 -0
  197. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md026_no_trailing_punctuation.rs +0 -0
  198. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md029_ordered_list_prefix/md029_config.rs +0 -0
  199. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md029_ordered_list_prefix.rs +0 -0
  200. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md030_list_marker_space/md030_config.rs +0 -0
  201. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md030_list_marker_space.rs +0 -0
  202. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md032_blanks_around_lists.rs +0 -0
  203. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md033_no_inline_html/md033_config.rs +0 -0
  204. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md035_hr_style/md035_config.rs +0 -0
  205. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md035_hr_style.rs +0 -0
  206. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md036_no_emphasis_only_first/md036_config.rs +0 -0
  207. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md036_no_emphasis_only_first.rs +0 -0
  208. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md037_spaces_around_emphasis.rs +0 -0
  209. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md038_no_space_in_code.rs +0 -0
  210. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md039_no_space_in_links.rs +0 -0
  211. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md041_first_line_heading.rs +0 -0
  212. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md042_no_empty_links.rs +0 -0
  213. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md043_required_headings.rs +0 -0
  214. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md044_proper_names/md044_config.rs +0 -0
  215. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md044_proper_names.rs +0 -0
  216. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md045_no_alt_text/md045_config.rs +0 -0
  217. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md045_no_alt_text.rs +0 -0
  218. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md046_code_block_style/md046_config.rs +0 -0
  219. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md047_single_trailing_newline.rs +0 -0
  220. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md048_code_fence_style/md048_config.rs +0 -0
  221. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md048_code_fence_style.rs +0 -0
  222. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md049_emphasis_style/md049_config.rs +0 -0
  223. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md049_emphasis_style.rs +0 -0
  224. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md050_strong_style/md050_config.rs +0 -0
  225. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md050_strong_style.rs +0 -0
  226. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md051_link_fragments.rs +0 -0
  227. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md054_link_image_style/md054_config.rs +0 -0
  228. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md054_link_image_style.rs +0 -0
  229. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md055_table_pipe_style/md055_config.rs +0 -0
  230. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md055_table_pipe_style.rs +0 -0
  231. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md056_table_column_count.rs +0 -0
  232. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md057_existing_relative_links/md057_config.rs +0 -0
  233. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md057_existing_relative_links.rs +0 -0
  234. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/md058_blanks_around_tables.rs +0 -0
  235. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/mod.rs +0 -0
  236. {rumdl-0.0.128 → rumdl-0.0.130}/src/rules/strong_style.rs +0 -0
  237. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/anchor_styles/github.rs +0 -0
  238. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/anchor_styles/jekyll.rs +0 -0
  239. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/anchor_styles/kramdown.rs +0 -0
  240. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/anchor_styles/kramdown_gfm.rs +0 -0
  241. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/anchor_styles/mod.rs +0 -0
  242. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/ast_utils.rs +0 -0
  243. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/code_block_utils.rs +0 -0
  244. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/document_structure.rs +0 -0
  245. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/early_returns.rs +0 -0
  246. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/element_cache.rs +0 -0
  247. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/emphasis_utils.rs +0 -0
  248. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/fix_utils.rs +0 -0
  249. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/header_id_utils.rs +0 -0
  250. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/kramdown_utils.rs +0 -0
  251. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/markdown_elements.rs +0 -0
  252. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/range_utils.rs +0 -0
  253. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/regex_cache.rs +0 -0
  254. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/string_interner.rs +0 -0
  255. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/table_utils.rs +0 -0
  256. {rumdl-0.0.128 → rumdl-0.0.130}/src/utils/text_reflow.rs +0 -0
  257. {rumdl-0.0.128 → rumdl-0.0.130}/src/vscode.rs +0 -0
  258. {rumdl-0.0.128 → rumdl-0.0.130}/tests/advanced_integration_tests.rs +0 -0
  259. {rumdl-0.0.128 → rumdl-0.0.130}/tests/character_ranges/additional_tests.rs +0 -0
  260. {rumdl-0.0.128 → rumdl-0.0.130}/tests/character_ranges/basic_tests.rs +0 -0
  261. {rumdl-0.0.128 → rumdl-0.0.130}/tests/character_ranges/comprehensive_tests.rs +0 -0
  262. {rumdl-0.0.128 → rumdl-0.0.130}/tests/character_ranges/extended_tests.rs +0 -0
  263. {rumdl-0.0.128 → rumdl-0.0.130}/tests/character_ranges/mod.rs +0 -0
  264. {rumdl-0.0.128 → rumdl-0.0.130}/tests/character_ranges/unicode_utils.rs +0 -0
  265. {rumdl-0.0.128 → rumdl-0.0.130}/tests/cli_duplication_test.rs +0 -0
  266. {rumdl-0.0.128 → rumdl-0.0.130}/tests/cli_explain_test.rs +0 -0
  267. {rumdl-0.0.128 → rumdl-0.0.130}/tests/cli_flag_precedence_test.rs +0 -0
  268. {rumdl-0.0.128 → rumdl-0.0.130}/tests/cli_integration_tests.rs +0 -0
  269. {rumdl-0.0.128 → rumdl-0.0.130}/tests/cli_lsp_fix_consistency.rs +0 -0
  270. {rumdl-0.0.128 → rumdl-0.0.130}/tests/cli_statistics_test.rs +0 -0
  271. {rumdl-0.0.128 → rumdl-0.0.130}/tests/common/cli_test_utils.rs +0 -0
  272. {rumdl-0.0.128 → rumdl-0.0.130}/tests/common/fixtures.rs +0 -0
  273. {rumdl-0.0.128 → rumdl-0.0.130}/tests/common/mod.rs +0 -0
  274. {rumdl-0.0.128 → rumdl-0.0.130}/tests/common/test_utils.rs +0 -0
  275. {rumdl-0.0.128 → rumdl-0.0.130}/tests/commonmark_compliance_tests.rs +0 -0
  276. {rumdl-0.0.128 → rumdl-0.0.130}/tests/comprehensive_integration_tests.rs +0 -0
  277. {rumdl-0.0.128 → rumdl-0.0.130}/tests/comprehensive_output_format_tests.rs +0 -0
  278. {rumdl-0.0.128 → rumdl-0.0.130}/tests/config_application_tests.rs +0 -0
  279. {rumdl-0.0.128 → rumdl-0.0.130}/tests/config_file_command_test.rs +0 -0
  280. {rumdl-0.0.128 → rumdl-0.0.130}/tests/config_tests.rs +0 -0
  281. {rumdl-0.0.128 → rumdl-0.0.130}/tests/config_upward_traversal_test.rs +0 -0
  282. {rumdl-0.0.128 → rumdl-0.0.130}/tests/configuration_inheritance_tests.rs +0 -0
  283. {rumdl-0.0.128 → rumdl-0.0.130}/tests/consistency_regression_tests.rs +0 -0
  284. {rumdl-0.0.128 → rumdl-0.0.130}/tests/cross_platform_compatibility_tests.rs +0 -0
  285. {rumdl-0.0.128 → rumdl-0.0.130}/tests/deeply_nested_lists_performance_test.rs +0 -0
  286. {rumdl-0.0.128 → rumdl-0.0.130}/tests/escaped_brackets_test.rs +0 -0
  287. {rumdl-0.0.128 → rumdl-0.0.130}/tests/final_confidence_assessment.rs +0 -0
  288. {rumdl-0.0.128 → rumdl-0.0.130}/tests/fixable_unfixable_config_test.rs +0 -0
  289. {rumdl-0.0.128 → rumdl-0.0.130}/tests/init_command_test.rs +0 -0
  290. {rumdl-0.0.128 → rumdl-0.0.130}/tests/init_tests.rs +0 -0
  291. {rumdl-0.0.128 → rumdl-0.0.130}/tests/inline_config_blocks_test.rs +0 -0
  292. {rumdl-0.0.128 → rumdl-0.0.130}/tests/inline_config_test.rs +0 -0
  293. {rumdl-0.0.128 → rumdl-0.0.130}/tests/integration_tests.rs +0 -0
  294. {rumdl-0.0.128 → rumdl-0.0.130}/tests/json_output_test.rs +0 -0
  295. {rumdl-0.0.128 → rumdl-0.0.130}/tests/kramdown_integration_test.rs +0 -0
  296. {rumdl-0.0.128 → rumdl-0.0.130}/tests/lib.rs +0 -0
  297. {rumdl-0.0.128 → rumdl-0.0.130}/tests/lsp_editor_integration_tests.rs +0 -0
  298. {rumdl-0.0.128 → rumdl-0.0.130}/tests/lsp_integration_tests.rs +0 -0
  299. {rumdl-0.0.128 → rumdl-0.0.130}/tests/lsp_memory_leak_tests.rs +0 -0
  300. {rumdl-0.0.128 → rumdl-0.0.130}/tests/lsp_tests.rs +0 -0
  301. {rumdl-0.0.128 → rumdl-0.0.130}/tests/malformed_markdown_stress_tests.rs +0 -0
  302. {rumdl-0.0.128 → rumdl-0.0.130}/tests/markdownlint_cli_integration.rs +0 -0
  303. {rumdl-0.0.128 → rumdl-0.0.130}/tests/markdownlintignore_test.rs +0 -0
  304. {rumdl-0.0.128 → rumdl-0.0.130}/tests/md013_reflow_integration_test.rs +0 -0
  305. {rumdl-0.0.128 → rumdl-0.0.130}/tests/md051_issue_39_regression_test.rs +0 -0
  306. {rumdl-0.0.128 → rumdl-0.0.130}/tests/nested_code_block_test.rs +0 -0
  307. {rumdl-0.0.128 → rumdl-0.0.130}/tests/output_format_integration_tests.rs +0 -0
  308. {rumdl-0.0.128 → rumdl-0.0.130}/tests/output_format_tests.rs +0 -0
  309. {rumdl-0.0.128 → rumdl-0.0.130}/tests/perf_check.rs +0 -0
  310. {rumdl-0.0.128 → rumdl-0.0.130}/tests/performance_validation_tests.rs +0 -0
  311. {rumdl-0.0.128 → rumdl-0.0.130}/tests/pyproject_config_tests.rs +0 -0
  312. {rumdl-0.0.128 → rumdl-0.0.130}/tests/python_bindings_test.rs +0 -0
  313. {rumdl-0.0.128 → rumdl-0.0.130}/tests/real_world_repository_tests.rs +0 -0
  314. {rumdl-0.0.128 → rumdl-0.0.130}/tests/regression_prevention_tests.rs +0 -0
  315. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/emphasis_edge_cases_test.rs +0 -0
  316. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/heading_edge_cases_test.rs +0 -0
  317. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/inline_content_edge_cases_test.rs +0 -0
  318. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/link_edge_cases_test.rs +0 -0
  319. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/list_rules_integration_test.rs +0 -0
  320. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md001_test.rs +0 -0
  321. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md001_unicode_test.rs +0 -0
  322. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md002_test.rs +0 -0
  323. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md003_test.rs +0 -0
  324. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md004_test.rs +0 -0
  325. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md005_dynamic_indent_test.rs +0 -0
  326. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md005_test.rs +0 -0
  327. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md005_unicode_test.rs +0 -0
  328. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md006_test.rs +0 -0
  329. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md006_unicode_test.rs +0 -0
  330. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md007_test.rs +0 -0
  331. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md010_test.rs +0 -0
  332. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md011_test.rs +0 -0
  333. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md012_test.rs +0 -0
  334. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md013_test.rs +0 -0
  335. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md014_test.rs +0 -0
  336. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md018_test.rs +0 -0
  337. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md019_test.rs +0 -0
  338. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md020_test.rs +0 -0
  339. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md021_test.rs +0 -0
  340. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md022_test.rs +0 -0
  341. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md023_extended_test.rs +0 -0
  342. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md023_test.rs +0 -0
  343. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md024_test.rs +0 -0
  344. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md025_test.rs +0 -0
  345. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md026_kramdown_test.rs +0 -0
  346. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md026_test.rs +0 -0
  347. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md027_test.rs +0 -0
  348. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md028_test.rs +0 -0
  349. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md029_code_block_separation_test.rs +0 -0
  350. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md029_fix_test.rs +0 -0
  351. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md029_issue42_test.rs +0 -0
  352. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md029_markdownlint_parity_test.rs +0 -0
  353. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md029_pathological_edge_cases_test.rs +0 -0
  354. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md029_test.rs +0 -0
  355. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md029_unicode_test.rs +0 -0
  356. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md030_test.rs +0 -0
  357. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md031_kramdown_test.rs +0 -0
  358. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md031_test.rs +0 -0
  359. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md032_test.rs +0 -0
  360. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md033_extended_test.rs +0 -0
  361. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md033_kramdown_test.rs +0 -0
  362. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md033_test.rs +0 -0
  363. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md034_ipv6_test.rs +0 -0
  364. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md034_test.rs +0 -0
  365. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md035_test.rs +0 -0
  366. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md036_test.rs +0 -0
  367. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md037_kramdown_test.rs +0 -0
  368. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md037_test.rs +0 -0
  369. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md038_nested_backticks_test.rs +0 -0
  370. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md038_test.rs +0 -0
  371. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md039_test.rs +0 -0
  372. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md040_test.rs +0 -0
  373. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md041_test.rs +0 -0
  374. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md042_test.rs +0 -0
  375. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md043_test.rs +0 -0
  376. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md044_test.rs +0 -0
  377. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md045_test.rs +0 -0
  378. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md046_test.rs +0 -0
  379. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md047_test.rs +0 -0
  380. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md048_test.rs +0 -0
  381. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md049_test.rs +0 -0
  382. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md050_test.rs +0 -0
  383. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md051_comprehensive_test.rs +0 -0
  384. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md051_critical_edge_cases_test.rs +0 -0
  385. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md051_edge_cases_test.rs +0 -0
  386. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md051_issue_39_regression_test.rs +0 -0
  387. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md051_performance_edge_cases_test.rs +0 -0
  388. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md051_property_based_test.rs +0 -0
  389. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md051_regression_prevention_test.rs +0 -0
  390. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md051_test.rs +0 -0
  391. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md051_unicode_security_test.rs +0 -0
  392. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md052_test.rs +0 -0
  393. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md053_proptest.rs +0 -0
  394. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md054_test.rs +0 -0
  395. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md054_unicode_test.rs +0 -0
  396. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md055_test.rs +0 -0
  397. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md056_test.rs +0 -0
  398. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md057_test.rs +0 -0
  399. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md058_kramdown_test.rs +0 -0
  400. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules/md058_test.rs +0 -0
  401. {rumdl-0.0.128 → rumdl-0.0.130}/tests/rules_mod_test.rs +0 -0
  402. {rumdl-0.0.128 → rumdl-0.0.130}/tests/skip_context_tests.rs +0 -0
  403. {rumdl-0.0.128 → rumdl-0.0.130}/tests/test_underscore_edge_cases.rs +0 -0
  404. {rumdl-0.0.128 → rumdl-0.0.130}/tests/thread_safety_tests.rs +0 -0
  405. {rumdl-0.0.128 → rumdl-0.0.130}/tests/unfixable_rules_test.rs +0 -0
  406. {rumdl-0.0.128 → rumdl-0.0.130}/tests/unicode_edge_case_tests.rs +0 -0
  407. {rumdl-0.0.128 → rumdl-0.0.130}/tests/utils/blockquote_utils_test.rs +0 -0
  408. {rumdl-0.0.128 → rumdl-0.0.130}/tests/utils/code_block_utils_extended_test.rs +0 -0
  409. {rumdl-0.0.128 → rumdl-0.0.130}/tests/utils/code_block_utils_test.rs +0 -0
  410. {rumdl-0.0.128 → rumdl-0.0.130}/tests/utils/core_utils_test.rs +0 -0
  411. {rumdl-0.0.128 → rumdl-0.0.130}/tests/utils/front_matter_utils_test.rs +0 -0
  412. {rumdl-0.0.128 → rumdl-0.0.130}/tests/utils/line_index_test.rs +0 -0
  413. {rumdl-0.0.128 → rumdl-0.0.130}/tests/utils/mod.rs +0 -0
  414. {rumdl-0.0.128 → rumdl-0.0.130}/tests/utils_markdown_edge_cases.rs +0 -0
  415. {rumdl-0.0.128 → rumdl-0.0.130}/tests/utils_tests.rs +0 -0
  416. {rumdl-0.0.128 → rumdl-0.0.130}/tests/vscode_extension_fixes.rs +0 -0
  417. {rumdl-0.0.128 → rumdl-0.0.130}/tests/vscode_test.rs +0 -0
  418. {rumdl-0.0.128 → rumdl-0.0.130}/tests/vscode_tests.rs +0 -0
  419. {rumdl-0.0.128 → rumdl-0.0.130}/tests/vscode_windows_comprehensive_test.rs +0 -0
  420. {rumdl-0.0.128 → rumdl-0.0.130}/tests/vscode_windows_test.rs +0 -0
@@ -7,8 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.0.130] - 2025-08-27
11
+
12
+ ### Fixed
13
+ - **MD052**: Fixed false positives with IPv6 URLs containing brackets (e.g., `http://[::1]:8080/path[0]`)
14
+ - **MD053**: Made rule warning-only, removed automatic fixes to prevent accidental removal of intentionally kept references (fixes #69)
15
+ - **MD009/MD028**: Resolved formatting loop between trailing spaces and blank blockquote lines
16
+ - **MD002/MD041**: Fixed interaction where MD002 incorrectly flagged documents starting with level-1 heading
17
+ - **MD011**: Prevented false positives with math-like expressions (e.g., `[0,1]`) outside code blocks
18
+ - **MD034**: Improved bare URL detection to avoid false positives with bracketed paths in URLs
19
+
20
+ ## [0.0.129] - 2025-08-26
21
+
22
+ ### Added
23
+ - **MkDocs Extended Support**: Enhanced MkDocs compatibility with PyMdown Extensions
24
+ - Snippets syntax (`--8<--`) support (fixes #62)
25
+ - Admonitions (`!!!`, `???`, `???+`) for collapsible note blocks
26
+ - Tabs (`=== "Tab Name"`) for content organization
27
+ - Footnotes (`[^ref]`) for reference-style citations
28
+ - Cross-references and auto-doc blocks
29
+
30
+ ### Fixed
31
+ - **MkDocs Validation**: Made validation more lenient to detect malformed syntax
32
+ - **Configuration Migration**: Fixed migration of multiple disabled rules from markdownlint config
33
+
10
34
  ## [0.0.128] - 2025-08-25
11
35
 
36
+ ### Fixed
37
+ - **MD042/MD052**: Added support for simple identifiers in MkDocs auto-references
38
+
12
39
  ## [0.0.127] - 2025-08-25
13
40
 
14
41
  ### Added
@@ -481,7 +508,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
481
508
 
482
509
  - Initial implementation of remaining rules for markdownlint parity
483
510
 
484
- [Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.128...HEAD
511
+ [Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.130...HEAD
512
+ [0.0.130]: https://github.com/rvben/rumdl/compare/v0.0.129...v0.0.130
513
+ [0.0.129]: https://github.com/rvben/rumdl/compare/v0.0.128...v0.0.129
485
514
  [0.0.128]: https://github.com/rvben/rumdl/compare/v0.0.127...v0.0.128
486
515
  [0.0.127]: https://github.com/rvben/rumdl/compare/v0.0.126...v0.0.127
487
516
  [0.0.126]: https://github.com/rvben/rumdl/compare/v0.0.125...v0.0.126
@@ -277,9 +277,9 @@ dependencies = [
277
277
 
278
278
  [[package]]
279
279
  name = "clap"
280
- version = "4.5.45"
280
+ version = "4.5.46"
281
281
  source = "registry+https://github.com/rust-lang/crates.io-index"
282
- checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318"
282
+ checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57"
283
283
  dependencies = [
284
284
  "clap_builder",
285
285
  "clap_derive",
@@ -287,9 +287,9 @@ dependencies = [
287
287
 
288
288
  [[package]]
289
289
  name = "clap_builder"
290
- version = "4.5.44"
290
+ version = "4.5.46"
291
291
  source = "registry+https://github.com/rust-lang/crates.io-index"
292
- checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8"
292
+ checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41"
293
293
  dependencies = [
294
294
  "anstream",
295
295
  "anstyle",
@@ -1605,7 +1605,7 @@ checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
1605
1605
 
1606
1606
  [[package]]
1607
1607
  name = "rumdl"
1608
- version = "0.0.128"
1608
+ version = "0.0.130"
1609
1609
  dependencies = [
1610
1610
  "anyhow",
1611
1611
  "assert_cmd",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rumdl"
3
- version = "0.0.128"
3
+ version = "0.0.130"
4
4
  edition = "2024"
5
5
  rust-version = "1.89.0"
6
6
  description = "A fast Markdown linter written in Rust (Ru(st) MarkDown Linter)"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rumdl
3
- Version: 0.0.128
3
+ Version: 0.0.130
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -390,11 +390,11 @@ impl<'a> LintContext<'a> {
390
390
  let code_blocks = CodeBlockUtils::detect_code_blocks(content);
391
391
 
392
392
  // Pre-compute line information
393
- let lines = Self::compute_line_info(content, &line_offsets, &code_blocks);
393
+ let lines = Self::compute_line_info(content, &line_offsets, &code_blocks, flavor);
394
394
 
395
395
  // Parse links, images, references, and list blocks
396
396
  // Skip code spans - they'll be computed lazily
397
- let links = Self::parse_links(content, &lines, &code_blocks);
397
+ let links = Self::parse_links(content, &lines, &code_blocks, flavor);
398
398
  let images = Self::parse_images(content, &lines, &code_blocks);
399
399
  let reference_defs = Self::parse_reference_defs(content, &lines);
400
400
  let list_blocks = Self::parse_list_blocks(&lines);
@@ -671,7 +671,14 @@ impl<'a> LintContext<'a> {
671
671
  }
672
672
 
673
673
  /// Parse all links in the content
674
- fn parse_links(content: &str, lines: &[LineInfo], code_blocks: &[(usize, usize)]) -> Vec<ParsedLink> {
674
+ fn parse_links(
675
+ content: &str,
676
+ lines: &[LineInfo],
677
+ code_blocks: &[(usize, usize)],
678
+ flavor: MarkdownFlavor,
679
+ ) -> Vec<ParsedLink> {
680
+ use crate::utils::skip_context::is_mkdocs_snippet_line;
681
+
675
682
  // Pre-size based on a heuristic: most markdown files have relatively few links
676
683
  let mut links = Vec::with_capacity(content.len() / 500); // ~1 link per 500 chars
677
684
 
@@ -696,6 +703,19 @@ impl<'a> LintContext<'a> {
696
703
  continue;
697
704
  }
698
705
 
706
+ // Skip if this link is on a MkDocs snippet line
707
+ // Find which line this link is on
708
+ let line_idx = lines
709
+ .iter()
710
+ .position(|line| {
711
+ match_start >= line.byte_offset && (match_start < line.byte_offset + line.content.len() + 1)
712
+ })
713
+ .unwrap_or(0);
714
+
715
+ if is_mkdocs_snippet_line(&lines[line_idx].content, flavor) {
716
+ continue;
717
+ }
718
+
699
719
  // Find which line this link starts on
700
720
  let mut line_num = 1;
701
721
  let mut col_start = match_start;
@@ -895,7 +915,12 @@ impl<'a> LintContext<'a> {
895
915
  }
896
916
 
897
917
  /// Pre-compute line information
898
- fn compute_line_info(content: &str, line_offsets: &[usize], code_blocks: &[(usize, usize)]) -> Vec<LineInfo> {
918
+ fn compute_line_info(
919
+ content: &str,
920
+ line_offsets: &[usize],
921
+ code_blocks: &[(usize, usize)],
922
+ flavor: MarkdownFlavor,
923
+ ) -> Vec<LineInfo> {
899
924
  lazy_static! {
900
925
  // Regex for list detection - allow any whitespace including no space (to catch malformed lists)
901
926
  static ref UNORDERED_REGEX: regex::Regex = regex::Regex::new(r"^(\s*)([-*+])([ \t]*)(.*)").unwrap();
@@ -1065,8 +1090,10 @@ impl<'a> LintContext<'a> {
1065
1090
  // Consider tabs as multiple spaces, or actual multiple spaces
1066
1091
  let has_multiple_spaces = spaces_after.len() > 1 || spaces_after.contains('\t');
1067
1092
 
1068
- // Check if needs MD028 fix (empty blockquote without proper spacing)
1069
- let needs_md028_fix = content.trim().is_empty() && spaces_after.is_empty();
1093
+ // Check if needs MD028 fix (empty blockquote line without proper spacing)
1094
+ // MD028 flags empty blockquote lines that don't have a single space after the marker
1095
+ // Lines like "> " or ">> " are already correct and don't need fixing
1096
+ let needs_md028_fix = content.is_empty() && spaces_after.is_empty();
1070
1097
 
1071
1098
  lines[i].blockquote = Some(BlockquoteInfo {
1072
1099
  nesting_level,
@@ -1085,8 +1112,16 @@ impl<'a> LintContext<'a> {
1085
1112
  continue;
1086
1113
  }
1087
1114
 
1088
- // Check for ATX headings
1089
- if let Some(caps) = ATX_HEADING_REGEX.captures(line) {
1115
+ // Check for ATX headings (but skip MkDocs snippet lines)
1116
+ // In MkDocs flavor, lines like "# -8<- [start:name]" are snippet markers, not headings
1117
+ let is_snippet_line = if flavor == MarkdownFlavor::MkDocs {
1118
+ crate::utils::mkdocs_snippets::is_snippet_section_start(line)
1119
+ || crate::utils::mkdocs_snippets::is_snippet_section_end(line)
1120
+ } else {
1121
+ false
1122
+ };
1123
+
1124
+ if !is_snippet_line && let Some(caps) = ATX_HEADING_REGEX.captures(line) {
1090
1125
  let leading_spaces = caps.get(1).map_or("", |m| m.as_str());
1091
1126
  let hashes = caps.get(2).map_or("", |m| m.as_str());
1092
1127
  let spaces_after = caps.get(3).map_or("", |m| m.as_str());
@@ -191,6 +191,11 @@ impl MarkdownlintConfig {
191
191
  ) -> crate::config::SourcedConfigFragment {
192
192
  let mut fragment = crate::config::SourcedConfigFragment::default();
193
193
  let file = file_path.map(|s| s.to_string());
194
+
195
+ // Accumulate disabled and enabled rules
196
+ let mut disabled_rules = Vec::new();
197
+ let mut enabled_rules = Vec::new();
198
+
194
199
  for (key, value) in &self.0 {
195
200
  // Special handling for line-length as a global setting
196
201
  if key.eq_ignore_ascii_case("line-length") || key.eq_ignore_ascii_case("line_length") {
@@ -211,21 +216,11 @@ impl MarkdownlintConfig {
211
216
  // Special handling for boolean values (true/false)
212
217
  if value.is_bool() {
213
218
  if !value.as_bool().unwrap_or(false) {
214
- // Add to global.disable
215
- fragment.global.disable.push_override(
216
- vec![norm_rule_key.clone()],
217
- crate::config::ConfigSource::Markdownlint,
218
- file.clone(),
219
- None,
220
- );
219
+ // Accumulate disabled rules
220
+ disabled_rules.push(norm_rule_key.clone());
221
221
  } else {
222
- // Add to global.enable (if true)
223
- fragment.global.enable.push_override(
224
- vec![norm_rule_key.clone()],
225
- crate::config::ConfigSource::Markdownlint,
226
- file.clone(),
227
- None,
228
- );
222
+ // Accumulate enabled rules
223
+ enabled_rules.push(norm_rule_key.clone());
229
224
  }
230
225
  continue;
231
226
  }
@@ -269,6 +264,27 @@ impl MarkdownlintConfig {
269
264
  }
270
265
  }
271
266
  }
267
+
268
+ // Set all disabled rules at once
269
+ if !disabled_rules.is_empty() {
270
+ fragment.global.disable.push_override(
271
+ disabled_rules,
272
+ crate::config::ConfigSource::Markdownlint,
273
+ file.clone(),
274
+ None,
275
+ );
276
+ }
277
+
278
+ // Set all enabled rules at once
279
+ if !enabled_rules.is_empty() {
280
+ fragment.global.enable.push_override(
281
+ enabled_rules,
282
+ crate::config::ConfigSource::Markdownlint,
283
+ file.clone(),
284
+ None,
285
+ );
286
+ }
287
+
272
288
  if let Some(_f) = file {
273
289
  // SourcedConfigFragment does not have loaded_files, so skip
274
290
  }
@@ -28,11 +28,6 @@ impl MD009TrailingSpaces {
28
28
  Self { config }
29
29
  }
30
30
 
31
- fn is_empty_blockquote_line(line: &str) -> bool {
32
- let trimmed = line.trim_start();
33
- trimmed.starts_with('>') && trimmed.trim_end() == ">"
34
- }
35
-
36
31
  fn count_trailing_spaces(line: &str) -> usize {
37
32
  line.chars().rev().take_while(|&c| c == ' ').count()
38
33
  }
@@ -88,6 +83,17 @@ impl Rule for MD009TrailingSpaces {
88
83
  continue;
89
84
  }
90
85
 
86
+ // Check if this is an empty blockquote line (like "> " or ">> ")
87
+ // These are allowed to have a single trailing space by MD028
88
+ let trimmed_line = line.trim_end();
89
+ if trimmed_line.chars().all(|c| c == '>' || c == ' ' || c == '\t')
90
+ && trimmed_line.contains('>')
91
+ && trailing_spaces == 1
92
+ {
93
+ // This is an empty blockquote line with single trailing space - allowed
94
+ continue;
95
+ }
96
+
91
97
  // Calculate precise character range for all trailing spaces on empty line
92
98
  let (start_line, start_col, end_line, end_col) = calculate_trailing_range(line_num + 1, line, 0);
93
99
 
@@ -126,34 +132,16 @@ impl Rule for MD009TrailingSpaces {
126
132
  continue;
127
133
  }
128
134
 
129
- // Special handling for empty blockquote lines
130
- if Self::is_empty_blockquote_line(line) {
131
- let trimmed = line.trim_end();
132
- // Calculate precise character range for trailing spaces after blockquote marker
133
- let (start_line, start_col, end_line, end_col) =
134
- calculate_trailing_range(line_num + 1, line, trimmed.len());
135
-
136
- warnings.push(LintWarning {
137
- rule_name: Some(self.name()),
138
- line: start_line,
139
- column: start_col,
140
- end_line,
141
- end_column: end_col,
142
- message: "Empty blockquote line needs a space after >".to_string(),
143
- severity: Severity::Warning,
144
- fix: Some(Fix {
145
- range: _line_index.line_col_to_byte_range_with_length(
146
- line_num + 1,
147
- trimmed.len() + 1,
148
- line.len() - trimmed.len(),
149
- ),
150
- replacement: " ".to_string(),
151
- }),
152
- });
153
- continue;
154
- }
155
-
135
+ // Check if this is an empty blockquote line ("> " or ">> " etc)
136
+ // These are allowed by MD028 to have a single trailing space
156
137
  let trimmed = line.trim_end();
138
+ let is_empty_blockquote_with_space = trimmed.chars().all(|c| c == '>' || c == ' ' || c == '\t')
139
+ && trimmed.contains('>')
140
+ && trailing_spaces == 1;
141
+
142
+ if is_empty_blockquote_with_space {
143
+ continue; // Allow single trailing space for empty blockquote lines
144
+ }
157
145
  // Calculate precise character range for all trailing spaces
158
146
  let (start_line, start_col, end_line, end_col) =
159
147
  calculate_trailing_range(line_num + 1, line, trimmed.len());
@@ -222,7 +210,7 @@ impl Rule for MD009TrailingSpaces {
222
210
  if self.config.list_item_empty_lines && Self::is_empty_list_item_line(line, prev_line) {
223
211
  result.push_str(line);
224
212
  } else {
225
- // Remove all trailing spaces
213
+ // Remove all trailing spaces - line is empty so don't add anything
226
214
  }
227
215
  result.push('\n');
228
216
  continue;
@@ -237,13 +225,7 @@ impl Rule for MD009TrailingSpaces {
237
225
  continue;
238
226
  }
239
227
 
240
- // Special handling for empty blockquote lines
241
- if Self::is_empty_blockquote_line(line) {
242
- result.push_str(trimmed);
243
- result.push(' '); // Add a space after the blockquote marker
244
- result.push('\n');
245
- continue;
246
- }
228
+ // No special handling for empty blockquote lines - treat them like regular lines
247
229
 
248
230
  // Handle lines with trailing spaces
249
231
  let is_truly_last_line = i == lines.len() - 1 && !content.ends_with('\n');
@@ -258,9 +240,17 @@ impl Rule for MD009TrailingSpaces {
258
240
  trimmed.starts_with('#')
259
241
  };
260
242
 
243
+ // Check if this is an empty blockquote line (just ">")
244
+ let is_empty_blockquote = if let Some(line_info) = ctx.line_info(i + 1) {
245
+ line_info.blockquote.as_ref().is_some_and(|bq| bq.content.is_empty())
246
+ } else {
247
+ false
248
+ };
249
+
261
250
  // In non-strict mode, preserve line breaks by normalizing to br_spaces
262
- // BUT: Never preserve trailing spaces in headings as they serve no purpose
263
- if !self.config.strict && !is_truly_last_line && trailing_spaces > 0 && !is_heading {
251
+ // BUT: Never preserve trailing spaces in headings or empty blockquotes as they serve no purpose
252
+ if !self.config.strict && !is_truly_last_line && trailing_spaces > 0 && !is_heading && !is_empty_blockquote
253
+ {
264
254
  // Optimize for common case of 2 spaces
265
255
  match self.config.br_spaces {
266
256
  0 => {}
@@ -425,10 +415,10 @@ mod tests {
425
415
  let result = rule.check(&ctx).unwrap();
426
416
  assert_eq!(result.len(), 1);
427
417
  assert_eq!(result[0].line, 2);
428
- assert_eq!(result[0].message, "Empty blockquote line needs a space after >");
418
+ assert_eq!(result[0].message, "3 trailing spaces found");
429
419
 
430
420
  let fixed = rule.fix(&ctx).unwrap();
431
- assert_eq!(fixed, "> Quote\n> \n> More quote");
421
+ assert_eq!(fixed, "> Quote\n>\n> More quote"); // All trailing spaces removed
432
422
  }
433
423
 
434
424
  #[test]
@@ -19,6 +19,16 @@ lazy_static! {
19
19
  // Pattern to detect escaped brackets and parentheses
20
20
  static ref ESCAPED_CHARS: Regex = Regex::new(r"\\[\[\]()]").unwrap();
21
21
 
22
+ // Pattern to detect mathematical context indicators
23
+ static ref MATH_CONTEXT: Regex = Regex::new(
24
+ r"(?:f|g|h|sin|cos|tan|log|ln|exp|matrix|vector|det|lim|sum|prod|int)\s*\([^)]+\)|[∈∉⊆⊂⊃⊇∩∪∧∨¬∀∃∅∞∫∑∏√±×÷≠≤≥≈≡]|\b(?:where|such that|for all|exists|if and only if)\b"
25
+ ).unwrap();
26
+
27
+ // Pattern to detect function/array notation that shouldn't be flagged
28
+ static ref FUNCTION_ARRAY_NOTATION: Regex = Regex::new(
29
+ r"(?:[a-zA-Z_]\w*\([^)]*\)\[[^\]]+\])|(?:\([^)]+\)\[(?:element|index|derivative|integral|component|row|column|entry|coefficient|term)\])"
30
+ ).unwrap();
31
+
22
32
  // New patterns for detecting malformed link attempts where user intent is clear
23
33
  static ref MALFORMED_LINK_PATTERNS: Vec<(Regex, &'static str)> = vec![
24
34
  // Missing closing bracket: (URL)[text or [text](URL
@@ -77,11 +87,45 @@ impl MD011NoReversedLinks {
77
87
  continue;
78
88
  }
79
89
 
90
+ // Skip if line contains mathematical context
91
+ if MATH_CONTEXT.is_match(line) {
92
+ line_start += line.len() + 1;
93
+ current_line += 1;
94
+ continue;
95
+ }
96
+
97
+ // Skip if line contains function/array notation
98
+ if FUNCTION_ARRAY_NOTATION.is_match(line) {
99
+ line_start += line.len() + 1;
100
+ current_line += 1;
101
+ continue;
102
+ }
103
+
80
104
  for cap in REVERSED_LINK_CHECK_REGEX.captures_iter(line) {
81
105
  // Extract URL and text
82
106
  let url = &cap[1];
83
107
  let text = &cap[2];
84
108
 
109
+ // Additional check: Skip if this looks like mathematical notation
110
+ // e.g., (0,1)[inclusive], (a,b)[intersection]
111
+ if text.len() < 20
112
+ && (text.contains("inclusive")
113
+ || text.contains("exclusive")
114
+ || text.contains("intersection")
115
+ || text.contains("union")
116
+ || text.contains("element")
117
+ || text.contains("derivative")
118
+ || text.contains("component")
119
+ || text.contains("index"))
120
+ {
121
+ continue;
122
+ }
123
+
124
+ // Skip if URL part looks like coordinates or intervals
125
+ if url.contains(',') && !url.contains("://") && !url.contains('.') {
126
+ continue;
127
+ }
128
+
85
129
  let start = line_start + cap.get(0).unwrap().start();
86
130
  results.push((current_line, start - line_start + 1, text.to_string(), url.to_string()));
87
131
  }
@@ -51,8 +51,28 @@ impl Rule for MD024NoDuplicateHeading {
51
51
  let mut current_section_path: Vec<(u8, String)> = Vec::new(); // Stack of (level, heading_text)
52
52
  let mut seen_siblings: HashMap<String, HashSet<String>> = HashMap::new(); // parent_path -> set of child headings
53
53
 
54
+ // Track if we're in a snippet section (MkDocs flavor)
55
+ let is_mkdocs = ctx.flavor == crate::config::MarkdownFlavor::MkDocs;
56
+ let mut in_snippet_section = false;
57
+
54
58
  // Process headings using cached heading information
55
59
  for (line_num, line_info) in ctx.lines.iter().enumerate() {
60
+ // Check for MkDocs snippet markers if using MkDocs flavor
61
+ if is_mkdocs {
62
+ if crate::utils::mkdocs_snippets::is_snippet_section_start(&line_info.content) {
63
+ in_snippet_section = true;
64
+ continue; // Skip this line
65
+ } else if crate::utils::mkdocs_snippets::is_snippet_section_end(&line_info.content) {
66
+ in_snippet_section = false;
67
+ continue; // Skip this line
68
+ }
69
+ }
70
+
71
+ // Skip lines within snippet sections (for MkDocs)
72
+ if is_mkdocs && in_snippet_section {
73
+ continue;
74
+ }
75
+
56
76
  if let Some(heading) = &line_info.heading {
57
77
  // Skip empty headings
58
78
  if heading.text.is_empty() {
@@ -144,12 +144,17 @@ impl Rule for MD027MultipleSpacesBlockquote {
144
144
  // Fix blockquotes with multiple spaces after the marker
145
145
  if blockquote.has_multiple_spaces_after_marker {
146
146
  // Rebuild the line with exactly one space after the markers
147
- let fixed_line = format!(
148
- "{}{} {}",
149
- blockquote.indent,
150
- ">".repeat(blockquote.nesting_level),
151
- blockquote.content
152
- );
147
+ // But don't add a space if the content is empty to avoid MD009 conflicts
148
+ let fixed_line = if blockquote.content.is_empty() {
149
+ format!("{}{}", blockquote.indent, ">".repeat(blockquote.nesting_level))
150
+ } else {
151
+ format!(
152
+ "{}{} {}",
153
+ blockquote.indent,
154
+ ">".repeat(blockquote.nesting_level),
155
+ blockquote.content
156
+ )
157
+ };
153
158
  result.push(fixed_line);
154
159
  } else {
155
160
  result.push(line_info.content.clone());
@@ -17,7 +17,7 @@ impl MD028NoBlanksBlockquote {
17
17
  for _ in 0..level {
18
18
  result.push('>');
19
19
  }
20
- // Add a single space after the last '>'
20
+ // Add a single space after the marker for proper blockquote formatting
21
21
  result.push(' ');
22
22
 
23
23
  result
@@ -5,6 +5,7 @@ use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule, RuleCategory, S
5
5
  use crate::rule_config_serde::RuleConfig;
6
6
  use crate::utils::document_structure::{DocumentStructure, DocumentStructureExtensions};
7
7
  use crate::utils::kramdown_utils::is_kramdown_block_attribute;
8
+ use crate::utils::mkdocs_admonitions;
8
9
  use crate::utils::range_utils::{LineIndex, calculate_line_range};
9
10
  use serde::{Deserialize, Serialize};
10
11
 
@@ -126,12 +127,76 @@ impl Rule for MD031BlanksAroundFences {
126
127
 
127
128
  let mut in_code_block = false;
128
129
  let mut current_fence_marker: Option<String> = None;
130
+ let mut in_admonition = false;
131
+ let mut admonition_indent = 0;
132
+ let is_mkdocs = ctx.flavor == crate::config::MarkdownFlavor::MkDocs;
129
133
  let mut i = 0;
130
134
 
131
135
  while i < lines.len() {
132
136
  let line = lines[i];
133
137
  let trimmed = line.trim_start();
134
138
 
139
+ // Check for MkDocs admonition start
140
+ if is_mkdocs && mkdocs_admonitions::is_admonition_start(line) {
141
+ // Check for blank line before admonition (similar to code blocks)
142
+ if i > 0 && !Self::is_empty_line(lines[i - 1]) && self.should_require_blank_line(i, &lines) {
143
+ let (start_line, start_col, end_line, end_col) = calculate_line_range(i + 1, lines[i]);
144
+
145
+ warnings.push(LintWarning {
146
+ rule_name: Some(self.name()),
147
+ line: start_line,
148
+ column: start_col,
149
+ end_line,
150
+ end_column: end_col,
151
+ message: "No blank line before admonition block".to_string(),
152
+ severity: Severity::Warning,
153
+ fix: Some(Fix {
154
+ range: line_index.line_col_to_byte_range_with_length(i + 1, 1, 0),
155
+ replacement: "\n".to_string(),
156
+ }),
157
+ });
158
+ }
159
+
160
+ in_admonition = true;
161
+ admonition_indent = mkdocs_admonitions::get_admonition_indent(line).unwrap_or(0);
162
+ i += 1;
163
+ continue;
164
+ }
165
+
166
+ // Check if we're exiting an admonition
167
+ if in_admonition {
168
+ if !line.trim().is_empty() && !mkdocs_admonitions::is_admonition_content(line, admonition_indent) {
169
+ // We've exited the admonition
170
+ in_admonition = false;
171
+
172
+ // Check for blank line after admonition (current line should be blank)
173
+ if !Self::is_empty_line(line) && self.should_require_blank_line(i - 1, &lines) {
174
+ let (start_line, start_col, end_line, end_col) = calculate_line_range(i + 1, lines[i]);
175
+
176
+ warnings.push(LintWarning {
177
+ rule_name: Some(self.name()),
178
+ line: start_line,
179
+ column: start_col,
180
+ end_line,
181
+ end_column: end_col,
182
+ message: "No blank line after admonition block".to_string(),
183
+ severity: Severity::Warning,
184
+ fix: Some(Fix {
185
+ range: line_index.line_col_to_byte_range_with_length(i, 0, 0),
186
+ replacement: "\n".to_string(),
187
+ }),
188
+ });
189
+ }
190
+
191
+ admonition_indent = 0;
192
+ // Don't continue - process this line normally
193
+ } else {
194
+ // Still in admonition
195
+ i += 1;
196
+ continue;
197
+ }
198
+ }
199
+
135
200
  // Determine fence marker if this is a fence line
136
201
  let fence_marker = if trimmed.starts_with("```") {
137
202
  let backtick_count = trimmed.chars().take_while(|&c| c == '`').count();
@@ -145,6 +145,14 @@ impl MD033NoInlineHtml {
145
145
  && content.split('@').all(|part| !part.is_empty())
146
146
  }
147
147
 
148
+ // Check if a tag has the markdown attribute (MkDocs/Material for MkDocs)
149
+ #[inline]
150
+ fn has_markdown_attribute(&self, tag: &str) -> bool {
151
+ // Check for various forms of markdown attribute
152
+ // Examples: <div markdown>, <div markdown="1">, <div class="result" markdown>
153
+ tag.contains(" markdown>") || tag.contains(" markdown=") || tag.contains(" markdown ")
154
+ }
155
+
148
156
  // Check if a tag is actually a URL in angle brackets
149
157
  #[inline]
150
158
  fn is_url_in_angle_brackets(&self, tag: &str) -> bool {
@@ -160,6 +168,7 @@ impl MD033NoInlineHtml {
160
168
  /// Find HTML tags that span multiple lines
161
169
  fn find_multiline_html_tags(
162
170
  &self,
171
+ ctx: &crate::lint_context::LintContext,
163
172
  content: &str,
164
173
  structure: &DocumentStructure,
165
174
  nomarkdown_ranges: &[(usize, usize)],
@@ -230,11 +239,15 @@ impl MD033NoInlineHtml {
230
239
  let final_tag = &complete_tag[0..=end_pos];
231
240
 
232
241
  // Apply the same filters as single-line tags
242
+ let skip_mkdocs_markdown = ctx.flavor == crate::config::MarkdownFlavor::MkDocs
243
+ && self.has_markdown_attribute(final_tag);
244
+
233
245
  if !self.is_html_comment(final_tag)
234
246
  && !self.is_likely_type_annotation(final_tag)
235
247
  && !self.is_email_address(final_tag)
236
248
  && !self.is_url_in_angle_brackets(final_tag)
237
249
  && !self.is_tag_allowed(final_tag)
250
+ && !skip_mkdocs_markdown
238
251
  && HTML_TAG_FINDER.is_match(final_tag)
239
252
  {
240
253
  // Check for duplicates (avoid flagging the same position twice)
@@ -398,6 +411,11 @@ impl Rule for MD033NoInlineHtml {
398
411
  continue;
399
412
  }
400
413
 
414
+ // Skip tags with markdown attribute in MkDocs mode
415
+ if ctx.flavor == crate::config::MarkdownFlavor::MkDocs && self.has_markdown_attribute(tag) {
416
+ continue;
417
+ }
418
+
401
419
  // Report each HTML tag individually (true markdownlint compatibility)
402
420
  let (start_line, start_col, end_line, end_col) =
403
421
  calculate_html_tag_range(line_num, line, tag_match.start(), tag_match.len());
@@ -415,7 +433,7 @@ impl Rule for MD033NoInlineHtml {
415
433
  }
416
434
 
417
435
  // Third pass: find multi-line HTML tags
418
- self.find_multiline_html_tags(ctx.content, structure, &nomarkdown_ranges, &mut warnings);
436
+ self.find_multiline_html_tags(ctx, ctx.content, structure, &nomarkdown_ranges, &mut warnings);
419
437
 
420
438
  Ok(warnings)
421
439
  }