rumdl 0.0.97__tar.gz → 0.0.99__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 (363) hide show
  1. rumdl-0.0.99/.pre-commit-config.yaml +59 -0
  2. {rumdl-0.0.97 → rumdl-0.0.99}/CHANGELOG.md +28 -1
  3. {rumdl-0.0.97 → rumdl-0.0.99}/Cargo.lock +5 -5
  4. {rumdl-0.0.97 → rumdl-0.0.99}/Cargo.toml +1 -1
  5. {rumdl-0.0.97 → rumdl-0.0.99}/PKG-INFO +9 -1
  6. {rumdl-0.0.97 → rumdl-0.0.99}/README.md +8 -0
  7. rumdl-0.0.99/scripts/setup-pre-commit.sh +49 -0
  8. {rumdl-0.0.97 → rumdl-0.0.99}/src/bin/benchmark_rule.rs +26 -27
  9. {rumdl-0.0.97 → rumdl-0.0.99}/src/config.rs +4 -11
  10. rumdl-0.0.99/src/exit_codes.rs +32 -0
  11. {rumdl-0.0.97 → rumdl-0.0.99}/src/lib.rs +1 -3
  12. {rumdl-0.0.97 → rumdl-0.0.99}/src/lint_context.rs +90 -8
  13. {rumdl-0.0.97 → rumdl-0.0.99}/src/lsp/server.rs +21 -22
  14. {rumdl-0.0.97 → rumdl-0.0.99}/src/main.rs +112 -33
  15. {rumdl-0.0.97 → rumdl-0.0.99}/src/parallel.rs +1 -6
  16. {rumdl-0.0.97 → rumdl-0.0.99}/src/performance.rs +12 -16
  17. {rumdl-0.0.97 → rumdl-0.0.99}/src/python.rs +2 -3
  18. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/heading_utils.rs +2 -2
  19. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md001_heading_increment.rs +27 -27
  20. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md003_heading_style.rs +19 -5
  21. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md004_unordered_list_style.rs +28 -8
  22. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md005_list_indent.rs +181 -182
  23. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md007_ul_indent.rs +24 -15
  24. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md009_trailing_spaces.rs +22 -18
  25. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md010_no_hard_tabs.rs +36 -27
  26. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md011_no_reversed_links.rs +13 -13
  27. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md012_no_multiple_blanks.rs +8 -9
  28. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md013_line_length.rs +108 -82
  29. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md018_no_missing_space_atx.rs +12 -10
  30. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md020_no_missing_space_closed_atx.rs +2 -6
  31. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md024_no_duplicate_heading.rs +5 -7
  32. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md025_single_title.rs +5 -3
  33. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md029_ordered_list_prefix.rs +173 -9
  34. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md030_list_marker_space.rs +2 -3
  35. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md031_blanks_around_fences.rs +17 -10
  36. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md033_no_inline_html.rs +66 -18
  37. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md034_no_bare_urls.rs +43 -29
  38. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md035_hr_style.rs +2 -1
  39. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md036_no_emphasis_only_first.rs +11 -9
  40. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md038_no_space_in_code.rs +26 -23
  41. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md041_first_line_heading.rs +26 -22
  42. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md044_proper_names.rs +215 -51
  43. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md045_no_alt_text/md045_config.rs +1 -1
  44. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md047_single_trailing_newline.rs +7 -2
  45. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md049_emphasis_style.rs +5 -1
  46. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md050_strong_style.rs +26 -8
  47. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md051_link_fragments.rs +6 -3
  48. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md052_reference_links_images.rs +143 -10
  49. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md053_link_image_reference_definitions.rs +5 -5
  50. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md057_existing_relative_links.rs +1 -3
  51. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/document_structure.rs +1 -4
  52. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/text_reflow.rs +91 -90
  53. {rumdl-0.0.97 → rumdl-0.0.99}/tests/advanced_integration_tests.rs +32 -33
  54. rumdl-0.0.99/tests/cli_explain_test.rs +104 -0
  55. rumdl-0.0.99/tests/cli_flag_precedence_test.rs +292 -0
  56. {rumdl-0.0.97 → rumdl-0.0.99}/tests/cli_integration_tests.rs +1 -4
  57. {rumdl-0.0.97 → rumdl-0.0.99}/tests/cli_lsp_fix_consistency.rs +3 -9
  58. {rumdl-0.0.97 → rumdl-0.0.99}/tests/commonmark_compliance_tests.rs +13 -4
  59. {rumdl-0.0.97 → rumdl-0.0.99}/tests/comprehensive_integration_tests.rs +30 -32
  60. {rumdl-0.0.97 → rumdl-0.0.99}/tests/config_tests.rs +15 -3
  61. {rumdl-0.0.97 → rumdl-0.0.99}/tests/final_confidence_assessment.rs +9 -22
  62. {rumdl-0.0.97 → rumdl-0.0.99}/tests/lsp_integration_tests.rs +2 -6
  63. {rumdl-0.0.97 → rumdl-0.0.99}/tests/lsp_memory_leak_tests.rs +1 -1
  64. {rumdl-0.0.97 → rumdl-0.0.99}/tests/md013_reflow_integration_test.rs +77 -59
  65. {rumdl-0.0.97 → rumdl-0.0.99}/tests/nested_code_block_test.rs +24 -20
  66. rumdl-0.0.99/tests/python_bindings_test.rs +40 -0
  67. rumdl-0.0.99/tests/rules/emphasis_edge_cases_test.rs +664 -0
  68. rumdl-0.0.99/tests/rules/heading_edge_cases_test.rs +835 -0
  69. rumdl-0.0.99/tests/rules/inline_content_edge_cases_test.rs +839 -0
  70. rumdl-0.0.99/tests/rules/link_edge_cases_test.rs +652 -0
  71. rumdl-0.0.99/tests/rules/list_rules_integration_test.rs +386 -0
  72. rumdl-0.0.99/tests/rules/md005_unicode_test.rs +191 -0
  73. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md013_test.rs +126 -107
  74. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md018_test.rs +18 -9
  75. rumdl-0.0.99/tests/rules/md029_test.rs +447 -0
  76. rumdl-0.0.99/tests/rules/md029_unicode_test.rs +247 -0
  77. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md032_test.rs +1 -3
  78. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md034_ipv6_test.rs +33 -21
  79. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md034_test.rs +1 -5
  80. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md036_test.rs +17 -16
  81. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md038_nested_backticks_test.rs +17 -21
  82. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md041_test.rs +17 -13
  83. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md044_test.rs +2 -1
  84. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md051_unicode_test.rs +27 -34
  85. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/mod.rs +12 -3
  86. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules_mod_test.rs +80 -67
  87. {rumdl-0.0.97 → rumdl-0.0.99}/tests/utils/core_utils_test.rs +5 -5
  88. {rumdl-0.0.97 → rumdl-0.0.99}/tests/vscode_tests.rs +37 -37
  89. rumdl-0.0.97/src/exit_codes.rs +0 -34
  90. rumdl-0.0.97/tests/rules/md029_test.rs +0 -207
  91. {rumdl-0.0.97 → rumdl-0.0.99}/.config/nextest.toml +0 -0
  92. {rumdl-0.0.97 → rumdl-0.0.99}/.mise.toml +0 -0
  93. {rumdl-0.0.97 → rumdl-0.0.99}/.rumdl.toml +0 -0
  94. {rumdl-0.0.97 → rumdl-0.0.99}/.rustfmt.toml +0 -0
  95. {rumdl-0.0.97 → rumdl-0.0.99}/LICENSE +0 -0
  96. {rumdl-0.0.97 → rumdl-0.0.99}/MANIFEST.in +0 -0
  97. {rumdl-0.0.97 → rumdl-0.0.99}/Makefile +0 -0
  98. {rumdl-0.0.97 → rumdl-0.0.99}/assets/logo.png +0 -0
  99. {rumdl-0.0.97 → rumdl-0.0.99}/benches/fix_performance.rs +0 -0
  100. {rumdl-0.0.97 → rumdl-0.0.99}/benches/range_performance.rs +0 -0
  101. {rumdl-0.0.97 → rumdl-0.0.99}/benches/range_utils_benchmark.rs +0 -0
  102. {rumdl-0.0.97 → rumdl-0.0.99}/benches/rule_performance.rs +0 -0
  103. {rumdl-0.0.97 → rumdl-0.0.99}/benches/simple_fix_bench.rs +0 -0
  104. {rumdl-0.0.97 → rumdl-0.0.99}/docs/RULES.md +0 -0
  105. {rumdl-0.0.97 → rumdl-0.0.99}/docs/global-settings.md +0 -0
  106. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md001.md +0 -0
  107. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md002.md +0 -0
  108. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md003.md +0 -0
  109. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md004.md +0 -0
  110. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md005.md +0 -0
  111. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md006.md +0 -0
  112. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md007.md +0 -0
  113. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md009.md +0 -0
  114. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md010.md +0 -0
  115. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md011.md +0 -0
  116. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md012.md +0 -0
  117. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md013.md +0 -0
  118. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md014.md +0 -0
  119. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md018.md +0 -0
  120. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md019.md +0 -0
  121. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md020.md +0 -0
  122. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md021.md +0 -0
  123. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md022.md +0 -0
  124. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md023.md +0 -0
  125. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md024.md +0 -0
  126. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md025.md +0 -0
  127. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md026.md +0 -0
  128. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md027.md +0 -0
  129. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md028.md +0 -0
  130. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md029.md +0 -0
  131. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md030.md +0 -0
  132. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md031.md +0 -0
  133. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md032.md +0 -0
  134. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md033.md +0 -0
  135. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md034.md +0 -0
  136. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md035.md +0 -0
  137. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md036.md +0 -0
  138. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md037.md +0 -0
  139. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md038.md +0 -0
  140. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md039.md +0 -0
  141. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md040.md +0 -0
  142. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md041.md +0 -0
  143. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md042.md +0 -0
  144. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md043.md +0 -0
  145. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md044.md +0 -0
  146. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md045.md +0 -0
  147. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md046.md +0 -0
  148. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md047.md +0 -0
  149. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md048.md +0 -0
  150. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md049.md +0 -0
  151. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md050.md +0 -0
  152. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md051.md +0 -0
  153. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md052.md +0 -0
  154. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md053.md +0 -0
  155. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md054.md +0 -0
  156. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md055.md +0 -0
  157. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md056.md +0 -0
  158. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md057.md +0 -0
  159. {rumdl-0.0.97 → rumdl-0.0.99}/docs/md058.md +0 -0
  160. {rumdl-0.0.97 → rumdl-0.0.99}/docs/vscode-extension.md +0 -0
  161. {rumdl-0.0.97 → rumdl-0.0.99}/parity_check.py +0 -0
  162. {rumdl-0.0.97 → rumdl-0.0.99}/pyproject.toml +0 -0
  163. {rumdl-0.0.97 → rumdl-0.0.99}/python/MANIFEST.in +0 -0
  164. {rumdl-0.0.97 → rumdl-0.0.99}/python/PYTHON-README.md +0 -0
  165. {rumdl-0.0.97 → rumdl-0.0.99}/python/rumdl/__init__.py +0 -0
  166. {rumdl-0.0.97 → rumdl-0.0.99}/python/rumdl/__main__.py +0 -0
  167. {rumdl-0.0.97 → rumdl-0.0.99}/python/rumdl/py.typed +0 -0
  168. {rumdl-0.0.97 → rumdl-0.0.99}/rumdl.toml.example +0 -0
  169. {rumdl-0.0.97 → rumdl-0.0.99}/rust-toolchain.toml +0 -0
  170. {rumdl-0.0.97 → rumdl-0.0.99}/scripts/extract-changelog.sh +0 -0
  171. {rumdl-0.0.97 → rumdl-0.0.99}/scripts/prepare-release.sh +0 -0
  172. {rumdl-0.0.97 → rumdl-0.0.99}/src/bin/benchmark.rs +0 -0
  173. {rumdl-0.0.97 → rumdl-0.0.99}/src/bin/file_parallel_benchmark.rs +0 -0
  174. {rumdl-0.0.97 → rumdl-0.0.99}/src/bin/measure_code_span_performance.rs +0 -0
  175. {rumdl-0.0.97 → rumdl-0.0.99}/src/init.rs +0 -0
  176. {rumdl-0.0.97 → rumdl-0.0.99}/src/inline_config.rs +0 -0
  177. {rumdl-0.0.97 → rumdl-0.0.99}/src/lsp/mod.rs +0 -0
  178. {rumdl-0.0.97 → rumdl-0.0.99}/src/lsp/types.rs +0 -0
  179. {rumdl-0.0.97 → rumdl-0.0.99}/src/markdownlint_config.rs +0 -0
  180. {rumdl-0.0.97 → rumdl-0.0.99}/src/output/formatters/azure.rs +0 -0
  181. {rumdl-0.0.97 → rumdl-0.0.99}/src/output/formatters/concise.rs +0 -0
  182. {rumdl-0.0.97 → rumdl-0.0.99}/src/output/formatters/github.rs +0 -0
  183. {rumdl-0.0.97 → rumdl-0.0.99}/src/output/formatters/gitlab.rs +0 -0
  184. {rumdl-0.0.97 → rumdl-0.0.99}/src/output/formatters/grouped.rs +0 -0
  185. {rumdl-0.0.97 → rumdl-0.0.99}/src/output/formatters/json.rs +0 -0
  186. {rumdl-0.0.97 → rumdl-0.0.99}/src/output/formatters/json_lines.rs +0 -0
  187. {rumdl-0.0.97 → rumdl-0.0.99}/src/output/formatters/junit.rs +0 -0
  188. {rumdl-0.0.97 → rumdl-0.0.99}/src/output/formatters/mod.rs +0 -0
  189. {rumdl-0.0.97 → rumdl-0.0.99}/src/output/formatters/pylint.rs +0 -0
  190. {rumdl-0.0.97 → rumdl-0.0.99}/src/output/formatters/sarif.rs +0 -0
  191. {rumdl-0.0.97 → rumdl-0.0.99}/src/output/formatters/text.rs +0 -0
  192. {rumdl-0.0.97 → rumdl-0.0.99}/src/output/mod.rs +0 -0
  193. {rumdl-0.0.97 → rumdl-0.0.99}/src/profiling.rs +0 -0
  194. {rumdl-0.0.97 → rumdl-0.0.99}/src/rule.rs +0 -0
  195. {rumdl-0.0.97 → rumdl-0.0.99}/src/rule_config.rs +0 -0
  196. {rumdl-0.0.97 → rumdl-0.0.99}/src/rule_config_serde.rs +0 -0
  197. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/blockquote_utils.rs +0 -0
  198. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/code_block_utils.rs +0 -0
  199. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/code_fence_utils.rs +0 -0
  200. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/emphasis_style.rs +0 -0
  201. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/front_matter_utils.rs +0 -0
  202. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/list_utils.rs +0 -0
  203. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md002_first_heading_h1/md002_config.rs +0 -0
  204. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md002_first_heading_h1.rs +0 -0
  205. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md003_heading_style/md003_config.rs +0 -0
  206. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md004_unordered_list_style/md004_config.rs +0 -0
  207. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md006_start_bullets.rs +0 -0
  208. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md007_ul_indent/md007_config.rs +0 -0
  209. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md009_trailing_spaces/md009_config.rs +0 -0
  210. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md010_no_hard_tabs/md010_config.rs +0 -0
  211. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md012_no_multiple_blanks/md012_config.rs +0 -0
  212. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md013_line_length/md013_config.rs +0 -0
  213. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md014_commands_show_output/md014_config.rs +0 -0
  214. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md014_commands_show_output.rs +0 -0
  215. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md019_no_multiple_space_atx.rs +0 -0
  216. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
  217. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md022_blanks_around_headings/md022_config.rs +0 -0
  218. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md022_blanks_around_headings.rs +0 -0
  219. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md023_heading_start_left.rs +0 -0
  220. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md024_no_duplicate_heading/md024_config.rs +0 -0
  221. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md025_single_title/md025_config.rs +0 -0
  222. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md026_no_trailing_punctuation/md026_config.rs +0 -0
  223. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md026_no_trailing_punctuation.rs +0 -0
  224. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md027_multiple_spaces_blockquote.rs +0 -0
  225. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md028_no_blanks_blockquote.rs +0 -0
  226. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md030_list_marker_space/md030_config.rs +0 -0
  227. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md032_blanks_around_lists.rs +0 -0
  228. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md033_no_inline_html/md033_config.rs +0 -0
  229. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md035_hr_style/md035_config.rs +0 -0
  230. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md036_no_emphasis_only_first/md036_config.rs +0 -0
  231. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md037_spaces_around_emphasis.rs +0 -0
  232. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md039_no_space_in_links.rs +0 -0
  233. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md040_fenced_code_language.rs +0 -0
  234. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md042_no_empty_links.rs +0 -0
  235. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md043_required_headings.rs +0 -0
  236. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md044_proper_names/md044_config.rs +0 -0
  237. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md045_no_alt_text.rs +0 -0
  238. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md046_code_block_style/md046_config.rs +0 -0
  239. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md046_code_block_style.rs +0 -0
  240. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md048_code_fence_style/md048_config.rs +0 -0
  241. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md048_code_fence_style.rs +0 -0
  242. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md049_emphasis_style/md049_config.rs +0 -0
  243. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md050_strong_style/md050_config.rs +0 -0
  244. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md054_link_image_style/md054_config.rs +0 -0
  245. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md054_link_image_style.rs +0 -0
  246. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md055_table_pipe_style/md055_config.rs +0 -0
  247. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md055_table_pipe_style.rs +0 -0
  248. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md056_table_column_count.rs +0 -0
  249. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md057_existing_relative_links/md057_config.rs +0 -0
  250. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/md058_blanks_around_tables.rs +0 -0
  251. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/mod.rs +0 -0
  252. {rumdl-0.0.97 → rumdl-0.0.99}/src/rules/strong_style.rs +0 -0
  253. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/ast_utils.rs +0 -0
  254. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/code_block_utils.rs +0 -0
  255. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/early_returns.rs +0 -0
  256. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/element_cache.rs +0 -0
  257. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/emphasis_utils.rs +0 -0
  258. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/fix_utils.rs +0 -0
  259. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/markdown_elements.rs +0 -0
  260. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/mod.rs +0 -0
  261. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/range_utils.rs +0 -0
  262. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/regex_cache.rs +0 -0
  263. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/string_interner.rs +0 -0
  264. {rumdl-0.0.97 → rumdl-0.0.99}/src/utils/table_utils.rs +0 -0
  265. {rumdl-0.0.97 → rumdl-0.0.99}/src/vscode.rs +0 -0
  266. {rumdl-0.0.97 → rumdl-0.0.99}/tests/character_ranges/additional_tests.rs +0 -0
  267. {rumdl-0.0.97 → rumdl-0.0.99}/tests/character_ranges/basic_tests.rs +0 -0
  268. {rumdl-0.0.97 → rumdl-0.0.99}/tests/character_ranges/comprehensive_tests.rs +0 -0
  269. {rumdl-0.0.97 → rumdl-0.0.99}/tests/character_ranges/extended_tests.rs +0 -0
  270. {rumdl-0.0.97 → rumdl-0.0.99}/tests/character_ranges/mod.rs +0 -0
  271. {rumdl-0.0.97 → rumdl-0.0.99}/tests/character_ranges/unicode_utils.rs +0 -0
  272. {rumdl-0.0.97 → rumdl-0.0.99}/tests/cli_duplication_test.rs +0 -0
  273. {rumdl-0.0.97 → rumdl-0.0.99}/tests/cli_statistics_test.rs +0 -0
  274. {rumdl-0.0.97 → rumdl-0.0.99}/tests/comprehensive_output_format_tests.rs +0 -0
  275. {rumdl-0.0.97 → rumdl-0.0.99}/tests/config_application_tests.rs +0 -0
  276. {rumdl-0.0.97 → rumdl-0.0.99}/tests/config_file_command_test.rs +0 -0
  277. {rumdl-0.0.97 → rumdl-0.0.99}/tests/configuration_inheritance_tests.rs +0 -0
  278. {rumdl-0.0.97 → rumdl-0.0.99}/tests/consistency_regression_tests.rs +0 -0
  279. {rumdl-0.0.97 → rumdl-0.0.99}/tests/cross_platform_compatibility_tests.rs +0 -0
  280. {rumdl-0.0.97 → rumdl-0.0.99}/tests/init_command_test.rs +0 -0
  281. {rumdl-0.0.97 → rumdl-0.0.99}/tests/init_tests.rs +0 -0
  282. {rumdl-0.0.97 → rumdl-0.0.99}/tests/inline_config_test.rs +0 -0
  283. {rumdl-0.0.97 → rumdl-0.0.99}/tests/integration_tests.rs +0 -0
  284. {rumdl-0.0.97 → rumdl-0.0.99}/tests/json_output_test.rs +0 -0
  285. {rumdl-0.0.97 → rumdl-0.0.99}/tests/lib.rs +0 -0
  286. {rumdl-0.0.97 → rumdl-0.0.99}/tests/lsp_editor_integration_tests.rs +0 -0
  287. {rumdl-0.0.97 → rumdl-0.0.99}/tests/lsp_tests.rs +0 -0
  288. {rumdl-0.0.97 → rumdl-0.0.99}/tests/malformed_markdown_stress_tests.rs +0 -0
  289. {rumdl-0.0.97 → rumdl-0.0.99}/tests/markdownlint_cli_integration.rs +0 -0
  290. {rumdl-0.0.97 → rumdl-0.0.99}/tests/markdownlint_config_test.rs +0 -0
  291. {rumdl-0.0.97 → rumdl-0.0.99}/tests/markdownlintignore_test.rs +0 -0
  292. {rumdl-0.0.97 → rumdl-0.0.99}/tests/output_format_integration_tests.rs +0 -0
  293. {rumdl-0.0.97 → rumdl-0.0.99}/tests/output_format_tests.rs +0 -0
  294. {rumdl-0.0.97 → rumdl-0.0.99}/tests/perf_check.rs +0 -0
  295. {rumdl-0.0.97 → rumdl-0.0.99}/tests/performance_validation_tests.rs +0 -0
  296. {rumdl-0.0.97 → rumdl-0.0.99}/tests/pyproject_config_tests.rs +0 -0
  297. {rumdl-0.0.97 → rumdl-0.0.99}/tests/real_world_repository_tests.rs +0 -0
  298. {rumdl-0.0.97 → rumdl-0.0.99}/tests/regression_prevention_tests.rs +0 -0
  299. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md001_test.rs +0 -0
  300. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md001_unicode_test.rs +0 -0
  301. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md002_test.rs +0 -0
  302. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md003_test.rs +0 -0
  303. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md004_test.rs +0 -0
  304. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md005_test.rs +0 -0
  305. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md006_test.rs +0 -0
  306. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md006_unicode_test.rs +0 -0
  307. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md007_test.rs +0 -0
  308. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md009_test.rs +0 -0
  309. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md010_test.rs +0 -0
  310. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md011_test.rs +0 -0
  311. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md012_test.rs +0 -0
  312. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md014_test.rs +0 -0
  313. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md019_test.rs +0 -0
  314. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md020_test.rs +0 -0
  315. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md021_test.rs +0 -0
  316. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md022_test.rs +0 -0
  317. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md023_extended_test.rs +0 -0
  318. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md023_test.rs +0 -0
  319. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md024_test.rs +0 -0
  320. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md025_test.rs +0 -0
  321. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md026_test.rs +0 -0
  322. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md027_test.rs +0 -0
  323. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md028_test.rs +0 -0
  324. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md030_test.rs +0 -0
  325. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md031_test.rs +0 -0
  326. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md033_extended_test.rs +0 -0
  327. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md033_test.rs +0 -0
  328. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md035_test.rs +0 -0
  329. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md037_test.rs +0 -0
  330. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md038_test.rs +0 -0
  331. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md039_test.rs +0 -0
  332. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md040_test.rs +0 -0
  333. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md042_test.rs +0 -0
  334. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md043_test.rs +0 -0
  335. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md045_test.rs +0 -0
  336. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md046_test.rs +0 -0
  337. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md047_test.rs +0 -0
  338. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md048_test.rs +0 -0
  339. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md049_test.rs +0 -0
  340. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md050_test.rs +0 -0
  341. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md051_test.rs +0 -0
  342. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md052_test.rs +0 -0
  343. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md053_additional_test.rs +0 -0
  344. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md053_proptest.rs +0 -0
  345. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md053_test.rs +0 -0
  346. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md054_test.rs +0 -0
  347. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md054_unicode_test.rs +0 -0
  348. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md055_test.rs +0 -0
  349. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md056_test.rs +0 -0
  350. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md057_test.rs +0 -0
  351. {rumdl-0.0.97 → rumdl-0.0.99}/tests/rules/md058_test.rs +0 -0
  352. {rumdl-0.0.97 → rumdl-0.0.99}/tests/thread_safety_tests.rs +0 -0
  353. {rumdl-0.0.97 → rumdl-0.0.99}/tests/unicode_edge_case_tests.rs +0 -0
  354. {rumdl-0.0.97 → rumdl-0.0.99}/tests/utils/blockquote_utils_test.rs +0 -0
  355. {rumdl-0.0.97 → rumdl-0.0.99}/tests/utils/code_block_utils_extended_test.rs +0 -0
  356. {rumdl-0.0.97 → rumdl-0.0.99}/tests/utils/code_block_utils_test.rs +0 -0
  357. {rumdl-0.0.97 → rumdl-0.0.99}/tests/utils/front_matter_utils_test.rs +0 -0
  358. {rumdl-0.0.97 → rumdl-0.0.99}/tests/utils/line_index_test.rs +0 -0
  359. {rumdl-0.0.97 → rumdl-0.0.99}/tests/utils/mod.rs +0 -0
  360. {rumdl-0.0.97 → rumdl-0.0.99}/tests/utils_markdown_edge_cases.rs +0 -0
  361. {rumdl-0.0.97 → rumdl-0.0.99}/tests/utils_tests.rs +0 -0
  362. {rumdl-0.0.97 → rumdl-0.0.99}/tests/vscode_extension_fixes.rs +0 -0
  363. {rumdl-0.0.97 → rumdl-0.0.99}/tests/vscode_test.rs +0 -0
