rumdl 0.0.100__tar.gz → 0.0.101__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 (364) hide show
  1. {rumdl-0.0.100 → rumdl-0.0.101}/CHANGELOG.md +22 -1
  2. {rumdl-0.0.100 → rumdl-0.0.101}/Cargo.lock +1 -1
  3. {rumdl-0.0.100 → rumdl-0.0.101}/Cargo.toml +1 -1
  4. {rumdl-0.0.100 → rumdl-0.0.101}/PKG-INFO +1 -1
  5. {rumdl-0.0.100 → rumdl-0.0.101}/src/main.rs +37 -1
  6. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md005_list_indent.rs +1 -7
  7. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md006_start_bullets.rs +4 -13
  8. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md007_ul_indent.rs +5 -12
  9. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md009_trailing_spaces.rs +7 -14
  10. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md010_no_hard_tabs.rs +2 -7
  11. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md011_no_reversed_links.rs +0 -1
  12. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md013_line_length.rs +3 -24
  13. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md020_no_missing_space_closed_atx.rs +3 -10
  14. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md025_single_title.rs +3 -15
  15. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md029_ordered_list_prefix.rs +4 -5
  16. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md031_blanks_around_fences.rs +0 -6
  17. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md032_blanks_around_lists.rs +1 -1
  18. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md034_no_bare_urls.rs +3 -9
  19. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md035_hr_style.rs +3 -11
  20. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md037_spaces_around_emphasis.rs +3 -9
  21. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md041_first_line_heading.rs +2 -9
  22. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md045_no_alt_text.rs +6 -9
  23. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md046_code_block_style.rs +0 -6
  24. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/regex_cache.rs +35 -0
  25. {rumdl-0.0.100 → rumdl-0.0.101}/.config/nextest.toml +0 -0
  26. {rumdl-0.0.100 → rumdl-0.0.101}/.mise.toml +0 -0
  27. {rumdl-0.0.100 → rumdl-0.0.101}/.pre-commit-config.yaml +0 -0
  28. {rumdl-0.0.100 → rumdl-0.0.101}/.rumdl.toml +0 -0
  29. {rumdl-0.0.100 → rumdl-0.0.101}/.rustfmt.toml +0 -0
  30. {rumdl-0.0.100 → rumdl-0.0.101}/LICENSE +0 -0
  31. {rumdl-0.0.100 → rumdl-0.0.101}/MANIFEST.in +0 -0
  32. {rumdl-0.0.100 → rumdl-0.0.101}/Makefile +0 -0
  33. {rumdl-0.0.100 → rumdl-0.0.101}/README.md +0 -0
  34. {rumdl-0.0.100 → rumdl-0.0.101}/assets/logo.png +0 -0
  35. {rumdl-0.0.100 → rumdl-0.0.101}/benches/fix_performance.rs +0 -0
  36. {rumdl-0.0.100 → rumdl-0.0.101}/benches/range_performance.rs +0 -0
  37. {rumdl-0.0.100 → rumdl-0.0.101}/benches/range_utils_benchmark.rs +0 -0
  38. {rumdl-0.0.100 → rumdl-0.0.101}/benches/rule_performance.rs +0 -0
  39. {rumdl-0.0.100 → rumdl-0.0.101}/benches/simple_fix_bench.rs +0 -0
  40. {rumdl-0.0.100 → rumdl-0.0.101}/docs/RULES.md +0 -0
  41. {rumdl-0.0.100 → rumdl-0.0.101}/docs/global-settings.md +0 -0
  42. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md001.md +0 -0
  43. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md002.md +0 -0
  44. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md003.md +0 -0
  45. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md004.md +0 -0
  46. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md005.md +0 -0
  47. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md006.md +0 -0
  48. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md007.md +0 -0
  49. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md009.md +0 -0
  50. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md010.md +0 -0
  51. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md011.md +0 -0
  52. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md012.md +0 -0
  53. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md013.md +0 -0
  54. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md014.md +0 -0
  55. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md018.md +0 -0
  56. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md019.md +0 -0
  57. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md020.md +0 -0
  58. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md021.md +0 -0
  59. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md022.md +0 -0
  60. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md023.md +0 -0
  61. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md024.md +0 -0
  62. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md025.md +0 -0
  63. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md026.md +0 -0
  64. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md027.md +0 -0
  65. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md028.md +0 -0
  66. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md029.md +0 -0
  67. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md030.md +0 -0
  68. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md031.md +0 -0
  69. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md032.md +0 -0
  70. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md033.md +0 -0
  71. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md034.md +0 -0
  72. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md035.md +0 -0
  73. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md036.md +0 -0
  74. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md037.md +0 -0
  75. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md038.md +0 -0
  76. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md039.md +0 -0
  77. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md040.md +0 -0
  78. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md041.md +0 -0
  79. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md042.md +0 -0
  80. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md043.md +0 -0
  81. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md044.md +0 -0
  82. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md045.md +0 -0
  83. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md046.md +0 -0
  84. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md047.md +0 -0
  85. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md048.md +0 -0
  86. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md049.md +0 -0
  87. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md050.md +0 -0
  88. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md051.md +0 -0
  89. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md052.md +0 -0
  90. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md053.md +0 -0
  91. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md054.md +0 -0
  92. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md055.md +0 -0
  93. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md056.md +0 -0
  94. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md057.md +0 -0
  95. {rumdl-0.0.100 → rumdl-0.0.101}/docs/md058.md +0 -0
  96. {rumdl-0.0.100 → rumdl-0.0.101}/docs/vscode-extension.md +0 -0
  97. {rumdl-0.0.100 → rumdl-0.0.101}/parity_check.py +0 -0
  98. {rumdl-0.0.100 → rumdl-0.0.101}/pyproject.toml +0 -0
  99. {rumdl-0.0.100 → rumdl-0.0.101}/python/MANIFEST.in +0 -0
  100. {rumdl-0.0.100 → rumdl-0.0.101}/python/PYTHON-README.md +0 -0
  101. {rumdl-0.0.100 → rumdl-0.0.101}/python/rumdl/__init__.py +0 -0
  102. {rumdl-0.0.100 → rumdl-0.0.101}/python/rumdl/__main__.py +0 -0
  103. {rumdl-0.0.100 → rumdl-0.0.101}/python/rumdl/py.typed +0 -0
  104. {rumdl-0.0.100 → rumdl-0.0.101}/rumdl.toml.example +0 -0
  105. {rumdl-0.0.100 → rumdl-0.0.101}/rust-toolchain.toml +0 -0
  106. {rumdl-0.0.100 → rumdl-0.0.101}/scripts/extract-changelog.sh +0 -0
  107. {rumdl-0.0.100 → rumdl-0.0.101}/scripts/prepare-release.sh +0 -0
  108. {rumdl-0.0.100 → rumdl-0.0.101}/scripts/setup-pre-commit.sh +0 -0
  109. {rumdl-0.0.100 → rumdl-0.0.101}/scripts/update-pre-commit-docs.sh +0 -0
  110. {rumdl-0.0.100 → rumdl-0.0.101}/src/bin/benchmark.rs +0 -0
  111. {rumdl-0.0.100 → rumdl-0.0.101}/src/bin/benchmark_rule.rs +0 -0
  112. {rumdl-0.0.100 → rumdl-0.0.101}/src/bin/file_parallel_benchmark.rs +0 -0
  113. {rumdl-0.0.100 → rumdl-0.0.101}/src/bin/measure_code_span_performance.rs +0 -0
  114. {rumdl-0.0.100 → rumdl-0.0.101}/src/config.rs +0 -0
  115. {rumdl-0.0.100 → rumdl-0.0.101}/src/exit_codes.rs +0 -0
  116. {rumdl-0.0.100 → rumdl-0.0.101}/src/init.rs +0 -0
  117. {rumdl-0.0.100 → rumdl-0.0.101}/src/inline_config.rs +0 -0
  118. {rumdl-0.0.100 → rumdl-0.0.101}/src/lib.rs +0 -0
  119. {rumdl-0.0.100 → rumdl-0.0.101}/src/lint_context.rs +0 -0
  120. {rumdl-0.0.100 → rumdl-0.0.101}/src/lsp/mod.rs +0 -0
  121. {rumdl-0.0.100 → rumdl-0.0.101}/src/lsp/server.rs +0 -0
  122. {rumdl-0.0.100 → rumdl-0.0.101}/src/lsp/types.rs +0 -0
  123. {rumdl-0.0.100 → rumdl-0.0.101}/src/markdownlint_config.rs +0 -0
  124. {rumdl-0.0.100 → rumdl-0.0.101}/src/output/formatters/azure.rs +0 -0
  125. {rumdl-0.0.100 → rumdl-0.0.101}/src/output/formatters/concise.rs +0 -0
  126. {rumdl-0.0.100 → rumdl-0.0.101}/src/output/formatters/github.rs +0 -0
  127. {rumdl-0.0.100 → rumdl-0.0.101}/src/output/formatters/gitlab.rs +0 -0
  128. {rumdl-0.0.100 → rumdl-0.0.101}/src/output/formatters/grouped.rs +0 -0
  129. {rumdl-0.0.100 → rumdl-0.0.101}/src/output/formatters/json.rs +0 -0
  130. {rumdl-0.0.100 → rumdl-0.0.101}/src/output/formatters/json_lines.rs +0 -0
  131. {rumdl-0.0.100 → rumdl-0.0.101}/src/output/formatters/junit.rs +0 -0
  132. {rumdl-0.0.100 → rumdl-0.0.101}/src/output/formatters/mod.rs +0 -0
  133. {rumdl-0.0.100 → rumdl-0.0.101}/src/output/formatters/pylint.rs +0 -0
  134. {rumdl-0.0.100 → rumdl-0.0.101}/src/output/formatters/sarif.rs +0 -0
  135. {rumdl-0.0.100 → rumdl-0.0.101}/src/output/formatters/text.rs +0 -0
  136. {rumdl-0.0.100 → rumdl-0.0.101}/src/output/mod.rs +0 -0
  137. {rumdl-0.0.100 → rumdl-0.0.101}/src/parallel.rs +0 -0
  138. {rumdl-0.0.100 → rumdl-0.0.101}/src/performance.rs +0 -0
  139. {rumdl-0.0.100 → rumdl-0.0.101}/src/profiling.rs +0 -0
  140. {rumdl-0.0.100 → rumdl-0.0.101}/src/python.rs +0 -0
  141. {rumdl-0.0.100 → rumdl-0.0.101}/src/rule.rs +0 -0
  142. {rumdl-0.0.100 → rumdl-0.0.101}/src/rule_config.rs +0 -0
  143. {rumdl-0.0.100 → rumdl-0.0.101}/src/rule_config_serde.rs +0 -0
  144. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/blockquote_utils.rs +0 -0
  145. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/code_block_utils.rs +0 -0
  146. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/code_fence_utils.rs +0 -0
  147. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/emphasis_style.rs +0 -0
  148. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/front_matter_utils.rs +0 -0
  149. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/heading_utils.rs +0 -0
  150. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/list_utils.rs +0 -0
  151. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md001_heading_increment.rs +0 -0
  152. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md002_first_heading_h1/md002_config.rs +0 -0
  153. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md002_first_heading_h1.rs +0 -0
  154. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md003_heading_style/md003_config.rs +0 -0
  155. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md003_heading_style.rs +0 -0
  156. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md004_unordered_list_style/md004_config.rs +0 -0
  157. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md004_unordered_list_style.rs +0 -0
  158. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md007_ul_indent/md007_config.rs +0 -0
  159. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md009_trailing_spaces/md009_config.rs +0 -0
  160. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md010_no_hard_tabs/md010_config.rs +0 -0
  161. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md012_no_multiple_blanks/md012_config.rs +0 -0
  162. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md012_no_multiple_blanks.rs +0 -0
  163. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md013_line_length/md013_config.rs +0 -0
  164. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md014_commands_show_output/md014_config.rs +0 -0
  165. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md014_commands_show_output.rs +0 -0
  166. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md018_no_missing_space_atx.rs +0 -0
  167. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md019_no_multiple_space_atx.rs +0 -0
  168. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
  169. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md022_blanks_around_headings/md022_config.rs +0 -0
  170. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md022_blanks_around_headings.rs +0 -0
  171. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md023_heading_start_left.rs +0 -0
  172. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md024_no_duplicate_heading/md024_config.rs +0 -0
  173. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md024_no_duplicate_heading.rs +0 -0
  174. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md025_single_title/md025_config.rs +0 -0
  175. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md026_no_trailing_punctuation/md026_config.rs +0 -0
  176. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md026_no_trailing_punctuation.rs +0 -0
  177. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md027_multiple_spaces_blockquote.rs +0 -0
  178. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md028_no_blanks_blockquote.rs +0 -0
  179. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md030_list_marker_space/md030_config.rs +0 -0
  180. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md030_list_marker_space.rs +0 -0
  181. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md033_no_inline_html/md033_config.rs +0 -0
  182. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md033_no_inline_html.rs +0 -0
  183. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md035_hr_style/md035_config.rs +0 -0
  184. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md036_no_emphasis_only_first/md036_config.rs +0 -0
  185. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md036_no_emphasis_only_first.rs +0 -0
  186. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md038_no_space_in_code.rs +0 -0
  187. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md039_no_space_in_links.rs +0 -0
  188. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md040_fenced_code_language.rs +0 -0
  189. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md042_no_empty_links.rs +0 -0
  190. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md043_required_headings.rs +0 -0
  191. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md044_proper_names/md044_config.rs +0 -0
  192. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md044_proper_names.rs +0 -0
  193. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md045_no_alt_text/md045_config.rs +0 -0
  194. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md046_code_block_style/md046_config.rs +0 -0
  195. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md047_single_trailing_newline.rs +0 -0
  196. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md048_code_fence_style/md048_config.rs +0 -0
  197. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md048_code_fence_style.rs +0 -0
  198. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md049_emphasis_style/md049_config.rs +0 -0
  199. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md049_emphasis_style.rs +0 -0
  200. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md050_strong_style/md050_config.rs +0 -0
  201. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md050_strong_style.rs +0 -0
  202. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md051_link_fragments.rs +0 -0
  203. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md052_reference_links_images.rs +0 -0
  204. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md053_link_image_reference_definitions.rs +0 -0
  205. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md054_link_image_style/md054_config.rs +0 -0
  206. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md054_link_image_style.rs +0 -0
  207. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md055_table_pipe_style/md055_config.rs +0 -0
  208. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md055_table_pipe_style.rs +0 -0
  209. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md056_table_column_count.rs +0 -0
  210. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md057_existing_relative_links/md057_config.rs +0 -0
  211. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md057_existing_relative_links.rs +0 -0
  212. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/md058_blanks_around_tables.rs +0 -0
  213. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/mod.rs +0 -0
  214. {rumdl-0.0.100 → rumdl-0.0.101}/src/rules/strong_style.rs +0 -0
  215. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/ast_utils.rs +0 -0
  216. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/code_block_utils.rs +0 -0
  217. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/document_structure.rs +0 -0
  218. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/early_returns.rs +0 -0
  219. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/element_cache.rs +0 -0
  220. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/emphasis_utils.rs +0 -0
  221. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/fix_utils.rs +0 -0
  222. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/markdown_elements.rs +0 -0
  223. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/mod.rs +0 -0
  224. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/range_utils.rs +0 -0
  225. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/string_interner.rs +0 -0
  226. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/table_utils.rs +0 -0
  227. {rumdl-0.0.100 → rumdl-0.0.101}/src/utils/text_reflow.rs +0 -0
  228. {rumdl-0.0.100 → rumdl-0.0.101}/src/vscode.rs +0 -0
  229. {rumdl-0.0.100 → rumdl-0.0.101}/tests/advanced_integration_tests.rs +0 -0
  230. {rumdl-0.0.100 → rumdl-0.0.101}/tests/character_ranges/additional_tests.rs +0 -0
  231. {rumdl-0.0.100 → rumdl-0.0.101}/tests/character_ranges/basic_tests.rs +0 -0
  232. {rumdl-0.0.100 → rumdl-0.0.101}/tests/character_ranges/comprehensive_tests.rs +0 -0
  233. {rumdl-0.0.100 → rumdl-0.0.101}/tests/character_ranges/extended_tests.rs +0 -0
  234. {rumdl-0.0.100 → rumdl-0.0.101}/tests/character_ranges/mod.rs +0 -0
  235. {rumdl-0.0.100 → rumdl-0.0.101}/tests/character_ranges/unicode_utils.rs +0 -0
  236. {rumdl-0.0.100 → rumdl-0.0.101}/tests/cli_duplication_test.rs +0 -0
  237. {rumdl-0.0.100 → rumdl-0.0.101}/tests/cli_explain_test.rs +0 -0
  238. {rumdl-0.0.100 → rumdl-0.0.101}/tests/cli_flag_precedence_test.rs +0 -0
  239. {rumdl-0.0.100 → rumdl-0.0.101}/tests/cli_integration_tests.rs +0 -0
  240. {rumdl-0.0.100 → rumdl-0.0.101}/tests/cli_lsp_fix_consistency.rs +0 -0
  241. {rumdl-0.0.100 → rumdl-0.0.101}/tests/cli_statistics_test.rs +0 -0
  242. {rumdl-0.0.100 → rumdl-0.0.101}/tests/commonmark_compliance_tests.rs +0 -0
  243. {rumdl-0.0.100 → rumdl-0.0.101}/tests/comprehensive_integration_tests.rs +0 -0
  244. {rumdl-0.0.100 → rumdl-0.0.101}/tests/comprehensive_output_format_tests.rs +0 -0
  245. {rumdl-0.0.100 → rumdl-0.0.101}/tests/config_application_tests.rs +0 -0
  246. {rumdl-0.0.100 → rumdl-0.0.101}/tests/config_file_command_test.rs +0 -0
  247. {rumdl-0.0.100 → rumdl-0.0.101}/tests/config_tests.rs +0 -0
  248. {rumdl-0.0.100 → rumdl-0.0.101}/tests/configuration_inheritance_tests.rs +0 -0
  249. {rumdl-0.0.100 → rumdl-0.0.101}/tests/consistency_regression_tests.rs +0 -0
  250. {rumdl-0.0.100 → rumdl-0.0.101}/tests/cross_platform_compatibility_tests.rs +0 -0
  251. {rumdl-0.0.100 → rumdl-0.0.101}/tests/deeply_nested_lists_performance_test.rs +0 -0
  252. {rumdl-0.0.100 → rumdl-0.0.101}/tests/escaped_brackets_test.rs +0 -0
  253. {rumdl-0.0.100 → rumdl-0.0.101}/tests/final_confidence_assessment.rs +0 -0
  254. {rumdl-0.0.100 → rumdl-0.0.101}/tests/init_command_test.rs +0 -0
  255. {rumdl-0.0.100 → rumdl-0.0.101}/tests/init_tests.rs +0 -0
  256. {rumdl-0.0.100 → rumdl-0.0.101}/tests/inline_config_test.rs +0 -0
  257. {rumdl-0.0.100 → rumdl-0.0.101}/tests/integration_tests.rs +0 -0
  258. {rumdl-0.0.100 → rumdl-0.0.101}/tests/json_output_test.rs +0 -0
  259. {rumdl-0.0.100 → rumdl-0.0.101}/tests/lib.rs +0 -0
  260. {rumdl-0.0.100 → rumdl-0.0.101}/tests/lsp_editor_integration_tests.rs +0 -0
  261. {rumdl-0.0.100 → rumdl-0.0.101}/tests/lsp_integration_tests.rs +0 -0
  262. {rumdl-0.0.100 → rumdl-0.0.101}/tests/lsp_memory_leak_tests.rs +0 -0
  263. {rumdl-0.0.100 → rumdl-0.0.101}/tests/lsp_tests.rs +0 -0
  264. {rumdl-0.0.100 → rumdl-0.0.101}/tests/malformed_markdown_stress_tests.rs +0 -0
  265. {rumdl-0.0.100 → rumdl-0.0.101}/tests/markdownlint_cli_integration.rs +0 -0
  266. {rumdl-0.0.100 → rumdl-0.0.101}/tests/markdownlint_config_test.rs +0 -0
  267. {rumdl-0.0.100 → rumdl-0.0.101}/tests/markdownlintignore_test.rs +0 -0
  268. {rumdl-0.0.100 → rumdl-0.0.101}/tests/md013_reflow_integration_test.rs +0 -0
  269. {rumdl-0.0.100 → rumdl-0.0.101}/tests/nested_code_block_test.rs +0 -0
  270. {rumdl-0.0.100 → rumdl-0.0.101}/tests/output_format_integration_tests.rs +0 -0
  271. {rumdl-0.0.100 → rumdl-0.0.101}/tests/output_format_tests.rs +0 -0
  272. {rumdl-0.0.100 → rumdl-0.0.101}/tests/perf_check.rs +0 -0
  273. {rumdl-0.0.100 → rumdl-0.0.101}/tests/performance_validation_tests.rs +0 -0
  274. {rumdl-0.0.100 → rumdl-0.0.101}/tests/pyproject_config_tests.rs +0 -0
  275. {rumdl-0.0.100 → rumdl-0.0.101}/tests/python_bindings_test.rs +0 -0
  276. {rumdl-0.0.100 → rumdl-0.0.101}/tests/real_world_repository_tests.rs +0 -0
  277. {rumdl-0.0.100 → rumdl-0.0.101}/tests/regression_prevention_tests.rs +0 -0
  278. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/emphasis_edge_cases_test.rs +0 -0
  279. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/heading_edge_cases_test.rs +0 -0
  280. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/inline_content_edge_cases_test.rs +0 -0
  281. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/link_edge_cases_test.rs +0 -0
  282. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/list_rules_integration_test.rs +0 -0
  283. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md001_test.rs +0 -0
  284. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md001_unicode_test.rs +0 -0
  285. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md002_test.rs +0 -0
  286. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md003_test.rs +0 -0
  287. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md004_test.rs +0 -0
  288. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md005_test.rs +0 -0
  289. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md005_unicode_test.rs +0 -0
  290. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md006_test.rs +0 -0
  291. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md006_unicode_test.rs +0 -0
  292. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md007_test.rs +0 -0
  293. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md009_test.rs +0 -0
  294. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md010_test.rs +0 -0
  295. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md011_test.rs +0 -0
  296. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md012_test.rs +0 -0
  297. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md013_test.rs +0 -0
  298. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md014_test.rs +0 -0
  299. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md018_test.rs +0 -0
  300. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md019_test.rs +0 -0
  301. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md020_test.rs +0 -0
  302. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md021_test.rs +0 -0
  303. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md022_test.rs +0 -0
  304. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md023_extended_test.rs +0 -0
  305. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md023_test.rs +0 -0
  306. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md024_test.rs +0 -0
  307. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md025_test.rs +0 -0
  308. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md026_test.rs +0 -0
  309. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md027_test.rs +0 -0
  310. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md028_test.rs +0 -0
  311. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md029_test.rs +0 -0
  312. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md029_unicode_test.rs +0 -0
  313. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md030_test.rs +0 -0
  314. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md031_test.rs +0 -0
  315. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md032_test.rs +0 -0
  316. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md033_extended_test.rs +0 -0
  317. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md033_test.rs +0 -0
  318. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md034_ipv6_test.rs +0 -0
  319. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md034_test.rs +0 -0
  320. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md035_test.rs +0 -0
  321. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md036_test.rs +0 -0
  322. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md037_test.rs +0 -0
  323. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md038_nested_backticks_test.rs +0 -0
  324. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md038_test.rs +0 -0
  325. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md039_test.rs +0 -0
  326. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md040_test.rs +0 -0
  327. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md041_test.rs +0 -0
  328. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md042_test.rs +0 -0
  329. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md043_test.rs +0 -0
  330. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md044_test.rs +0 -0
  331. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md045_test.rs +0 -0
  332. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md046_test.rs +0 -0
  333. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md047_test.rs +0 -0
  334. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md048_test.rs +0 -0
  335. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md049_test.rs +0 -0
  336. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md050_test.rs +0 -0
  337. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md051_test.rs +0 -0
  338. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md051_unicode_test.rs +0 -0
  339. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md052_test.rs +0 -0
  340. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md053_additional_test.rs +0 -0
  341. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md053_proptest.rs +0 -0
  342. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md053_test.rs +0 -0
  343. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md054_test.rs +0 -0
  344. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md054_unicode_test.rs +0 -0
  345. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md055_test.rs +0 -0
  346. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md056_test.rs +0 -0
  347. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md057_test.rs +0 -0
  348. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/md058_test.rs +0 -0
  349. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules/mod.rs +0 -0
  350. {rumdl-0.0.100 → rumdl-0.0.101}/tests/rules_mod_test.rs +0 -0
  351. {rumdl-0.0.100 → rumdl-0.0.101}/tests/thread_safety_tests.rs +0 -0
  352. {rumdl-0.0.100 → rumdl-0.0.101}/tests/unicode_edge_case_tests.rs +0 -0
  353. {rumdl-0.0.100 → rumdl-0.0.101}/tests/utils/blockquote_utils_test.rs +0 -0
  354. {rumdl-0.0.100 → rumdl-0.0.101}/tests/utils/code_block_utils_extended_test.rs +0 -0
  355. {rumdl-0.0.100 → rumdl-0.0.101}/tests/utils/code_block_utils_test.rs +0 -0
  356. {rumdl-0.0.100 → rumdl-0.0.101}/tests/utils/core_utils_test.rs +0 -0
  357. {rumdl-0.0.100 → rumdl-0.0.101}/tests/utils/front_matter_utils_test.rs +0 -0
  358. {rumdl-0.0.100 → rumdl-0.0.101}/tests/utils/line_index_test.rs +0 -0
  359. {rumdl-0.0.100 → rumdl-0.0.101}/tests/utils/mod.rs +0 -0
  360. {rumdl-0.0.100 → rumdl-0.0.101}/tests/utils_markdown_edge_cases.rs +0 -0
  361. {rumdl-0.0.100 → rumdl-0.0.101}/tests/utils_tests.rs +0 -0
  362. {rumdl-0.0.100 → rumdl-0.0.101}/tests/vscode_extension_fixes.rs +0 -0
  363. {rumdl-0.0.100 → rumdl-0.0.101}/tests/vscode_test.rs +0 -0
  364. {rumdl-0.0.100 → rumdl-0.0.101}/tests/vscode_tests.rs +0 -0
