rumdl 0.0.54__tar.gz → 0.0.56__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 (263) hide show
  1. {rumdl-0.0.54 → rumdl-0.0.56}/Cargo.lock +1 -1
  2. {rumdl-0.0.54 → rumdl-0.0.56}/Cargo.toml +1 -1
  3. {rumdl-0.0.54 → rumdl-0.0.56}/Makefile +3 -2
  4. {rumdl-0.0.54 → rumdl-0.0.56}/PKG-INFO +1 -1
  5. {rumdl-0.0.54 → rumdl-0.0.56}/benches/rule_performance.rs +14 -24
  6. {rumdl-0.0.54 → rumdl-0.0.56}/docs/RULES.md +1 -2
  7. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md030.md +4 -2
  8. rumdl-0.0.56/parity_check.py +130 -0
  9. {rumdl-0.0.54 → rumdl-0.0.56}/src/config.rs +26 -11
  10. {rumdl-0.0.54 → rumdl-0.0.56}/src/main.rs +78 -16
  11. {rumdl-0.0.54 → rumdl-0.0.56}/src/rule.rs +4 -3
  12. rumdl-0.0.56/src/rules/md004_unordered_list_style.rs +456 -0
  13. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md007_ul_indent.rs +91 -66
  14. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md013_line_length.rs +58 -43
  15. rumdl-0.0.56/src/rules/md030_list_marker_space.rs +226 -0
  16. rumdl-0.0.56/src/rules/md032_blanks_around_lists.rs +575 -0
  17. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md033_no_inline_html.rs +57 -130
  18. rumdl-0.0.56/src/rules/md034_no_bare_urls.rs +496 -0
  19. rumdl-0.0.56/src/rules/md039_no_space_in_links.rs +466 -0
  20. rumdl-0.0.56/src/rules/md049_emphasis_style.rs +303 -0
  21. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/mod.rs +1 -12
  22. {rumdl-0.0.54 → rumdl-0.0.56}/src/utils/document_structure.rs +55 -0
  23. {rumdl-0.0.54 → rumdl-0.0.56}/src/utils/element_cache.rs +2 -1
  24. {rumdl-0.0.54 → rumdl-0.0.56}/tests/advanced_integration_tests.rs +19 -10
  25. {rumdl-0.0.54 → rumdl-0.0.56}/tests/config_application_tests.rs +2 -1
  26. rumdl-0.0.56/tests/integration_tests.rs +18 -0
  27. rumdl-0.0.56/tests/json_output_test.rs +34 -0
  28. {rumdl-0.0.54 → rumdl-0.0.56}/tests/perf_check.rs +5 -1
  29. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md004_test.rs +164 -122
  30. rumdl-0.0.56/tests/rules/md007_test.rs +292 -0
  31. rumdl-0.0.56/tests/rules/md013_test.rs +262 -0
  32. rumdl-0.0.56/tests/rules/md030_test.rs +194 -0
  33. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md032_test.rs +34 -1
  34. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md033_test.rs +23 -31
  35. rumdl-0.0.56/tests/rules/md034_test.rs +336 -0
  36. rumdl-0.0.56/tests/rules/md039_test.rs +296 -0
  37. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/mod.rs +0 -1
  38. rumdl-0.0.54/docs/md015.md +0 -93
  39. rumdl-0.0.54/src/rules/md004_unordered_list_style.rs +0 -361
  40. rumdl-0.0.54/src/rules/md015_no_missing_space_after_list_marker.rs +0 -157
  41. rumdl-0.0.54/src/rules/md030_list_marker_space.rs +0 -528
  42. rumdl-0.0.54/src/rules/md032_blanks_around_lists.rs +0 -418
  43. rumdl-0.0.54/src/rules/md034_no_bare_urls.rs +0 -328
  44. rumdl-0.0.54/src/rules/md039_no_space_in_links.rs +0 -365
  45. rumdl-0.0.54/src/rules/md049_emphasis_style.rs +0 -375
  46. rumdl-0.0.54/tests/integration_tests.rs +0 -40
  47. rumdl-0.0.54/tests/rules/md007_test.rs +0 -127
  48. rumdl-0.0.54/tests/rules/md013_test.rs +0 -128
  49. rumdl-0.0.54/tests/rules/md015_proptest.rs +0 -23
  50. rumdl-0.0.54/tests/rules/md015_test.rs +0 -243
  51. rumdl-0.0.54/tests/rules/md030_test.rs +0 -221
  52. rumdl-0.0.54/tests/rules/md034_test.rs +0 -255
  53. rumdl-0.0.54/tests/rules/md039_test.rs +0 -89
  54. {rumdl-0.0.54 → rumdl-0.0.56}/.rumdl.toml +0 -0
  55. {rumdl-0.0.54 → rumdl-0.0.56}/MANIFEST.in +0 -0
  56. {rumdl-0.0.54 → rumdl-0.0.56}/README.md +0 -0
  57. {rumdl-0.0.54 → rumdl-0.0.56}/assets/logo.png +0 -0
  58. {rumdl-0.0.54 → rumdl-0.0.56}/benches/range_performance.rs +0 -0
  59. {rumdl-0.0.54 → rumdl-0.0.56}/benches/range_utils_benchmark.rs +0 -0
  60. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md001.md +0 -0
  61. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md002.md +0 -0
  62. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md003.md +0 -0
  63. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md004.md +0 -0
  64. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md005.md +0 -0
  65. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md006.md +0 -0
  66. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md007.md +0 -0
  67. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md008.md +0 -0
  68. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md009.md +0 -0
  69. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md010.md +0 -0
  70. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md011.md +0 -0
  71. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md012.md +0 -0
  72. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md013.md +0 -0
  73. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md014.md +0 -0
  74. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md018.md +0 -0
  75. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md019.md +0 -0
  76. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md020.md +0 -0
  77. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md021.md +0 -0
  78. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md022.md +0 -0
  79. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md023.md +0 -0
  80. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md024.md +0 -0
  81. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md025.md +0 -0
  82. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md026.md +0 -0
  83. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md027.md +0 -0
  84. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md028.md +0 -0
  85. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md029.md +0 -0
  86. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md031.md +0 -0
  87. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md032.md +0 -0
  88. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md033.md +0 -0
  89. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md034.md +0 -0
  90. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md035.md +0 -0
  91. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md036.md +0 -0
  92. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md037.md +0 -0
  93. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md038.md +0 -0
  94. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md039.md +0 -0
  95. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md040.md +0 -0
  96. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md041.md +0 -0
  97. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md042.md +0 -0
  98. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md043.md +0 -0
  99. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md044.md +0 -0
  100. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md045.md +0 -0
  101. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md046.md +0 -0
  102. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md047.md +0 -0
  103. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md048.md +0 -0
  104. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md049.md +0 -0
  105. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md050.md +0 -0
  106. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md051.md +0 -0
  107. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md052.md +0 -0
  108. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md053.md +0 -0
  109. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md054.md +0 -0
  110. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md055.md +0 -0
  111. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md056.md +0 -0
  112. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md057.md +0 -0
  113. {rumdl-0.0.54 → rumdl-0.0.56}/docs/md058.md +0 -0
  114. {rumdl-0.0.54 → rumdl-0.0.56}/issues/plan-rule-parity-with-markdownlint.md +0 -0
  115. {rumdl-0.0.54 → rumdl-0.0.56}/pyproject.toml +0 -0
  116. {rumdl-0.0.54 → rumdl-0.0.56}/python/MANIFEST.in +0 -0
  117. {rumdl-0.0.54 → rumdl-0.0.56}/python/PYTHON-README.md +0 -0
  118. {rumdl-0.0.54 → rumdl-0.0.56}/python/rumdl/__init__.py +0 -0
  119. {rumdl-0.0.54 → rumdl-0.0.56}/python/rumdl/__main__.py +0 -0
  120. {rumdl-0.0.54 → rumdl-0.0.56}/python/rumdl/py.typed +0 -0
  121. {rumdl-0.0.54 → rumdl-0.0.56}/rumdl.toml.example +0 -0
  122. {rumdl-0.0.54 → rumdl-0.0.56}/src/init.rs +0 -0
  123. {rumdl-0.0.54 → rumdl-0.0.56}/src/lib.rs +0 -0
  124. {rumdl-0.0.54 → rumdl-0.0.56}/src/lint_context.rs +0 -0
  125. {rumdl-0.0.54 → rumdl-0.0.56}/src/markdownlint_config.rs +0 -0
  126. {rumdl-0.0.54 → rumdl-0.0.56}/src/profiling.rs +0 -0
  127. {rumdl-0.0.54 → rumdl-0.0.56}/src/python.rs +0 -0
  128. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/blockquote_utils.rs +0 -0
  129. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/code_block_utils.rs +0 -0
  130. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/code_fence_utils.rs +0 -0
  131. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/emphasis_style.rs +0 -0
  132. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/front_matter_utils.rs +0 -0
  133. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/heading_utils.rs +0 -0
  134. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/list_utils.rs +0 -0
  135. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md001_heading_increment.rs +0 -0
  136. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md002_first_heading_h1.rs +0 -0
  137. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md003_heading_style.rs +0 -0
  138. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md005_list_indent.rs +0 -0
  139. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md006_start_bullets.rs +0 -0
  140. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md008_ul_style.rs +0 -0
  141. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md009_trailing_spaces.rs +0 -0
  142. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md010_no_hard_tabs.rs +0 -0
  143. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md011_no_reversed_links.rs +0 -0
  144. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md012_no_multiple_blanks.rs +0 -0
  145. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md014_commands_show_output.rs +0 -0
  146. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md018_no_missing_space_atx.rs +0 -0
  147. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md019_no_multiple_space_atx.rs +0 -0
  148. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md020_no_missing_space_closed_atx.rs +0 -0
  149. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
  150. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md022_blanks_around_headings.rs +0 -0
  151. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md023_heading_start_left.rs +0 -0
  152. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md024_no_duplicate_heading.rs +0 -0
  153. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md025_single_title.rs +0 -0
  154. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md026_no_trailing_punctuation.rs +0 -0
  155. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md027_multiple_spaces_blockquote.rs +0 -0
  156. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md028_no_blanks_blockquote.rs +0 -0
  157. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md029_ordered_list_prefix.rs +0 -0
  158. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md031_blanks_around_fences.rs +0 -0
  159. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md035_hr_style.rs +0 -0
  160. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md036_no_emphasis_only_first.rs +0 -0
  161. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md037_spaces_around_emphasis.rs +0 -0
  162. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md038_no_space_in_code.rs +0 -0
  163. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md040_fenced_code_language.rs +0 -0
  164. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md041_first_line_heading.rs +0 -0
  165. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md042_no_empty_links.rs +0 -0
  166. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md043_required_headings.rs +0 -0
  167. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md044_proper_names.rs +0 -0
  168. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md045_no_alt_text.rs +0 -0
  169. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md046_code_block_style.rs +0 -0
  170. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md047_single_trailing_newline.rs +0 -0
  171. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md048_code_fence_style.rs +0 -0
  172. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md050_strong_style.rs +0 -0
  173. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md051_link_fragments.rs +0 -0
  174. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md052_reference_links_images.rs +0 -0
  175. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md053_link_image_reference_definitions.rs +0 -0
  176. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md054_link_image_style.rs +0 -0
  177. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md055_table_pipe_style.rs +0 -0
  178. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md056_table_column_count.rs +0 -0
  179. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md057_existing_relative_links.rs +0 -0
  180. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/md058_blanks_around_tables.rs +0 -0
  181. {rumdl-0.0.54 → rumdl-0.0.56}/src/rules/strong_style.rs +0 -0
  182. {rumdl-0.0.54 → rumdl-0.0.56}/src/utils/code_block_utils.rs +0 -0
  183. {rumdl-0.0.54 → rumdl-0.0.56}/src/utils/early_returns.rs +0 -0
  184. {rumdl-0.0.54 → rumdl-0.0.56}/src/utils/markdown_elements.rs +0 -0
  185. {rumdl-0.0.54 → rumdl-0.0.56}/src/utils/mod.rs +0 -0
  186. {rumdl-0.0.54 → rumdl-0.0.56}/src/utils/range_utils.rs +0 -0
  187. {rumdl-0.0.54 → rumdl-0.0.56}/src/utils/regex_cache.rs +0 -0
  188. {rumdl-0.0.54 → rumdl-0.0.56}/tests/cli_duplication_test.rs +0 -0
  189. {rumdl-0.0.54 → rumdl-0.0.56}/tests/cli_integration_tests.rs +0 -0
  190. {rumdl-0.0.54 → rumdl-0.0.56}/tests/commonmark_compliance_tests.rs +0 -0
  191. {rumdl-0.0.54 → rumdl-0.0.56}/tests/comprehensive_integration_tests.rs +0 -0
  192. {rumdl-0.0.54 → rumdl-0.0.56}/tests/config_tests.rs +0 -0
  193. {rumdl-0.0.54 → rumdl-0.0.56}/tests/init_command_test.rs +0 -0
  194. {rumdl-0.0.54 → rumdl-0.0.56}/tests/init_tests.rs +0 -0
  195. {rumdl-0.0.54 → rumdl-0.0.56}/tests/lib.rs +0 -0
  196. {rumdl-0.0.54 → rumdl-0.0.56}/tests/markdownlint_cli_integration.rs +0 -0
  197. {rumdl-0.0.54 → rumdl-0.0.56}/tests/markdownlint_config_test.rs +0 -0
  198. {rumdl-0.0.54 → rumdl-0.0.56}/tests/md030_edge_cases.md +0 -0
  199. {rumdl-0.0.54 → rumdl-0.0.56}/tests/output_format_tests.rs +0 -0
  200. {rumdl-0.0.54 → rumdl-0.0.56}/tests/pyproject_config_tests.rs +0 -0
  201. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md001_test.rs +0 -0
  202. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md001_unicode_test.rs +0 -0
  203. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md002_test.rs +0 -0
  204. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md003_test.rs +0 -0
  205. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md005_test.rs +0 -0
  206. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md006_test.rs +0 -0
  207. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md006_unicode_test.rs +0 -0
  208. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md008_test.rs +0 -0
  209. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md009_test.rs +0 -0
  210. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md010_test.rs +0 -0
  211. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md011_test.rs +0 -0
  212. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md012_test.rs +0 -0
  213. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md014_test.rs +0 -0
  214. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md018_test.rs +0 -0
  215. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md019_test.rs +0 -0
  216. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md020_test.rs +0 -0
  217. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md021_test.rs +0 -0
  218. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md022_test.rs +0 -0
  219. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md023_extended_test.rs +0 -0
  220. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md023_test.rs +0 -0
  221. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md024_test.rs +0 -0
  222. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md025_test.rs +0 -0
  223. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md026_test.rs +0 -0
  224. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md027_test.rs +0 -0
  225. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md028_test.rs +0 -0
  226. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md029_test.rs +0 -0
  227. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md031_test.rs +0 -0
  228. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md033_extended_test.rs +0 -0
  229. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md035_test.rs +0 -0
  230. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md036_test.rs +0 -0
  231. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md037_test.rs +0 -0
  232. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md038_test.rs +0 -0
  233. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md040_test.rs +0 -0
  234. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md041_test.rs +0 -0
  235. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md042_test.rs +0 -0
  236. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md043_test.rs +0 -0
  237. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md044_test.rs +0 -0
  238. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md045_test.rs +0 -0
  239. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md046_test.rs +0 -0
  240. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md047_test.rs +0 -0
  241. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md048_test.rs +0 -0
  242. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md049_test.rs +0 -0
  243. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md050_test.rs +0 -0
  244. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md051_test.rs +0 -0
  245. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md052_test.rs +0 -0
  246. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md053_additional_test.rs +0 -0
  247. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md053_proptest.rs +0 -0
  248. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md053_test.rs +0 -0
  249. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md054_test.rs +0 -0
  250. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md054_unicode_test.rs +0 -0
  251. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md055_test.rs +0 -0
  252. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md056_test.rs +0 -0
  253. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md057_test.rs +0 -0
  254. {rumdl-0.0.54 → rumdl-0.0.56}/tests/rules/md058_test.rs +0 -0
  255. {rumdl-0.0.54 → rumdl-0.0.56}/tests/utils/blockquote_utils_test.rs +0 -0
  256. {rumdl-0.0.54 → rumdl-0.0.56}/tests/utils/code_block_utils_extended_test.rs +0 -0
  257. {rumdl-0.0.54 → rumdl-0.0.56}/tests/utils/code_block_utils_test.rs +0 -0
  258. {rumdl-0.0.54 → rumdl-0.0.56}/tests/utils/core_utils_test.rs +0 -0
  259. {rumdl-0.0.54 → rumdl-0.0.56}/tests/utils/front_matter_utils_test.rs +0 -0
  260. {rumdl-0.0.54 → rumdl-0.0.56}/tests/utils/line_index_test.rs +0 -0
  261. {rumdl-0.0.54 → rumdl-0.0.56}/tests/utils/mod.rs +0 -0
  262. {rumdl-0.0.54 → rumdl-0.0.56}/tests/utils_markdown_edge_cases.rs +0 -0
  263. {rumdl-0.0.54 → rumdl-0.0.56}/tests/utils_tests.rs +0 -0
