rumdl 0.0.56__tar.gz → 0.0.57__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 (249) hide show
  1. {rumdl-0.0.56 → rumdl-0.0.57}/Cargo.lock +1 -1
  2. {rumdl-0.0.56 → rumdl-0.0.57}/Cargo.toml +1 -1
  3. {rumdl-0.0.56 → rumdl-0.0.57}/PKG-INFO +1 -1
  4. rumdl-0.0.57/parity_check.py +211 -0
  5. {rumdl-0.0.56 → rumdl-0.0.57}/src/config.rs +60 -34
  6. {rumdl-0.0.56 → rumdl-0.0.57}/src/lib.rs +4 -5
  7. {rumdl-0.0.56 → rumdl-0.0.57}/src/main.rs +12 -10
  8. {rumdl-0.0.56 → rumdl-0.0.57}/src/markdownlint_config.rs +1 -5
  9. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/emphasis_style.rs +1 -1
  10. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md003_heading_style.rs +16 -25
  11. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md004_unordered_list_style.rs +52 -63
  12. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md012_no_multiple_blanks.rs +38 -29
  13. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md013_line_length.rs +4 -4
  14. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md025_single_title.rs +26 -19
  15. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md032_blanks_around_lists.rs +22 -9
  16. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md033_no_inline_html.rs +194 -52
  17. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md034_no_bare_urls.rs +116 -143
  18. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md055_table_pipe_style.rs +2 -2
  19. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/mod.rs +0 -3
  20. {rumdl-0.0.56 → rumdl-0.0.57}/src/utils/document_structure.rs +184 -41
  21. {rumdl-0.0.56 → rumdl-0.0.57}/tests/advanced_integration_tests.rs +14 -19
  22. {rumdl-0.0.56 → rumdl-0.0.57}/tests/config_application_tests.rs +6 -6
  23. rumdl-0.0.57/tests/config_tests.rs +859 -0
  24. {rumdl-0.0.56 → rumdl-0.0.57}/tests/perf_check.rs +2 -2
  25. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md004_test.rs +12 -6
  26. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md012_test.rs +27 -12
  27. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md013_test.rs +6 -5
  28. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md025_test.rs +4 -3
  29. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md032_test.rs +70 -0
  30. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md033_test.rs +22 -12
  31. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md034_test.rs +203 -53
  32. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/mod.rs +0 -1
  33. rumdl-0.0.56/docs/md008.md +0 -119
  34. rumdl-0.0.56/parity_check.py +0 -130
  35. rumdl-0.0.56/src/rules/md008_ul_style.rs +0 -520
  36. rumdl-0.0.56/tests/config_tests.rs +0 -472
  37. rumdl-0.0.56/tests/rules/md008_test.rs +0 -318
  38. {rumdl-0.0.56 → rumdl-0.0.57}/.rumdl.toml +0 -0
  39. {rumdl-0.0.56 → rumdl-0.0.57}/MANIFEST.in +0 -0
  40. {rumdl-0.0.56 → rumdl-0.0.57}/Makefile +0 -0
  41. {rumdl-0.0.56 → rumdl-0.0.57}/README.md +0 -0
  42. {rumdl-0.0.56 → rumdl-0.0.57}/assets/logo.png +0 -0
  43. {rumdl-0.0.56 → rumdl-0.0.57}/benches/range_performance.rs +0 -0
  44. {rumdl-0.0.56 → rumdl-0.0.57}/benches/range_utils_benchmark.rs +0 -0
  45. {rumdl-0.0.56 → rumdl-0.0.57}/benches/rule_performance.rs +0 -0
  46. {rumdl-0.0.56 → rumdl-0.0.57}/docs/RULES.md +0 -0
  47. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md001.md +0 -0
  48. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md002.md +0 -0
  49. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md003.md +0 -0
  50. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md004.md +0 -0
  51. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md005.md +0 -0
  52. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md006.md +0 -0
  53. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md007.md +0 -0
  54. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md009.md +0 -0
  55. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md010.md +0 -0
  56. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md011.md +0 -0
  57. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md012.md +0 -0
  58. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md013.md +0 -0
  59. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md014.md +0 -0
  60. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md018.md +0 -0
  61. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md019.md +0 -0
  62. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md020.md +0 -0
  63. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md021.md +0 -0
  64. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md022.md +0 -0
  65. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md023.md +0 -0
  66. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md024.md +0 -0
  67. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md025.md +0 -0
  68. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md026.md +0 -0
  69. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md027.md +0 -0
  70. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md028.md +0 -0
  71. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md029.md +0 -0
  72. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md030.md +0 -0
  73. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md031.md +0 -0
  74. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md032.md +0 -0
  75. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md033.md +0 -0
  76. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md034.md +0 -0
  77. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md035.md +0 -0
  78. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md036.md +0 -0
  79. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md037.md +0 -0
  80. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md038.md +0 -0
  81. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md039.md +0 -0
  82. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md040.md +0 -0
  83. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md041.md +0 -0
  84. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md042.md +0 -0
  85. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md043.md +0 -0
  86. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md044.md +0 -0
  87. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md045.md +0 -0
  88. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md046.md +0 -0
  89. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md047.md +0 -0
  90. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md048.md +0 -0
  91. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md049.md +0 -0
  92. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md050.md +0 -0
  93. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md051.md +0 -0
  94. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md052.md +0 -0
  95. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md053.md +0 -0
  96. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md054.md +0 -0
  97. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md055.md +0 -0
  98. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md056.md +0 -0
  99. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md057.md +0 -0
  100. {rumdl-0.0.56 → rumdl-0.0.57}/docs/md058.md +0 -0
  101. {rumdl-0.0.56 → rumdl-0.0.57}/issues/plan-rule-parity-with-markdownlint.md +0 -0
  102. {rumdl-0.0.56 → rumdl-0.0.57}/pyproject.toml +0 -0
  103. {rumdl-0.0.56 → rumdl-0.0.57}/python/MANIFEST.in +0 -0
  104. {rumdl-0.0.56 → rumdl-0.0.57}/python/PYTHON-README.md +0 -0
  105. {rumdl-0.0.56 → rumdl-0.0.57}/python/rumdl/__init__.py +0 -0
  106. {rumdl-0.0.56 → rumdl-0.0.57}/python/rumdl/__main__.py +0 -0
  107. {rumdl-0.0.56 → rumdl-0.0.57}/python/rumdl/py.typed +0 -0
  108. {rumdl-0.0.56 → rumdl-0.0.57}/rumdl.toml.example +0 -0
  109. {rumdl-0.0.56 → rumdl-0.0.57}/src/init.rs +0 -0
  110. {rumdl-0.0.56 → rumdl-0.0.57}/src/lint_context.rs +0 -0
  111. {rumdl-0.0.56 → rumdl-0.0.57}/src/profiling.rs +0 -0
  112. {rumdl-0.0.56 → rumdl-0.0.57}/src/python.rs +0 -0
  113. {rumdl-0.0.56 → rumdl-0.0.57}/src/rule.rs +0 -0
  114. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/blockquote_utils.rs +0 -0
  115. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/code_block_utils.rs +0 -0
  116. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/code_fence_utils.rs +0 -0
  117. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/front_matter_utils.rs +0 -0
  118. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/heading_utils.rs +0 -0
  119. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/list_utils.rs +0 -0
  120. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md001_heading_increment.rs +0 -0
  121. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md002_first_heading_h1.rs +0 -0
  122. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md005_list_indent.rs +0 -0
  123. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md006_start_bullets.rs +0 -0
  124. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md007_ul_indent.rs +0 -0
  125. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md009_trailing_spaces.rs +0 -0
  126. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md010_no_hard_tabs.rs +0 -0
  127. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md011_no_reversed_links.rs +0 -0
  128. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md014_commands_show_output.rs +0 -0
  129. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md018_no_missing_space_atx.rs +0 -0
  130. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md019_no_multiple_space_atx.rs +0 -0
  131. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md020_no_missing_space_closed_atx.rs +0 -0
  132. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
  133. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md022_blanks_around_headings.rs +0 -0
  134. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md023_heading_start_left.rs +0 -0
  135. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md024_no_duplicate_heading.rs +0 -0
  136. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md026_no_trailing_punctuation.rs +0 -0
  137. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md027_multiple_spaces_blockquote.rs +0 -0
  138. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md028_no_blanks_blockquote.rs +0 -0
  139. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md029_ordered_list_prefix.rs +0 -0
  140. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md030_list_marker_space.rs +0 -0
  141. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md031_blanks_around_fences.rs +0 -0
  142. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md035_hr_style.rs +0 -0
  143. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md036_no_emphasis_only_first.rs +0 -0
  144. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md037_spaces_around_emphasis.rs +0 -0
  145. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md038_no_space_in_code.rs +0 -0
  146. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md039_no_space_in_links.rs +0 -0
  147. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md040_fenced_code_language.rs +0 -0
  148. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md041_first_line_heading.rs +0 -0
  149. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md042_no_empty_links.rs +0 -0
  150. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md043_required_headings.rs +0 -0
  151. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md044_proper_names.rs +0 -0
  152. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md045_no_alt_text.rs +0 -0
  153. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md046_code_block_style.rs +0 -0
  154. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md047_single_trailing_newline.rs +0 -0
  155. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md048_code_fence_style.rs +0 -0
  156. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md049_emphasis_style.rs +0 -0
  157. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md050_strong_style.rs +0 -0
  158. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md051_link_fragments.rs +0 -0
  159. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md052_reference_links_images.rs +0 -0
  160. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md053_link_image_reference_definitions.rs +0 -0
  161. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md054_link_image_style.rs +0 -0
  162. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md056_table_column_count.rs +0 -0
  163. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md057_existing_relative_links.rs +0 -0
  164. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/md058_blanks_around_tables.rs +0 -0
  165. {rumdl-0.0.56 → rumdl-0.0.57}/src/rules/strong_style.rs +0 -0
  166. {rumdl-0.0.56 → rumdl-0.0.57}/src/utils/code_block_utils.rs +0 -0
  167. {rumdl-0.0.56 → rumdl-0.0.57}/src/utils/early_returns.rs +0 -0
  168. {rumdl-0.0.56 → rumdl-0.0.57}/src/utils/element_cache.rs +0 -0
  169. {rumdl-0.0.56 → rumdl-0.0.57}/src/utils/markdown_elements.rs +0 -0
  170. {rumdl-0.0.56 → rumdl-0.0.57}/src/utils/mod.rs +0 -0
  171. {rumdl-0.0.56 → rumdl-0.0.57}/src/utils/range_utils.rs +0 -0
  172. {rumdl-0.0.56 → rumdl-0.0.57}/src/utils/regex_cache.rs +0 -0
  173. {rumdl-0.0.56 → rumdl-0.0.57}/tests/cli_duplication_test.rs +0 -0
  174. {rumdl-0.0.56 → rumdl-0.0.57}/tests/cli_integration_tests.rs +0 -0
  175. {rumdl-0.0.56 → rumdl-0.0.57}/tests/commonmark_compliance_tests.rs +0 -0
  176. {rumdl-0.0.56 → rumdl-0.0.57}/tests/comprehensive_integration_tests.rs +0 -0
  177. {rumdl-0.0.56 → rumdl-0.0.57}/tests/init_command_test.rs +0 -0
  178. {rumdl-0.0.56 → rumdl-0.0.57}/tests/init_tests.rs +0 -0
  179. {rumdl-0.0.56 → rumdl-0.0.57}/tests/integration_tests.rs +0 -0
  180. {rumdl-0.0.56 → rumdl-0.0.57}/tests/json_output_test.rs +0 -0
  181. {rumdl-0.0.56 → rumdl-0.0.57}/tests/lib.rs +0 -0
  182. {rumdl-0.0.56 → rumdl-0.0.57}/tests/markdownlint_cli_integration.rs +0 -0
  183. {rumdl-0.0.56 → rumdl-0.0.57}/tests/markdownlint_config_test.rs +0 -0
  184. {rumdl-0.0.56 → rumdl-0.0.57}/tests/md030_edge_cases.md +0 -0
  185. {rumdl-0.0.56 → rumdl-0.0.57}/tests/output_format_tests.rs +0 -0
  186. {rumdl-0.0.56 → rumdl-0.0.57}/tests/pyproject_config_tests.rs +0 -0
  187. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md001_test.rs +0 -0
  188. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md001_unicode_test.rs +0 -0
  189. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md002_test.rs +0 -0
  190. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md003_test.rs +0 -0
  191. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md005_test.rs +0 -0
  192. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md006_test.rs +0 -0
  193. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md006_unicode_test.rs +0 -0
  194. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md007_test.rs +0 -0
  195. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md009_test.rs +0 -0
  196. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md010_test.rs +0 -0
  197. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md011_test.rs +0 -0
  198. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md014_test.rs +0 -0
  199. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md018_test.rs +0 -0
  200. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md019_test.rs +0 -0
  201. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md020_test.rs +0 -0
  202. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md021_test.rs +0 -0
  203. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md022_test.rs +0 -0
  204. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md023_extended_test.rs +0 -0
  205. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md023_test.rs +0 -0
  206. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md024_test.rs +0 -0
  207. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md026_test.rs +0 -0
  208. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md027_test.rs +0 -0
  209. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md028_test.rs +0 -0
  210. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md029_test.rs +0 -0
  211. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md030_test.rs +0 -0
  212. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md031_test.rs +0 -0
  213. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md033_extended_test.rs +0 -0
  214. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md035_test.rs +0 -0
  215. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md036_test.rs +0 -0
  216. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md037_test.rs +0 -0
  217. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md038_test.rs +0 -0
  218. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md039_test.rs +0 -0
  219. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md040_test.rs +0 -0
  220. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md041_test.rs +0 -0
  221. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md042_test.rs +0 -0
  222. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md043_test.rs +0 -0
  223. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md044_test.rs +0 -0
  224. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md045_test.rs +0 -0
  225. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md046_test.rs +0 -0
  226. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md047_test.rs +0 -0
  227. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md048_test.rs +0 -0
  228. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md049_test.rs +0 -0
  229. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md050_test.rs +0 -0
  230. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md051_test.rs +0 -0
  231. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md052_test.rs +0 -0
  232. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md053_additional_test.rs +0 -0
  233. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md053_proptest.rs +0 -0
  234. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md053_test.rs +0 -0
  235. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md054_test.rs +0 -0
  236. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md054_unicode_test.rs +0 -0
  237. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md055_test.rs +0 -0
  238. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md056_test.rs +0 -0
  239. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md057_test.rs +0 -0
  240. {rumdl-0.0.56 → rumdl-0.0.57}/tests/rules/md058_test.rs +0 -0
  241. {rumdl-0.0.56 → rumdl-0.0.57}/tests/utils/blockquote_utils_test.rs +0 -0
  242. {rumdl-0.0.56 → rumdl-0.0.57}/tests/utils/code_block_utils_extended_test.rs +0 -0
  243. {rumdl-0.0.56 → rumdl-0.0.57}/tests/utils/code_block_utils_test.rs +0 -0
  244. {rumdl-0.0.56 → rumdl-0.0.57}/tests/utils/core_utils_test.rs +0 -0
  245. {rumdl-0.0.56 → rumdl-0.0.57}/tests/utils/front_matter_utils_test.rs +0 -0
  246. {rumdl-0.0.56 → rumdl-0.0.57}/tests/utils/line_index_test.rs +0 -0
  247. {rumdl-0.0.56 → rumdl-0.0.57}/tests/utils/mod.rs +0 -0
  248. {rumdl-0.0.56 → rumdl-0.0.57}/tests/utils_markdown_edge_cases.rs +0 -0
  249. {rumdl-0.0.56 → rumdl-0.0.57}/tests/utils_tests.rs +0 -0