@@ -7,8 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.0.101] - 2025-07-23
11
+
10
12
  ## [0.0.100] - 2025-07-22
11
13
 
14
+ ### Performance Improvements
15
+ - **MD032**: Eliminated redundant DocumentStructure creation through optimization interface delegation
16
+ - Refactored check() method to delegate to check_with_structure() for shared parsing
17
+ - Added fix_with_structure() helper method for optimized fixing operations
18
+ - **List Processing**: Major refactoring of complex list block merging logic for better maintainability
19
+ - Extracted merge_adjacent_list_blocks into clean ListBlockMerger struct
20
+ - Introduced BlockSpacing enum for clear categorization of list spacing types
21
+ - Separated compatibility checking, spacing analysis, and merging logic into focused methods
22
+ - **Memory Management**: Added comprehensive performance stress tests for deeply nested lists
23
+ - Created benchmarks for up to 20 levels of nesting with measurable performance baselines
24
+ - Established performance thresholds: <3ms parsing, <4ms rule checking for extreme nesting
25
+ - Added memory stress testing to prevent performance regressions
26
+
27
+ ### Code Quality
28
+ - Improved separation of concerns in list processing logic
29
+ - Enhanced code maintainability through better structured algorithms
30
+ - Added comprehensive test coverage for pathological markdown structures
31
+
12
32
  ## [0.0.99] - 2025-07-22
