rumdl 0.0.71__tar.gz → 0.0.73__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 (264) hide show
  1. {rumdl-0.0.71 → rumdl-0.0.73}/Cargo.lock +1 -1
  2. {rumdl-0.0.71 → rumdl-0.0.73}/Cargo.toml +1 -1
  3. {rumdl-0.0.71 → rumdl-0.0.73}/PKG-INFO +1 -1
  4. {rumdl-0.0.71 → rumdl-0.0.73}/src/lib.rs +1 -1
  5. {rumdl-0.0.71 → rumdl-0.0.73}/src/main.rs +7 -10
  6. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md001_heading_increment.rs +1 -1
  7. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md006_start_bullets.rs +19 -8
  8. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md009_trailing_spaces.rs +2 -2
  9. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md011_no_reversed_links.rs +85 -0
  10. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md014_commands_show_output.rs +19 -4
  11. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md022_blanks_around_headings.rs +6 -6
  12. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md025_single_title.rs +58 -1
  13. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md026_no_trailing_punctuation.rs +2 -2
  14. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md028_no_blanks_blockquote.rs +1 -1
  15. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md029_ordered_list_prefix.rs +46 -2
  16. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md032_blanks_around_lists.rs +9 -9
  17. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md033_no_inline_html.rs +20 -26
  18. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md034_no_bare_urls.rs +90 -95
  19. rumdl-0.0.73/src/rules/md037_spaces_around_emphasis.rs +620 -0
  20. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md039_no_space_in_links.rs +1 -1
  21. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md040_fenced_code_language.rs +3 -2
  22. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md045_no_alt_text.rs +1 -1
  23. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md046_code_block_style.rs +4 -4
  24. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md048_code_fence_style.rs +2 -2
  25. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md055_table_pipe_style.rs +24 -1
  26. {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/regex_cache.rs +6 -4
  27. {rumdl-0.0.71 → rumdl-0.0.73}/tests/output_format_tests.rs +2 -2
  28. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md001_test.rs +1 -1
  29. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md001_unicode_test.rs +1 -1
  30. rumdl-0.0.73/tests/rules/md006_test.rs +243 -0
  31. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md009_test.rs +1 -4
  32. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md032_test.rs +3 -5
  33. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md034_test.rs +72 -5
  34. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md037_test.rs +205 -12
  35. rumdl-0.0.71/src/rules/md037_spaces_around_emphasis.rs +0 -595
  36. rumdl-0.0.71/tests/rules/md006_test.rs +0 -143
  37. {rumdl-0.0.71 → rumdl-0.0.73}/.rumdl.toml +0 -0
  38. {rumdl-0.0.71 → rumdl-0.0.73}/MANIFEST.in +0 -0
  39. {rumdl-0.0.71 → rumdl-0.0.73}/Makefile +0 -0
  40. {rumdl-0.0.71 → rumdl-0.0.73}/README.md +0 -0
  41. {rumdl-0.0.71 → rumdl-0.0.73}/assets/logo.png +0 -0
  42. {rumdl-0.0.71 → rumdl-0.0.73}/benches/fix_performance.rs +0 -0
  43. {rumdl-0.0.71 → rumdl-0.0.73}/benches/range_performance.rs +0 -0
  44. {rumdl-0.0.71 → rumdl-0.0.73}/benches/range_utils_benchmark.rs +0 -0
  45. {rumdl-0.0.71 → rumdl-0.0.73}/benches/rule_performance.rs +0 -0
  46. {rumdl-0.0.71 → rumdl-0.0.73}/benches/simple_fix_bench.rs +0 -0
  47. {rumdl-0.0.71 → rumdl-0.0.73}/docs/RULES.md +0 -0
  48. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md001.md +0 -0
  49. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md002.md +0 -0
  50. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md003.md +0 -0
  51. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md004.md +0 -0
  52. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md005.md +0 -0
  53. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md006.md +0 -0
  54. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md007.md +0 -0
  55. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md009.md +0 -0
  56. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md010.md +0 -0
  57. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md011.md +0 -0
  58. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md012.md +0 -0
  59. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md013.md +0 -0
  60. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md014.md +0 -0
  61. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md018.md +0 -0
  62. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md019.md +0 -0
  63. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md020.md +0 -0
  64. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md021.md +0 -0
  65. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md022.md +0 -0
  66. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md023.md +0 -0
  67. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md024.md +0 -0
  68. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md025.md +0 -0
  69. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md026.md +0 -0
  70. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md027.md +0 -0
  71. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md028.md +0 -0
  72. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md029.md +0 -0
  73. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md030.md +0 -0
  74. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md031.md +0 -0
  75. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md032.md +0 -0
  76. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md033.md +0 -0
  77. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md034.md +0 -0
  78. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md035.md +0 -0
  79. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md036.md +0 -0
  80. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md037.md +0 -0
  81. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md038.md +0 -0
  82. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md039.md +0 -0
  83. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md040.md +0 -0
  84. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md041.md +0 -0
  85. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md042.md +0 -0
  86. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md043.md +0 -0
  87. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md044.md +0 -0
  88. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md045.md +0 -0
  89. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md046.md +0 -0
  90. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md047.md +0 -0
  91. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md048.md +0 -0
  92. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md049.md +0 -0
  93. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md050.md +0 -0
  94. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md051.md +0 -0
  95. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md052.md +0 -0
  96. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md053.md +0 -0
  97. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md054.md +0 -0
  98. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md055.md +0 -0
  99. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md056.md +0 -0
  100. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md057.md +0 -0
  101. {rumdl-0.0.71 → rumdl-0.0.73}/docs/md058.md +0 -0
  102. {rumdl-0.0.71 → rumdl-0.0.73}/issues/plan-rule-parity-with-markdownlint.md +0 -0
  103. {rumdl-0.0.71 → rumdl-0.0.73}/parity_check.py +0 -0
  104. {rumdl-0.0.71 → rumdl-0.0.73}/pyproject.toml +0 -0
  105. {rumdl-0.0.71 → rumdl-0.0.73}/python/MANIFEST.in +0 -0
  106. {rumdl-0.0.71 → rumdl-0.0.73}/python/PYTHON-README.md +0 -0
  107. {rumdl-0.0.71 → rumdl-0.0.73}/python/rumdl/__init__.py +0 -0
  108. {rumdl-0.0.71 → rumdl-0.0.73}/python/rumdl/__main__.py +0 -0
  109. {rumdl-0.0.71 → rumdl-0.0.73}/python/rumdl/py.typed +0 -0
  110. {rumdl-0.0.71 → rumdl-0.0.73}/rumdl.toml.example +0 -0
  111. {rumdl-0.0.71 → rumdl-0.0.73}/src/config.rs +0 -0
  112. {rumdl-0.0.71 → rumdl-0.0.73}/src/init.rs +0 -0
  113. {rumdl-0.0.71 → rumdl-0.0.73}/src/lint_context.rs +0 -0
  114. {rumdl-0.0.71 → rumdl-0.0.73}/src/lsp/mod.rs +0 -0
  115. {rumdl-0.0.71 → rumdl-0.0.73}/src/lsp/server.rs +0 -0
  116. {rumdl-0.0.71 → rumdl-0.0.73}/src/lsp/types.rs +0 -0
  117. {rumdl-0.0.71 → rumdl-0.0.73}/src/markdownlint_config.rs +0 -0
  118. {rumdl-0.0.71 → rumdl-0.0.73}/src/parallel.rs +0 -0
  119. {rumdl-0.0.71 → rumdl-0.0.73}/src/performance.rs +0 -0
  120. {rumdl-0.0.71 → rumdl-0.0.73}/src/profiling.rs +0 -0
  121. {rumdl-0.0.71 → rumdl-0.0.73}/src/python.rs +0 -0
  122. {rumdl-0.0.71 → rumdl-0.0.73}/src/rule.rs +0 -0
  123. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/blockquote_utils.rs +0 -0
  124. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/code_block_utils.rs +0 -0
  125. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/code_fence_utils.rs +0 -0
  126. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/emphasis_style.rs +0 -0
  127. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/front_matter_utils.rs +0 -0
  128. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/heading_utils.rs +0 -0
  129. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/list_utils.rs +0 -0
  130. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md002_first_heading_h1.rs +0 -0
  131. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md003_heading_style.rs +0 -0
  132. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md004_unordered_list_style.rs +0 -0
  133. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md005_list_indent.rs +0 -0
  134. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md007_ul_indent.rs +0 -0
  135. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md010_no_hard_tabs.rs +0 -0
  136. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md012_no_multiple_blanks.rs +0 -0
  137. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md013_line_length.rs +0 -0
  138. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md018_no_missing_space_atx.rs +0 -0
  139. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md019_no_multiple_space_atx.rs +0 -0
  140. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md020_no_missing_space_closed_atx.rs +0 -0
  141. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
  142. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md023_heading_start_left.rs +0 -0
  143. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md024_no_duplicate_heading.rs +0 -0
  144. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md027_multiple_spaces_blockquote.rs +0 -0
  145. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md030_list_marker_space.rs +0 -0
  146. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md031_blanks_around_fences.rs +0 -0
  147. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md035_hr_style.rs +0 -0
  148. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md036_no_emphasis_only_first.rs +0 -0
  149. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md038_no_space_in_code.rs +0 -0
  150. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md041_first_line_heading.rs +0 -0
  151. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md042_no_empty_links.rs +0 -0
  152. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md043_required_headings.rs +0 -0
  153. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md044_proper_names.rs +0 -0
  154. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md047_single_trailing_newline.rs +0 -0
  155. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md049_emphasis_style.rs +0 -0
  156. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md050_strong_style.rs +0 -0
  157. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md051_link_fragments.rs +0 -0
  158. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md052_reference_links_images.rs +0 -0
  159. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md053_link_image_reference_definitions.rs +0 -0
  160. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md054_link_image_style.rs +0 -0
  161. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md056_table_column_count.rs +0 -0
  162. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md057_existing_relative_links.rs +0 -0
  163. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md058_blanks_around_tables.rs +0 -0
  164. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/mod.rs +0 -0
  165. {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/strong_style.rs +0 -0
  166. {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/ast_utils.rs +0 -0
  167. {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/code_block_utils.rs +0 -0
  168. {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/document_structure.rs +0 -0
  169. {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/early_returns.rs +0 -0
  170. {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/element_cache.rs +0 -0
  171. {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/markdown_elements.rs +0 -0
  172. {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/mod.rs +0 -0
  173. {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/range_utils.rs +0 -0
  174. {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/string_interner.rs +0 -0
  175. {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/table_utils.rs +0 -0
  176. {rumdl-0.0.71 → rumdl-0.0.73}/tests/advanced_integration_tests.rs +0 -0
  177. {rumdl-0.0.71 → rumdl-0.0.73}/tests/character_ranges/additional_tests.rs +0 -0
  178. {rumdl-0.0.71 → rumdl-0.0.73}/tests/character_ranges/basic_tests.rs +0 -0
  179. {rumdl-0.0.71 → rumdl-0.0.73}/tests/character_ranges/comprehensive_tests.rs +0 -0
  180. {rumdl-0.0.71 → rumdl-0.0.73}/tests/character_ranges/extended_tests.rs +0 -0
  181. {rumdl-0.0.71 → rumdl-0.0.73}/tests/character_ranges/mod.rs +0 -0
  182. {rumdl-0.0.71 → rumdl-0.0.73}/tests/character_ranges/unicode_utils.rs +0 -0
  183. {rumdl-0.0.71 → rumdl-0.0.73}/tests/cli_duplication_test.rs +0 -0
  184. {rumdl-0.0.71 → rumdl-0.0.73}/tests/cli_integration_tests.rs +0 -0
  185. {rumdl-0.0.71 → rumdl-0.0.73}/tests/commonmark_compliance_tests.rs +0 -0
  186. {rumdl-0.0.71 → rumdl-0.0.73}/tests/comprehensive_integration_tests.rs +0 -0
  187. {rumdl-0.0.71 → rumdl-0.0.73}/tests/config_application_tests.rs +0 -0
  188. {rumdl-0.0.71 → rumdl-0.0.73}/tests/config_tests.rs +0 -0
  189. {rumdl-0.0.71 → rumdl-0.0.73}/tests/init_command_test.rs +0 -0
  190. {rumdl-0.0.71 → rumdl-0.0.73}/tests/init_tests.rs +0 -0
  191. {rumdl-0.0.71 → rumdl-0.0.73}/tests/integration_tests.rs +0 -0
  192. {rumdl-0.0.71 → rumdl-0.0.73}/tests/json_output_test.rs +0 -0
  193. {rumdl-0.0.71 → rumdl-0.0.73}/tests/lib.rs +0 -0
  194. {rumdl-0.0.71 → rumdl-0.0.73}/tests/lsp_integration_tests.rs +0 -0
  195. {rumdl-0.0.71 → rumdl-0.0.73}/tests/lsp_tests.rs +0 -0
  196. {rumdl-0.0.71 → rumdl-0.0.73}/tests/markdownlint_cli_integration.rs +0 -0
  197. {rumdl-0.0.71 → rumdl-0.0.73}/tests/markdownlint_config_test.rs +0 -0
  198. {rumdl-0.0.71 → rumdl-0.0.73}/tests/md030_edge_cases.md +0 -0
  199. {rumdl-0.0.71 → rumdl-0.0.73}/tests/perf_check.rs +0 -0
  200. {rumdl-0.0.71 → rumdl-0.0.73}/tests/pyproject_config_tests.rs +0 -0
  201. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md002_test.rs +0 -0
  202. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md003_test.rs +0 -0
  203. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md004_test.rs +0 -0
  204. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md005_test.rs +0 -0
  205. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md006_unicode_test.rs +0 -0
  206. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md007_test.rs +0 -0
  207. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md010_test.rs +0 -0
  208. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md011_test.rs +0 -0
  209. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md012_test.rs +0 -0
  210. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md013_test.rs +0 -0
  211. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md014_test.rs +0 -0
  212. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md018_test.rs +0 -0
  213. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md019_test.rs +0 -0
  214. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md020_test.rs +0 -0
  215. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md021_test.rs +0 -0
  216. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md022_test.rs +0 -0
  217. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md023_extended_test.rs +0 -0
  218. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md023_test.rs +0 -0
  219. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md024_test.rs +0 -0
  220. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md025_test.rs +0 -0
  221. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md026_test.rs +0 -0
  222. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md027_test.rs +0 -0
  223. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md028_test.rs +0 -0
  224. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md029_test.rs +0 -0
  225. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md030_test.rs +0 -0
  226. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md031_test.rs +0 -0
  227. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md033_extended_test.rs +0 -0
  228. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md033_test.rs +0 -0
  229. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md035_test.rs +0 -0
  230. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md036_test.rs +0 -0
  231. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md038_test.rs +0 -0
  232. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md039_test.rs +0 -0
  233. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md040_test.rs +0 -0
  234. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md041_test.rs +0 -0
  235. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md042_test.rs +0 -0
  236. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md043_test.rs +0 -0
  237. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md044_test.rs +0 -0
  238. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md045_test.rs +0 -0
  239. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md046_test.rs +0 -0
  240. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md047_test.rs +0 -0
  241. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md048_test.rs +0 -0
  242. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md049_test.rs +0 -0
  243. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md050_test.rs +0 -0
  244. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md051_test.rs +0 -0
  245. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md052_test.rs +0 -0
  246. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md053_additional_test.rs +0 -0
  247. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md053_proptest.rs +0 -0
  248. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md053_test.rs +0 -0
  249. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md054_test.rs +0 -0
  250. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md054_unicode_test.rs +0 -0
  251. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md055_test.rs +0 -0
  252. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md056_test.rs +0 -0
  253. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md057_test.rs +0 -0
  254. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md058_test.rs +0 -0
  255. {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/mod.rs +0 -0
  256. {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/blockquote_utils_test.rs +0 -0
  257. {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/code_block_utils_extended_test.rs +0 -0
  258. {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/code_block_utils_test.rs +0 -0
  259. {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/core_utils_test.rs +0 -0
  260. {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/front_matter_utils_test.rs +0 -0
  261. {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/line_index_test.rs +0 -0
  262. {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/mod.rs +0 -0
  263. {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils_markdown_edge_cases.rs +0 -0
  264. {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils_tests.rs +0 -0
@@ -1789,7 +1789,7 @@ dependencies = [
1789
1789
 
1790
1790
  [[package]]
1791
1791
  name = "rumdl"
1792
- version = "0.0.71"
1792
+ version = "0.0.73"
1793
1793
  dependencies = [
1794
1794
  "anyhow",
1795
1795
  "assert_cmd",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rumdl"
3
- version = "0.0.71"
3
+ version = "0.0.73"
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.71
3
+ Version: 0.0.73
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -70,7 +70,7 @@ impl ContentCharacteristics {
70
70
  {
71
71
  chars.has_lists = true;
72
72
  }
73
- if !chars.has_links && line.contains('[') {
73
+ if !chars.has_links && (line.contains('[') || line.contains("http://") || line.contains("https://") || line.contains("ftp://")) {
74
74
  chars.has_links = true;
75
75
  }
76
76
  if !chars.has_images && line.contains("![") {
@@ -1297,16 +1297,13 @@ fn process_stdin(rules: &[Box<dyn Rule>], args: &CheckArgs) {
1297
1297
  let has_issues = !all_warnings.is_empty();
1298
1298
  if has_issues {
1299
1299
  for warning in &all_warnings {
1300
+ let rule_name = warning.rule_name.unwrap_or("unknown");
1300
1301
  println!(
1301
- "<stdin>:{}:{}: {}: {} [{}]",
1302
- warning.line,
1303
- warning.column,
1304
- match warning.severity {
1305
- rumdl::rule::Severity::Error => "error".red(),
1306
- rumdl::rule::Severity::Warning => "warning".yellow(),
1307
- },
1308
- warning.message,
1309
- warning.rule_name.unwrap_or("unknown")
1302
+ "<stdin>:{}:{}: {} {}",
1303
+ warning.line.to_string().cyan(),
1304
+ warning.column.to_string().cyan(),
1305
+ format!("[{:5}]", rule_name).yellow(), // Align rule names consistently
1306
+ warning.message
1310
1307
  );
1311
1308
  }
1312
1309
  }
@@ -1611,7 +1608,7 @@ fn process_file(
1611
1608
  file_path.blue().underline(),
1612
1609
  warning.line.to_string().cyan(),
1613
1610
  warning.column.to_string().cyan(),
1614
- format!("[{}]", rule_name).yellow(),
1611
+ format!("[{:5}]", rule_name).yellow(), // Pad rule name to 5 characters for alignment
1615
1612
  warning.message,
1616
1613
  fix_indicator.green()
1617
1614
  );
@@ -162,7 +162,7 @@ impl Rule for MD001HeadingIncrement {
162
162
  column: start_col,
163
163
  end_line,
164
164
  end_column: end_col,
165
- message: format!("Heading level should be {} for this level", prev_level + 1),
165
+ message: format!("Expected heading level {}", prev_level + 1),
166
166
  severity: Severity::Warning,
167
167
  fix: Some(Fix {
168
168
  range: line_index.line_col_to_byte_range(line_num, indentation + 1),
@@ -66,9 +66,15 @@ impl MD006StartBullets {
66
66
  if Self::is_bullet_list_item(lines[check_idx]).is_none() {
67
67
  // Found non-list content - check if it breaks the list structure
68
68
  let content_indent = lines[check_idx].len() - lines[check_idx].trim_start().len();
69
- // Content is only acceptable if it's indented at least as much as current item
70
- // AND we have a true parent relationship (prev_indent < current_indent)
71
- if content_indent < current_indent || prev_indent >= current_indent {
69
+
70
+ // Content is acceptable if:
71
+ // 1. It's indented at least as much as the current item (continuation of parent)
72
+ // 2. OR it's indented more than the previous bullet (continuation of previous item)
73
+ // 3. AND we have a true parent relationship (prev_indent < current_indent)
74
+ let is_continuation = content_indent >= prev_indent.max(2); // At least 2 spaces for continuation
75
+ let is_valid_nesting = prev_indent < current_indent;
76
+
77
+ if !is_continuation || !is_valid_nesting {
72
78
  has_breaking_content = true;
73
79
  break;
74
80
  }
@@ -78,13 +84,19 @@ impl MD006StartBullets {
78
84
  if !has_breaking_content {
79
85
  return Some((i, prev_indent));
80
86
  } else {
81
- // Content breaks the list structure
82
- return None;
87
+ // Content breaks the list structure, but continue searching for an earlier valid parent
88
+ continue;
83
89
  }
84
90
  }
85
91
  // If prev_indent > current_indent, it's a child of a sibling, ignore it and keep searching.
86
92
  } else {
87
- // Found non-list content - this breaks the search
93
+ // Found non-list content - check if it's a continuation line
94
+ let content_indent = lines[i].len() - lines[i].trim_start().len();
95
+ // If it's indented enough to be a continuation, don't break the search
96
+ if content_indent >= 2 {
97
+ continue;
98
+ }
99
+ // Otherwise, this breaks the search
88
100
  return None;
89
101
  }
90
102
  }
@@ -247,8 +259,7 @@ impl Rule for MD006StartBullets {
247
259
  column: start_col,
248
260
  end_line: line_num,
249
261
  end_column: end_col,
250
- message: "List item should start at the beginning of the line (remove indentation)"
251
- .to_string(),
262
+ message: "List item indentation".to_string(),
252
263
  fix: Some(Fix {
253
264
  range: line_index.line_col_to_byte_range(line_num, 1),
254
265
  replacement,
@@ -100,7 +100,7 @@ impl Rule for MD009TrailingSpaces {
100
100
  column: start_col,
101
101
  end_line,
102
102
  end_column: end_col,
103
- message: "Empty line should not have trailing spaces".to_string(),
103
+ message: "Empty line has trailing spaces".to_string(),
104
104
  severity: Severity::Warning,
105
105
  fix: Some(Fix {
106
106
  range: _line_index.line_col_to_byte_range(line_num + 1, 1),
@@ -134,7 +134,7 @@ impl Rule for MD009TrailingSpaces {
134
134
  column: start_col,
135
135
  end_line,
136
136
  end_column: end_col,
137
- message: "Empty blockquote line should have a space after >".to_string(),
137
+ message: "Empty blockquote line needs a space after >".to_string(),
138
138
  severity: Severity::Warning,
139
139
  fix: Some(Fix {
140
140
  range: _line_index.line_col_to_byte_range(line_num + 1, trimmed.len() + 1),
@@ -146,3 +146,88 @@ impl Rule for MD011NoReversedLinks {
146
146
  Box::new(MD011NoReversedLinks)
147
147
  }
148
148
  }
149
+
150
+ #[cfg(test)]
151
+ mod tests {
152
+ use super::*;
153
+ use crate::lint_context::LintContext;
154
+
155
+ #[test]
156
+ fn test_capture_group_order_fix() {
157
+ // This test confirms that the capture group order bug is fixed
158
+ // The regex pattern \(([^)]+)\)\[([^\]]+)\] captures:
159
+ // cap[1] = URL (inside parentheses)
160
+ // cap[2] = text (inside brackets)
161
+ // So (URL)[text] should become [text](URL)
162
+
163
+ let rule = MD011NoReversedLinks;
164
+
165
+ // Test with reversed link syntax
166
+ let content = "Check out (https://example.com)[this link] for more info.";
167
+ let ctx = LintContext::new(content);
168
+
169
+ // This should detect the reversed syntax
170
+ let result = rule.check(&ctx).unwrap();
171
+ assert_eq!(result.len(), 1);
172
+ assert!(result[0].message.contains("Reversed link syntax"));
173
+
174
+ // Verify the fix produces correct output
175
+ let fix = result[0].fix.as_ref().unwrap();
176
+ assert_eq!(fix.replacement, "[this link](https://example.com)");
177
+ }
178
+
179
+ #[test]
180
+ fn test_multiple_reversed_links() {
181
+ // Test multiple reversed links in the same content
182
+ let rule = MD011NoReversedLinks;
183
+
184
+ let content = "Visit (https://example.com)[Example] and (https://test.com)[Test Site].";
185
+ let ctx = LintContext::new(content);
186
+
187
+ let result = rule.check(&ctx).unwrap();
188
+ assert_eq!(result.len(), 2);
189
+
190
+ // Verify both fixes are correct
191
+ assert_eq!(result[0].fix.as_ref().unwrap().replacement, "[Example](https://example.com)");
192
+ assert_eq!(result[1].fix.as_ref().unwrap().replacement, "[Test Site](https://test.com)");
193
+ }
194
+
195
+ #[test]
196
+ fn test_normal_links_not_flagged() {
197
+ // Test that normal link syntax is not flagged
198
+ let rule = MD011NoReversedLinks;
199
+
200
+ let content = "This is a normal [link](https://example.com) and another [link](https://test.com).";
201
+ let ctx = LintContext::new(content);
202
+
203
+ let result = rule.check(&ctx).unwrap();
204
+ assert_eq!(result.len(), 0);
205
+ }
206
+
207
+ #[test]
208
+ fn debug_capture_groups() {
209
+ // Debug test to understand capture group behavior
210
+ let pattern = r"\(([^)]+)\)\[([^\]]+)\]";
211
+ let regex = Regex::new(pattern).unwrap();
212
+
213
+ let test_text = "(https://example.com)[Click here]";
214
+
215
+ if let Some(cap) = regex.captures(test_text) {
216
+ println!("Full match: {}", &cap[0]);
217
+ println!("cap[1] (first group): {}", &cap[1]);
218
+ println!("cap[2] (second group): {}", &cap[2]);
219
+
220
+ // Current fix format
221
+ let current_fix = format!("[{}]({})", &cap[2], &cap[1]);
222
+ println!("Current fix produces: {}", current_fix);
223
+
224
+ // Test what the actual rule produces
225
+ let rule = MD011NoReversedLinks;
226
+ let ctx = LintContext::new(test_text);
227
+ let result = rule.check(&ctx).unwrap();
228
+ if !result.is_empty() {
229
+ println!("Rule fix produces: {}", result[0].fix.as_ref().unwrap().replacement);
230
+ }
231
+ }
232
+ }
233
+ }
@@ -70,9 +70,7 @@ impl MD014CommandsShowOutput {
70
70
  }
71
71
 
72
72
  let mut has_command = false;
73
-
74
73
  let mut has_output = false;
75
-
76
74
  let mut last_command = String::new();
77
75
 
78
76
  for line in block {
@@ -88,6 +86,16 @@ impl MD014CommandsShowOutput {
88
86
  has_command && !has_output && !self.is_no_output_command(&last_command)
89
87
  }
90
88
 
89
+ fn get_command_from_block(&self, block: &[&str]) -> String {
90
+ for line in block {
91
+ let trimmed = line.trim();
92
+ if self.is_command_line(line) {
93
+ return trimmed[1..].trim().to_string();
94
+ }
95
+ }
96
+ String::new()
97
+ }
98
+
91
99
  fn fix_command_block(&self, block: &[&str]) -> String {
92
100
  block
93
101
  .iter()
@@ -175,14 +183,21 @@ impl Rule for MD014CommandsShowOutput {
175
183
  match_obj.len(),
176
184
  );
177
185
 
186
+ // Get the command for a more helpful message
187
+ let command = self.get_command_from_block(&current_block);
188
+ let message = if command.is_empty() {
189
+ "Command should show output (add example output or remove $ prompt)".to_string()
190
+ } else {
191
+ format!("Command '{}' should show output (add example output or remove $ prompt)", command)
192
+ };
193
+
178
194
  warnings.push(LintWarning {
179
195
  rule_name: Some(self.name()),
180
196
  line: start_line,
181
197
  column: start_col,
182
198
  end_line,
183
199
  end_column: end_col,
184
- message: "Commands in code blocks should show output"
185
- .to_string(),
200
+ message,
186
201
  severity: Severity::Warning,
187
202
  fix: Some(Fix {
188
203
  range: _line_index
@@ -582,7 +582,7 @@ impl Rule for MD022BlanksAroundHeadings {
582
582
  } else {
583
583
  "lines"
584
584
  };
585
- issues.push(format!("Headings should be surrounded by blank lines. Expected at least {} blank {} between headings.", required_blanks, line_word));
585
+ issues.push(format!("Expected {} blank {} between headings", required_blanks, line_word));
586
586
  }
587
587
  }
588
588
 
@@ -604,7 +604,7 @@ impl Rule for MD022BlanksAroundHeadings {
604
604
  "lines"
605
605
  };
606
606
  issues.push(format!(
607
- "Heading should have at least {} blank {} above.",
607
+ "Expected {} blank {} above heading",
608
608
  self.lines_above, line_word
609
609
  ));
610
610
  }
@@ -663,7 +663,7 @@ impl Rule for MD022BlanksAroundHeadings {
663
663
  "lines"
664
664
  };
665
665
  issues.push(format!(
666
- "Heading should have at least {} blank {} below.",
666
+ "Expected {} blank {} below heading",
667
667
  self.lines_below, line_word
668
668
  ));
669
669
  }
@@ -784,7 +784,7 @@ impl Rule for MD022BlanksAroundHeadings {
784
784
  } else {
785
785
  "lines"
786
786
  };
787
- issues.push(format!("Headings should be surrounded by blank lines. Expected at least {} blank {} between headings.", required_blanks, line_word));
787
+ issues.push(format!("Expected {} blank {} between headings", required_blanks, line_word));
788
788
  }
789
789
  }
790
790
 
@@ -806,7 +806,7 @@ impl Rule for MD022BlanksAroundHeadings {
806
806
  "lines"
807
807
  };
808
808
  issues.push(format!(
809
- "Heading should have at least {} blank {} above.",
809
+ "Expected {} blank {} above heading",
810
810
  self.lines_above, line_word
811
811
  ));
812
812
  }
@@ -865,7 +865,7 @@ impl Rule for MD022BlanksAroundHeadings {
865
865
  "lines"
866
866
  };
867
867
  issues.push(format!(
868
- "Heading should have at least {} blank {} below.",
868
+ "Expected {} blank {} below heading",
869
869
  self.lines_below, line_word
870
870
  ));
871
871
  }
@@ -253,7 +253,13 @@ impl Rule for MD025SingleTitle {
253
253
  "{} {}",
254
254
  "#".repeat(self.level + 1),
255
255
  if line_content.trim_start().starts_with('#') {
256
- &line_content[(col + self.level)..]
256
+ // Add bounds checking to prevent panic
257
+ let slice_start = col + self.level;
258
+ if slice_start < line_content.len() {
259
+ &line_content[slice_start..]
260
+ } else {
261
+ "" // If bounds exceeded, use empty string
262
+ }
257
263
  } else {
258
264
  line_content.trim() // For Setext, use the whole line
259
265
  }
@@ -357,4 +363,55 @@ mod tests {
357
363
  "Should not flag a single title after front matter"
358
364
  );
359
365
  }
366
+
367
+ #[test]
368
+ fn test_bounds_checking_bug() {
369
+ // Test case that could trigger bounds error in fix generation
370
+ // When col + self.level exceeds line_content.len()
371
+ let rule = MD025SingleTitle::default();
372
+
373
+ // Create content with very short second heading
374
+ let content = "# First\n#";
375
+ let ctx = crate::lint_context::LintContext::new(content);
376
+
377
+ // This should not panic
378
+ let result = rule.check(&ctx);
379
+ assert!(result.is_ok());
380
+
381
+ // Test the fix as well
382
+ let fix_result = rule.fix(&ctx);
383
+ assert!(fix_result.is_ok());
384
+ }
385
+
386
+ #[test]
387
+ fn test_bounds_checking_edge_case() {
388
+ // Test case that specifically targets the bounds checking fix
389
+ // Create a heading where col + self.level would exceed line length
390
+ let rule = MD025SingleTitle::default();
391
+
392
+ // Create content where the second heading is just "#" (length 1)
393
+ // col will be 0, self.level is 1, so col + self.level = 1
394
+ // This should not exceed bounds for "#" but tests the edge case
395
+ let content = "# First Title\n#";
396
+ let ctx = crate::lint_context::LintContext::new(content);
397
+
398
+ // This should not panic and should handle the edge case gracefully
399
+ let result = rule.check(&ctx);
400
+ assert!(result.is_ok());
401
+
402
+ if let Ok(warnings) = result {
403
+ if !warnings.is_empty() {
404
+ // Check that the fix doesn't cause a panic
405
+ let fix_result = rule.fix(&ctx);
406
+ assert!(fix_result.is_ok());
407
+
408
+ // The fix should produce valid content
409
+ if let Ok(fixed_content) = fix_result {
410
+ assert!(!fixed_content.is_empty());
411
+ // Should convert the second "#" to "##" (or "## " if there's content)
412
+ assert!(fixed_content.contains("##"));
413
+ }
414
+ }
415
+ }
416
+ }
360
417
  }
@@ -292,7 +292,7 @@ impl MD026NoTrailingPunctuation {
292
292
  end_line,
293
293
  end_column: end_col,
294
294
  message: format!(
295
- "Heading '{}' should not end with punctuation '{}'",
295
+ "Heading '{}' ends with punctuation '{}'",
296
296
  heading_text.trim(),
297
297
  last_char
298
298
  ),
@@ -337,7 +337,7 @@ impl MD026NoTrailingPunctuation {
337
337
  end_column: end_col,
338
338
  message: format!(
339
339
  "Heading '{
340
- }' should not end with punctuation '{}'",
340
+ }' ends with punctuation '{}'",
341
341
  lines[heading_line - 1].trim(),
342
342
  last_char
343
343
  ),
@@ -73,7 +73,7 @@ impl Rule for MD028NoBlanksBlockquote {
73
73
 
74
74
  warnings.push(LintWarning {
75
75
  rule_name: Some(self.name()),
76
- message: "Blank line inside blockquote".to_string(),
76
+ message: "Empty blockquote line should contain '>' marker".to_string(),
77
77
  line: start_line,
78
78
  column: start_col,
79
79
  end_line,
@@ -307,9 +307,8 @@ impl MD029OrderedListPrefix {
307
307
 
308
308
  // Check each item in the group for correct sequence
309
309
  for (idx, (line_num, line)) in group.iter().enumerate() {
310
- if Self::get_list_number(line).is_some() {
310
+ if let Some(actual_num) = Self::get_list_number(line) {
311
311
  let expected_num = self.get_expected_number(idx);
312
- let actual_num = Self::get_list_number(line).unwrap();
313
312
 
314
313
  if actual_num != expected_num {
315
314
  warnings.push(LintWarning {
@@ -378,4 +377,49 @@ mod tests {
378
377
  let result = rule.check_with_structure(&ctx, &structure).unwrap();
379
378
  assert!(result.is_empty());
380
379
  }
380
+
381
+ #[test]
382
+ fn test_redundant_computation_fix() {
383
+ // This test confirms that the redundant computation bug is fixed
384
+ // Previously: get_list_number() was called twice (once for is_some(), once for unwrap())
385
+ // Now: get_list_number() is called once with if let pattern
386
+
387
+ let rule = MD029OrderedListPrefix::default();
388
+
389
+ // Test with mixed valid and edge case content
390
+ let content = "1. First item\n3. Wrong number\n2. Another wrong number";
391
+ let structure = DocumentStructure::new(content);
392
+ let ctx = crate::lint_context::LintContext::new(content);
393
+
394
+ // This should not panic and should produce warnings for incorrect numbering
395
+ let result = rule.check_with_structure(&ctx, &structure).unwrap();
396
+ assert_eq!(result.len(), 2); // Should have warnings for items 3 and 2
397
+
398
+ // Verify the warnings have correct content
399
+ assert!(result[0].message.contains("3 does not match style (expected 2)"));
400
+ assert!(result[1].message.contains("2 does not match style (expected 3)"));
401
+ }
402
+
403
+ #[test]
404
+ fn test_performance_improvement() {
405
+ // This test verifies that the fix improves performance by avoiding redundant calls
406
+ let rule = MD029OrderedListPrefix::default();
407
+
408
+ // Create a larger list to test performance
409
+ let mut content = String::new();
410
+ for i in 1..=100 {
411
+ content.push_str(&format!("{}. Item {}\n", i + 1, i)); // All wrong numbers
412
+ }
413
+
414
+ let structure = DocumentStructure::new(&content);
415
+ let ctx = crate::lint_context::LintContext::new(&content);
416
+
417
+ // This should complete without issues and produce warnings for all items
418
+ let result = rule.check_with_structure(&ctx, &structure).unwrap();
419
+ assert_eq!(result.len(), 100); // Should have warnings for all 100 items
420
+
421
+ // Verify first and last warnings
422
+ assert!(result[0].message.contains("2 does not match style (expected 1)"));
423
+ assert!(result[99].message.contains("101 does not match style (expected 100)"));
424
+ }
381
425
  }
@@ -254,7 +254,7 @@ impl MD032BlanksAroundLists {
254
254
  end_column: end_col,
255
255
  severity: Severity::Error,
256
256
  rule_name: Some(self.name()),
257
- message: "Lists should be preceded by a blank line".to_string(),
257
+ message: "List should be preceded by blank line".to_string(),
258
258
  fix: Some(Fix {
259
259
  range: line_index.line_col_to_byte_range(start_line, 1),
260
260
  replacement: format!("{}\n{}", prefix, lines[start_line - 1]),
@@ -288,7 +288,7 @@ impl MD032BlanksAroundLists {
288
288
  end_column: end_col_last,
289
289
  severity: Severity::Error,
290
290
  rule_name: Some(self.name()),
291
- message: "Lists should be followed by a blank line".to_string(),
291
+ message: "List should be followed by blank line".to_string(),
292
292
  fix: Some(Fix {
293
293
  range: line_index.line_col_to_byte_range(end_line + 1, 1),
294
294
  replacement: format!("{}\n{}", prefix, lines[end_line]),
@@ -577,7 +577,7 @@ mod tests {
577
577
  warnings[0].line, 2,
578
578
  "Warning should be on the last line of the list (line 2)"
579
579
  );
580
- assert!(warnings[0].message.contains("followed by a blank line"));
580
+ assert!(warnings[0].message.contains("followed by blank line"));
581
581
 
582
582
  // Test that warning has fix
583
583
  check_warnings_have_fixes(content);
@@ -607,7 +607,7 @@ mod tests {
607
607
  warnings[0].line, 2,
608
608
  "Warning should be on the first line of the list (line 2)"
609
609
  );
610
- assert!(warnings[0].message.contains("preceded by a blank line"));
610
+ assert!(warnings[0].message.contains("preceded by blank line"));
611
611
 
612
612
  // Test that warning has fix
613
613
  check_warnings_have_fixes(content);
@@ -634,9 +634,9 @@ mod tests {
634
634
  "Expected 2 warnings for list in middle without surrounding blank lines"
635
635
  );
636
636
  assert_eq!(warnings[0].line, 2, "First warning on line 2 (start)");
637
- assert!(warnings[0].message.contains("preceded by a blank line"));
637
+ assert!(warnings[0].message.contains("preceded by blank line"));
638
638
  assert_eq!(warnings[1].line, 3, "Second warning on line 3 (end)");
639
- assert!(warnings[1].message.contains("followed by a blank line"));
639
+ assert!(warnings[1].message.contains("followed by blank line"));
640
640
 
641
641
  // Test that warnings have fixes
642
642
  check_warnings_have_fixes(content);
@@ -682,9 +682,9 @@ mod tests {
682
682
  );
683
683
  if warnings.len() == 2 {
684
684
  assert_eq!(warnings[0].line, 2, "Warning 1 should be on line 2 (start)");
685
- assert!(warnings[0].message.contains("preceded by a blank line"));
685
+ assert!(warnings[0].message.contains("preceded by blank line"));
686
686
  assert_eq!(warnings[1].line, 5, "Warning 2 should be on line 5 (end)");
687
- assert!(warnings[1].message.contains("followed by a blank line"));
687
+ assert!(warnings[1].message.contains("followed by blank line"));
688
688
  }
689
689
 
690
690
  // Test that warnings have fixes
@@ -794,7 +794,7 @@ mod tests {
794
794
  );
795
795
  if !warnings.is_empty() {
796
796
  assert_eq!(warnings[0].line, 4); // Warning on last line of list
797
- assert!(warnings[0].message.contains("followed by a blank line"));
797
+ assert!(warnings[0].message.contains("followed by blank line"));
798
798
  }
799
799
 
800
800
  // Test that warnings have fixes