rumdl 0.0.73__tar.gz → 0.0.74__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rumdl might be problematic. Click here for more details.

Files changed (263) hide show
  1. {rumdl-0.0.73 → rumdl-0.0.74}/Cargo.lock +1 -1
  2. {rumdl-0.0.73 → rumdl-0.0.74}/Cargo.toml +1 -1
  3. {rumdl-0.0.73 → rumdl-0.0.74}/PKG-INFO +1 -1
  4. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md032_blanks_around_lists.rs +36 -2
  5. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md042_no_empty_links.rs +7 -49
  6. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md051_link_fragments.rs +74 -51
  7. {rumdl-0.0.73 → rumdl-0.0.74}/src/utils/document_structure.rs +70 -68
  8. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md033_test.rs +321 -0
  9. rumdl-0.0.74/tests/rules/md042_test.rs +291 -0
  10. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md051_test.rs +128 -0
  11. rumdl-0.0.73/tests/rules/md042_test.rs +0 -84
  12. {rumdl-0.0.73 → rumdl-0.0.74}/.rumdl.toml +0 -0
  13. {rumdl-0.0.73 → rumdl-0.0.74}/MANIFEST.in +0 -0
  14. {rumdl-0.0.73 → rumdl-0.0.74}/Makefile +0 -0
  15. {rumdl-0.0.73 → rumdl-0.0.74}/README.md +0 -0
  16. {rumdl-0.0.73 → rumdl-0.0.74}/assets/logo.png +0 -0
  17. {rumdl-0.0.73 → rumdl-0.0.74}/benches/fix_performance.rs +0 -0
  18. {rumdl-0.0.73 → rumdl-0.0.74}/benches/range_performance.rs +0 -0
  19. {rumdl-0.0.73 → rumdl-0.0.74}/benches/range_utils_benchmark.rs +0 -0
  20. {rumdl-0.0.73 → rumdl-0.0.74}/benches/rule_performance.rs +0 -0
  21. {rumdl-0.0.73 → rumdl-0.0.74}/benches/simple_fix_bench.rs +0 -0
  22. {rumdl-0.0.73 → rumdl-0.0.74}/docs/RULES.md +0 -0
  23. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md001.md +0 -0
  24. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md002.md +0 -0
  25. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md003.md +0 -0
  26. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md004.md +0 -0
  27. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md005.md +0 -0
  28. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md006.md +0 -0
  29. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md007.md +0 -0
  30. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md009.md +0 -0
  31. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md010.md +0 -0
  32. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md011.md +0 -0
  33. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md012.md +0 -0
  34. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md013.md +0 -0
  35. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md014.md +0 -0
  36. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md018.md +0 -0
  37. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md019.md +0 -0
  38. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md020.md +0 -0
  39. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md021.md +0 -0
  40. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md022.md +0 -0
  41. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md023.md +0 -0
  42. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md024.md +0 -0
  43. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md025.md +0 -0
  44. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md026.md +0 -0
  45. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md027.md +0 -0
  46. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md028.md +0 -0
  47. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md029.md +0 -0
  48. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md030.md +0 -0
  49. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md031.md +0 -0
  50. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md032.md +0 -0
  51. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md033.md +0 -0
  52. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md034.md +0 -0
  53. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md035.md +0 -0
  54. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md036.md +0 -0
  55. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md037.md +0 -0
  56. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md038.md +0 -0
  57. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md039.md +0 -0
  58. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md040.md +0 -0
  59. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md041.md +0 -0
  60. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md042.md +0 -0
  61. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md043.md +0 -0
  62. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md044.md +0 -0
  63. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md045.md +0 -0
  64. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md046.md +0 -0
  65. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md047.md +0 -0
  66. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md048.md +0 -0
  67. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md049.md +0 -0
  68. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md050.md +0 -0
  69. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md051.md +0 -0
  70. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md052.md +0 -0
  71. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md053.md +0 -0
  72. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md054.md +0 -0
  73. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md055.md +0 -0
  74. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md056.md +0 -0
  75. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md057.md +0 -0
  76. {rumdl-0.0.73 → rumdl-0.0.74}/docs/md058.md +0 -0
  77. {rumdl-0.0.73 → rumdl-0.0.74}/issues/plan-rule-parity-with-markdownlint.md +0 -0
  78. {rumdl-0.0.73 → rumdl-0.0.74}/parity_check.py +0 -0
  79. {rumdl-0.0.73 → rumdl-0.0.74}/pyproject.toml +0 -0
  80. {rumdl-0.0.73 → rumdl-0.0.74}/python/MANIFEST.in +0 -0
  81. {rumdl-0.0.73 → rumdl-0.0.74}/python/PYTHON-README.md +0 -0
  82. {rumdl-0.0.73 → rumdl-0.0.74}/python/rumdl/__init__.py +0 -0
  83. {rumdl-0.0.73 → rumdl-0.0.74}/python/rumdl/__main__.py +0 -0
  84. {rumdl-0.0.73 → rumdl-0.0.74}/python/rumdl/py.typed +0 -0
  85. {rumdl-0.0.73 → rumdl-0.0.74}/rumdl.toml.example +0 -0
  86. {rumdl-0.0.73 → rumdl-0.0.74}/src/config.rs +0 -0
  87. {rumdl-0.0.73 → rumdl-0.0.74}/src/init.rs +0 -0
  88. {rumdl-0.0.73 → rumdl-0.0.74}/src/lib.rs +0 -0
  89. {rumdl-0.0.73 → rumdl-0.0.74}/src/lint_context.rs +0 -0
  90. {rumdl-0.0.73 → rumdl-0.0.74}/src/lsp/mod.rs +0 -0
  91. {rumdl-0.0.73 → rumdl-0.0.74}/src/lsp/server.rs +0 -0
  92. {rumdl-0.0.73 → rumdl-0.0.74}/src/lsp/types.rs +0 -0
  93. {rumdl-0.0.73 → rumdl-0.0.74}/src/main.rs +0 -0
  94. {rumdl-0.0.73 → rumdl-0.0.74}/src/markdownlint_config.rs +0 -0
  95. {rumdl-0.0.73 → rumdl-0.0.74}/src/parallel.rs +0 -0
  96. {rumdl-0.0.73 → rumdl-0.0.74}/src/performance.rs +0 -0
  97. {rumdl-0.0.73 → rumdl-0.0.74}/src/profiling.rs +0 -0
  98. {rumdl-0.0.73 → rumdl-0.0.74}/src/python.rs +0 -0
  99. {rumdl-0.0.73 → rumdl-0.0.74}/src/rule.rs +0 -0
  100. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/blockquote_utils.rs +0 -0
  101. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/code_block_utils.rs +0 -0
  102. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/code_fence_utils.rs +0 -0
  103. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/emphasis_style.rs +0 -0
  104. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/front_matter_utils.rs +0 -0
  105. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/heading_utils.rs +0 -0
  106. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/list_utils.rs +0 -0
  107. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md001_heading_increment.rs +0 -0
  108. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md002_first_heading_h1.rs +0 -0
  109. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md003_heading_style.rs +0 -0
  110. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md004_unordered_list_style.rs +0 -0
  111. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md005_list_indent.rs +0 -0
  112. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md006_start_bullets.rs +0 -0
  113. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md007_ul_indent.rs +0 -0
  114. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md009_trailing_spaces.rs +0 -0
  115. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md010_no_hard_tabs.rs +0 -0
  116. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md011_no_reversed_links.rs +0 -0
  117. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md012_no_multiple_blanks.rs +0 -0
  118. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md013_line_length.rs +0 -0
  119. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md014_commands_show_output.rs +0 -0
  120. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md018_no_missing_space_atx.rs +0 -0
  121. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md019_no_multiple_space_atx.rs +0 -0
  122. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md020_no_missing_space_closed_atx.rs +0 -0
  123. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
  124. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md022_blanks_around_headings.rs +0 -0
  125. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md023_heading_start_left.rs +0 -0
  126. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md024_no_duplicate_heading.rs +0 -0
  127. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md025_single_title.rs +0 -0
  128. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md026_no_trailing_punctuation.rs +0 -0
  129. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md027_multiple_spaces_blockquote.rs +0 -0
  130. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md028_no_blanks_blockquote.rs +0 -0
  131. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md029_ordered_list_prefix.rs +0 -0
  132. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md030_list_marker_space.rs +0 -0
  133. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md031_blanks_around_fences.rs +0 -0
  134. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md033_no_inline_html.rs +0 -0
  135. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md034_no_bare_urls.rs +0 -0
  136. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md035_hr_style.rs +0 -0
  137. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md036_no_emphasis_only_first.rs +0 -0
  138. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md037_spaces_around_emphasis.rs +0 -0
  139. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md038_no_space_in_code.rs +0 -0
  140. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md039_no_space_in_links.rs +0 -0
  141. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md040_fenced_code_language.rs +0 -0
  142. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md041_first_line_heading.rs +0 -0
  143. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md043_required_headings.rs +0 -0
  144. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md044_proper_names.rs +0 -0
  145. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md045_no_alt_text.rs +0 -0
  146. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md046_code_block_style.rs +0 -0
  147. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md047_single_trailing_newline.rs +0 -0
  148. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md048_code_fence_style.rs +0 -0
  149. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md049_emphasis_style.rs +0 -0
  150. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md050_strong_style.rs +0 -0
  151. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md052_reference_links_images.rs +0 -0
  152. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md053_link_image_reference_definitions.rs +0 -0
  153. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md054_link_image_style.rs +0 -0
  154. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md055_table_pipe_style.rs +0 -0
  155. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md056_table_column_count.rs +0 -0
  156. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md057_existing_relative_links.rs +0 -0
  157. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/md058_blanks_around_tables.rs +0 -0
  158. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/mod.rs +0 -0
  159. {rumdl-0.0.73 → rumdl-0.0.74}/src/rules/strong_style.rs +0 -0
  160. {rumdl-0.0.73 → rumdl-0.0.74}/src/utils/ast_utils.rs +0 -0
  161. {rumdl-0.0.73 → rumdl-0.0.74}/src/utils/code_block_utils.rs +0 -0
  162. {rumdl-0.0.73 → rumdl-0.0.74}/src/utils/early_returns.rs +0 -0
  163. {rumdl-0.0.73 → rumdl-0.0.74}/src/utils/element_cache.rs +0 -0
  164. {rumdl-0.0.73 → rumdl-0.0.74}/src/utils/markdown_elements.rs +0 -0
  165. {rumdl-0.0.73 → rumdl-0.0.74}/src/utils/mod.rs +0 -0
  166. {rumdl-0.0.73 → rumdl-0.0.74}/src/utils/range_utils.rs +0 -0
  167. {rumdl-0.0.73 → rumdl-0.0.74}/src/utils/regex_cache.rs +0 -0
  168. {rumdl-0.0.73 → rumdl-0.0.74}/src/utils/string_interner.rs +0 -0
  169. {rumdl-0.0.73 → rumdl-0.0.74}/src/utils/table_utils.rs +0 -0
  170. {rumdl-0.0.73 → rumdl-0.0.74}/tests/advanced_integration_tests.rs +0 -0
  171. {rumdl-0.0.73 → rumdl-0.0.74}/tests/character_ranges/additional_tests.rs +0 -0
  172. {rumdl-0.0.73 → rumdl-0.0.74}/tests/character_ranges/basic_tests.rs +0 -0
  173. {rumdl-0.0.73 → rumdl-0.0.74}/tests/character_ranges/comprehensive_tests.rs +0 -0
  174. {rumdl-0.0.73 → rumdl-0.0.74}/tests/character_ranges/extended_tests.rs +0 -0
  175. {rumdl-0.0.73 → rumdl-0.0.74}/tests/character_ranges/mod.rs +0 -0
  176. {rumdl-0.0.73 → rumdl-0.0.74}/tests/character_ranges/unicode_utils.rs +0 -0
  177. {rumdl-0.0.73 → rumdl-0.0.74}/tests/cli_duplication_test.rs +0 -0
  178. {rumdl-0.0.73 → rumdl-0.0.74}/tests/cli_integration_tests.rs +0 -0
  179. {rumdl-0.0.73 → rumdl-0.0.74}/tests/commonmark_compliance_tests.rs +0 -0
  180. {rumdl-0.0.73 → rumdl-0.0.74}/tests/comprehensive_integration_tests.rs +0 -0
  181. {rumdl-0.0.73 → rumdl-0.0.74}/tests/config_application_tests.rs +0 -0
  182. {rumdl-0.0.73 → rumdl-0.0.74}/tests/config_tests.rs +0 -0
  183. {rumdl-0.0.73 → rumdl-0.0.74}/tests/init_command_test.rs +0 -0
  184. {rumdl-0.0.73 → rumdl-0.0.74}/tests/init_tests.rs +0 -0
  185. {rumdl-0.0.73 → rumdl-0.0.74}/tests/integration_tests.rs +0 -0
  186. {rumdl-0.0.73 → rumdl-0.0.74}/tests/json_output_test.rs +0 -0
  187. {rumdl-0.0.73 → rumdl-0.0.74}/tests/lib.rs +0 -0
  188. {rumdl-0.0.73 → rumdl-0.0.74}/tests/lsp_integration_tests.rs +0 -0
  189. {rumdl-0.0.73 → rumdl-0.0.74}/tests/lsp_tests.rs +0 -0
  190. {rumdl-0.0.73 → rumdl-0.0.74}/tests/markdownlint_cli_integration.rs +0 -0
  191. {rumdl-0.0.73 → rumdl-0.0.74}/tests/markdownlint_config_test.rs +0 -0
  192. {rumdl-0.0.73 → rumdl-0.0.74}/tests/md030_edge_cases.md +0 -0
  193. {rumdl-0.0.73 → rumdl-0.0.74}/tests/output_format_tests.rs +0 -0
  194. {rumdl-0.0.73 → rumdl-0.0.74}/tests/perf_check.rs +0 -0
  195. {rumdl-0.0.73 → rumdl-0.0.74}/tests/pyproject_config_tests.rs +0 -0
  196. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md001_test.rs +0 -0
  197. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md001_unicode_test.rs +0 -0
  198. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md002_test.rs +0 -0
  199. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md003_test.rs +0 -0
  200. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md004_test.rs +0 -0
  201. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md005_test.rs +0 -0
  202. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md006_test.rs +0 -0
  203. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md006_unicode_test.rs +0 -0
  204. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md007_test.rs +0 -0
  205. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md009_test.rs +0 -0
  206. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md010_test.rs +0 -0
  207. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md011_test.rs +0 -0
  208. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md012_test.rs +0 -0
  209. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md013_test.rs +0 -0
  210. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md014_test.rs +0 -0
  211. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md018_test.rs +0 -0
  212. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md019_test.rs +0 -0
  213. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md020_test.rs +0 -0
  214. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md021_test.rs +0 -0
  215. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md022_test.rs +0 -0
  216. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md023_extended_test.rs +0 -0
  217. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md023_test.rs +0 -0
  218. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md024_test.rs +0 -0
  219. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md025_test.rs +0 -0
  220. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md026_test.rs +0 -0
  221. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md027_test.rs +0 -0
  222. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md028_test.rs +0 -0
  223. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md029_test.rs +0 -0
  224. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md030_test.rs +0 -0
  225. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md031_test.rs +0 -0
  226. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md032_test.rs +0 -0
  227. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md033_extended_test.rs +0 -0
  228. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md034_test.rs +0 -0
  229. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md035_test.rs +0 -0
  230. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md036_test.rs +0 -0
  231. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md037_test.rs +0 -0
  232. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md038_test.rs +0 -0
  233. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md039_test.rs +0 -0
  234. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md040_test.rs +0 -0
  235. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md041_test.rs +0 -0
  236. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md043_test.rs +0 -0
  237. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md044_test.rs +0 -0
  238. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md045_test.rs +0 -0
  239. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md046_test.rs +0 -0
  240. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md047_test.rs +0 -0
  241. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md048_test.rs +0 -0
  242. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md049_test.rs +0 -0
  243. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md050_test.rs +0 -0
  244. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md052_test.rs +0 -0
  245. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md053_additional_test.rs +0 -0
  246. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md053_proptest.rs +0 -0
  247. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md053_test.rs +0 -0
  248. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md054_test.rs +0 -0
  249. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md054_unicode_test.rs +0 -0
  250. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md055_test.rs +0 -0
  251. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md056_test.rs +0 -0
  252. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md057_test.rs +0 -0
  253. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/md058_test.rs +0 -0
  254. {rumdl-0.0.73 → rumdl-0.0.74}/tests/rules/mod.rs +0 -0
  255. {rumdl-0.0.73 → rumdl-0.0.74}/tests/utils/blockquote_utils_test.rs +0 -0
  256. {rumdl-0.0.73 → rumdl-0.0.74}/tests/utils/code_block_utils_extended_test.rs +0 -0
  257. {rumdl-0.0.73 → rumdl-0.0.74}/tests/utils/code_block_utils_test.rs +0 -0
  258. {rumdl-0.0.73 → rumdl-0.0.74}/tests/utils/core_utils_test.rs +0 -0
  259. {rumdl-0.0.73 → rumdl-0.0.74}/tests/utils/front_matter_utils_test.rs +0 -0
  260. {rumdl-0.0.73 → rumdl-0.0.74}/tests/utils/line_index_test.rs +0 -0
  261. {rumdl-0.0.73 → rumdl-0.0.74}/tests/utils/mod.rs +0 -0
  262. {rumdl-0.0.73 → rumdl-0.0.74}/tests/utils_markdown_edge_cases.rs +0 -0
  263. {rumdl-0.0.73 → rumdl-0.0.74}/tests/utils_tests.rs +0 -0