@@ -1385,7 +1385,7 @@ dependencies = [
1385
1385
 
1386
1386
  [[package]]
1387
1387
  name = "rumdl"
1388
- version = "0.0.54"
1388
+ version = "0.0.56"
1389
1389
  dependencies = [
1390
1390
  "anyhow",
1391
1391
  "assert_cmd",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rumdl"
3
- version = "0.0.54"
3
+ version = "0.0.56"
4
4
  edition = "2021"
5
5
  description = "A fast Markdown linter written in Rust (Ru(st) MarkDown Linter)"
6
6
  authors = ["Ruben J. Jongejan <ruben.jongejan@gmail.com>"]
@@ -12,6 +12,7 @@ clean:
12
12
  fmt:
13
13
  cargo fmt
14
14
  cargo clippy --fix --allow-dirty --allow-staged
15
+ cargo fix --allow-dirty --allow-staged
15
16
 
16
17
  lint:
17
18
  cargo clippy --all-targets --all-features -- -D warnings
@@ -117,14 +118,14 @@ version-push:
117
118
  # Combined targets for one-step release
118
119
  release-major: version-major version-push
119
120
  release-minor: version-minor version-push
120
- release-patch: version-patch version-push
121
+ release-patch: version-patch version-push
121
122
 
122
123
  maturin-build:
123
124
  uv run --with pip,maturin[zig],cffi maturin build --release
124
125
 
125
126
  maturin-sdist:
126
127
  uv run --with pip,maturin[zig],cffi maturin sdist
127
-
128
+
128
129
  run:
129
130
  cargo run --release --bin rumdl check .
130
131
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rumdl
3
- Version: 0.0.54
3
+ Version: 0.0.56
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -1,8 +1,8 @@
1
1
  use criterion::{black_box, criterion_group, criterion_main, Criterion};
2
2
  use rumdl::rule::Rule;
3
3
  use rumdl::rules::{
4
- MD013LineLength, MD015NoMissingSpaceAfterListMarker, MD033NoInlineHtml, MD037NoSpaceInEmphasis,
5
- MD044ProperNames, MD051LinkFragments, MD053LinkImageReferenceDefinitions,
4
+ MD013LineLength, MD033NoInlineHtml, MD037NoSpaceInEmphasis, MD044ProperNames, MD051LinkFragments,
5
+ MD053LinkImageReferenceDefinitions,
6
6
  };
7
7
 
8
8
  /// Benchmark MD013 rule on a large content with long lines
@@ -16,20 +16,11 @@ fn bench_md013(c: &mut Criterion) {
16
16
  let rule = MD013LineLength::default();
17
17
 
18
18
  c.bench_function("MD013 check 100 long lines", |b| {
19
- b.iter(|| rule.check(black_box(&content)))
19
+ b.iter(|| rule.check(&rumdl::lint_context::LintContext::new(&content)))
20
20
  });
21
21
 
22
22
  c.bench_function("MD013 fix 100 long lines", |b| {
23
- b.iter(|| rule.fix(black_box(&content)))
24
- });
25
- }
26
-
27
- /// Benchmark MD015 rule on a large content with list items
28
- fn bench_md015(c: &mut Criterion) {
29
- let rule = MD015NoMissingSpaceAfterListMarker::new();
30
- let content = "-Item 1\n*Item 2\n+Item 3".repeat(1000);
31
- c.bench_function("MD015 fix 1000 items", |b| {
32
- b.iter(|| rule.fix(black_box(&content)))
23
+ b.iter(|| rule.fix(&rumdl::lint_context::LintContext::new(&content)))
33
24
  });
34
25
  }
35
26
 
@@ -44,7 +35,7 @@ fn bench_md033(c: &mut Criterion) {
44
35
  let rule = MD033NoInlineHtml::default();
45
36
 
46
37
  c.bench_function("MD033 check 500 HTML tags", |b| {
47
- b.iter(|| rule.check(black_box(&content)))
38
+ b.iter(|| rule.check(&rumdl::lint_context::LintContext::new(&content)))
48
39
  });
49
40
  }
50
41
 
@@ -68,11 +59,11 @@ fn bench_md037(c: &mut Criterion) {
68
59
  let rule = MD037NoSpaceInEmphasis;
69
60
 
70
61
  c.bench_function("MD037 check 500 emphasis markers", |b| {
71
- b.iter(|| rule.check(black_box(&content)))
62
+ b.iter(|| rule.check(&rumdl::lint_context::LintContext::new(&content)))
72
63
  });
73
64
 
74
65
  c.bench_function("MD037 fix 500 emphasis markers", |b| {
75
- b.iter(|| rule.fix(black_box(&content)))
66
+ b.iter(|| rule.fix(&rumdl::lint_context::LintContext::new(&content)))
76
67
  });
77
68
  }
78
69
 
@@ -117,11 +108,11 @@ fn bench_md044(c: &mut Criterion) {
117
108
  let rule = MD044ProperNames::new(proper_names, true); // true = exclude code blocks
118
109
 
119
110
  c.bench_function("MD044 check 500 proper name occurrences", |b| {
120
- b.iter(|| rule.check(black_box(&content)))
111
+ b.iter(|| rule.check(&rumdl::lint_context::LintContext::new(&content)))
121
112
  });
122
113
 
123
114
  c.bench_function("MD044 fix 500 proper name occurrences", |b| {
124
- b.iter(|| rule.fix(black_box(&content)))
115
+ b.iter(|| rule.fix(&rumdl::lint_context::LintContext::new(&content)))
125
116
  });
126
117
  }
127
118
 
@@ -155,7 +146,7 @@ fn bench_md051(c: &mut Criterion) {
155
146
  let rule = MD051LinkFragments::new();
156
147
 
157
148
  c.bench_function("MD051 check 500 link fragments", |b| {
158
- b.iter(|| rule.check(black_box(&content)))
149
+ b.iter(|| rule.check(&rumdl::lint_context::LintContext::new(&content)))
159
150
  });
160
151
  }
161
152
 
@@ -190,7 +181,7 @@ fn bench_md053(c: &mut Criterion) {
190
181
  c.bench_function("MD053 check cold cache", |b| {
191
182
  b.iter_with_setup(
192
183
  MD053LinkImageReferenceDefinitions::default, // Create a new instance for each iteration
193
- |r| r.check(black_box(&content)),
184
+ |r| r.check(&rumdl::lint_context::LintContext::new(&content)),
194
185
  )
195
186
  });
196
187
 
@@ -198,21 +189,20 @@ fn bench_md053(c: &mut Criterion) {
198
189
  c.bench_function("MD053 check warm cache", |b| {
199
190
  // First, prime the cache
200
191
  let primed_rule = rule.clone();
201
- let _ = primed_rule.check(&content);
192
+ let _ = primed_rule.check(&rumdl::lint_context::LintContext::new(&content));
202
193
 
203
194
  // Then benchmark with warm cache
204
- b.iter(|| primed_rule.check(black_box(&content)))
195
+ b.iter(|| primed_rule.check(&rumdl::lint_context::LintContext::new(&content)))
205
196
  });
206
197
 
207
198
  c.bench_function("MD053 fix unused references", |b| {
208
- b.iter(|| rule.fix(black_box(&content)))
199
+ b.iter(|| rule.fix(&rumdl::lint_context::LintContext::new(&content)))
209
200
  });
210
201
  }
211
202
 
212
203
  criterion_group!(
213
204
  benches,
214
205
  bench_md013,
215
- bench_md015,
216
206
  bench_md033,
217
207
  bench_md037,
218
208
  bench_md044,
@@ -82,7 +82,7 @@ Each rule has a brief description and a link to its detailed documentation.
82
82
 
83
83
  | Rule ID | Rule Name | Description |
84
84
  |---------|-----------|-------------|
85
- | [MD014](md014.md) | Commands show output | Dollar signs used before commands without showing output |
85
+ | [MD014](md014.md) | Commands show output | Code blocks should show output when appropriate |
86
86
  | [MD040](md040.md) | Fenced code language | Fenced code blocks should have a language specified |
87
87
  | [MD046](md046.md) | Code block style | Code block style |
88
88
  | [MD048](md048.md) | Code fence style | Code fence style |
@@ -111,7 +111,6 @@ Each rule has a brief description and a link to its detailed documentation.
111
111
 
112
112
  | Rule ID | Rule Name | Description |
113
113
  |---------|-----------|-------------|
114
- | [MD015](md015.md) | No multiple space list | Multiple spaces after list marker |
115
114
  | [MD057](md057.md) | Relative links | Relative links should exist |
116
115
 
117
116
  ## Using Rules
@@ -2,10 +2,12 @@
2
2
 
3
3
  ## Description
4
4
 
5
- This rule ensures that there is a consistent number of spaces between list markers and the list content.
6
- By default, ordered lists should have one space after the list marker, and unordered lists should have
5
+ This rule ensures that there is a consistent number of spaces between list markers and the list content.
6
+ By default, ordered lists should have one space after the list marker, and unordered lists should have
7
7
  one space after the list marker.
8
8
 
9
+ **Note:** This rule covers multiple spaces (e.g., `* Item`) after list markers, but does **not** warn for missing space (e.g., `*Item`) after the marker. Lines like `*Item` are not considered valid list items per CommonMark and markdownlint, and are ignored.
10
+
9
11
  Consistent spacing improves readability and ensures proper rendering across different Markdown processors.
10
12
 
11
13
  <!-- markdownlint-disable -->
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env python3
2
+ import subprocess
3
+ import json
4
+ import sys
5
+ from pathlib import Path
6
+
7
+ PARITY_CORPUS = Path(__file__).parent / "parity_corpus"
8
+ RUMDL_BIN = "cargo run --bin rumdl --"
9
+ MARKDOWNLINT_BIN = "markdownlint-cli2"
10
+
11
+
12
+ def run_rumdl(md_file):
13
+ cmd = f"{RUMDL_BIN} check '{md_file}' --output json --no-config"
14
+ result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
15
+ if result.returncode != 0 and not result.stdout.strip():
16
+ print(f"[rumdl] Error running on {md_file}: {result.stderr}")
17
+ return []
18
+ try:
19
+ return json.loads(result.stdout)
20
+ except Exception as e:
21
+ print(f"[rumdl] Failed to parse JSON for {md_file}: {e}")
22
+ return []
23
+
24
+ def run_markdownlint(md_file):
25
+ cmd = ["npx", MARKDOWNLINT_BIN, str(md_file), "--json", "--no-config", "--no-summary", "--quiet"]
26
+ result = subprocess.run(cmd, capture_output=True, text=True)
27
+ if result.returncode not in (0, 1):
28
+ print(f"[markdownlint] Error running on {md_file}: {result.stderr}")
29
+ return []
30
+ # Try stdout first
31
+ if result.stdout.strip():
32
+ try:
33
+ return json.loads(result.stdout)
34
+ except Exception as e:
35
+ print(f"[markdownlint] Failed to parse JSON from stdout for {md_file}: {e}")
36
+ print(f"[markdownlint] stdout for {md_file}:")
37
+ print(result.stdout)
38
+ # If stdout is empty, try stderr
39
+ if result.stderr.strip():
40
+ try:
41
+ return json.loads(result.stderr)
42
+ except Exception as e:
43
+ print(f"[markdownlint] Failed to parse JSON from stderr for {md_file}: {e}")
44
+ print(f"[markdownlint] stderr for {md_file}:")
45
+ print(result.stderr)
46
+ return []
47
+
48
+ def normalize_rumdl(warning, file):
49
+ # TODO: Implement normalization logic for rumdl output
50
+ return {
51
+ "file": str(file),
52
+ "line": warning.get("line"),
53
+ "column": warning.get("column"),
54
+ "rule": warning.get("rule_name"),
55
+ "message": warning.get("message"),
56
+ "fix": warning.get("fix"),
57
+ }
58
+
59
+ def normalize_markdownlint(warning):
60
+ # TODO: Implement normalization logic for markdownlint output
61
+ return {
62
+ "file": warning.get("fileName"),
63
+ "line": warning.get("lineNumber"),
64
+ "column": (warning.get("errorRange") or [1])[0] if warning.get("errorRange") else 1,
65
+ "rule": warning.get("ruleNames", [None])[0],
66
+ "message": warning.get("ruleDescription"),
67
+ "fix": warning.get("fixInfo"),
68
+ }
69
+
70
+ def compare_warnings(rumdl_warnings, markdownlint_warnings):
71
+ # Sort by (line, column, rule, message)
72
+ def key(w):
73
+ return (
74
+ w.get("line", 0),
75
+ w.get("column", 0),
76
+ w.get("rule", ""),
77
+ w.get("message", "")
78
+ )
79
+ r_sorted = sorted(rumdl_warnings, key=key)
80
+ m_sorted = sorted(markdownlint_warnings, key=key)
81
+
82
+ r_set = set(json.dumps(w, sort_keys=True) for w in r_sorted)
83
+ m_set = set(json.dumps(w, sort_keys=True) for w in m_sorted)
84
+
85
+ only_in_rumdl = r_set - m_set
86
+ only_in_markdownlint = m_set - r_set
87
+
88
+ if not only_in_rumdl and not only_in_markdownlint:
89
+ print("All warnings match!")
90
+ return True
91
+
92
+ if only_in_rumdl:
93
+ print(f" Warnings only in rumdl ({len(only_in_rumdl)}):")
94
+ for w in list(only_in_rumdl)[:10]:
95
+ print(" ", json.loads(w))
96
+ if len(only_in_rumdl) > 10:
97
+ print(f" ...and {len(only_in_rumdl) - 10} more.")
98
+ if only_in_markdownlint:
99
+ print(f" Warnings only in markdownlint ({len(only_in_markdownlint)}):")
100
+ for w in list(only_in_markdownlint)[:10]:
101
+ print(" ", json.loads(w))
102
+ if len(only_in_markdownlint) > 10:
103
+ print(f" ...and {len(only_in_markdownlint) - 10} more.")
104
+ print(f" Common warnings: {len(r_set & m_set)}")
105
+ return False
106
+
107
+ def main():
108
+ md_files = sorted(PARITY_CORPUS.glob("*.md"))
109
+ if not md_files:
110
+ print("No markdown files found in parity_corpus/")
111
+ sys.exit(1)
112
+ all_passed = True
113
+ for md_file in md_files:
114
+ print(f"\n=== {md_file} ===")
115
+ rumdl_raw = run_rumdl(md_file)
116
+ markdownlint_raw = run_markdownlint(md_file)
117
+ rumdl_norm = [normalize_rumdl(w, md_file) for w in rumdl_raw]
118
+ markdownlint_norm = [normalize_markdownlint(w) for w in markdownlint_raw if w.get("fileName") == str(md_file)]
119
+ if not compare_warnings(rumdl_norm, markdownlint_norm):
120
+ print(f"Mismatch found in {md_file}")
121
+ all_passed = False
122
+ if all_passed:
123
+ print("\nAll files match between rumdl and markdownlint!")
124
+ sys.exit(0)
125
+ else:
126
+ print("\nSome files have mismatches.")
127
+ sys.exit(1)
128
+
129
+ if __name__ == "__main__":
130
+ main()
@@ -12,6 +12,8 @@ use std::fs;
12
12
  use std::io;
13
13
  use std::path::Path;
14
14
  use toml_edit::DocumentMut;
15
+ use std::env;
16
+ use log;
15
17
 
16
18
  lazy_static! {
17
19
  // Map common markdownlint config keys to rumdl rule names
@@ -150,7 +152,7 @@ exclude = [
150
152
  "vendor",
151
153
  "dist",
152
154
  "build",
153
-
155
+
154
156
  # Specific files or patterns
155
157
  "CHANGELOG.md",
156
158
  "LICENSE.md",
@@ -670,6 +672,13 @@ impl SourcedConfig {
670
672
  config_path: Option<&str>,
671
673
  cli_overrides: Option<&SourcedGlobalConfig>,
672
674
  ) -> Result<Self, ConfigError> {
675
+ use std::env;
676
+ log::debug!("[rumdl-config] Current working directory: {:?}", env::current_dir());
677
+ if config_path.is_none() {
678
+ log::debug!("[rumdl-config] No explicit config_path provided, will search default locations");
679
+ } else {
680
+ log::debug!("[rumdl-config] Explicit config_path provided: {:?}", config_path);
681
+ }
673
682
  let mut sourced_config = SourcedConfig::default();
674
683
  let mut loaded_toml_or_pyproject = false;
675
684
 
@@ -680,6 +689,8 @@ impl SourcedConfig {
680
689
  .file_name()
681
690
  .and_then(|name| name.to_str())
682
691
  .unwrap_or("");
692
+ log::debug!("[rumdl-config] Trying to load config file: {}", filename);
693
+ let path_str = path.to_string();
683
694
 
684
695
  // Known markdownlint config files
685
696
  const MARKDOWNLINT_FILENAMES: &[&str] = &[
@@ -692,40 +703,41 @@ impl SourcedConfig {
692
703
  {
693
704
  let content = std::fs::read_to_string(path).map_err(|e| ConfigError::IoError {
694
705
  source: e,
695
- path: path.to_string(),
706
+ path: path_str.clone(),
696
707
  })?;
697
708
  if filename == "pyproject.toml" {
698
- if let Some(fragment) = parse_pyproject_toml(&content, path)? {
709
+ if let Some(fragment) = parse_pyproject_toml(&content, &path_str)? {
699
710
  sourced_config.merge(fragment);
700
- sourced_config.loaded_files.push(path.to_string());
711
+ sourced_config.loaded_files.push(path_str.clone());
701
712
  loaded_toml_or_pyproject = true;
702
713
  }
703
714
  } else {
704
- let fragment = parse_rumdl_toml(&content, path)?;
715
+ let fragment = parse_rumdl_toml(&content, &path_str)?;
705
716
  sourced_config.merge(fragment);
706
- sourced_config.loaded_files.push(path.to_string());
717
+ sourced_config.loaded_files.push(path_str.clone());
707
718
  loaded_toml_or_pyproject = true;
708
719
  }
709
720
  } else if MARKDOWNLINT_FILENAMES.contains(&filename) {
710
721
  // Parse as markdownlint config (JSON/YAML)
711
- let fragment = load_from_markdownlint(path)?;
722
+ let fragment = load_from_markdownlint(&path_str)?;
712
723
  sourced_config.merge(fragment);
713
- sourced_config.loaded_files.push(path.to_string());
724
+ sourced_config.loaded_files.push(path_str.clone());
714
725
  // Do NOT set loaded_toml_or_pyproject = true; markdownlint is fallback only
715
726
  } else {
716
727
  // Try TOML only
717
728
  let content = std::fs::read_to_string(path).map_err(|e| ConfigError::IoError {
718
729
  source: e,
719
- path: path.to_string(),
730
+ path: path_str.clone(),
720
731
  })?;
721
- let fragment = parse_rumdl_toml(&content, path)?;
732
+ let fragment = parse_rumdl_toml(&content, &path_str)?;
722
733
  sourced_config.merge(fragment);
723
- sourced_config.loaded_files.push(path.to_string());
734
+ sourced_config.loaded_files.push(path_str.clone());
724
735
  loaded_toml_or_pyproject = true;
725
736
  }
726
737
  } else {
727
738
  // 2. Discover and load default files: pyproject.toml first
728
739
  if std::path::Path::new("pyproject.toml").exists() {
740
+ log::debug!("[rumdl-config] Found pyproject.toml in current directory");
729
741
  let content = std::fs::read_to_string("pyproject.toml").map_err(|e| {
730
742
  ConfigError::IoError {
731
743
  source: e,
@@ -746,6 +758,7 @@ impl SourcedConfig {
746
758
  // 3. Discover and load .rumdl.toml / rumdl.toml (overrides pyproject)
747
759
  for filename in [".rumdl.toml", "rumdl.toml"] {
748
760
  if std::path::Path::new(filename).exists() {
761
+ log::debug!("[rumdl-config] Found {} in current directory", filename);
749
762
  let content =
750
763
  std::fs::read_to_string(filename).map_err(|e| ConfigError::IoError {
751
764
  source: e,
@@ -756,6 +769,8 @@ impl SourcedConfig {
756
769
  sourced_config.loaded_files.push(filename.to_string());
757
770
  loaded_toml_or_pyproject = true;
758
771
  break; // Load only the first one found
772
+ } else {
773
+ log::debug!("[rumdl-config] {} not found in current directory", filename);
759
774
  }
760
775
  }
761
776
  }
@@ -37,9 +37,13 @@ struct Cli {
37
37
  #[arg(long, global = true, help = "Path to configuration file")]
38
38
  config: Option<String>,
39
39
 
40
+ /// Ignore all configuration files and use built-in defaults
41
+ #[arg(long, global = true, help = "Ignore all configuration files and use built-in defaults")]
42
+ no_config: bool,
43
+
40
44
  /// Fix issues automatically where possible
41
45
  #[arg(short, long, default_value = "false", hide = true)]
42
- fix: bool,
46
+ _fix: bool,
43
47
 
44
48
  /// List all available rules
45
49
  #[arg(short, long, default_value = "false", hide = true)]
@@ -127,7 +131,7 @@ struct CheckArgs {
127
131
 
128
132
  /// Fix issues automatically where possible
129
133
  #[arg(short, long, default_value = "false")]
130
- fix: bool,
134
+ _fix: bool,
131
135
 
132
136
  /// List all available rules
133
137
  #[arg(short, long, default_value = "false")]
@@ -168,6 +172,10 @@ struct CheckArgs {
168
172
  /// Quiet mode
169
173
  #[arg(short, long)]
170
174
  quiet: bool,
175
+
176
+ /// Output format: text (default) or json
177
+ #[arg(long, short = 'o', default_value = "text")]
178
+ output: String,
171
179
  }
172
180
 
173
181
  // Get a complete set of enabled rules based on CLI options and config
@@ -203,11 +211,14 @@ fn get_enabled_rules_from_checkargs(
203
211
  config.global.disable.iter().map(|s| s.as_str()).collect();
204
212
 
205
213
  if let Some(enabled_cli) = &cli_enable_set {
206
- // --- Case 1: CLI --enable provided ---
207
- // CLI --enable overrides *everything* (config enable/disable are ignored).
214
+ // Normalize CLI enable values
215
+ let enabled_cli_normalized: HashSet<String> = enabled_cli.iter()
216
+ .map(|s| normalize_key(s))
217
+ .collect();
218
+ let _all_rule_names: Vec<String> = all_rules.iter().map(|r| normalize_key(r.name())).collect();
208
219
  final_rules = all_rules
209
220
  .into_iter()
210
- .filter(|rule| enabled_cli.contains(rule.name()))
221
+ .filter(|rule| enabled_cli_normalized.contains(&normalize_key(rule.name())))
211
222
  .collect();
212
223
  // Note: CLI --disable is IGNORED if CLI --enable is present.
213
224
  } else {
@@ -456,7 +467,7 @@ fn print_results_from_checkargs(params: PrintResultsArgs) {
456
467
  // Show results summary
457
468
  if has_issues {
458
469
  // If fix mode is enabled, only show the fixed summary
459
- if args.fix && total_issues_fixed > 0 {
470
+ if args._fix && total_issues_fixed > 0 {
460
471
  println!(
461
472
  "\n{} Fixed {}/{} issues in {} {} ({}ms)",
462
473
  "Fixed:".green().bold(),
@@ -485,7 +496,7 @@ fn print_results_from_checkargs(params: PrintResultsArgs) {
485
496
  duration_ms
486
497
  );
487
498
 
488
- if !args.fix && total_fixable_issues > 0 {
499
+ if !args._fix && total_fixable_issues > 0 {
489
500
  // Display the exact count of fixable issues
490
501
  println!(
491
502
  "Run with `--fix` to automatically fix {} of the {} issues",
@@ -561,7 +572,6 @@ fn print_config_with_provenance(sourced: &rumdl_config::SourcedConfig) {
561
572
  Box::new(MD011NoReversedLinks {}),
562
573
  Box::new(MD012NoMultipleBlanks::default()),
563
574
  Box::new(MD013LineLength::default()),
564
- Box::new(MD015NoMissingSpaceAfterListMarker::default()),
565
575
  Box::new(MD018NoMissingSpaceAtx {}),
566
576
  Box::new(MD019NoMultipleSpaceAtx {}),
567
577
  Box::new(MD020NoMissingSpaceClosedAtx {}),
@@ -802,7 +812,12 @@ build-backend = \"setuptools.build_meta\"
802
812
  }
803
813
  }
804
814
  Some(Commands::Check(args)) => {
805
- run_check(args, cli.config.as_deref());
815
+ // If --no-config is set, skip config loading
816
+ if cli.no_config {
817
+ run_check(args, None);
818
+ } else {
819
+ run_check(args, cli.config.as_deref());
820
+ }
806
821
  }
807
822
  Some(Commands::Rule { rule }) => {
808
823
  use rumdl::rules::*;
@@ -820,7 +835,6 @@ build-backend = \"setuptools.build_meta\"
820
835
  Box::new(MD011NoReversedLinks {}),
821
836
  Box::new(MD012NoMultipleBlanks::default()),
822
837
  Box::new(MD013LineLength::default()),
823
- Box::new(MD015NoMissingSpaceAfterListMarker::default()),
824
838
  Box::new(MD018NoMissingSpaceAtx {}),
825
839
  Box::new(MD019NoMultipleSpaceAtx {}),
826
840
  Box::new(MD020NoMissingSpaceClosedAtx {}),
@@ -1104,7 +1118,7 @@ build-backend = \"setuptools.build_meta\"
1104
1118
  if !cli.paths.is_empty() {
1105
1119
  let args = CheckArgs {
1106
1120
  paths: cli.paths.clone(),
1107
- fix: cli.fix,
1121
+ _fix: cli._fix,
1108
1122
  list_rules: cli.list_rules,
1109
1123
  disable: cli.disable.clone(),
1110
1124
  enable: cli.enable.clone(),
@@ -1114,6 +1128,7 @@ build-backend = \"setuptools.build_meta\"
1114
1128
  verbose: cli.verbose,
1115
1129
  profile: cli.profile,
1116
1130
  quiet: cli.quiet,
1131
+ output: "text".to_string(),
1117
1132
  };
1118
1133
  eprintln!("{}: Deprecation warning: Running 'rumdl .' or 'rumdl [PATHS...]' without a subcommand is deprecated and will be removed in a future release. Please use 'rumdl check .' instead.", "[rumdl]".yellow().bold());
1119
1134
  run_check(&args, cli.config.as_deref());
@@ -1182,8 +1197,25 @@ fn run_check(args: &CheckArgs, global_config_path: Option<&str>) {
1182
1197
  return;
1183
1198
  }
1184
1199
 
1200
+ // JSON output mode: collect all warnings and print as JSON
1201
+ if args.output == "json" {
1202
+ let mut all_warnings = Vec::new();
1203
+ for file_path in &file_paths {
1204
+ let warnings = process_file_collect_warnings(
1205
+ file_path,
1206
+ &enabled_rules,
1207
+ args._fix,
1208
+ args.verbose,
1209
+ args.quiet,
1210
+ );
1211
+ all_warnings.extend(warnings);
1212
+ }
1213
+ println!("{}", serde_json::to_string_pretty(&all_warnings).unwrap());
1214
+ return;
1215
+ }
1216
+
1185
1217
  // Confirm with the user if we're fixing a large number of files
1186
- if args.fix && file_paths.len() > 10 && !args.quiet {
1218
+ if args._fix && file_paths.len() > 10 && !args.quiet {
1187
1219
  println!(
1188
1220
  "You are about to fix {} files. This will modify files in-place.",
1189
1221
  file_paths.len()
@@ -1214,7 +1246,7 @@ fn run_check(args: &CheckArgs, global_config_path: Option<&str>) {
1214
1246
  let (file_has_issues, issues_found, issues_fixed, fixable_issues) = process_file(
1215
1247
  file_path,
1216
1248
  &enabled_rules,
1217
- args.fix,
1249
+ args._fix,
1218
1250
  args.verbose,
1219
1251
  args.quiet,
1220
1252
  );
@@ -1265,7 +1297,7 @@ fn run_check(args: &CheckArgs, global_config_path: Option<&str>) {
1265
1297
  fn process_file(
1266
1298
  file_path: &str,
1267
1299
  rules: &[Box<dyn Rule>],
1268
- fix: bool,
1300
+ _fix: bool,
1269
1301
  verbose: bool,
1270
1302
  quiet: bool,
1271
1303
  ) -> (bool, usize, usize, usize) {
@@ -1329,7 +1361,7 @@ fn process_file(
1329
1361
 
1330
1362
  // Add fix indicator if this warning has a fix
1331
1363
  let fix_indicator = if warning.fix.is_some() {
1332
- if fix {
1364
+ if _fix {
1333
1365
  " [fixed]"
1334
1366
  } else {
1335
1367
  " [*]"
@@ -1353,7 +1385,7 @@ fn process_file(
1353
1385
 
1354
1386
  // Fix issues if requested
1355
1387
  let mut warnings_fixed = 0;
1356
- if fix {
1388
+ if _fix {
1357
1389
  // Skip rules that don't have fixes
1358
1390
  for rule in rules {
1359
1391
  if all_warnings
@@ -1415,3 +1447,33 @@ fn process_file(
1415
1447
 
1416
1448
  (true, total_warnings, warnings_fixed, fixable_warnings)
1417
1449
  }
1450
+
1451
+ fn process_file_collect_warnings(
1452
+ file_path: &str,
1453
+ rules: &[Box<dyn Rule>],
1454
+ _fix: bool,
1455
+ verbose: bool,
1456
+ quiet: bool,
1457
+ ) -> Vec<rumdl::rule::LintWarning> {
1458
+ use std::time::Instant;
1459
+ let _start_time = Instant::now();
1460
+ if verbose && !quiet {
1461
+ println!("Processing file: {}", file_path);
1462
+ }
1463
+ let content = match std::fs::read_to_string(file_path) {
1464
+ Ok(content) => content,
1465
+ Err(_) => return Vec::new(),
1466
+ };
1467
+ std::env::set_var("RUMDL_FILE_PATH", file_path);
1468
+ let warnings_result = rumdl::lint(&content, rules, verbose);
1469
+ std::env::remove_var("RUMDL_FILE_PATH");
1470
+ let mut all_warnings = warnings_result.unwrap_or_default();
1471
+ all_warnings.sort_by(|a, b| {
1472
+ if a.line == b.line {
1473
+ a.column.cmp(&b.column)
1474
+ } else {
1475
+ a.line.cmp(&b.line)
1476
+ }
1477
+ });
1478
+ all_warnings
1479
+ }