@@ -1385,7 +1385,7 @@ dependencies = [
1385
1385
 
1386
1386
  [[package]]
1387
1387
  name = "rumdl"
1388
- version = "0.0.56"
1388
+ version = "0.0.57"
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.56"
3
+ version = "0.0.57"
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>"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rumdl
3
- Version: 0.0.56
3
+ Version: 0.0.57
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -0,0 +1,211 @@
1
+ #!/usr/bin/env python3
2
+ import subprocess
3
+ import json
4
+ import sys
5
+ from pathlib import Path
6
+ import os
7
+
8
+ PARITY_CORPUS = Path(__file__).parent / "parity_corpus"
9
+ RUMDL_BIN = "cargo run --bin rumdl --"
10
+ MARKDOWNLINT_BIN = "markdownlint"
11
+
12
+
13
+ def run_rumdl(md_file):
14
+ # Use --no-config to ensure no config is loaded (use built-in defaults only)
15
+ cmd = f"{RUMDL_BIN} check '{md_file}' -o json --no-config"
16
+ result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
17
+ if result.returncode != 0 and not result.stdout.strip():
18
+ print(f"[rumdl] Error running on {md_file}: {result.stderr}")
19
+ return []
20
+ try:
21
+ return json.loads(result.stdout)
22
+ except Exception as e:
23
+ print(f"[rumdl] Failed to parse JSON for {md_file}: {e}")
24
+ return []
25
+
26
+ def run_markdownlint(md_file):
27
+ cmd = ["npx", MARKDOWNLINT_BIN, str(md_file), "--json"]
28
+ result = subprocess.run(cmd, capture_output=True, text=True)
29
+ if result.returncode not in (0, 1):
30
+ print(f"[markdownlint] Error running on {md_file}: {result.stderr}")
31
+ return []
32
+
33
+ # markdownlint outputs JSON to stderr when using --json flag
34
+ output = result.stderr.strip() if result.stderr.strip() else result.stdout.strip()
35
+ if output:
36
+ try:
37
+ return json.loads(output)
38
+ except Exception as e:
39
+ print(f"[markdownlint] Failed to parse JSON for {md_file}: {e}")
40
+ print(f"[markdownlint] output for {md_file}:")
41
+ print(output)
42
+ return []
43
+
44
+ def normalize_rumdl(warning, file):
45
+ """Normalize rumdl warning to common format"""
46
+ return {
47
+ "file": str(file.relative_to(Path.cwd())), # Convert to relative path
48
+ "line": warning.get("line"),
49
+ "column": warning.get("column", 1),
50
+ "rule": warning.get("rule_name"),
51
+ "message": warning.get("message"),
52
+ "fix": warning.get("fix"),
53
+ }
54
+
55
+ def normalize_markdownlint(warning):
56
+ """Normalize markdownlint warning to common format"""
57
+ file_path = warning.get("fileName")
58
+ # Convert absolute paths to relative if possible
59
+ if file_path and file_path.startswith('/'):
60
+ try:
61
+ file_path = str(Path(file_path).relative_to(Path.cwd()))
62
+ except ValueError:
63
+ # If the path is not relative to cwd, keep it as is
64
+ pass
65
+
66
+ return {
67
+ "file": file_path,
68
+ "line": warning.get("lineNumber"),
69
+ "column": (warning.get("errorRange") or [1])[0] if warning.get("errorRange") else 1,
70
+ "rule": warning.get("ruleNames", [None])[0],
71
+ "message": warning.get("ruleDescription"),
72
+ "fix": warning.get("fixInfo"),
73
+ }
74
+
75
+ def compare_warnings(rumdl_warnings, markdownlint_warnings):
76
+ # Sort by (line, rule) for comparison - ignore column and message differences
77
+ def key(w):
78
+ return (
79
+ w.get("line", 0),
80
+ w.get("rule", "")
81
+ )
82
+ r_sorted = sorted(rumdl_warnings, key=key)
83
+ m_sorted = sorted(markdownlint_warnings, key=key)
84
+
85
+ # Compare based on file, line, and rule only
86
+ def warning_key(w):
87
+ return (w.get("file"), w.get("line"), w.get("rule"))
88
+
89
+ r_set = set(warning_key(w) for w in r_sorted)
90
+ m_set = set(warning_key(w) for w in m_sorted)
91
+
92
+ only_in_rumdl = r_set - m_set
93
+ only_in_markdownlint = m_set - r_set
94
+ common = r_set & m_set
95
+
96
+ if not only_in_rumdl and not only_in_markdownlint:
97
+ print("All warnings match!")
98
+ return True
99
+
100
+ if only_in_rumdl:
101
+ print(f" Warnings only in rumdl ({len(only_in_rumdl)}):")
102
+ for key in list(only_in_rumdl)[:3]: # Show fewer to reduce noise
103
+ file, line, rule = key
104
+ # Find the actual warning for context
105
+ warning = next((w for w in rumdl_warnings if w.get('file') == file and w.get('line') == line and w.get('rule') == rule), None)
106
+ message = warning.get('message', 'No message') if warning else 'No message'
107
+ print(f" Line {line}: {rule} - {message}")
108
+ if len(only_in_rumdl) > 3:
109
+ print(f" ...and {len(only_in_rumdl) - 3} more.")
110
+ if only_in_markdownlint:
111
+ print(f" Warnings only in markdownlint ({len(only_in_markdownlint)}):")
112
+ for key in list(only_in_markdownlint)[:3]: # Show fewer to reduce noise
113
+ file, line, rule = key
114
+ # Find the actual warning for context
115
+ warning = next((w for w in markdownlint_warnings if w.get('file') == file and w.get('line') == line and w.get('rule') == rule), None)
116
+ message = warning.get('message', 'No message') if warning else 'No message'
117
+ print(f" Line {line}: {rule} - {message}")
118
+ if len(only_in_markdownlint) > 3:
119
+ print(f" ...and {len(only_in_markdownlint) - 3} more.")
120
+ print(f" Common warnings: {len(r_set & m_set)}")
121
+ return False
122
+
123
+ def main():
124
+ md_files = sorted(PARITY_CORPUS.glob("*.md"))
125
+ if not md_files:
126
+ print("No markdown files found in parity_corpus/")
127
+ sys.exit(1)
128
+
129
+ all_passed = True
130
+ total_common = 0
131
+ total_rumdl_only = 0
132
+ total_markdownlint_only = 0
133
+
134
+ for md_file in md_files:
135
+ print(f"\n=== {md_file} ===")
136
+ rumdl_raw = run_rumdl(md_file)
137
+ markdownlint_raw = run_markdownlint(md_file)
138
+
139
+ rumdl_norm = [normalize_rumdl(w, md_file) for w in rumdl_raw]
140
+ markdownlint_norm = [normalize_markdownlint(w) for w in markdownlint_raw]
141
+
142
+ # Filter markdownlint warnings to only include the current file
143
+ file_relative = str(md_file.relative_to(Path.cwd()))
144
+ file_absolute = str(md_file.absolute())
145
+ markdownlint_norm = [w for w in markdownlint_norm if w.get("file") in (file_relative, file_absolute)]
146
+
147
+ # Sort by (line, rule) for comparison - ignore column and message differences
148
+ def key(w):
149
+ return (
150
+ w.get("line", 0),
151
+ w.get("rule", "")
152
+ )
153
+ r_sorted = sorted(rumdl_norm, key=key)
154
+ m_sorted = sorted(markdownlint_norm, key=key)
155
+
156
+ # Compare based on file, line, and rule only
157
+ def warning_key(w):
158
+ return (w.get("file"), w.get("line"), w.get("rule"))
159
+
160
+ r_set = set(warning_key(w) for w in r_sorted)
161
+ m_set = set(warning_key(w) for w in m_sorted)
162
+
163
+ only_in_rumdl = r_set - m_set
164
+ only_in_markdownlint = m_set - r_set
165
+ common = r_set & m_set
166
+
167
+ total_common += len(common)
168
+ total_rumdl_only += len(only_in_rumdl)
169
+ total_markdownlint_only += len(only_in_markdownlint)
170
+
171
+ if not only_in_rumdl and not only_in_markdownlint:
172
+ print("✓ All warnings match!")
173
+ else:
174
+ print("✗ Mismatches found:")
175
+ if only_in_rumdl:
176
+ print(f" Warnings only in rumdl ({len(only_in_rumdl)}):")
177
+ for key in list(only_in_rumdl)[:3]: # Show fewer to reduce noise
178
+ file, line, rule = key
179
+ # Find the actual warning for context
180
+ warning = next((w for w in rumdl_norm if w.get('file') == file and w.get('line') == line and w.get('rule') == rule), None)
181
+ message = warning.get('message', 'No message') if warning else 'No message'
182
+ print(f" Line {line}: {rule} - {message}")
183
+ if len(only_in_rumdl) > 3:
184
+ print(f" ...and {len(only_in_rumdl) - 3} more.")
185
+ if only_in_markdownlint:
186
+ print(f" Warnings only in markdownlint ({len(only_in_markdownlint)}):")
187
+ for key in list(only_in_markdownlint)[:3]: # Show fewer to reduce noise
188
+ file, line, rule = key
189
+ # Find the actual warning for context
190
+ warning = next((w for w in markdownlint_norm if w.get('file') == file and w.get('line') == line and w.get('rule') == rule), None)
191
+ message = warning.get('message', 'No message') if warning else 'No message'
192
+ print(f" Line {line}: {rule} - {message}")
193
+ if len(only_in_markdownlint) > 3:
194
+ print(f" ...and {len(only_in_markdownlint) - 3} more.")
195
+ print(f" Common warnings: {len(common)}")
196
+ all_passed = False
197
+
198
+ print(f"\n=== SUMMARY ===")
199
+ print(f"Total common warnings: {total_common}")
200
+ print(f"Total rumdl-only warnings: {total_rumdl_only}")
201
+ print(f"Total markdownlint-only warnings: {total_markdownlint_only}")
202
+
203
+ if all_passed:
204
+ print("✓ All files match between rumdl and markdownlint!")
205
+ sys.exit(0)
206
+ else:
207
+ print("✗ Some files have mismatches.")
208
+ sys.exit(1)
209
+
210
+ if __name__ == "__main__":
211
+ main()
@@ -294,8 +294,8 @@ respect-gitignore = true
294
294
 
295
295
  fs::write(&config_path, content).unwrap();
296
296
 
297
- // Load the config using the new sourced loader
298
- let sourced = SourcedConfig::load(Some(config_path.to_str().unwrap()), None).unwrap();
297
+ // Load the config with skip_auto_discovery to avoid environment config files
298
+ let sourced = SourcedConfig::load_with_discovery(Some(config_path.to_str().unwrap()), None, true).unwrap();
299
299
  let config: Config = sourced.into(); // Convert to plain config for assertions
300
300
 
301
301
  // Check global settings
@@ -304,6 +304,7 @@ respect-gitignore = true
304
304
  config.global.enable,
305
305
  vec!["MD001".to_string(), "MD004".to_string()]
306
306
  );