@@ -1789,7 +1789,7 @@ dependencies = [
1789
1789
 
1790
1790
  [[package]]
1791
1791
  name = "rumdl"
1792
- version = "0.0.73"
1792
+ version = "0.0.74"
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.73"
3
+ version = "0.0.74"
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.73
3
+ Version: 0.0.74
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -103,8 +103,42 @@ impl MD032BlanksAroundLists {
103
103
  if structure.is_in_code_block(current_line_idx_1)
104
104
  || structure.is_in_front_matter(current_line_idx_1)
105
105
  {
106
- current_line_idx_0 += 1;
107
- continue;
106
+ // Special case: Even if a line is in a code block (e.g., tab-indented),
107
+ // if it looks like a list item, the user probably intended it as such.
108
+ // We should warn about spacing issues rather than silently ignore it.
109
+ // But only apply this to INDENTED code blocks, not FENCED code blocks.
110
+ if structure.is_in_code_block(current_line_idx_1) {
111
+ // Check if this is an indented code block (starts with tab or 4+ spaces)
112
+ // vs a fenced code block (enclosed in ``` or ~~~)
113
+ let line_trimmed = line_str.trim_start();
114
+ let leading_whitespace = &line_str[..line_str.len() - line_trimmed.len()];
115
+ let is_indented_code = leading_whitespace.contains('\t') ||
116
+ leading_whitespace.chars().filter(|&c| c == ' ').count() >= 4;
117
+
118
+ if is_indented_code {
119
+ // Check if this "indented code block" line actually looks like a list item
120
+ let blockquote_prefix = BLOCKQUOTE_PREFIX_RE
121
+ .find(line_str)
122
+ .map_or(String::new(), |m| m.as_str().to_string());
123
+ let line_content = line_str.trim_start_matches(&blockquote_prefix);
124
+
125
+ // If it matches our list item pattern, treat it as a list item for linting purposes
126
+ if LIST_ITEM_START_REGEX.is_match(line_content) {
127
+ // Don't skip - process it as a potential list item
128
+ } else {
129
+ current_line_idx_0 += 1;
130
+ continue;
131
+ }
132
+ } else {
133
+ // Fenced code block - always skip
134
+ current_line_idx_0 += 1;
135
+ continue;
136
+ }
137
+ } else {
138
+ // Front matter - always skip
139
+ current_line_idx_0 += 1;
140
+ continue;
141
+ }
108
142
  }
109
143
 
110
144
  // Determine blockquote prefix and content *before* checking for list item
@@ -35,57 +35,15 @@ impl Rule for MD042NoEmptyLinks {
35
35
 
36
36
  fn check(&self, ctx: &crate::lint_context::LintContext) -> LintResult {
37
37
  let content = ctx.content;
38
- let line_index = LineIndex::new(content.to_string());
39
- let mut warnings = Vec::new();
40
-
41
- lazy_static! {
42
- static ref EMPTY_LINK_REGEX: Regex =
43
- Regex::new(r"(?<!\!)\[([^\]]*)\]\(([^\)]*)\)").unwrap();
44
- }
45
38
 
46
- for (line_num, line) in content.lines().enumerate() {
47
- for cap_result in EMPTY_LINK_REGEX.captures_iter(line) {
48
- let cap = match cap_result {
49
- Ok(cap) => cap,
50
- Err(_) => continue,
51
- };
52
-
53
- let full_match = cap.get(0).unwrap();
54
- let text = cap.get(1).map_or("", |m| m.as_str());
55
- let url = cap.get(2).map_or("", |m| m.as_str());
56
-
57
- if text.trim().is_empty() || url.trim().is_empty() {
58
- let replacement = if text.trim().is_empty() && url.trim().is_empty() {
59
- "[Link text](https://example.com)".to_string()
60
- } else if text.trim().is_empty() {
61
- format!("[Link text]({})", url)
62
- } else {
63
- format!("[{}](https://example.com)", text)
64
- };
65
-
66
- warnings.push(LintWarning {
67
- rule_name: Some(self.name()),
68
- message: format!(
69
- "Empty link found: [{
70
- }]({})",
71
- text, url
72
- ),
73
- line: line_num + 1,
74
- column: full_match.start() + 1,
75
- end_line: line_num + 1,
76
- end_column: full_match.end() + 1,
77
- severity: Severity::Warning,
78
- fix: Some(Fix {
79
- range: line_index
80
- .line_col_to_byte_range(line_num + 1, full_match.start() + 1),
81
- replacement,
82
- }),
83
- });
84
- }
85
- }
39
+ // Early return for empty content or content without links
40
+ if content.is_empty() || !content.contains('[') {
41
+ return Ok(Vec::new());
86
42
  }
87
43
 
88
- Ok(warnings)
44
+ // Use document structure for proper code block and code span detection
45
+ let structure = DocumentStructure::new(content);
46
+ self.check_with_structure(ctx, &structure)
89
47
  }
90
48
 
91
49
  /// Optimized check using document structure
@@ -125,7 +83,7 @@ impl Rule for MD042NoEmptyLinks {
125
83
  line: link.line,
126
84
  column: link.start_col,
127
85
  end_line: link.line,
128
- end_column: link.end_col,
86
+ end_column: link.end_col + 1,
129
87
  severity: Severity::Warning,
130
88
  fix: Some(Fix {
131
89
  range: line_index.line_col_to_byte_range(link.line, link.start_col),
@@ -98,43 +98,73 @@ impl MD051LinkFragments {
98
98
  /// Convert a heading to a fragment identifier following GitHub's algorithm:
99
99
  /// 1. Strip all formatting (code, emphasis, links, etc.)
100
100
  /// 2. Convert to lowercase
101
- /// 3. Replace spaces and non-alphanumeric chars with hyphens
102
- /// 4. Remove consecutive hyphens
101
+ /// 3. Replace spaces with hyphens, & with double hyphens, other special chars with hyphens
102
+ /// 4. Collapse multiple consecutive hyphens to single hyphens (except preserve & -> --)
103
+ /// 5. Remove leading and trailing hyphens
103
104
  fn heading_to_fragment(&self, heading: &str) -> String {
104
- let mut stripped = heading.to_string();
105
+ // Step 1: Strip markdown formatting
106
+ let mut result = self.strip_markdown_formatting(heading);
107
+
108
+ // Step 2: Convert to lowercase
109
+ result = result.to_lowercase();
110
+
111
+ // Step 3 & 4: Process character by character with GitHub's rules
112
+ let mut fragment = String::new();
113
+
114
+ for c in result.chars() {
115
+ match c {
116
+ // Keep alphanumeric characters
117
+ 'a'..='z' | '0'..='9' => {
118
+ fragment.push(c);
119
+ }
120
+ // Ampersand becomes double hyphen (special case)
121
+ '&' => {
122
+ // Only add hyphens if the last character isn't already a hyphen
123
+ if !fragment.ends_with('-') {
124
+ fragment.push_str("--");
125
+ } else {
126
+ // If we already have a hyphen, just add one more to make it double
127
+ fragment.push('-');
128
+ }
129
+ }
130
+ // Spaces and other characters become single hyphen (but avoid consecutive hyphens)
131
+ _ => {
132
+ if !fragment.ends_with('-') {
133
+ fragment.push('-');
134
+ }
135
+ // If fragment already ends with hyphen, skip adding another
136
+ }
137
+ }
138
+ }
139
+
140
+ // Step 5: Remove leading and trailing hyphens
141
+ fragment.trim_matches('-').to_string()
142
+ }
143
+
144
+ /// Strip markdown formatting from text, keeping only the content
145
+ fn strip_markdown_formatting(&self, text: &str) -> String {
146
+ let mut result = text.to_string();
105
147
 
106
148
  // Remove links but keep the link text: [text](url) -> text
107
- stripped = INLINE_LINK_REGEX.replace_all(&stripped, "$1").to_string();
149
+ result = INLINE_LINK_REGEX.replace_all(&result, "$1").to_string();
108
150
 
109
151
  // Remove emphasis and bold formatting more comprehensively
110
- stripped = BOLD_ASTERISK_REGEX.replace_all(&stripped, "$1").to_string();
111
- stripped = BOLD_UNDERSCORE_REGEX
112
- .replace_all(&stripped, "$1")
152
+ result = BOLD_ASTERISK_REGEX.replace_all(&result, "$1").to_string();
153
+ result = BOLD_UNDERSCORE_REGEX
154
+ .replace_all(&result, "$1")
113
155
  .to_string();
114
- stripped = ITALIC_ASTERISK_REGEX
115
- .replace_all(&stripped, "$1")
156
+ result = ITALIC_ASTERISK_REGEX
157
+ .replace_all(&result, "$1")
116
158
  .to_string();
117
- stripped = ITALIC_UNDERSCORE_REGEX
118
- .replace_all(&stripped, "$1")
159
+ result = ITALIC_UNDERSCORE_REGEX
160
+ .replace_all(&result, "$1")
119
161
  .to_string();
120
- stripped = STRIKETHROUGH_REGEX.replace_all(&stripped, "$1").to_string();
162
+ result = STRIKETHROUGH_REGEX.replace_all(&result, "$1").to_string();
121
163
 
122
164
  // Remove code spans by replacing with their content (simplified)
123
- stripped = stripped.replace("`", "");
124
-
125
- // Convert to lowercase and replace spaces/non-alphanumeric chars with hyphens
126
- let fragment = stripped
127
- .to_lowercase()
128
- .chars()
129
- .map(|c| match c {
130
- ' ' => '-',
131
- c if c.is_alphanumeric() => c,
132
- _ => '-',
133
- })
134
- .collect::<String>();
165
+ result = result.replace("`", "");
135
166
 
136
- // Replace multiple consecutive hyphens with a single one
137
- MULTIPLE_HYPHENS.replace_all(&fragment, "-").to_string()
167
+ result
138
168
  }
139
169
 
140
170
  /// Generate multiple possible fragment variations for a heading to handle
@@ -144,25 +174,13 @@ impl MD051LinkFragments {
144
174
 
145
175
  // Primary fragment (GitHub's algorithm)
146
176
  let primary = self.heading_to_fragment(heading);
147
- variations.push(primary.clone());
148
-
149
- // Alternative: preserve some consecutive hyphens (for manually created TOCs)
150
- let mut stripped = heading.to_string();
151
- stripped = INLINE_LINK_REGEX.replace_all(&stripped, "$1").to_string();
152
- stripped = BOLD_ASTERISK_REGEX.replace_all(&stripped, "$1").to_string();
153
- stripped = BOLD_UNDERSCORE_REGEX
154
- .replace_all(&stripped, "$1")
155
- .to_string();
156
- stripped = ITALIC_ASTERISK_REGEX
157
- .replace_all(&stripped, "$1")
158
- .to_string();
159
- stripped = ITALIC_UNDERSCORE_REGEX
160
- .replace_all(&stripped, "$1")
161
- .to_string();
162
- stripped = STRIKETHROUGH_REGEX.replace_all(&stripped, "$1").to_string();
163
- stripped = stripped.replace("`", "");
177
+ if !primary.is_empty() {
178
+ variations.push(primary.clone());
179
+ }
164
180
 
165
- // Alternative algorithm that preserves some patterns
181
+ // Alternative: preserve double hyphens (for manually created TOCs)
182
+ // Some tools or manual creation might use double hyphens for certain symbols
183
+ let stripped = self.strip_markdown_formatting(heading);
166
184
  let alt_fragment = stripped
167
185
  .to_lowercase()
168
186
  .chars()
@@ -173,15 +191,20 @@ impl MD051LinkFragments {
173
191
  })
174
192
  .collect::<String>();
175
193
 
176
- // Only reduce to double hyphens (not single) for some tools
177
- let alt_with_double = alt_fragment.replace("---", "--");
178
- if alt_with_double != primary {
179
- variations.push(alt_with_double);
194
+ // Create variation with double hyphens preserved for & symbols
195
+ let double_hyphen_variant = alt_fragment
196
+ .replace("---", "--") // Collapse triple+ to double
197
+ .trim_matches('-') // Remove leading/trailing hyphens
198
+ .to_string();
199
+
200
+ if !double_hyphen_variant.is_empty() && double_hyphen_variant != primary {
201
+ variations.push(double_hyphen_variant);
180
202
  }
181
203
 
182
- // Keep the original with triple hyphens for some manual TOCs
183
- if alt_fragment != primary {
184
- variations.push(alt_fragment);
204
+ // Create variation with all consecutive hyphens preserved (for some manual TOCs)
205
+ let preserved_hyphens = alt_fragment.trim_matches('-').to_string();
206
+ if !preserved_hyphens.is_empty() && preserved_hyphens != primary && !variations.contains(&preserved_hyphens) {
207
+ variations.push(preserved_hyphens);
185
208
  }
186
209
 
187
210
  variations
@@ -492,81 +492,59 @@ impl DocumentStructure {
492
492
  let lang = captures.get(3).map(|m| m.as_str().to_string());
493
493
  current_language = lang.filter(|l| !l.is_empty());
494
494
  }
495
- // Check for indented code block (simplified)
496
- else if line.starts_with(" ") && !line.trim().is_empty() {
497
- // Don't treat indented HTML tags as code blocks
498
- let trimmed = line.trim_start();
499
- if trimmed.starts_with('<') && trimmed.len() > 1 {
500
- let second_char = trimmed.chars().nth(1).unwrap();
501
- if second_char.is_ascii_alphabetic()
502
- || (second_char == '/'
503
- && trimmed.len() > 2
504
- && trimmed.chars().nth(2).unwrap().is_ascii_alphabetic())
505
- {
506
- // This looks like an HTML tag, don't treat as code block
507
- // Skip this line and continue
508
- } else {
509
- // Not an HTML tag, process as potential code block
510
- let mut end_line = i;
511
- while end_line + 1 < lines.len()
512
- && (lines[end_line + 1].starts_with(" ")
513
- || lines[end_line + 1].trim().is_empty())
514
- {
515
- // Check if the next indented line is also an HTML tag
516
- if lines[end_line + 1].starts_with(" ") {
517
- let next_trimmed = lines[end_line + 1].trim_start();
518
- if next_trimmed.starts_with('<') && next_trimmed.len() > 1 {
519
- let next_second_char = next_trimmed.chars().nth(1).unwrap();
520
- if next_second_char.is_ascii_alphabetic()
521
- || (next_second_char == '/'
522
- && next_trimmed.len() > 2
523
- && next_trimmed
524
- .chars()
525
- .nth(2)
526
- .unwrap()
527
- .is_ascii_alphabetic())
528
- {
529
- // Next line is also HTML, break the code block here
530
- break;
531
- }
532
- }
495
+ // Check for indented code block (CommonMark compliant)
496
+ else if Self::is_indented_code_line(line) && !line.trim().is_empty() {
497
+ // According to CommonMark, any content indented by 4+ spaces OR a tab is a code block
498
+ // regardless of what the content is (including HTML)
499
+ let mut end_line = i;
500
+
501
+ // Find the end of this indented code block
502
+ // Continue while we have indented lines OR blank lines that are followed by more indented lines
503
+ while end_line + 1 < lines.len() {
504
+ let next_line = lines[end_line + 1];
505
+
506
+ if Self::is_indented_code_line(next_line) && !next_line.trim().is_empty() {
507
+ // Found another indented line, continue the block
508
+ end_line += 1;
509
+ } else if next_line.trim().is_empty() {
510
+ // Found a blank line, check if there are more indented lines after it
511
+ let mut lookahead = end_line + 2;
512
+ let mut found_indented = false;
513
+
514
+ while lookahead < lines.len() {
515
+ let lookahead_line = lines[lookahead];
516
+ if Self::is_indented_code_line(lookahead_line) && !lookahead_line.trim().is_empty() {
517
+ found_indented = true;
518
+ break;
519
+ } else if !lookahead_line.trim().is_empty() {
520
+ // Found non-empty, non-indented line, stop looking
521
+ break;
533
522
  }
534
- end_line += 1;
523
+ lookahead += 1;
535
524
  }
536
525
 
537
- // Only create code block if we found non-HTML content
538
- if end_line > i {
539
- code_blocks.push(CodeBlock {
540
- start_line: i + 1,
541
- end_line: end_line + 1,
542
- language: None,
543
- block_type: CodeBlockType::Indented,
544
- });
545
-
546
- // Skip to end of block
547
- i = end_line;
526
+ if found_indented {
527
+ // Include this blank line as part of the code block
528
+ end_line += 1;
529
+ } else {
530
+ // No more indented lines, end the block here
531
+ break;
548
532
  }
533
+ } else {
534
+ // Found non-empty, non-indented line, end the block
535
+ break;
549
536
  }
550
- } else {
551
- // Not an HTML tag, process as normal indented code block
552
- let mut end_line = i;
553
- while end_line + 1 < lines.len()
554
- && (lines[end_line + 1].starts_with(" ")
555
- || lines[end_line + 1].trim().is_empty())
556
- {
557
- end_line += 1;
558
- }
537
+ }
559
538
 
560
- code_blocks.push(CodeBlock {
561
- start_line: i + 1,
562
- end_line: end_line + 1,
563
- language: None,
564
- block_type: CodeBlockType::Indented,
565
- });
539
+ code_blocks.push(CodeBlock {
540
+ start_line: i + 1,
541
+ end_line: end_line + 1,
542
+ language: None,
543
+ block_type: CodeBlockType::Indented,
544
+ });
566
545
 
567
- // Skip to end of block
568
- i = end_line;
569
- }
546
+ // Skip to end of block
547
+ i = end_line;
570
548
  }
571
549
  } else {
572
550
  // Check for fenced code block end - must start with the same fence character
@@ -653,6 +631,30 @@ impl DocumentStructure {
653
631
  Self::count_trailing_spaces(line) > 0
654
632
  }
655
633
 
634
+ /// Check if a line is indented code according to CommonMark specification
635
+ ///
636
+ /// According to CommonMark, a line is considered indented code if it starts with:
637
+ /// - 4 or more spaces, OR
638
+ /// - A tab character
639
+ #[inline]
640
+ fn is_indented_code_line(line: &str) -> bool {
641
+ if line.starts_with('\t') {
642
+ return true;
643
+ }
644
+
645
+ // Count leading spaces
646
+ let mut space_count = 0;
647
+ for c in line.chars() {
648
+ if c == ' ' {
649
+ space_count += 1;
650
+ } else {
651
+ break;
652
+ }
653
+ }
654
+
655
+ space_count >= 4
656
+ }
657
+
656
658
  /// Get a list of list start indices
657
659
  /// This method analyzes the list_lines to find where lists begin
658
660
  pub fn get_list_start_indices(&self) -> Vec<usize> {