13
33
 
14
34
  ### Fixed
@@ -225,7 +245,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
225
245
 
226
246
  - Initial implementation of remaining rules for markdownlint parity
227
247
 
228
- [Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.100...HEAD
248
+ [Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.101...HEAD
249
+ [0.0.101]: https://github.com/rvben/rumdl/compare/v0.0.100...v0.0.101
229
250
  [0.0.100]: https://github.com/rvben/rumdl/compare/v0.0.99...v0.0.100
230
251
  [0.0.99]: https://github.com/rvben/rumdl/compare/v0.0.98...v0.0.99
231
252
  [0.0.98]: https://github.com/rvben/rumdl/compare/v0.0.97...v0.0.98
@@ -1493,7 +1493,7 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
1493
1493
 
1494
1494
  [[package]]
1495
1495
  name = "rumdl"
1496
- version = "0.0.100"
1496
+ version = "0.0.101"
1497
1497
  dependencies = [
1498
1498
  "anyhow",
1499
1499
  "assert_cmd",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rumdl"
3
- version = "0.0.100"
3
+ version = "0.0.101"
4
4
  edition = "2024"
5
5
  rust-version = "1.88.0"
6
6
  description = "A fast Markdown linter written in Rust (Ru(st) MarkDown Linter)"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rumdl
3
- Version: 0.0.100
3
+ Version: 0.0.101
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -609,6 +609,37 @@ fn find_markdown_files(
609
609
  // Add support for .markdownlintignore file
610
610
  walk_builder.add_custom_ignore_filename(".markdownlintignore");
611
611
 
612
+ // --- Pre-check for explicit file paths ---
613
+ // If not in discovery mode, validate that specified paths exist
614
+ if !is_discovery_mode {
615
+ for path_str in paths {
616
+ let path = Path::new(path_str);
617
+ if !path.exists() {
618
+ return Err(format!("File not found: {path_str}").into());
619
+ }
620
+ // If it's a file, check if it's a markdown file and add it directly
621
+ if path.is_file() {
622
+ if let Some(ext) = path.extension() {
623
+ if ext == "md" || ext == "markdown" {
624
+ let cleaned_path = if let Some(stripped) = path_str.strip_prefix("./") {
625
+ stripped.to_string()
626
+ } else {
627
+ path_str.clone()
628
+ };
629
+ file_paths.push(cleaned_path);
630
+ }
631
+ }
632
+ }
633
+ }
634
+
635
+ // If we found files directly, skip the walker
636
+ if !file_paths.is_empty() {
637
+ file_paths.sort();
638
+ file_paths.dedup();
639
+ return Ok(file_paths);
640
+ }
641
+ }
642
+
612
643
  // --- Execute Walk ---
613
644
 
614
645
  for result in walk_builder.build() {
@@ -628,7 +659,12 @@ fn find_markdown_files(
628
659
  file_paths.push(cleaned_path);
629
660
  }
630
661
  }
631
- Err(err) => eprintln!("Error walking directory: {err}"),
662
+ Err(err) => {
663
+ // Only show generic walking errors for directories, not for missing files
664
+ if is_discovery_mode {
665
+ eprintln!("Error walking directory: {err}");
666
+ }
667
+ }
632
668
  }
633
669
  }
634
670
 
@@ -7,16 +7,10 @@ use crate::utils::range_utils::{LineIndex, calculate_match_range};
7
7
 
8
8
  use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule, RuleCategory, Severity};
9
9
  use crate::utils::document_structure::DocumentStructure;
10
- use lazy_static::lazy_static;
11
- use regex::Regex;
10
+ // No regex patterns needed for this rule
12
11
  use std::collections::HashMap;
13
12
  use toml;
14
13
 
15
- lazy_static! {
16
- // Regex to match blockquote prefixes (one or more '>' with optional spaces)
17
- static ref BLOCKQUOTE_PREFIX: Regex = Regex::new(r"^(\s*>\s*)+").unwrap();
18
- }
19
-
20
14
  /// Rule MD005: Inconsistent indentation for list items at the same level
21
15
  #[derive(Clone)]
22
16
  pub struct MD005ListIndent;
@@ -2,8 +2,7 @@ use crate::utils::range_utils::LineIndex;
2
2
 
3
3
  use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule, RuleCategory, Severity};