@@ -0,0 +1,59 @@
1
+ # Pre-commit hooks for rumdl
2
+ # Install with: pre-commit install
3
+ # Run manually: pre-commit run --all-files
4
+
5
+ repos:
6
+ # Rust formatting and linting
7
+ - repo: local
8
+ hooks:
9
+ - id: cargo-fmt
10
+ name: cargo fmt
11
+ entry: cargo fmt --all --
12
+ language: system
13
+ types: [rust]
14
+ pass_filenames: false
15
+
16
+ - id: cargo-clippy
17
+ name: cargo clippy
18
+ entry: make lint
19
+ language: system
20
+ types: [rust]
21
+ pass_filenames: false
22
+
23
+ - id: cargo-test-quick
24
+ name: cargo test (quick)
25
+ entry: make test-quick
26
+ language: system
27
+ types: [rust]
28
+ pass_filenames: false
29
+ stages: [pre-commit]
30
+
31
+ - id: cargo-check
32
+ name: cargo check
33
+ entry: cargo check --all-targets --all-features
34
+ language: system
35
+ types: [rust]
36
+ pass_filenames: false
37
+
38
+ # General file quality checks
39
+ - repo: https://github.com/pre-commit/pre-commit-hooks
40
+ rev: v4.6.0
41
+ hooks:
42
+ - id: trailing-whitespace
43
+ exclude: \.md$
44
+ - id: end-of-file-fixer
45
+ exclude: \.md$
46
+ - id: check-yaml
47
+ - id: check-toml
48
+ - id: check-json
49
+ - id: check-merge-conflict
50
+ - id: check-case-conflict
51
+ - id: mixed-line-ending
52
+ args: [--fix=lf]
53
+
54
+ # Markdown linting using rumdl itself
55
+ - repo: https://github.com/rvben/rumdl-pre-commit
56
+ rev: v0.0.45
57
+ hooks:
58
+ - id: rumdl
59
+ exclude: ^(test_tmp|benchmark/test-data|docs/temp|CHANGELOG\.md)
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.0.99] - 2025-07-22
11
+
12
+ ### Fixed
13
+ - MD034: Added support for `ftps://` URLs
14
+ - MD034: Fixed detection of URLs in HTML comments (now properly ignored)
15
+ - MD039: Fixed escaped character handling in link text
16
+ - MD044: Fixed clippy warnings and improved pattern matching for proper names
17
+ - MD052: Enhanced nested bracket handling in reference links and images
18
+ - Fixed flaky performance tests by increasing timeout threshold for CI environments
19
+ - Improved test stability for Unicode list indentation tests
20
+
21
+ ## [0.0.98] - 2025-07-18
22
+
23
+ ### Added
24
+ - Homebrew tap support for easy installation on macOS and Linux
25
+ - Created `homebrew-rumdl` tap repository
26
+ - Added automatic archive creation for macOS builds in release workflow
27
+ - Included SHA256 checksum generation for each platform
28
+ - Set up automated formula updates on new releases
29
+ - Homebrew installation instructions in README
30
+
31
+ ### Changed
32
+ - Enhanced release workflow to create platform-specific tar.gz archives
33
+ - Added repository dispatch to notify homebrew-rumdl on new releases
34
+
10
35
  ## [0.0.97] - 2025-07-17