307
+ // Should now contain only the configured pattern since auto-discovery is disabled
307
308
  assert_eq!(config.global.include, vec!["docs/*.md".to_string()]);
308
309
  assert_eq!(config.global.exclude, vec!["node_modules".to_string()]);
309
310
  assert!(config.global.respect_gitignore);
@@ -327,8 +328,8 @@ respect_gitignore = true
327
328
 
328
329
  fs::write(&config_path, content).unwrap();
329
330
 
330
- // Load the config using the new sourced loader
331
- let sourced = SourcedConfig::load(Some(config_path.to_str().unwrap()), None).unwrap();
331
+ // Load the config with skip_auto_discovery to avoid environment config files
332
+ let sourced = SourcedConfig::load_with_discovery(Some(config_path.to_str().unwrap()), None, true).unwrap();
332
333
  let config: Config = sourced.into(); // Convert to plain config for assertions
333
334
 
334
335
  // Check settings were correctly loaded
@@ -347,14 +348,15 @@ line_length = 111
347
348
  line-length = 222
348
349
  "#;
349
350
  fs::write(&config_path, config_content).unwrap();
350
- let sourced = SourcedConfig::load(Some(config_path.to_str().unwrap()), None).unwrap();
351
+ // Load the config with skip_auto_discovery to avoid environment config files
352
+ let sourced = SourcedConfig::load_with_discovery(Some(config_path.to_str().unwrap()), None, true).unwrap();
351
353
  // DEBUG: Print all rule keys and their value keys