4
4
  use crate::utils::document_structure::{DocumentStructure, DocumentStructureExtensions};
5
- use lazy_static::lazy_static;
6
- use regex::Regex;
5
+ use crate::utils::regex_cache::UNORDERED_LIST_MARKER_REGEX;
7
6
 
8
7
  /// Rule MD006: Consider starting bulleted lists at the leftmost column
9
8
  ///
@@ -16,14 +15,6 @@ use regex::Regex;
16
15
  #[derive(Clone)]
17
16
  pub struct MD006StartBullets;
18
17
 
19
- lazy_static! {
20
- // Pattern to match bullet list items: captures indentation, marker, and space after marker
21
- static ref BULLET_PATTERN: Regex = Regex::new(r"^(\s*)([*+-])(\s+)").unwrap();
22
-
23
- // Pattern to match code fence markers
24
- static ref CODE_FENCE_PATTERN: Regex = Regex::new(r"^(\s*)(```|~~~)").unwrap();
25
- }
26
-
27
18
  impl MD006StartBullets {
28
19
  /// Optimized check using centralized list blocks
29
20
  fn check_optimized(&self, ctx: &crate::lint_context::LintContext) -> LintResult {
@@ -84,7 +75,7 @@ impl MD006StartBullets {
84
75
 
85
76
  // For the fix, we need to replace the highlighted part with just the bullet marker
86
77
  let trimmed = line.trim_start();
87
- let bullet_part = if let Some(captures) = BULLET_PATTERN.captures(trimmed) {
78
+ let bullet_part = if let Some(captures) = UNORDERED_LIST_MARKER_REGEX.captures(trimmed) {
88
79
  let marker = captures.get(2).map_or("*", |m| m.as_str());
89
80
  format!("{marker} ")
90
81
  } else {
@@ -123,7 +114,7 @@ impl MD006StartBullets {
123
114
  }
124
115
  /// Checks if a line is a bullet list item and returns its indentation level
125
116
  fn is_bullet_list_item(line: &str) -> Option<usize> {
126
- if let Some(captures) = BULLET_PATTERN.captures(line) {
117
+ if let Some(captures) = UNORDERED_LIST_MARKER_REGEX.captures(line) {
127
118
  if let Some(indent) = captures.get(1) {
128
119
  return Some(indent.as_str().len());
129
120
  }
@@ -338,7 +329,7 @@ impl Rule for MD006StartBullets {
338
329
  let line = lines[line_idx];
339
330
  let trimmed = line.trim_start();
340
331
  // Extract just the bullet marker and normalize to single space
341
- let bullet_part = if let Some(captures) = BULLET_PATTERN.captures(trimmed) {
332
+ let bullet_part = if let Some(captures) = UNORDERED_LIST_MARKER_REGEX.captures(trimmed) {
342
333
  format!("{} ", captures.get(2).unwrap().as_str()) // Always use single space
343
334
  } else {
344
335
  "* ".to_string() // fallback
@@ -5,8 +5,7 @@ use crate::rule::{LintError, LintResult, LintWarning, Rule, RuleCategory, Severi
5
5
  use crate::rule_config_serde::RuleConfig;
6
6
  use crate::utils::document_structure::{DocumentStructure, DocumentStructureExtensions};
7
7
  use crate::utils::element_cache::{ElementCache, ListMarkerType};
8
- use lazy_static::lazy_static;
9
- use regex::Regex;
8
+ use crate::utils::regex_cache::{CODE_FENCE_REGEX, UNORDERED_LIST_MARKER_REGEX};
10
9
  use toml;
11
10
 
12
11
  mod md007_config;
@@ -17,10 +16,6 @@ pub struct MD007ULIndent {
17
16
  config: MD007Config,
18
17
  }
19
18
 
20
- lazy_static! {
21
- static ref LIST_ITEM_PATTERN: Regex = Regex::new(r"^(\s*)([*+-])(\s+)(.*)$").unwrap();
22
- }
23
-
24
19
  impl MD007ULIndent {
25
20
  pub fn new(indent: usize) -> Self {
26
21
  Self {
@@ -38,9 +33,7 @@ impl MD007ULIndent {
38
33
 
39
34
  #[allow(dead_code)]
40
35
  fn is_in_code_block(content: &str, line_idx: usize) -> bool {
41
- lazy_static! {
42
- static ref CODE_BLOCK_MARKER: Regex = Regex::new(r"^(```|~~~)").unwrap();
43
- }
36
+ // Use centralized code fence pattern
44
37
 
45
38
  let lines: Vec<&str> = content.lines().collect();
46
39
  let mut in_code_block = false;
@@ -50,7 +43,7 @@ impl MD007ULIndent {
50
43
  break;
51
44
  }
52
45
 
53
- if CODE_BLOCK_MARKER.is_match(line.trim_start()) {
46
+ if CODE_FENCE_REGEX.is_match(line.trim_start()) {
54
47
  in_code_block = !in_code_block;
55
48
  }
56
49
 
@@ -116,7 +109,7 @@ impl Rule for MD007ULIndent {
116
109
  let lines: Vec<&str> = content.lines().collect();
117
110
  if let Some(line) = lines.get(item.line_number - 1) {
118
111
  // Extract the marker and content
119
- if LIST_ITEM_PATTERN.captures(line).is_some() {
112
+ if UNORDERED_LIST_MARKER_REGEX.captures(line).is_some() {
120
113
  let correct_indent = " ".repeat(expected_indent);
121
114
 
122
115
  // Fix range should match warning range - only the problematic indentation
@@ -212,7 +205,7 @@ impl Rule for MD007ULIndent {
212
205
  let lines: Vec<&str> = content.lines().collect();
213
206
  if let Some(line) = lines.get(item.line_number - 1) {
214
207
  // Extract the marker and content
215
- if LIST_ITEM_PATTERN.captures(line).is_some() {
208
+ if UNORDERED_LIST_MARKER_REGEX.captures(line).is_some() {
216
209
  let correct_indent = " ".repeat(expected_indent);
217
210
 
218
211
  // Fix range should match warning range - only the problematic indentation
@@ -1,17 +1,12 @@
1
1
  use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule, RuleCategory, Severity};
2
2
  use crate::rule_config_serde::RuleConfig;
3
3
  use crate::utils::range_utils::{LineIndex, calculate_trailing_range};
4
- use crate::utils::regex_cache::get_cached_regex;
5
- use lazy_static::lazy_static;
6
- use regex::Regex;
4
+ use crate::utils::regex_cache::{ORDERED_LIST_MARKER_REGEX, UNORDERED_LIST_MARKER_REGEX, get_cached_regex};
7
5
 
8
6
  mod md009_config;
9
7
  use md009_config::MD009Config;
10
8
 
11
- lazy_static! {
12
- // Optimized regex patterns for fix operations
13
- static ref TRAILING_SPACES_REGEX: std::sync::Arc<Regex> = get_cached_regex(r"(?m) +$").unwrap();
14
- }
9
+ // No need for lazy_static, we'll use get_cached_regex directly
15
10
 
16
11
  #[derive(Debug, Clone, Default)]
17
12
  pub struct MD009TrailingSpaces {
@@ -52,12 +47,7 @@ impl MD009TrailingSpaces {
52
47
 
53
48
  if let Some(prev) = prev_line {
54
49
  // Check for unordered list markers (*, -, +) with proper formatting
55
- lazy_static! {
56
- static ref LIST_MARKER_REGEX: Regex = Regex::new(r"^(\s*)[-*+]\s+").unwrap();
57
- static ref ORDERED_LIST_REGEX: Regex = Regex::new(r"^(\s*)\d+[.)]\s+").unwrap();
58
- }
59
-
60
- LIST_MARKER_REGEX.is_match(prev) || ORDERED_LIST_REGEX.is_match(prev)
50
+ UNORDERED_LIST_MARKER_REGEX.is_match(prev) || ORDERED_LIST_MARKER_REGEX.is_match(prev)
61
51
  } else {
62
52
  false
63
53
  }
@@ -204,7 +194,10 @@ impl Rule for MD009TrailingSpaces {
204
194
  // For simple cases (strict mode), use fast regex approach
205
195
  if self.config.strict {
206
196
  // In strict mode, remove ALL trailing spaces everywhere
207
- return Ok(TRAILING_SPACES_REGEX.replace_all(content, "").to_string());
197
+ return Ok(get_cached_regex(r"(?m) +$")
198
+ .unwrap()
199
+ .replace_all(content, "")
200
+ .to_string());
208
201
  }
209
202
 
210
203
  // For complex cases, we need line-by-line processing but with optimizations
@@ -4,17 +4,12 @@ use crate::rule_config_serde::RuleConfig;
4
4
  ///
5
5
  /// See [docs/md010.md](../../docs/md010.md) for full documentation, configuration, and examples.
6
6
  use crate::utils::range_utils::{LineIndex, calculate_match_range};
7
- use lazy_static::lazy_static;
8
- use regex::Regex;
7
+ use crate::utils::regex_cache::{HTML_COMMENT_END, HTML_COMMENT_START};
9
8
 
10
9
  mod md010_config;
11
10
  use md010_config::MD010Config;
12
11
 
13
- lazy_static! {
14
- // Pattern to detect HTML comments (start and end tags separately)
15
- static ref HTML_COMMENT_START: Regex = Regex::new(r"<!--").unwrap();
16
- static ref HTML_COMMENT_END: Regex = Regex::new(r"-->").unwrap();
17
- }
12
+ // HTML comment patterns are now imported from regex_cache
18
13
 
19
14
  /// Rule MD010: Hard tabs
20
15
  #[derive(Clone, Default)]
@@ -14,7 +14,6 @@ lazy_static! {
14
14
  static ref REVERSED_LINK_CHECK_REGEX: Regex = Regex::new(
15
15
  r"\(([^)]*(?:\([^)]*\)[^)]*)*)\)\[([^\]]+)\]"
16
16
  ).unwrap();
17
- static ref CODE_FENCE_REGEX: Regex = Regex::new(r"^(\s*)(```|~~~)").unwrap();
18
17
 
19
18
  // Pattern to detect escaped brackets and parentheses
20
19
  static ref ESCAPED_CHARS: Regex = Regex::new(r"\\[\[\]()]").unwrap();
@@ -5,35 +5,14 @@ use crate::rule::{LintError, LintResult, LintWarning, Rule, RuleCategory, Severi
5
5
  use crate::rule_config_serde::RuleConfig;
6
6
  use crate::utils::document_structure::{DocumentStructure, DocumentStructureExtensions};
7
7
  use crate::utils::range_utils::calculate_excess_range;
8
- use lazy_static::lazy_static;
9
- use regex::Regex;
8
+ use crate::utils::regex_cache::{
9
+ IMAGE_REF_PATTERN, INLINE_LINK_REGEX as MARKDOWN_LINK_PATTERN, LINK_REF_PATTERN, URL_IN_TEXT, URL_PATTERN,
10
+ };
10
11
  use toml;
11
12
 
12
13
  pub mod md013_config;
13
14
  use md013_config::MD013Config;
14
15
 
15
- lazy_static! {
16
- static ref URL_PATTERN: Regex = Regex::new(r"^https?://\S+$").unwrap();
17
- static ref IMAGE_REF_PATTERN: Regex = Regex::new(r"^!\[.*?\]\[.*?\]$" ).unwrap();
18
- static ref LINK_REF_PATTERN: Regex = Regex::new(r"^\[.*?\]:\s*https?://\S+$").unwrap();
19
-
20
- // Pattern to find URLs anywhere in text
21
- static ref URL_IN_TEXT: Regex = Regex::new(r"https?://\S+").unwrap();
22
-
23
- // Pattern to find markdown links [text](url) for URL exclusion
24
- static ref MARKDOWN_LINK_PATTERN: Regex = Regex::new(r"\[([^\]]*)\]\(([^)]+)\)").unwrap();
25
-
26
- // Sentence splitting patterns
27
- static ref SENTENCE_END: Regex = Regex::new(r"[.!?]\s+[A-Z]").unwrap();
28
- static ref ABBREVIATION: Regex = Regex::new(r"\b(?:Mr|Mrs|Ms|Dr|Prof|Sr|Jr|vs|etc|i\.e|e\.g|Inc|Corp|Ltd|Co|St|Ave|Blvd|Rd|Ph\.D|M\.D|B\.A|M\.A|Ph\.D|U\.S|U\.K|U\.N|N\.Y|L\.A|D\.C)\.\s+[A-Z]").unwrap();
29
- static ref DECIMAL_NUMBER: Regex = Regex::new(r"\d+\.\s*\d+").unwrap();
30
- static ref LIST_ITEM: Regex = Regex::new(r"^\s*\d+\.\s+").unwrap();
31
-
32
- // Link detection patterns
33
- static ref INLINE_LINK: Regex = Regex::new(r"\[([^\]]*)\]\(([^)]*)\)").unwrap();
34
- static ref REFERENCE_LINK: Regex = Regex::new(r"\[([^\]]*)\]\[([^\]]*)\]").unwrap();
35
- }
36
-
37
16
  #[derive(Clone, Default)]
38
17
  pub struct MD013LineLength {
39
18
  config: MD013Config,
@@ -7,16 +7,9 @@ use lazy_static::lazy_static;
7
7
  use regex::Regex;
8
8
 
9
9
  lazy_static! {
10
- static ref CLOSED_ATX_NO_SPACE_PATTERN: Regex =
11
- Regex::new(r"^(\s*)(#+)([^#\s].*?)([^#\s])(#+)\s*$").unwrap();
12
- static ref CLOSED_ATX_NO_SPACE_START_PATTERN: Regex =
13
- Regex::new(r"^(\s*)(#+)([^#\s].*?)\s(#+)\s*$").unwrap();
14
- static ref CLOSED_ATX_NO_SPACE_END_PATTERN: Regex =
15
- Regex::new(r"^(\s*)(#+)\s(.*?)([^#\s])(#+)\s*$").unwrap();
16
-
17
- // Matches code fence blocks
18
- static ref CODE_FENCE_PATTERN: Regex =
19
- Regex::new(r"^(\s*)(`{3,}|~{3,})").unwrap();
10
+ static ref CLOSED_ATX_NO_SPACE_PATTERN: Regex = Regex::new(r"^(\s*)(#+)([^#\s].*?)([^#\s])(#+)\s*$").unwrap();
11
+ static ref CLOSED_ATX_NO_SPACE_START_PATTERN: Regex = Regex::new(r"^(\s*)(#+)([^#\s].*?)\s(#+)\s*$").unwrap();
12
+ static ref CLOSED_ATX_NO_SPACE_END_PATTERN: Regex = Regex::new(r"^(\s*)(#+)\s(.*?)([^#\s])(#+)\s*$").unwrap();
20
13
  }
21
14
 
22
15
  #[derive(Clone)]
@@ -3,26 +3,14 @@
3
3
  /// See [docs/md025.md](../../docs/md025.md) for full documentation, configuration, and examples.
4
4
  use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule, RuleCategory, Severity};
5
5
  use crate::utils::range_utils::{LineIndex, calculate_match_range};
6
- use lazy_static::lazy_static;
7
- use regex::Regex;
6
+ use crate::utils::regex_cache::{
7
+ HR_ASTERISK, HR_DASH, HR_SPACED_ASTERISK, HR_SPACED_DASH, HR_SPACED_UNDERSCORE, HR_UNDERSCORE,
8
+ };
8
9
  use toml;
9
10
 
10
11
  mod md025_config;
11
12
  use md025_config::MD025Config;
12
13
 
13
- lazy_static! {
14
- // Pattern for quick check if content has any headings at all
15
- static ref HEADING_CHECK: Regex = Regex::new(r"(?m)^(?:\s*)#").unwrap();
16
-
17
- // Horizontal rule patterns (from MD035)
18
- static ref HR_DASH: Regex = Regex::new(r"^\-{3,}\s*$").unwrap();
19
- static ref HR_ASTERISK: Regex = Regex::new(r"^\*{3,}\s*$").unwrap();
20
- static ref HR_UNDERSCORE: Regex = Regex::new(r"^_{3,}\s*$").unwrap();
21
- static ref HR_SPACED_DASH: Regex = Regex::new(r"^(\-\s+){2,}\-\s*$").unwrap();
22
- static ref HR_SPACED_ASTERISK: Regex = Regex::new(r"^(\*\s+){2,}\*\s*$").unwrap();
23
- static ref HR_SPACED_UNDERSCORE: Regex = Regex::new(r"^(_\s+){2,}_\s*$").unwrap();
24
- }
25
-
26
14
  #[derive(Clone, Default)]
27
15
  pub struct MD025SingleTitle {
28
16
  config: MD025Config,
@@ -4,13 +4,12 @@
4
4
  use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule, RuleCategory, Severity};
5
5
  use crate::utils::document_structure::{DocumentStructure, DocumentStructureExtensions};
6
6
  use crate::utils::range_utils::LineIndex;
7
+ use crate::utils::regex_cache::ORDERED_LIST_MARKER_REGEX;
7
8
  use lazy_static::lazy_static;
8
9
  use regex::Regex;
9
10
  use serde::{Deserialize, Serialize};
10
11
 
11
12
  lazy_static! {
12
- static ref ORDERED_LIST_ITEM_REGEX: Regex = Regex::new(r"^(\s*)\d+\.\s").unwrap();
13
- static ref LIST_NUMBER_REGEX: Regex = Regex::new(r"^\s*(\d+)\.\s").unwrap();
14
13
  static ref FIX_LINE_REGEX: Regex = Regex::new(r"^(\s*)\d+(\.\s.*)$").unwrap();
15
14
  }
16
15
 
@@ -43,9 +42,9 @@ impl MD029OrderedListPrefix {
43
42
 
44
43
  #[inline]
45
44
  fn get_list_number(line: &str) -> Option<usize> {
46
- LIST_NUMBER_REGEX
45
+ ORDERED_LIST_MARKER_REGEX
47
46
  .captures(line)
48
- .and_then(|cap| cap[1].parse::<usize>().ok())
47
+ .and_then(|cap| cap[2].parse::<usize>().ok())
49
48
  }
50
49
 
51
50
  #[inline]
@@ -93,7 +92,7 @@ impl Rule for MD029OrderedListPrefix {
93
92
  }
94
93
 
95
94
  // Quick check for any ordered list markers before processing
96
- if !ctx.content.contains('.') || !ctx.content.lines().any(|line| ORDERED_LIST_ITEM_REGEX.is_match(line)) {
95
+ if !ctx.content.contains('.') || !ctx.content.lines().any(|line| ORDERED_LIST_MARKER_REGEX.is_match(line)) {
97
96
  return Ok(Vec::new());
98
97
  }
99
98
 
@@ -4,12 +4,6 @@
4
4
  use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule, RuleCategory, Severity};
5
5
  use crate::utils::document_structure::{DocumentStructure, DocumentStructureExtensions};
6
6
  use crate::utils::range_utils::{LineIndex, calculate_line_range};
7
- use lazy_static::lazy_static;
8
- use regex::Regex;
9
-
10
- lazy_static! {
11
- static ref CODE_FENCE: Regex = Regex::new(r"^(```|~~~)").unwrap();
12
- }
13
7
 
14
8
  /// Rule MD031: Fenced code blocks should be surrounded by blank lines
15
9
  #[derive(Clone)]
@@ -2,11 +2,11 @@ use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule, RuleCategory, S
2
2
  use crate::utils::document_structure::document_structure_from_str;
3
3
  use crate::utils::document_structure::{DocumentStructure, DocumentStructureExtensions};
4
4
  use crate::utils::range_utils::{LineIndex, calculate_line_range};
5
+ use crate::utils::regex_cache::BLOCKQUOTE_PREFIX_RE;
5
6
  use lazy_static::lazy_static;
6
7
  use regex::Regex;
7
8
 
8
9
  lazy_static! {
9
- static ref BLOCKQUOTE_PREFIX_RE: Regex = Regex::new(r"^(\s*>)+(\s*)").unwrap();
10
10
  static ref BLANK_LINE_RE: Regex = Regex::new(r"^\s*$").unwrap();
11
11
  }
12
12
 
@@ -6,6 +6,7 @@ use crate::rule::{
6
6
  };
7
7
  use crate::utils::early_returns;
8
8
  use crate::utils::range_utils::calculate_url_range;
9
+ use crate::utils::regex_cache::EMAIL_PATTERN;
9
10
 
10
11
  use crate::lint_context::LintContext;
11
12
  use fancy_regex::Regex as FancyRegex;
@@ -30,9 +31,6 @@ lazy_static! {
30
31
  // Updated to support IPv6 addresses
31
32
  static ref ANGLE_LINK_PATTERN: Regex = Regex::new(r#"<((?:https?|ftps?)://(?:\[[0-9a-fA-F:]+(?:%[a-zA-Z0-9]+)?\]|[^>]+)|[^@\s]+@[^@\s]+\.[^@\s>]+)>"#).unwrap();
32
33
 
33
- // Pattern to match code fences
34
- static ref CODE_FENCE_RE: Regex = Regex::new(r#"^(`{3,}|~{3,})"#).unwrap();
35
-
36
34
  // Add regex to identify lines containing only a badge link
37
35
  static ref BADGE_LINK_LINE: Regex = Regex::new(r#"^\s*\[!\[[^\]]*\]\([^)]*\)\]\([^)]*\)\s*$"#).unwrap();
38
36
 
@@ -55,10 +53,6 @@ lazy_static! {
55
53
  // Note: This is permissive to match markdownlint behavior, allowing technically invalid IPv6 for examples
56
54
  static ref IPV6_URL_REGEX: Regex = Regex::new(r#"(https?|ftps?)://\[[0-9a-fA-F:%.\-a-zA-Z]+\](?::\d+)?(?:/[^\s<>\[\]()\\'\"`]*)?(?:\?[^\s<>\[\]()\\'\"`]*)?(?:#[^\s<>\[\]()\\'\"`]*)?"#).unwrap();
57
55
 
58
- // Add regex for email addresses - matches markdownlint behavior
59
- // Detects email addresses that should be autolinked like URLs
60
- static ref EMAIL_REGEX: Regex = Regex::new(r#"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"#).unwrap();
61
-
62
56
  // Add regex for reference definitions
63
57
  // Updated to support IPv6 addresses
64
58
  static ref REFERENCE_DEF_RE: Regex = Regex::new(r"^\s*\[[^\]]+\]:\s*(?:https?|ftps?)://\S+$").unwrap();
@@ -219,7 +213,7 @@ impl MD034NoBareUrls {
219
213
  }
220
214
 
221
215
  // Check for emails in this line
222
- for email_match in EMAIL_REGEX.find_iter(line_content) {
216
+ for email_match in EMAIL_PATTERN.find_iter(line_content) {
223
217
  let global_start = line_info.byte_offset + email_match.start();
224
218
  let global_end = line_info.byte_offset + email_match.end();
225
219
  all_matches.push((global_start, global_end, true));
@@ -383,7 +377,7 @@ impl MD034NoBareUrls {
383
377
  }
384
378
 
385
379
  // Check for email addresses
386
- for email_match in EMAIL_REGEX.find_iter(text_str) {
380
+ for email_match in EMAIL_PATTERN.find_iter(text_str) {
387
381
  let email_start = email_match.start();
388
382
  let email_end = email_match.end();
389
383
  let before = if email_start == 0 {
@@ -6,22 +6,14 @@
6
6
  use crate::utils::range_utils::{LineIndex, calculate_line_range};
7
7
 
8
8
  use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule, Severity};
9
- use lazy_static::lazy_static;
10
- use regex::Regex;
9
+ use crate::utils::regex_cache::{
10
+ HR_ASTERISK, HR_DASH, HR_SPACED_ASTERISK, HR_SPACED_DASH, HR_SPACED_UNDERSCORE, HR_UNDERSCORE,
11
+ };
11
12
  use toml;
12
13
 
13
14
  mod md035_config;
14
15
  use md035_config::MD035Config;
15
16
 
16
- lazy_static! {
17
- static ref HR_DASH: Regex = Regex::new(r"^-{3,}\s*$").unwrap();
18
- static ref HR_ASTERISK: Regex = Regex::new(r"^\*{3,}\s*$").unwrap();
19
- static ref HR_UNDERSCORE: Regex = Regex::new(r"^_{3,}\s*$").unwrap();
20
- static ref HR_SPACED_DASH: Regex = Regex::new(r"^(-\s+){2,}-\s*$").unwrap();
21
- static ref HR_SPACED_ASTERISK: Regex = Regex::new(r"^(\*\s+){2,}\*\s*$").unwrap();
22
- static ref HR_SPACED_UNDERSCORE: Regex = Regex::new(r"^(_\s+){2,}_\s*$").unwrap();
23
- }
24
-
25
17
  /// Represents the style for horizontal rules
26
18
  #[derive(Clone, Default)]
27
19
  pub struct MD035HRStyle {
@@ -6,13 +6,7 @@ use crate::utils::document_structure::{DocumentStructure, DocumentStructureExten
6
6
  use crate::utils::emphasis_utils::{
7
7
  EmphasisSpan, find_emphasis_markers, find_emphasis_spans, has_doc_patterns, replace_inline_code,
8
8
  };
9
- use lazy_static::lazy_static;
10
- use regex::Regex;
11
-
12
- lazy_static! {
13
- // List markers pattern - used to avoid confusion with emphasis
14
- static ref LIST_MARKER: Regex = Regex::new(r"^\s*[*+-]\s+").unwrap();
15
- }
9
+ use crate::utils::regex_cache::UNORDERED_LIST_MARKER_REGEX;
16
10
 
17
11
  /// Check if an emphasis span has spacing issues that should be flagged
18
12
  #[inline]
@@ -198,9 +192,9 @@ impl MD037NoSpaceInEmphasis {
198
192
 
199
193
  // Optimized list detection with fast path
200
194
  if (line.starts_with(' ') || line.starts_with('*') || line.starts_with('+') || line.starts_with('-'))
201
- && LIST_MARKER.is_match(line)
195
+ && UNORDERED_LIST_MARKER_REGEX.is_match(line)
202
196
  {
203
- if let Some(caps) = LIST_MARKER.captures(line) {
197
+ if let Some(caps) = UNORDERED_LIST_MARKER_REGEX.captures(line) {
204
198
  if let Some(full_match) = caps.get(0) {
205
199
  let list_marker_end = full_match.end();
206
200
  if list_marker_end < line.len() {
@@ -1,16 +1,9 @@
1
- use crate::utils::range_utils::{LineIndex, calculate_line_range};
2
-
3
1
  use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule, Severity};
4
2
  use crate::rules::front_matter_utils::FrontMatterUtils;
5
- use fancy_regex::Regex as FancyRegex;
6
- use lazy_static::lazy_static;
3
+ use crate::utils::range_utils::{LineIndex, calculate_line_range};
4
+ use crate::utils::regex_cache::HTML_HEADING_PATTERN;
7
5
  use regex::Regex;
8
6
 
9
- lazy_static! {
10
- /// Pattern for HTML heading tags
11
- static ref HTML_HEADING_PATTERN: FancyRegex = FancyRegex::new(r"^\s*<h([1-6])(?:\s[^>]*)?>.*</h\1>\s*$").unwrap();
12
- }
13
-
14
7
  /// Rule MD041: First line in file should be a top-level heading
15
8
  ///
16
9
  /// See [docs/md041.md](../../docs/md041.md) for full documentation, configuration, and examples.
@@ -1,14 +1,9 @@
1
1
  use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule, Severity};
2
- use lazy_static::lazy_static;
3
- use regex::Regex;
2
+ use crate::utils::regex_cache::IMAGE_REGEX;
4
3
 
5
4
  pub mod md045_config;
6
5
  use md045_config::MD045Config;
7
6
 
8
- lazy_static! {
9
- static ref IMAGE_REGEX: Regex = Regex::new(r"!\[([^\]]*)\](\([^)]+\))").unwrap();
10
- }
11
-
12
7
  /// Rule MD045: Images should have alt text
13
8
  ///
14
9
  /// See [docs/md045.md](../../docs/md045.md) for full documentation, configuration, and examples.
@@ -140,7 +135,7 @@ impl Rule for MD045NoAltText {
140
135
  for caps in IMAGE_REGEX.captures_iter(content) {
141
136
  let full_match = caps.get(0).unwrap();
142
137
  let alt_text = caps.get(1).map_or("", |m| m.as_str());
143
- let url_part = caps.get(2).map_or("", |m| m.as_str());
138
+ let url = caps.get(2).map_or("", |m| m.as_str());
144
139
 
145
140
  // Add text before this match
146
141
  result.push_str(&content[last_end..full_match.start()]);
@@ -151,8 +146,10 @@ impl Rule for MD045NoAltText {
151
146
  result.push_str(&caps[0]);
152
147
  } else if alt_text.trim().is_empty() {
153
148
  // Generate a more helpful placeholder based on the image URL
154
- let placeholder = self.generate_placeholder_text(url_part);
155
- result.push_str(&format!("![{placeholder}]{url_part}"));
149
+ // The centralized regex captures just the URL, so we need to add parentheses
150
+ let url_part = format!("({url})");
151
+ let placeholder = self.generate_placeholder_text(&url_part);
152
+ result.push_str(&format!("![{placeholder}]({url})"));
156
153
  } else {
157
154
  // Keep the original if alt text is not empty
158
155
  result.push_str(&caps[0]);