11
36
 
12
37
  ### Changed
@@ -198,7 +223,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
198
223
 
199
224
  - Initial implementation of remaining rules for markdownlint parity
200
225
 
201
- [Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.97...HEAD
226
+ [Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.99...HEAD
227
+ [0.0.99]: https://github.com/rvben/rumdl/compare/v0.0.98...v0.0.99
228
+ [0.0.98]: https://github.com/rvben/rumdl/compare/v0.0.97...v0.0.98
202
229
  [0.0.97]: https://github.com/rvben/rumdl/compare/v0.0.96...v0.0.97
203
230
  [0.0.96]: https://github.com/rvben/rumdl/compare/v0.0.95...v0.0.96
204
231
  [0.0.95]: https://github.com/rvben/rumdl/compare/v0.0.94...v0.0.95
@@ -220,9 +220,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
220
220
 
221
221
  [[package]]
222
222
  name = "cc"
223
- version = "1.2.29"
223
+ version = "1.2.30"
224
224
  source = "registry+https://github.com/rust-lang/crates.io-index"
225
- checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362"
225
+ checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7"
226
226
  dependencies = [
227
227
  "shlex",
228
228
  ]
@@ -1493,7 +1493,7 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
1493
1493
 
1494
1494
  [[package]]
1495
1495
  name = "rumdl"
1496
- version = "0.0.97"
1496
+ version = "0.0.99"
1497
1497
  dependencies = [
1498
1498
  "anyhow",
1499
1499
  "assert_cmd",
@@ -1629,9 +1629,9 @@ dependencies = [
1629
1629
 
1630
1630
  [[package]]
1631
1631
  name = "serde_json"
1632
- version = "1.0.140"
1632
+ version = "1.0.141"
1633
1633
  source = "registry+https://github.com/rust-lang/crates.io-index"
1634
- checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
1634
+ checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
1635
1635
  dependencies = [
1636
1636
  "itoa",
1637
1637
  "memchr",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rumdl"
3
- version = "0.0.97"
3
+ version = "0.0.99"
4
4
  edition = "2024"
5
5
  rust-version = "1.88.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.97
3
+ Version: 0.0.99
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -87,6 +87,7 @@ It offers:
87
87
  - [Quick Start](#quick-start)
88
88
  - [Overview](#overview)
89
89
  - [Installation](#installation)
90
+ - [Using Homebrew (macOS/Linux)](#using-homebrew-macoslinux)
90
91
  - [Using Cargo (Rust)](#using-cargo-rust)
91
92
  - [Using pip (Python)](#using-pip-python)
92
93
  - [Using uv](#using-uv)
@@ -118,6 +119,13 @@ It offers:
118
119
 
119
120
  Choose the installation method that works best for you:
120
121
 
122
+ ### Using Homebrew (macOS/Linux)
123
+
124
+ ```bash
125
+ brew tap rvben/rumdl
126
+ brew install rumdl
127
+ ```
128
+
121
129
  ### Using Cargo (Rust)
122
130
 
123
131
  ```bash
@@ -56,6 +56,7 @@ It offers:
56
56
  - [Quick Start](#quick-start)
57
57
  - [Overview](#overview)
58
58
  - [Installation](#installation)
59
+ - [Using Homebrew (macOS/Linux)](#using-homebrew-macoslinux)
59
60
  - [Using Cargo (Rust)](#using-cargo-rust)
60
61
  - [Using pip (Python)](#using-pip-python)
61
62
  - [Using uv](#using-uv)
@@ -87,6 +88,13 @@ It offers:
87
88
 
88
89
  Choose the installation method that works best for you:
89
90
 
91
+ ### Using Homebrew (macOS/Linux)
92
+
93
+ ```bash
94
+ brew tap rvben/rumdl
95
+ brew install rumdl
96
+ ```
97
+
90
98
  ### Using Cargo (Rust)
91
99
 
92
100
  ```bash
@@ -0,0 +1,49 @@
1
+ #!/bin/bash
2
+
3
+ # Setup pre-commit hooks for rumdl development
4
+ # This script installs pre-commit and sets up the hooks
5
+
6
+ set -e
7
+
8
+ echo "Setting up pre-commit hooks for rumdl..."
9
+
10
+ # Check if pre-commit is installed
11
+ if ! command -v pre-commit &> /dev/null; then
12
+ echo "Installing pre-commit..."
13
+ if command -v uv &> /dev/null; then
14
+ uv tool install pre-commit
15
+ elif command -v pip &> /dev/null; then
16
+ pip install pre-commit
17
+ else
18
+ echo "Error: Neither uv nor pip found. Please install one of them first."
19
+ exit 1
20
+ fi
21
+ else
22
+ echo "pre-commit is already installed"
23
+ fi
24
+
25
+ # Install the hooks
26
+ echo "Installing pre-commit hooks..."
27
+ pre-commit install
28
+
29
+ # Run hooks on all files to ensure everything is set up correctly
30
+ echo "Running pre-commit hooks on all files..."
31
+ pre-commit run --all-files || {
32
+ echo "Some hooks failed, but that's normal for first run."
33
+ echo "The hooks will automatically fix formatting issues."
34
+ echo "You may need to stage and commit the changes."
35
+ }
36
+
37
+ echo ""
38
+ echo "✅ Pre-commit hooks are now set up!"
39
+ echo ""
40
+ echo "The following hooks will run on every commit:"
41
+ echo " - cargo fmt (automatic formatting)"
42
+ echo " - make lint (clippy linting)"
43
+ echo " - make test-quick (fast tests)"
44
+ echo " - cargo check (compilation check)"
45
+ echo " - File quality checks (trailing whitespace, etc.)"
46
+ echo " - rumdl markdown linting"
47
+ echo ""
48
+ echo "To manually run all hooks: pre-commit run --all-files"
49
+ echo "To skip hooks for emergency commits: git commit --no-verify"
@@ -7,7 +7,7 @@ use std::time::Instant;
7
7
 
8
8
  fn benchmark_rule(rule: &dyn Rule, test_cases: &[(&str, &str)], iterations: u32) -> Vec<(String, u64, u64)> {
9
9
  let mut results = Vec::new();
10
-
10
+
11
11
  for (name, content) in test_cases {
12
12
  // Warm up
13
13
  for _ in 0..10 {
@@ -15,7 +15,7 @@ fn benchmark_rule(rule: &dyn Rule, test_cases: &[(&str, &str)], iterations: u32)
15
15
  let _ = rule.check(&ctx);
16
16
  let _ = rule.fix(&ctx);
17
17
  }
18
-
18
+
19
19
  // Benchmark check
20
20
  let start = Instant::now();
21
21
  for _ in 0..iterations {
@@ -23,7 +23,7 @@ fn benchmark_rule(rule: &dyn Rule, test_cases: &[(&str, &str)], iterations: u32)
23
23
  let _ = rule.check(&ctx);
24
24
  }
25
25
  let check_time = start.elapsed().as_micros() as u64 / iterations as u64;
26
-
26
+
27
27
  // Benchmark fix
28
28
  let start = Instant::now();
29
29
  for _ in 0..iterations {
@@ -31,10 +31,10 @@ fn benchmark_rule(rule: &dyn Rule, test_cases: &[(&str, &str)], iterations: u32)
31
31
  let _ = rule.fix(&ctx);
32
32
  }
33
33
  let fix_time = start.elapsed().as_micros() as u64 / iterations as u64;
34
-
34
+
35
35
  results.push((name.to_string(), check_time, fix_time));
36
36
  }
37
-
37
+
38
38
  results
39
39
  }
40
40
 
@@ -83,7 +83,7 @@ fn generate_test_content(rule_name: &str) -> Vec<(&'static str, String)> {
83
83
  ("Many URLs", {
84
84
  let mut content = String::new();
85
85
  for i in 0..200 {
86
- content.push_str(&format!("URL {}: http://example{}.com/path/{}/file?id={}\n", i, i, i, i));
86
+ content.push_str(&format!("URL {i}: http://example{i}.com/path/{i}/file?id={i}\n"));
87
87
  }
88
88
  content
89
89
  }),
@@ -96,11 +96,11 @@ fn generate_test_content(rule_name: &str) -> Vec<(&'static str, String)> {
96
96
  ("Many references", {
97
97
  let mut content = String::new();
98
98
  for i in 0..100 {
99
- content.push_str(&format!("[link{}][ref{}]\n", i, i));
99
+ content.push_str(&format!("[link{i}][ref{i}]\n"));
100
100
  }
101
- content.push_str("\n");
101
+ content.push('\n');
102
102
  for i in 0..200 {
103
- content.push_str(&format!("[ref{}]: http://example{}.com\n", i, i));
103
+ content.push_str(&format!("[ref{i}]: http://example{i}.com\n"));
104
104
  }
105
105
  content
106
106
  }),
@@ -117,40 +117,39 @@ fn main() {
117
117
  eprintln!("Usage: {} <rule_name>", args[0]);
118
118
  std::process::exit(1);
119
119
  }
120
-
120
+
121
121
  let rule_name = &args[1];
122
122
  let config = Config::default();
123
123
  let rules = all_rules(&config);
124
-
125
- let rule = rules.into_iter()
126
- .find(|r| r.name() == rule_name)
127
- .unwrap_or_else(|| {
128
- eprintln!("Rule {} not found", rule_name);
129
- std::process::exit(1);
130
- });
131
-
124
+
125
+ let rule = rules.into_iter().find(|r| r.name() == rule_name).unwrap_or_else(|| {
126
+ eprintln!("Rule {rule_name} not found");
127
+ std::process::exit(1);
128
+ });
129
+
132
130
  let test_cases_vec = generate_test_content(rule_name);
133
- let test_cases: Vec<(&str, &str)> = test_cases_vec.iter()
131
+ let test_cases: Vec<(&str, &str)> = test_cases_vec
132
+ .iter()
134
133
  .map(|(name, content)| (*name, content.as_str()))
135
134
  .collect();
136
-
137
- println!("Benchmarking {} Rule", rule_name);
135
+
136
+ println!("Benchmarking {rule_name} Rule");
138
137
  println!("{}", "=".repeat(50));
139
138
  println!();
140
-
139
+
141
140
  let results = benchmark_rule(rule.as_ref(), &test_cases, 100);
142
-
141
+
143
142
  let mut total_check = 0u64;
144
143
  let mut total_fix = 0u64;
145
-
144
+
146
145
  for (test_name, check_time, fix_time) in &results {
147
- println!("{:<30} Check: {:>6} μs Fix: {:>6} μs", test_name, check_time, fix_time);
146
+ println!("{test_name:<30} Check: {check_time:>6} μs Fix: {fix_time:>6} μs");
148
147
  total_check += check_time;
149
148
  total_fix += fix_time;
150
149
  }
151
-
150
+
152
151
  println!();
153
152
  println!("Average times:");
154
153
  println!(" Check: {} μs", total_check / results.len() as u64);
155
154
  println!(" Fix: {} μs", total_fix / results.len() as u64);
156
- }
155
+ }
@@ -1035,12 +1035,7 @@ impl SourcedConfig {
1035
1035
  .overrides
1036
1036
  .first()
1037
1037
  .and_then(|o| o.file.clone()),
1038
- fragment
1039
- .global
1040
- .respect_gitignore
1041
- .overrides
1042
- .first()
1043
- .and_then(|o| o.line),
1038
+ fragment.global.respect_gitignore.overrides.first().and_then(|o| o.line),
1044
1039
  );
1045
1040
 
1046
1041
  // Merge output_format if present
@@ -1441,8 +1436,8 @@ fn toml_value_type_matches(expected: &toml::Value, actual: &toml::Value) -> bool
1441
1436
 
1442
1437
  /// Parses pyproject.toml content and extracts the [tool.rumdl] section if present.
1443
1438
  fn parse_pyproject_toml(content: &str, path: &str) -> Result<Option<SourcedConfigFragment>, ConfigError> {
1444
- let doc: toml::Value = toml::from_str(content)
1445
- .map_err(|e| ConfigError::ParseError(format!("{path}: Failed to parse TOML: {e}")))?;
1439
+ let doc: toml::Value =
1440
+ toml::from_str(content).map_err(|e| ConfigError::ParseError(format!("{path}: Failed to parse TOML: {e}")))?;
1446
1441
  let mut fragment = SourcedConfigFragment::default();
1447
1442
  let source = ConfigSource::PyprojectToml;
1448
1443
  let file = Some(path.to_string());
@@ -1867,9 +1862,7 @@ fn parse_rumdl_toml(content: &str, path: &str) -> Result<SourcedConfigFragment,
1867
1862
  }
1868
1863
  }
1869
1864
  } else if item.is_value() {
1870
- log::warn!(
1871
- "[WARN] Ignoring top-level value key in {path}: '{key}'. Expected a table like [{key}]."
1872
- );
1865
+ log::warn!("[WARN] Ignoring top-level value key in {path}: '{key}'. Expected a table like [{key}].");
1873
1866
  }
1874
1867
  }
1875
1868
 
@@ -0,0 +1,32 @@
1
+ /// Exit codes for rumdl, following Ruff's convention
2
+ ///
3
+ /// These exit codes allow users and CI/CD systems to distinguish between
4
+ /// different types of failures.
5
+ /// Success - No issues found or all issues were fixed
6
+ pub const SUCCESS: i32 = 0;
7
+
8
+ /// Linting issues found - One or more Markdown violations detected
9
+ pub const VIOLATIONS_FOUND: i32 = 1;
10
+
11
+ /// Tool error - Configuration error, file access error, or internal error
12
+ pub const TOOL_ERROR: i32 = 2;
13
+
14
+ /// Helper functions for consistent exit behavior
15
+ pub mod exit {
16
+ use super::{SUCCESS, TOOL_ERROR, VIOLATIONS_FOUND};
17
+
18
+ /// Exit with success code (0)
19
+ pub fn success() -> ! {
20
+ std::process::exit(SUCCESS);
21
+ }
22
+
23
+ /// Exit with violations found code (1)
24
+ pub fn violations_found() -> ! {
25
+ std::process::exit(VIOLATIONS_FOUND);
26
+ }
27
+
28
+ /// Exit with tool error code (2)
29
+ pub fn tool_error() -> ! {
30
+ std::process::exit(TOOL_ERROR);
31
+ }
32
+ }
@@ -217,9 +217,7 @@ pub fn lint(content: &str, rules: &[Box<dyn Rule>], _verbose: bool) -> LintResul
217
217
  if _verbose {
218
218
  let skipped_rules = _total_rules - _applicable_count;
219
219
  if skipped_rules > 0 {
220
- log::debug!(
221
- "Skipped {skipped_rules} of {_total_rules} rules based on content analysis"
222
- );
220
+ log::debug!("Skipped {skipped_rules} of {_total_rules} rules based on content analysis");
223
221
  }
224
222
  if ast.is_some() {
225
223
  log::debug!("Used shared AST for {ast_rules_count} rules");
@@ -7,7 +7,7 @@ lazy_static! {
7
7
  // Use (?s) flag to make . match newlines
8
8
  static ref LINK_PATTERN: Regex = Regex::new(
9
9
  r"(?sx)
10
- \[([^\]]*)\] # Link text in group 1
10
+ \[((?:[^\[\]\\]|\\.|\[[^\]]*\])*)\] # Link text in group 1 (handles nested brackets)
11
11
  (?:
12
12
  \(([^)]*)\) # Inline URL in group 2 (can be empty)
13
13
  |
@@ -19,7 +19,7 @@ lazy_static! {
19
19
  // Use (?s) flag to make . match newlines
20
20
  static ref IMAGE_PATTERN: Regex = Regex::new(
21
21
  r"(?sx)
22
- !\[([^\]]*)\] # Alt text in group 1
22
+ !\[((?:[^\[\]\\]|\\.|\[[^\]]*\])*)\] # Alt text in group 1 (handles nested brackets)
23
23
  (?:
24
24
  \(([^)]*)\) # Inline URL in group 2 (can be empty)
25
25
  |
@@ -295,13 +295,13 @@ impl<'a> LintContext<'a> {
295
295
  /// Get code spans - computed lazily on first access
296
296
  pub fn code_spans(&self) -> Arc<Vec<CodeSpan>> {
297
297
  let mut cache = self.code_spans_cache.lock().unwrap();
298
-
298
+
299
299
  // Check if we need to compute code spans
300
300
  if cache.is_none() {
301
301
  let code_spans = Self::parse_code_spans(self.content, &self.lines);
302
302
  *cache = Some(Arc::new(code_spans));
303
303
  }
304
-
304
+
305
305
  // Return a reference to the cached code spans
306
306
  cache.as_ref().unwrap().clone()
307
307
  }
@@ -388,6 +388,11 @@ impl<'a> LintContext<'a> {
388
388
  let match_start = full_match.start();
389
389
  let match_end = full_match.end();
390
390
 
391
+ // Skip if the opening bracket is escaped (preceded by \)
392
+ if match_start > 0 && content.as_bytes().get(match_start - 1) == Some(&b'\\') {
393
+ continue;
394
+ }
395
+
391
396
  // Skip if this is actually an image (preceded by !)
392
397
  if match_start > 0 && content.as_bytes().get(match_start - 1) == Some(&b'!') {
393
398
  continue;
@@ -482,6 +487,11 @@ impl<'a> LintContext<'a> {
482
487
  let match_start = full_match.start();
483
488
  let match_end = full_match.end();
484
489
 
490
+ // Skip if the ! is escaped (preceded by \)
491
+ if match_start > 0 && content.as_bytes().get(match_start - 1) == Some(&b'\\') {
492
+ continue;
493
+ }
494
+
485
495
  // Skip if in code block or span
486
496
  if CodeBlockUtils::is_in_code_block_or_span(code_blocks, match_start) {
487
497
  continue;
@@ -1155,7 +1165,33 @@ impl<'a> LintContext<'a> {
1155
1165
  && item.is_ordered == block.is_ordered
1156
1166
  && block.blockquote_prefix.trim() == next_blockquote_prefix.trim()
1157
1167
  {
1158
- found_continuation = true;
1168
+ // Check if there was meaningful content between the list items
1169
+ let has_meaningful_content = (line_idx + 1..check_idx).any(|idx| {
1170
+ if let Some(between_line) = lines.get(idx) {
1171
+ let trimmed = between_line.content.trim();
1172
+ // Skip empty lines
1173
+ if trimmed.is_empty() {
1174
+ return false;
1175
+ }
1176
+ // Check for meaningful content
1177
+ let line_indent =
1178
+ between_line.content.len() - between_line.content.trim_start().len();
1179
+ // Code fences or properly indented content
1180
+ trimmed.starts_with("```")
1181
+ || trimmed.starts_with("~~~")
1182
+ || line_indent >= current_indent_level + 2
1183
+ } else {
1184
+ false
1185
+ }
1186
+ });
1187
+
1188
+ if block.is_ordered {
1189
+ // For ordered lists: only continue if there's meaningful content
1190
+ found_continuation = has_meaningful_content;
1191
+ } else {
1192
+ // For unordered lists: continue regardless
1193
+ found_continuation = true;
1194
+ }
1159
1195
  }
1160
1196
  }
1161
1197
  }
@@ -1215,14 +1251,14 @@ impl<'a> LintContext<'a> {
1215
1251
  }
1216
1252
 
1217
1253
  // Merge adjacent blocks that should be one
1218
- merge_adjacent_list_blocks(&mut list_blocks);
1254
+ merge_adjacent_list_blocks(&mut list_blocks, lines);
1219
1255
 
1220
1256
  list_blocks
1221
1257
  }
1222
1258
  }
1223
1259
 
1224
1260
  /// Merge adjacent list blocks that should be treated as one
1225
- fn merge_adjacent_list_blocks(list_blocks: &mut Vec<ListBlock>) {
1261
+ fn merge_adjacent_list_blocks(list_blocks: &mut Vec<ListBlock>, lines: &[LineInfo]) {
1226
1262
  if list_blocks.len() < 2 {
1227
1263
  return;
1228
1264
  }
@@ -1237,10 +1273,20 @@ fn merge_adjacent_list_blocks(list_blocks: &mut Vec<ListBlock>) {
1237
1273
  let consecutive = next.start_line == current.end_line + 1;
1238
1274
  let only_blank_between = next.start_line == current.end_line + 2;
1239
1275
 
1276
+ // For ordered lists, we need to be more careful about merging
1277
+ let should_merge_condition = if current.is_ordered && next.is_ordered {
1278
+ // Only merge ordered lists if there's meaningful content between them
1279
+ // (like code blocks, continuation paragraphs) not just blank lines
1280
+ consecutive || has_meaningful_content_between(&current, next, lines)
1281
+ } else {
1282
+ // For unordered lists, use original logic
1283
+ consecutive || (only_blank_between && current.marker == next.marker)
1284
+ };
1285
+
1240
1286
  let should_merge = next.is_ordered == current.is_ordered
1241
1287
  && next.blockquote_prefix == current.blockquote_prefix
1242
1288
  && next.nesting_level == current.nesting_level
1243
- && (consecutive || (only_blank_between && current.marker == next.marker));
1289
+ && should_merge_condition;
1244
1290
 
1245
1291
  if should_merge {
1246
1292
  // Merge blocks
@@ -1265,6 +1311,42 @@ fn merge_adjacent_list_blocks(list_blocks: &mut Vec<ListBlock>) {
1265
1311
  *list_blocks = merged;
1266
1312
  }
1267
1313
 
1314
+ /// Check if there's meaningful content (not just blank lines) between two list blocks
1315
+ fn has_meaningful_content_between(current: &ListBlock, next: &ListBlock, lines: &[LineInfo]) -> bool {
1316
+ // Check lines between current.end_line and next.start_line
1317
+ for line_num in (current.end_line + 1)..next.start_line {
1318
+ if let Some(line_info) = lines.get(line_num - 1) {
1319
+ // Convert to 0-indexed
1320
+ let trimmed = line_info.content.trim();
1321
+
1322
+ // Skip empty lines
1323
+ if trimmed.is_empty() {
1324
+ continue;
1325
+ }
1326
+
1327
+ // Check if this line has proper indentation for list continuation
1328
+ let line_indent = line_info.content.len() - line_info.content.trim_start().len();
1329
+
1330
+ // If the line is indented enough to be list continuation content, it's meaningful
1331
+ // List content should be indented at least 2 spaces beyond the marker
1332
+ if line_indent >= current.nesting_level + 2 {
1333
+ return true;
1334
+ }
1335
+
1336
+ // Code fences are meaningful content
1337
+ if trimmed.starts_with("```") || trimmed.starts_with("~~~") {
1338
+ return true;
1339
+ }
1340
+
1341
+ // Any other non-blank content at this level breaks the sequence
1342
+ return false;
1343
+ }
1344
+ }
1345
+
1346
+ // Only blank lines between blocks - should not merge
1347
+ false
1348
+ }
1349
+
1268
1350
  /// Check if content contains patterns that cause the markdown crate to panic
1269
1351
  #[cfg(test)]
1270
1352
  mod tests {