352
- eprintln!(
354
+ log::debug!(
353
355
  "[DEBUG] All rules loaded: {:?}",
354
356
  sourced.rules.keys().collect::<Vec<_>>()
355
357
  );
356
358
  for (rule, cfg) in &sourced.rules {
357
- eprintln!(
359
+ log::debug!(
358
360
  "[DEBUG] Rule '{}' value keys: {:?}",
359
361
  rule,
360
362
  cfg.values.keys().collect::<Vec<_>>()
@@ -364,7 +366,7 @@ line-length = 222
364
366
  .rules
365
367
  .get("MD013")
366
368
  .expect("MD013 rule config should exist");
367
- // Both keys should be normalized to 'line-length', with the last one winning
369
+ // Now we should only get the explicitly configured key
368
370
  let keys: Vec<_> = rule_cfg.values.keys().cloned().collect();
369
371
  assert_eq!(keys, vec!["line-length"]);
370
372
  let val = &rule_cfg.values["line-length"].value;
@@ -392,7 +394,8 @@ line-length = 102
392
394
  line-length = 103
393
395
  "#;
394
396
  fs::write(&config_path, config_content).unwrap();
395
- let sourced = SourcedConfig::load(Some(config_path.to_str().unwrap()), None).unwrap();
397
+ // Load the config with skip_auto_discovery to avoid environment config files
398
+ let sourced = SourcedConfig::load_with_discovery(Some(config_path.to_str().unwrap()), None, true).unwrap();
396
399
  let config: Config = sourced.clone().into();
397
400
  // Only the last section should win, and be present
398
401
  let rule_cfg = sourced
@@ -417,7 +420,8 @@ line_length = 201
417
420
  line-length = 202
418
421
  "#;
419
422
  fs::write(&config_path, config_content).unwrap();
420
- let sourced = SourcedConfig::load(Some(config_path.to_str().unwrap()), None).unwrap();
423
+ // Load the config with skip_auto_discovery to avoid environment config files
424
+ let sourced = SourcedConfig::load_with_discovery(Some(config_path.to_str().unwrap()), None, true).unwrap();
421
425
  let config: Config = sourced.clone().into();
422
426
  let rule_cfg = sourced
423
427
  .rules
@@ -445,7 +449,8 @@ bar = 2
445
449
  line-length = 303
446
450
  "#;
447
451
  fs::write(&config_path, config_content).unwrap();
448
- let sourced = SourcedConfig::load(Some(config_path.to_str().unwrap()), None).unwrap();
452
+ // Load the config with skip_auto_discovery to avoid environment config files
453
+ let sourced = SourcedConfig::load_with_discovery(Some(config_path.to_str().unwrap()), None, true).unwrap();
449
454
  let config: Config = sourced.clone().into();
450
455
  // MD999 should not be present
451
456
  assert!(!sourced.rules.contains_key("MD999"));
@@ -671,11 +676,25 @@ impl SourcedConfig {
671
676
  pub fn load(
672
677
  config_path: Option<&str>,
673
678
  cli_overrides: Option<&SourcedGlobalConfig>,
679
+ ) -> Result<Self, ConfigError> {
680
+ Self::load_with_discovery(config_path, cli_overrides, false)
681
+ }
682
+
683
+ /// Load and merge configurations from files and CLI overrides.
684
+ /// If skip_auto_discovery is true, only explicit config paths are loaded.
685
+ pub fn load_with_discovery(
686
+ config_path: Option<&str>,
687
+ cli_overrides: Option<&SourcedGlobalConfig>,
688
+ skip_auto_discovery: bool,
674
689
  ) -> Result<Self, ConfigError> {
675
690
  use std::env;
676
691
  log::debug!("[rumdl-config] Current working directory: {:?}", env::current_dir());
677
692
  if config_path.is_none() {
678
- log::debug!("[rumdl-config] No explicit config_path provided, will search default locations");
693
+ if skip_auto_discovery {
694
+ log::debug!("[rumdl-config] Skipping auto-discovery due to --no-config flag");
695
+ } else {
696
+ log::debug!("[rumdl-config] No explicit config_path provided, will search default locations");
697
+ }
679
698
  } else {
680
699
  log::debug!("[rumdl-config] Explicit config_path provided: {:?}", config_path);
681
700
  }
@@ -717,7 +736,11 @@ impl SourcedConfig {
717
736
  sourced_config.loaded_files.push(path_str.clone());
718
737
  loaded_toml_or_pyproject = true;
719
738
  }
720
- } else if MARKDOWNLINT_FILENAMES.contains(&filename) {
739
+ } else if MARKDOWNLINT_FILENAMES.contains(&filename)
740
+ || path_str.ends_with(".json")
741
+ || path_str.ends_with(".jsonc")
742
+ || path_str.ends_with(".yaml")
743
+ || path_str.ends_with(".yml") {
721
744
  // Parse as markdownlint config (JSON/YAML)
722
745
  let fragment = load_from_markdownlint(&path_str)?;
723
746
  sourced_config.merge(fragment);
@@ -734,7 +757,10 @@ impl SourcedConfig {
734
757
  sourced_config.loaded_files.push(path_str.clone());
735
758
  loaded_toml_or_pyproject = true;
736
759
  }
737
- } else {
760
+ }
761
+
762
+ // Only perform auto-discovery if not skipped AND no explicit config path provided
763
+ if !skip_auto_discovery && config_path.is_none() {
738
764
  // 2. Discover and load default files: pyproject.toml first
739
765
  if std::path::Path::new("pyproject.toml").exists() {
740
766
  log::debug!("[rumdl-config] Found pyproject.toml in current directory");
@@ -773,20 +799,20 @@ impl SourcedConfig {
773
799
  log::debug!("[rumdl-config] {} not found in current directory", filename);
774
800
  }
775
801
  }
776
- }
777
802
 
778
- // 4. Markdownlint config fallback if no TOML/pyproject config was loaded
779
- if !loaded_toml_or_pyproject {
780
- for filename in MARKDOWNLINT_CONFIG_FILES {
781
- if std::path::Path::new(filename).exists() {
782
- match load_from_markdownlint(filename) {
783
- Ok(fragment) => {
784
- sourced_config.merge(fragment);
785
- sourced_config.loaded_files.push(filename.to_string());
786
- break; // Load only the first one found
787
- }
788
- Err(_e) => {
789
- // Log error but continue (it's just a fallback)
803
+ // 4. Markdownlint config fallback if no TOML/pyproject config was loaded
804
+ if !loaded_toml_or_pyproject {
805
+ for filename in MARKDOWNLINT_CONFIG_FILES {
806
+ if std::path::Path::new(filename).exists() {
807
+ match load_from_markdownlint(filename) {
808
+ Ok(fragment) => {
809
+ sourced_config.merge(fragment);
810
+ sourced_config.loaded_files.push(filename.to_string());
811
+ break; // Load only the first one found
812
+ }
813
+ Err(_e) => {
814
+ // Log error but continue (it's just a fallback)
815
+ }
790
816
  }
791
817
  }
792
818
  }
@@ -1281,7 +1307,7 @@ fn parse_rumdl_toml(content: &str, path: &str) -> Result<SourcedConfigFragment,
1281
1307
  _ => unreachable!(), // Should not happen due to outer match
1282
1308
  }
1283
1309
  } else {
1284
- eprintln!(
1310
+ log::warn!(
1285
1311
  "[WARN] Expected array for global key '{}' in {}, found {}",
1286
1312
  key,
1287
1313
  path,
@@ -1302,7 +1328,7 @@ fn parse_rumdl_toml(content: &str, path: &str) -> Result<SourcedConfigFragment,
1302
1328
  None,
1303
1329
  );
1304
1330
  } else {
1305
- eprintln!(
1331
+ log::warn!(
1306
1332
  "[WARN] Expected boolean for global key '{}' in {}, found {}",
1307
1333
  key,
1308
1334
  path,
@@ -1313,7 +1339,7 @@ fn parse_rumdl_toml(content: &str, path: &str) -> Result<SourcedConfigFragment,
1313
1339
  _ => {
1314
1340
  // Add to unknown_keys for potential validation later
1315
1341
  // fragment.unknown_keys.push(("[global]".to_string(), key.to_string()));
1316
- eprintln!(
1342
+ log::warn!(
1317
1343
  "[WARN] Unknown key in [global] section of {}: {}",
1318
1344
  path, key
1319
1345
  );
@@ -1350,21 +1376,21 @@ fn parse_rumdl_toml(content: &str, path: &str) -> Result<SourcedConfigFragment,
1350
1376
  Some(toml::Value::Datetime(*formatted.value()))
1351
1377
  }
1352
1378
  Some(toml_edit::Value::Array(_)) => {
1353
- eprintln!(
1379
+ log::warn!(
1354
1380
  "[WARN] Skipping array value for key '{}.{}' in {}. Array conversion not yet fully implemented in parser.",
1355
1381
  norm_rule_name, norm_rk, path
1356
1382
  );
1357
1383
  None
1358
1384
  }
1359
1385
  Some(toml_edit::Value::InlineTable(_)) => {
1360
- eprintln!(
1386
+ log::warn!(
1361
1387
  "[WARN] Skipping inline table value for key '{}.{}' in {}. Table conversion not yet fully implemented in parser.",
1362
1388
  norm_rule_name, norm_rk, path
1363
1389
  );
1364
1390
  None
1365
1391
  }
1366
1392
  None => {
1367
- eprintln!(
1393
+ log::warn!(
1368
1394
  "[WARN] Skipping non-value item for key '{}.{}' in {}. Expected simple value.",
1369
1395
  norm_rule_name, norm_rk, path
1370
1396
  );
@@ -1379,7 +1405,7 @@ fn parse_rumdl_toml(content: &str, path: &str) -> Result<SourcedConfigFragment,
1379
1405
  }
1380
1406
  }
1381
1407
  } else if item.is_value() {
1382
- eprintln!(
1408
+ log::warn!(
1383
1409
  "[WARN] Ignoring top-level value key in {}: '{}'. Expected a table like [{}].",
1384
1410
  path, key, key
1385
1411
  );
@@ -46,8 +46,7 @@ pub fn lint(content: &str, rules: &[Box<dyn Rule>], _verbose: bool) -> LintResul
46
46
  warnings.extend(rule_warnings);
47
47
  }
48
48
  Err(e) => {
49
- #[cfg(not(test))]
50
- eprintln!("Error checking rule {}: {}", rule.name(), e);
49
+ log::error!("Error checking rule {}: {}", rule.name(), e);
51
50
  return Err(e);
52
51
  }
53
52
  }
@@ -56,7 +55,7 @@ pub fn lint(content: &str, rules: &[Box<dyn Rule>], _verbose: bool) -> LintResul
56
55
  if _verbose {
57
56
  let rule_duration = _rule_start.elapsed();
58
57
  if rule_duration.as_millis() > 500 {
59
- eprintln!("Rule {} took {:?}", rule.name(), rule_duration);
58
+ log::debug!("Rule {} took {:?}", rule.name(), rule_duration);
60
59
  }
61
60
  }
62
61
  }
@@ -64,12 +63,12 @@ pub fn lint(content: &str, rules: &[Box<dyn Rule>], _verbose: bool) -> LintResul
64
63
  #[cfg(not(test))]
65
64
  if _verbose {
66
65
  let total_duration = _overall_start.elapsed();
67
- eprintln!("Total lint time: {:?}", total_duration);
66
+ log::debug!("Total lint time: {:?}", total_duration);
68
67
  }
69
68
 
70
69
  #[cfg(all(debug_assertions, not(test)))]
71
70
  if !warnings.is_empty() {
72
- eprintln!("Found {} warnings", warnings.len());
71
+ log::info!("Found {} warnings", warnings.len());
73
72
  }
74
73
 
75
74
  Ok(warnings)
@@ -566,7 +566,6 @@ fn print_config_with_provenance(sourced: &rumdl_config::SourcedConfig) {
566
566
  Box::new(MD005ListIndent),
567
567
  Box::new(MD006StartBullets),
568
568
  Box::new(MD007ULIndent::default()),
569
- Box::new(MD008ULStyle::default()),
570
569
  Box::new(MD009TrailingSpaces::default()),
571
570
  Box::new(MD010NoHardTabs::default()),
572
571
  Box::new(MD011NoReversedLinks {}),
@@ -814,9 +813,9 @@ build-backend = \"setuptools.build_meta\"
814
813
  Some(Commands::Check(args)) => {
815
814
  // If --no-config is set, skip config loading
816
815
  if cli.no_config {
817
- run_check(args, None);
816
+ run_check(args, None, cli.no_config);
818
817
  } else {
819
- run_check(args, cli.config.as_deref());
818
+ run_check(args, cli.config.as_deref(), cli.no_config);
820
819
  }
821
820
  }
822
821
  Some(Commands::Rule { rule }) => {
@@ -829,7 +828,6 @@ build-backend = \"setuptools.build_meta\"
829
828
  Box::new(MD005ListIndent),
830
829
  Box::new(MD006StartBullets),
831
830
  Box::new(MD007ULIndent::default()),
832
- Box::new(MD008ULStyle::default()),
833
831
  Box::new(MD009TrailingSpaces::default()),
834
832
  Box::new(MD010NoHardTabs::default()),
835
833
  Box::new(MD011NoReversedLinks {}),
@@ -910,7 +908,7 @@ build-backend = \"setuptools.build_meta\"
910
908
  if let Some((section_part, field_part)) = key.split_once('.') {
911
909
  // 1. Load the full SourcedConfig once
912
910
  let sourced =
913
- match rumdl_config::SourcedConfig::load(cli.config.as_deref(), None) {
911
+ match rumdl_config::SourcedConfig::load_with_discovery(cli.config.as_deref(), None, cli.no_config) {
914
912
  Ok(s) => s,
915
913
  Err(e) => {
916
914
  eprintln!("{}: {}", "Config error".red().bold(), e);
@@ -1056,7 +1054,7 @@ build-backend = \"setuptools.build_meta\"
1056
1054
  let sourced_reg = if *defaults {
1057
1055
  rumdl_config::SourcedConfig::default()
1058
1056
  } else {
1059
- match rumdl_config::SourcedConfig::load(cli.config.as_deref(), None) {
1057
+ match rumdl_config::SourcedConfig::load_with_discovery(cli.config.as_deref(), None, cli.no_config) {
1060
1058
  Ok(s) => s,
1061
1059
  Err(e) => {
1062
1060
  eprintln!("{}: {}", "Config error".red().bold(), e);
@@ -1080,7 +1078,7 @@ build-backend = \"setuptools.build_meta\"
1080
1078
  rumdl_config::SourcedConfig::default()
1081
1079
  } else {
1082
1080
  // Reload config if not defaults (necessary because we exited early in 'get' case)
1083
- match rumdl_config::SourcedConfig::load(cli.config.as_deref(), None) {
1081
+ match rumdl_config::SourcedConfig::load_with_discovery(cli.config.as_deref(), None, cli.no_config) {
1084
1082
  Ok(s) => s,
1085
1083
  Err(e) => {
1086
1084
  eprintln!("{}: {}", "Config error".red().bold(), e);
@@ -1131,7 +1129,7 @@ build-backend = \"setuptools.build_meta\"
1131
1129
  output: "text".to_string(),
1132
1130
  };
1133
1131
  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());
1134
- run_check(&args, cli.config.as_deref());
1132
+ run_check(&args, cli.config.as_deref(), cli.no_config);
1135
1133
  } else {
1136
1134
  eprintln!(
1137
1135
  "{}: No files or directories specified. Please provide at least one path to lint.",
@@ -1150,9 +1148,13 @@ build-backend = \"setuptools.build_meta\"
1150
1148
  }
1151
1149
  }
1152
1150
 
1153
- fn run_check(args: &CheckArgs, global_config_path: Option<&str>) {
1151
+ fn run_check(args: &CheckArgs, global_config_path: Option<&str>, no_config: bool) {
1154
1152
  // 1. Load sourced config (for provenance and validation)
1155
- let sourced = match rumdl_config::SourcedConfig::load(global_config_path, None) {
1153
+ let sourced = match rumdl_config::SourcedConfig::load_with_discovery(
1154
+ global_config_path,
1155
+ None,
1156
+ no_config
1157
+ ) {
1156
1158
  Ok(sourced) => sourced,
1157
1159
  Err(e) => {
1158
1160
  // Syntax error or type mismatch: fail and exit
@@ -24,10 +24,6 @@ pub fn load_markdownlint_config(path: &str) -> Result<MarkdownlintConfig, String
24
24
  .or_else(|_| serde_yaml::from_str(&content))
25
25
  .map_err(|e| format!("Failed to parse config as JSON or YAML: {}", e))
26
26
  };
27
- if let Err(ref err) = parse_result {
28
- eprintln!("\x1b[31mError: Failed to parse configuration file '{}':\n {}\n\nPlease ensure your JSON is valid. All keys and string values must be double-quoted.\x1b[0m", path, err);
29
- std::process::exit(1);
30
- }
31
27
  parse_result
32
28
  }
33
29
 
@@ -182,7 +178,7 @@ impl MarkdownlintConfig {
182
178
  });
183
179
  }
184
180
  } else {
185
- eprintln!("\x1b[31mError: Could not convert value for rule key {:?} to rumdl's internal config format. This likely means the configuration value is invalid or not supported for this rule. Please check your markdownlint config.\x1b[0m", key);
181
+ log::error!("Could not convert value for rule key {:?} to rumdl's internal config format. This likely means the configuration value is invalid or not supported for this rule. Please check your markdownlint config.", key);
186
182
  std::process::exit(1);
187
183
  }
188
184
  }
@@ -5,7 +5,7 @@ use std::fmt;
5
5
  /// The style for emphasis (MD049)
6
6
  #[derive(Debug, PartialEq, Eq, Clone, Copy, Default, Hash)]
7
7
  pub enum EmphasisStyle {
8
- /// Consistent with the first emphasis style found
8
+ /// Consistent with the most prevalent emphasis style found (or first found if tied)
9
9
  #[default]
10
10
  Consistent,
11
11
  /// Asterisk style (*)