rumdl 0.0.121__tar.gz → 0.0.123__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 (404) hide show
  1. {rumdl-0.0.121 → rumdl-0.0.123}/CHANGELOG.md +29 -1
  2. {rumdl-0.0.121 → rumdl-0.0.123}/Cargo.lock +21 -21
  3. {rumdl-0.0.121 → rumdl-0.0.123}/Cargo.toml +1 -1
  4. {rumdl-0.0.121 → rumdl-0.0.123}/PKG-INFO +16 -1
  5. {rumdl-0.0.121 → rumdl-0.0.123}/README.md +15 -0
  6. {rumdl-0.0.121 → rumdl-0.0.123}/src/main.rs +41 -6
  7. {rumdl-0.0.121 → rumdl-0.0.123}/src/output/formatters/github.rs +165 -24
  8. {rumdl-0.0.121 → rumdl-0.0.123}/src/rule.rs +16 -0
  9. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md013_line_length.rs +189 -88
  10. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md033_no_inline_html.rs +4 -0
  11. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md052_reference_links_images.rs +1 -17
  12. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md054_link_image_style.rs +4 -0
  13. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/kramdown_utils.rs +1 -1
  14. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/regex_cache.rs +44 -1
  15. rumdl-0.0.123/src/utils/text_reflow.rs +1066 -0
  16. {rumdl-0.0.121 → rumdl-0.0.123}/tests/comprehensive_output_format_tests.rs +7 -2
  17. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md013_test.rs +24 -126
  18. rumdl-0.0.123/tests/unfixable_rules_test.rs +161 -0
  19. rumdl-0.0.121/src/utils/text_reflow.rs +0 -520
  20. {rumdl-0.0.121 → rumdl-0.0.123}/.config/nextest.toml +0 -0
  21. {rumdl-0.0.121 → rumdl-0.0.123}/.mise.toml +0 -0
  22. {rumdl-0.0.121 → rumdl-0.0.123}/.pre-commit-config.yaml +0 -0
  23. {rumdl-0.0.121 → rumdl-0.0.123}/.rumdl.toml +0 -0
  24. {rumdl-0.0.121 → rumdl-0.0.123}/.rustfmt.toml +0 -0
  25. {rumdl-0.0.121 → rumdl-0.0.123}/LICENSE +0 -0
  26. {rumdl-0.0.121 → rumdl-0.0.123}/MANIFEST.in +0 -0
  27. {rumdl-0.0.121 → rumdl-0.0.123}/Makefile +0 -0
  28. {rumdl-0.0.121 → rumdl-0.0.123}/assets/logo.png +0 -0
  29. {rumdl-0.0.121 → rumdl-0.0.123}/benches/fix_performance.rs +0 -0
  30. {rumdl-0.0.121 → rumdl-0.0.123}/benches/range_performance.rs +0 -0
  31. {rumdl-0.0.121 → rumdl-0.0.123}/benches/range_utils_benchmark.rs +0 -0
  32. {rumdl-0.0.121 → rumdl-0.0.123}/benches/rule_performance.rs +0 -0
  33. {rumdl-0.0.121 → rumdl-0.0.123}/benches/simple_fix_bench.rs +0 -0
  34. {rumdl-0.0.121 → rumdl-0.0.123}/benchmark/bin/bench_lint_context.rs +0 -0
  35. {rumdl-0.0.121 → rumdl-0.0.123}/benchmark/bin/benchmark.rs +0 -0
  36. {rumdl-0.0.121 → rumdl-0.0.123}/benchmark/bin/benchmark_rule.rs +0 -0
  37. {rumdl-0.0.121 → rumdl-0.0.123}/benchmark/bin/file_parallel_benchmark.rs +0 -0
  38. {rumdl-0.0.121 → rumdl-0.0.123}/benchmark/bin/measure_code_span_performance.rs +0 -0
  39. {rumdl-0.0.121 → rumdl-0.0.123}/docs/RULES.md +0 -0
  40. {rumdl-0.0.121 → rumdl-0.0.123}/docs/global-settings.md +0 -0
  41. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md001.md +0 -0
  42. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md002.md +0 -0
  43. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md003.md +0 -0
  44. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md004.md +0 -0
  45. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md005.md +0 -0
  46. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md006.md +0 -0
  47. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md007.md +0 -0
  48. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md009.md +0 -0
  49. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md010.md +0 -0
  50. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md011.md +0 -0
  51. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md012.md +0 -0
  52. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md013.md +0 -0
  53. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md014.md +0 -0
  54. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md018.md +0 -0
  55. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md019.md +0 -0
  56. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md020.md +0 -0
  57. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md021.md +0 -0
  58. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md022.md +0 -0
  59. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md023.md +0 -0
  60. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md024.md +0 -0
  61. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md025.md +0 -0
  62. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md026.md +0 -0
  63. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md027.md +0 -0
  64. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md028.md +0 -0
  65. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md029.md +0 -0
  66. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md030.md +0 -0
  67. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md031.md +0 -0
  68. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md032.md +0 -0
  69. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md033.md +0 -0
  70. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md034.md +0 -0
  71. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md035.md +0 -0
  72. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md036.md +0 -0
  73. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md037.md +0 -0
  74. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md038.md +0 -0
  75. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md039.md +0 -0
  76. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md040.md +0 -0
  77. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md041.md +0 -0
  78. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md042.md +0 -0
  79. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md043.md +0 -0
  80. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md044.md +0 -0
  81. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md045.md +0 -0
  82. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md046.md +0 -0
  83. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md047.md +0 -0
  84. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md048.md +0 -0
  85. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md049.md +0 -0
  86. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md050.md +0 -0
  87. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md051.md +0 -0
  88. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md052.md +0 -0
  89. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md053.md +0 -0
  90. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md054.md +0 -0
  91. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md055.md +0 -0
  92. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md056.md +0 -0
  93. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md057.md +0 -0
  94. {rumdl-0.0.121 → rumdl-0.0.123}/docs/md058.md +0 -0
  95. {rumdl-0.0.121 → rumdl-0.0.123}/docs/vscode-extension.md +0 -0
  96. {rumdl-0.0.121 → rumdl-0.0.123}/parity_check.py +0 -0
  97. {rumdl-0.0.121 → rumdl-0.0.123}/pyproject.toml +0 -0
  98. {rumdl-0.0.121 → rumdl-0.0.123}/python/MANIFEST.in +0 -0
  99. {rumdl-0.0.121 → rumdl-0.0.123}/python/PYTHON-README.md +0 -0
  100. {rumdl-0.0.121 → rumdl-0.0.123}/python/rumdl/__init__.py +0 -0
  101. {rumdl-0.0.121 → rumdl-0.0.123}/python/rumdl/__main__.py +0 -0
  102. {rumdl-0.0.121 → rumdl-0.0.123}/python/rumdl/py.typed +0 -0
  103. {rumdl-0.0.121 → rumdl-0.0.123}/rumdl.toml.example +0 -0
  104. {rumdl-0.0.121 → rumdl-0.0.123}/rust-toolchain.toml +0 -0
  105. {rumdl-0.0.121 → rumdl-0.0.123}/scripts/extract-changelog.sh +0 -0
  106. {rumdl-0.0.121 → rumdl-0.0.123}/scripts/generate-downloads-table.sh +0 -0
  107. {rumdl-0.0.121 → rumdl-0.0.123}/scripts/pre-release.sh +0 -0
  108. {rumdl-0.0.121 → rumdl-0.0.123}/scripts/prepare-release.sh +0 -0
  109. {rumdl-0.0.121 → rumdl-0.0.123}/scripts/setup-pre-commit.sh +0 -0
  110. {rumdl-0.0.121 → rumdl-0.0.123}/scripts/update-pre-commit-docs.sh +0 -0
  111. {rumdl-0.0.121 → rumdl-0.0.123}/src/config.rs +0 -0
  112. {rumdl-0.0.121 → rumdl-0.0.123}/src/exit_codes.rs +0 -0
  113. {rumdl-0.0.121 → rumdl-0.0.123}/src/inline_config.rs +0 -0
  114. {rumdl-0.0.121 → rumdl-0.0.123}/src/lib.rs +0 -0
  115. {rumdl-0.0.121 → rumdl-0.0.123}/src/lint_context.rs +0 -0
  116. {rumdl-0.0.121 → rumdl-0.0.123}/src/lsp/mod.rs +0 -0
  117. {rumdl-0.0.121 → rumdl-0.0.123}/src/lsp/server.rs +0 -0
  118. {rumdl-0.0.121 → rumdl-0.0.123}/src/lsp/types.rs +0 -0
  119. {rumdl-0.0.121 → rumdl-0.0.123}/src/markdownlint_config.rs +0 -0
  120. {rumdl-0.0.121 → rumdl-0.0.123}/src/output/formatters/azure.rs +0 -0
  121. {rumdl-0.0.121 → rumdl-0.0.123}/src/output/formatters/concise.rs +0 -0
  122. {rumdl-0.0.121 → rumdl-0.0.123}/src/output/formatters/gitlab.rs +0 -0
  123. {rumdl-0.0.121 → rumdl-0.0.123}/src/output/formatters/grouped.rs +0 -0
  124. {rumdl-0.0.121 → rumdl-0.0.123}/src/output/formatters/json.rs +0 -0
  125. {rumdl-0.0.121 → rumdl-0.0.123}/src/output/formatters/json_lines.rs +0 -0
  126. {rumdl-0.0.121 → rumdl-0.0.123}/src/output/formatters/junit.rs +0 -0
  127. {rumdl-0.0.121 → rumdl-0.0.123}/src/output/formatters/mod.rs +0 -0
  128. {rumdl-0.0.121 → rumdl-0.0.123}/src/output/formatters/pylint.rs +0 -0
  129. {rumdl-0.0.121 → rumdl-0.0.123}/src/output/formatters/sarif.rs +0 -0
  130. {rumdl-0.0.121 → rumdl-0.0.123}/src/output/formatters/text.rs +0 -0
  131. {rumdl-0.0.121 → rumdl-0.0.123}/src/output/mod.rs +0 -0
  132. {rumdl-0.0.121 → rumdl-0.0.123}/src/parallel.rs +0 -0
  133. {rumdl-0.0.121 → rumdl-0.0.123}/src/performance.rs +0 -0
  134. {rumdl-0.0.121 → rumdl-0.0.123}/src/profiling.rs +0 -0
  135. {rumdl-0.0.121 → rumdl-0.0.123}/src/python.rs +0 -0
  136. {rumdl-0.0.121 → rumdl-0.0.123}/src/rule_config.rs +0 -0
  137. {rumdl-0.0.121 → rumdl-0.0.123}/src/rule_config_serde.rs +0 -0
  138. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/blockquote_utils.rs +0 -0
  139. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/code_block_utils.rs +0 -0
  140. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/code_fence_utils.rs +0 -0
  141. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/emphasis_style.rs +0 -0
  142. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/front_matter_utils.rs +0 -0
  143. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/heading_utils.rs +0 -0
  144. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/list_utils.rs +0 -0
  145. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md001_heading_increment.rs +0 -0
  146. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md002_first_heading_h1/md002_config.rs +0 -0
  147. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md002_first_heading_h1.rs +0 -0
  148. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md003_heading_style/md003_config.rs +0 -0
  149. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md003_heading_style.rs +0 -0
  150. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md004_unordered_list_style/md004_config.rs +0 -0
  151. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md004_unordered_list_style.rs +0 -0
  152. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md005_list_indent.rs +0 -0
  153. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md006_start_bullets.rs +0 -0
  154. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md007_ul_indent/md007_config.rs +0 -0
  155. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md007_ul_indent.rs +0 -0
  156. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md009_trailing_spaces/md009_config.rs +0 -0
  157. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md009_trailing_spaces.rs +0 -0
  158. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md010_no_hard_tabs/md010_config.rs +0 -0
  159. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md010_no_hard_tabs.rs +0 -0
  160. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md011_no_reversed_links.rs +0 -0
  161. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md012_no_multiple_blanks/md012_config.rs +0 -0
  162. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md012_no_multiple_blanks.rs +0 -0
  163. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md013_line_length/md013_config.rs +0 -0
  164. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md014_commands_show_output/md014_config.rs +0 -0
  165. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md014_commands_show_output.rs +0 -0
  166. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md018_no_missing_space_atx.rs +0 -0
  167. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md019_no_multiple_space_atx.rs +0 -0
  168. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md020_no_missing_space_closed_atx.rs +0 -0
  169. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
  170. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md022_blanks_around_headings/md022_config.rs +0 -0
  171. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md022_blanks_around_headings.rs +0 -0
  172. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md023_heading_start_left.rs +0 -0
  173. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md024_no_duplicate_heading/md024_config.rs +0 -0
  174. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md024_no_duplicate_heading.rs +0 -0
  175. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md025_single_title/md025_config.rs +0 -0
  176. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md025_single_title.rs +0 -0
  177. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md026_no_trailing_punctuation/md026_config.rs +0 -0
  178. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md026_no_trailing_punctuation.rs +0 -0
  179. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md027_multiple_spaces_blockquote.rs +0 -0
  180. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md028_no_blanks_blockquote.rs +0 -0
  181. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md029_ordered_list_prefix/md029_config.rs +0 -0
  182. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md029_ordered_list_prefix.rs +0 -0
  183. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md030_list_marker_space/md030_config.rs +0 -0
  184. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md030_list_marker_space.rs +0 -0
  185. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md031_blanks_around_fences.rs +0 -0
  186. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md032_blanks_around_lists.rs +0 -0
  187. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md033_no_inline_html/md033_config.rs +0 -0
  188. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md034_no_bare_urls.rs +0 -0
  189. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md035_hr_style/md035_config.rs +0 -0
  190. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md035_hr_style.rs +0 -0
  191. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md036_no_emphasis_only_first/md036_config.rs +0 -0
  192. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md036_no_emphasis_only_first.rs +0 -0
  193. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md037_spaces_around_emphasis.rs +0 -0
  194. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md038_no_space_in_code.rs +0 -0
  195. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md039_no_space_in_links.rs +0 -0
  196. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md040_fenced_code_language.rs +0 -0
  197. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md041_first_line_heading.rs +0 -0
  198. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md042_no_empty_links.rs +0 -0
  199. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md043_required_headings.rs +0 -0
  200. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md044_proper_names/md044_config.rs +0 -0
  201. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md044_proper_names.rs +0 -0
  202. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md045_no_alt_text/md045_config.rs +0 -0
  203. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md045_no_alt_text.rs +0 -0
  204. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md046_code_block_style/md046_config.rs +0 -0
  205. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md046_code_block_style.rs +0 -0
  206. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md047_single_trailing_newline.rs +0 -0
  207. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md048_code_fence_style/md048_config.rs +0 -0
  208. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md048_code_fence_style.rs +0 -0
  209. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md049_emphasis_style/md049_config.rs +0 -0
  210. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md049_emphasis_style.rs +0 -0
  211. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md050_strong_style/md050_config.rs +0 -0
  212. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md050_strong_style.rs +0 -0
  213. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md051_link_fragments.rs +0 -0
  214. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md053_link_image_reference_definitions.rs +0 -0
  215. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md054_link_image_style/md054_config.rs +0 -0
  216. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md055_table_pipe_style/md055_config.rs +0 -0
  217. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md055_table_pipe_style.rs +0 -0
  218. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md056_table_column_count.rs +0 -0
  219. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md057_existing_relative_links/md057_config.rs +0 -0
  220. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md057_existing_relative_links.rs +0 -0
  221. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/md058_blanks_around_tables.rs +0 -0
  222. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/mod.rs +0 -0
  223. {rumdl-0.0.121 → rumdl-0.0.123}/src/rules/strong_style.rs +0 -0
  224. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/anchor_styles/github.rs +0 -0
  225. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/anchor_styles/jekyll.rs +0 -0
  226. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/anchor_styles/kramdown.rs +0 -0
  227. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/anchor_styles/kramdown_gfm.rs +0 -0
  228. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/anchor_styles/mod.rs +0 -0
  229. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/ast_utils.rs +0 -0
  230. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/code_block_utils.rs +0 -0
  231. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/document_structure.rs +0 -0
  232. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/early_returns.rs +0 -0
  233. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/element_cache.rs +0 -0
  234. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/emphasis_utils.rs +0 -0
  235. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/fix_utils.rs +0 -0
  236. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/header_id_utils.rs +0 -0
  237. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/markdown_elements.rs +0 -0
  238. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/mod.rs +0 -0
  239. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/range_utils.rs +0 -0
  240. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/skip_context.rs +0 -0
  241. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/string_interner.rs +0 -0
  242. {rumdl-0.0.121 → rumdl-0.0.123}/src/utils/table_utils.rs +0 -0
  243. {rumdl-0.0.121 → rumdl-0.0.123}/src/vscode.rs +0 -0
  244. {rumdl-0.0.121 → rumdl-0.0.123}/tests/advanced_integration_tests.rs +0 -0
  245. {rumdl-0.0.121 → rumdl-0.0.123}/tests/character_ranges/additional_tests.rs +0 -0
  246. {rumdl-0.0.121 → rumdl-0.0.123}/tests/character_ranges/basic_tests.rs +0 -0
  247. {rumdl-0.0.121 → rumdl-0.0.123}/tests/character_ranges/comprehensive_tests.rs +0 -0
  248. {rumdl-0.0.121 → rumdl-0.0.123}/tests/character_ranges/extended_tests.rs +0 -0
  249. {rumdl-0.0.121 → rumdl-0.0.123}/tests/character_ranges/mod.rs +0 -0
  250. {rumdl-0.0.121 → rumdl-0.0.123}/tests/character_ranges/unicode_utils.rs +0 -0
  251. {rumdl-0.0.121 → rumdl-0.0.123}/tests/cli_duplication_test.rs +0 -0
  252. {rumdl-0.0.121 → rumdl-0.0.123}/tests/cli_explain_test.rs +0 -0
  253. {rumdl-0.0.121 → rumdl-0.0.123}/tests/cli_flag_precedence_test.rs +0 -0
  254. {rumdl-0.0.121 → rumdl-0.0.123}/tests/cli_integration_tests.rs +0 -0
  255. {rumdl-0.0.121 → rumdl-0.0.123}/tests/cli_lsp_fix_consistency.rs +0 -0
  256. {rumdl-0.0.121 → rumdl-0.0.123}/tests/cli_statistics_test.rs +0 -0
  257. {rumdl-0.0.121 → rumdl-0.0.123}/tests/common/cli_test_utils.rs +0 -0
  258. {rumdl-0.0.121 → rumdl-0.0.123}/tests/common/fixtures.rs +0 -0
  259. {rumdl-0.0.121 → rumdl-0.0.123}/tests/common/mod.rs +0 -0
  260. {rumdl-0.0.121 → rumdl-0.0.123}/tests/common/test_utils.rs +0 -0
  261. {rumdl-0.0.121 → rumdl-0.0.123}/tests/commonmark_compliance_tests.rs +0 -0
  262. {rumdl-0.0.121 → rumdl-0.0.123}/tests/comprehensive_integration_tests.rs +0 -0
  263. {rumdl-0.0.121 → rumdl-0.0.123}/tests/config_application_tests.rs +0 -0
  264. {rumdl-0.0.121 → rumdl-0.0.123}/tests/config_file_command_test.rs +0 -0
  265. {rumdl-0.0.121 → rumdl-0.0.123}/tests/config_tests.rs +0 -0
  266. {rumdl-0.0.121 → rumdl-0.0.123}/tests/configuration_inheritance_tests.rs +0 -0
  267. {rumdl-0.0.121 → rumdl-0.0.123}/tests/consistency_regression_tests.rs +0 -0
  268. {rumdl-0.0.121 → rumdl-0.0.123}/tests/cross_platform_compatibility_tests.rs +0 -0
  269. {rumdl-0.0.121 → rumdl-0.0.123}/tests/deeply_nested_lists_performance_test.rs +0 -0
  270. {rumdl-0.0.121 → rumdl-0.0.123}/tests/escaped_brackets_test.rs +0 -0
  271. {rumdl-0.0.121 → rumdl-0.0.123}/tests/final_confidence_assessment.rs +0 -0
  272. {rumdl-0.0.121 → rumdl-0.0.123}/tests/fixable_unfixable_config_test.rs +0 -0
  273. {rumdl-0.0.121 → rumdl-0.0.123}/tests/init_command_test.rs +0 -0
  274. {rumdl-0.0.121 → rumdl-0.0.123}/tests/init_tests.rs +0 -0
  275. {rumdl-0.0.121 → rumdl-0.0.123}/tests/inline_config_blocks_test.rs +0 -0
  276. {rumdl-0.0.121 → rumdl-0.0.123}/tests/inline_config_test.rs +0 -0
  277. {rumdl-0.0.121 → rumdl-0.0.123}/tests/integration_tests.rs +0 -0
  278. {rumdl-0.0.121 → rumdl-0.0.123}/tests/json_output_test.rs +0 -0
  279. {rumdl-0.0.121 → rumdl-0.0.123}/tests/kramdown_integration_test.rs +0 -0
  280. {rumdl-0.0.121 → rumdl-0.0.123}/tests/lib.rs +0 -0
  281. {rumdl-0.0.121 → rumdl-0.0.123}/tests/lsp_editor_integration_tests.rs +0 -0
  282. {rumdl-0.0.121 → rumdl-0.0.123}/tests/lsp_integration_tests.rs +0 -0
  283. {rumdl-0.0.121 → rumdl-0.0.123}/tests/lsp_memory_leak_tests.rs +0 -0
  284. {rumdl-0.0.121 → rumdl-0.0.123}/tests/lsp_tests.rs +0 -0
  285. {rumdl-0.0.121 → rumdl-0.0.123}/tests/malformed_markdown_stress_tests.rs +0 -0
  286. {rumdl-0.0.121 → rumdl-0.0.123}/tests/markdownlint_cli_integration.rs +0 -0
  287. {rumdl-0.0.121 → rumdl-0.0.123}/tests/markdownlint_config_test.rs +0 -0
  288. {rumdl-0.0.121 → rumdl-0.0.123}/tests/markdownlintignore_test.rs +0 -0
  289. {rumdl-0.0.121 → rumdl-0.0.123}/tests/md013_reflow_integration_test.rs +0 -0
  290. {rumdl-0.0.121 → rumdl-0.0.123}/tests/md051_issue_39_regression_test.rs +0 -0
  291. {rumdl-0.0.121 → rumdl-0.0.123}/tests/nested_code_block_test.rs +0 -0
  292. {rumdl-0.0.121 → rumdl-0.0.123}/tests/output_format_integration_tests.rs +0 -0
  293. {rumdl-0.0.121 → rumdl-0.0.123}/tests/output_format_tests.rs +0 -0
  294. {rumdl-0.0.121 → rumdl-0.0.123}/tests/perf_check.rs +0 -0
  295. {rumdl-0.0.121 → rumdl-0.0.123}/tests/performance_validation_tests.rs +0 -0
  296. {rumdl-0.0.121 → rumdl-0.0.123}/tests/pyproject_config_tests.rs +0 -0
  297. {rumdl-0.0.121 → rumdl-0.0.123}/tests/python_bindings_test.rs +0 -0
  298. {rumdl-0.0.121 → rumdl-0.0.123}/tests/real_world_repository_tests.rs +0 -0
  299. {rumdl-0.0.121 → rumdl-0.0.123}/tests/regression_prevention_tests.rs +0 -0
  300. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/emphasis_edge_cases_test.rs +0 -0
  301. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/heading_edge_cases_test.rs +0 -0
  302. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/inline_content_edge_cases_test.rs +0 -0
  303. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/link_edge_cases_test.rs +0 -0
  304. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/list_rules_integration_test.rs +0 -0
  305. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md001_test.rs +0 -0
  306. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md001_unicode_test.rs +0 -0
  307. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md002_test.rs +0 -0
  308. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md003_test.rs +0 -0
  309. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md004_test.rs +0 -0
  310. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md005_test.rs +0 -0
  311. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md005_unicode_test.rs +0 -0
  312. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md006_test.rs +0 -0
  313. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md006_unicode_test.rs +0 -0
  314. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md007_test.rs +0 -0
  315. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md009_test.rs +0 -0
  316. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md010_test.rs +0 -0
  317. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md011_test.rs +0 -0
  318. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md012_test.rs +0 -0
  319. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md014_test.rs +0 -0
  320. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md018_test.rs +0 -0
  321. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md019_test.rs +0 -0
  322. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md020_test.rs +0 -0
  323. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md021_test.rs +0 -0
  324. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md022_test.rs +0 -0
  325. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md023_extended_test.rs +0 -0
  326. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md023_test.rs +0 -0
  327. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md024_test.rs +0 -0
  328. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md025_test.rs +0 -0
  329. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md026_kramdown_test.rs +0 -0
  330. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md026_test.rs +0 -0
  331. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md027_test.rs +0 -0
  332. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md028_test.rs +0 -0
  333. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md029_code_block_separation_test.rs +0 -0
  334. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md029_issue42_test.rs +0 -0
  335. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md029_pathological_edge_cases_test.rs +0 -0
  336. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md029_test.rs +0 -0
  337. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md029_unicode_test.rs +0 -0
  338. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md030_test.rs +0 -0
  339. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md031_kramdown_test.rs +0 -0
  340. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md031_test.rs +0 -0
  341. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md032_test.rs +0 -0
  342. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md033_extended_test.rs +0 -0
  343. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md033_kramdown_test.rs +0 -0
  344. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md033_test.rs +0 -0
  345. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md034_ipv6_test.rs +0 -0
  346. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md034_test.rs +0 -0
  347. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md035_test.rs +0 -0
  348. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md036_test.rs +0 -0
  349. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md037_kramdown_test.rs +0 -0
  350. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md037_test.rs +0 -0
  351. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md038_nested_backticks_test.rs +0 -0
  352. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md038_test.rs +0 -0
  353. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md039_test.rs +0 -0
  354. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md040_test.rs +0 -0
  355. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md041_test.rs +0 -0
  356. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md042_test.rs +0 -0
  357. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md043_test.rs +0 -0
  358. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md044_test.rs +0 -0
  359. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md045_test.rs +0 -0
  360. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md046_test.rs +0 -0
  361. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md047_test.rs +0 -0
  362. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md048_test.rs +0 -0
  363. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md049_test.rs +0 -0
  364. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md050_test.rs +0 -0
  365. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md051_comprehensive_test.rs +0 -0
  366. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md051_critical_edge_cases_test.rs +0 -0
  367. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md051_edge_cases_test.rs +0 -0
  368. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md051_issue_39_regression_test.rs +0 -0
  369. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md051_performance_edge_cases_test.rs +0 -0
  370. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md051_property_based_test.rs +0 -0
  371. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md051_regression_prevention_test.rs +0 -0
  372. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md051_test.rs +0 -0
  373. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md051_unicode_security_test.rs +0 -0
  374. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md052_test.rs +0 -0
  375. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md053_additional_test.rs +0 -0
  376. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md053_proptest.rs +0 -0
  377. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md053_test.rs +0 -0
  378. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md054_test.rs +0 -0
  379. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md054_unicode_test.rs +0 -0
  380. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md055_test.rs +0 -0
  381. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md056_test.rs +0 -0
  382. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md057_test.rs +0 -0
  383. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md058_kramdown_test.rs +0 -0
  384. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/md058_test.rs +0 -0
  385. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules/mod.rs +0 -0
  386. {rumdl-0.0.121 → rumdl-0.0.123}/tests/rules_mod_test.rs +0 -0
  387. {rumdl-0.0.121 → rumdl-0.0.123}/tests/skip_context_tests.rs +0 -0
  388. {rumdl-0.0.121 → rumdl-0.0.123}/tests/test_underscore_edge_cases.rs +0 -0
  389. {rumdl-0.0.121 → rumdl-0.0.123}/tests/thread_safety_tests.rs +0 -0
  390. {rumdl-0.0.121 → rumdl-0.0.123}/tests/unicode_edge_case_tests.rs +0 -0
  391. {rumdl-0.0.121 → rumdl-0.0.123}/tests/utils/blockquote_utils_test.rs +0 -0
  392. {rumdl-0.0.121 → rumdl-0.0.123}/tests/utils/code_block_utils_extended_test.rs +0 -0
  393. {rumdl-0.0.121 → rumdl-0.0.123}/tests/utils/code_block_utils_test.rs +0 -0
  394. {rumdl-0.0.121 → rumdl-0.0.123}/tests/utils/core_utils_test.rs +0 -0
  395. {rumdl-0.0.121 → rumdl-0.0.123}/tests/utils/front_matter_utils_test.rs +0 -0
  396. {rumdl-0.0.121 → rumdl-0.0.123}/tests/utils/line_index_test.rs +0 -0
  397. {rumdl-0.0.121 → rumdl-0.0.123}/tests/utils/mod.rs +0 -0
  398. {rumdl-0.0.121 → rumdl-0.0.123}/tests/utils_markdown_edge_cases.rs +0 -0
  399. {rumdl-0.0.121 → rumdl-0.0.123}/tests/utils_tests.rs +0 -0
  400. {rumdl-0.0.121 → rumdl-0.0.123}/tests/vscode_extension_fixes.rs +0 -0
  401. {rumdl-0.0.121 → rumdl-0.0.123}/tests/vscode_test.rs +0 -0
  402. {rumdl-0.0.121 → rumdl-0.0.123}/tests/vscode_tests.rs +0 -0
  403. {rumdl-0.0.121 → rumdl-0.0.123}/tests/vscode_windows_comprehensive_test.rs +0 -0
  404. {rumdl-0.0.121 → rumdl-0.0.123}/tests/vscode_windows_test.rs +0 -0
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.0.123] - 2025-08-21
11
+
12
+ ## [0.0.123] - 2025-08-21
13
+
14
+ ### Added
15
+ - **MD013**: Comprehensive markdown pattern preservation during text reflow
16
+ - Preserves reference links, footnotes, math formulas, wiki links, and more
17
+ - Centralized regex patterns for better maintainability
18
+
19
+ ### Fixed
20
+ - **CLI**: Correct unfixable rules status display and fix counts (closes #56)
21
+ - Rules marked as unfixable now show `[unfixable]` in yellow instead of `[fixed]`
22
+ - Fix count now correctly excludes unfixable rules (e.g., "3 of 6" instead of "6 of 6")
23
+ - Added FixCapability enum to Rule trait for compile-time safety
24
+ - **MD013**: Preserve reference links during text reflow
25
+ - Reference-style links are now properly preserved when reflowing text
26
+ - Fixed indicator display to correctly show `[fixed]` when issues are resolved
27
+ - **Tests**: Mark kramdown definition list doctest as text to fix test failures
28
+
29
+ ### Changed
30
+ - **Internal**: Centralized markdown pattern regexes and extended reflow support
31
+ - Improved code organization and reduced duplication
32
+ - Better performance through shared regex compilation
33
+
34
+ ## [0.0.122] - 2025-08-19
35
+
10
36
  ## [0.0.121] - 2025-08-19
11
37
 
12
38
  ### Fixed
@@ -370,7 +396,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
370
396
 
371
397
  - Initial implementation of remaining rules for markdownlint parity
372
398
 
373
- [Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.121...HEAD
399
+ [Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.123...HEAD
400
+ [0.0.123]: https://github.com/rvben/rumdl/compare/v0.0.122...v0.0.123
401
+ [0.0.122]: https://github.com/rvben/rumdl/compare/v0.0.121...v0.0.122
374
402
  [0.0.121]: https://github.com/rvben/rumdl/compare/v0.0.120...v0.0.121
375
403
  [0.0.120]: https://github.com/rvben/rumdl/compare/v0.0.119...v0.0.120
376
404
  [0.0.119]: https://github.com/rvben/rumdl/compare/v0.0.118...v0.0.119
@@ -229,9 +229,9 @@ dependencies = [
229
229
 
230
230
  [[package]]
231
231
  name = "cfg-if"
232
- version = "1.0.1"
232
+ version = "1.0.3"
233
233
  source = "registry+https://github.com/rust-lang/crates.io-index"
234
- checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
234
+ checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
235
235
 
236
236
  [[package]]
237
237
  name = "chrono"
@@ -530,9 +530,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
530
530
 
531
531
  [[package]]
532
532
  name = "form_urlencoded"
533
- version = "1.2.1"
533
+ version = "1.2.2"
534
534
  source = "registry+https://github.com/rust-lang/crates.io-index"
535
- checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
535
+ checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
536
536
  dependencies = [
537
537
  "percent-encoding",
538
538
  ]
@@ -806,9 +806,9 @@ dependencies = [
806
806
 
807
807
  [[package]]
808
808
  name = "idna"
809
- version = "1.0.3"
809
+ version = "1.1.0"
810
810
  source = "registry+https://github.com/rust-lang/crates.io-index"
811
- checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
811
+ checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
812
812
  dependencies = [
813
813
  "idna_adapter",
814
814
  "smallvec",
@@ -1126,9 +1126,9 @@ dependencies = [
1126
1126
 
1127
1127
  [[package]]
1128
1128
  name = "percent-encoding"
1129
- version = "2.3.1"
1129
+ version = "2.3.2"
1130
1130
  source = "registry+https://github.com/rust-lang/crates.io-index"
1131
- checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
1131
+ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
1132
1132
 
1133
1133
  [[package]]
1134
1134
  name = "pin-project"
@@ -1493,7 +1493,7 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
1493
1493
 
1494
1494
  [[package]]
1495
1495
  name = "rumdl"
1496
- version = "0.0.121"
1496
+ version = "0.0.123"
1497
1497
  dependencies = [
1498
1498
  "anyhow",
1499
1499
  "assert_cmd",
@@ -1751,15 +1751,15 @@ checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
1751
1751
 
1752
1752
  [[package]]
1753
1753
  name = "tempfile"
1754
- version = "3.20.0"
1754
+ version = "3.21.0"
1755
1755
  source = "registry+https://github.com/rust-lang/crates.io-index"
1756
- checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
1756
+ checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e"
1757
1757
  dependencies = [
1758
1758
  "fastrand",
1759
1759
  "getrandom",
1760
1760
  "once_cell",
1761
1761
  "rustix",
1762
- "windows-sys 0.59.0",
1762
+ "windows-sys 0.60.2",
1763
1763
  ]
1764
1764
 
1765
1765
  [[package]]
@@ -1770,18 +1770,18 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
1770
1770
 
1771
1771
  [[package]]
1772
1772
  name = "thiserror"
1773
- version = "2.0.15"
1773
+ version = "2.0.16"
1774
1774
  source = "registry+https://github.com/rust-lang/crates.io-index"
1775
- checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850"
1775
+ checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
1776
1776
  dependencies = [
1777
1777
  "thiserror-impl",
1778
1778
  ]
1779
1779
 
1780
1780
  [[package]]
1781
1781
  name = "thiserror-impl"
1782
- version = "2.0.15"
1782
+ version = "2.0.16"
1783
1783
  source = "registry+https://github.com/rust-lang/crates.io-index"
1784
- checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0"
1784
+ checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
1785
1785
  dependencies = [
1786
1786
  "proc-macro2",
1787
1787
  "quote",
@@ -2080,9 +2080,9 @@ checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
2080
2080
 
2081
2081
  [[package]]
2082
2082
  name = "url"
2083
- version = "2.5.4"
2083
+ version = "2.5.6"
2084
2084
  source = "registry+https://github.com/rust-lang/crates.io-index"
2085
- checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
2085
+ checksum = "137a3c834eaf7139b73688502f3f1141a0337c5d8e4d9b536f9b8c796e26a7c4"
2086
2086
  dependencies = [
2087
2087
  "form_urlencoded",
2088
2088
  "idna",
@@ -2206,11 +2206,11 @@ dependencies = [
2206
2206
 
2207
2207
  [[package]]
2208
2208
  name = "winapi-util"
2209
- version = "0.1.9"
2209
+ version = "0.1.10"
2210
2210
  source = "registry+https://github.com/rust-lang/crates.io-index"
2211
- checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
2211
+ checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22"
2212
2212
  dependencies = [
2213
- "windows-sys 0.59.0",
2213
+ "windows-sys 0.60.2",
2214
2214
  ]
2215
2215
 
2216
2216
  [[package]]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rumdl"
3
- version = "0.0.121"
3
+ version = "0.0.123"
4
4
  edition = "2024"
5
5
  rust-version = "1.89.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.121
3
+ Version: 0.0.123
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -96,6 +96,8 @@ It offers:
96
96
  - [VS Code Extension](#vs-code-extension)
97
97
  - [Usage](#usage)
98
98
  - [Pre-commit Integration](#pre-commit-integration)
99
+ - [CI/CD Integration](#cicd-integration)
100
+ - [GitHub Actions](#github-actions)
99
101
  - [Rules](#rules)
100
102
  - [Command-line Interface](#command-line-interface)
101
103
  - [Commands](#commands)
@@ -270,6 +272,19 @@ repos:
270
272
 
271
273
  When you run `pre-commit install` or `pre-commit run`, pre-commit will automatically install `rumdl` in an isolated Python environment using pip. You do **not** need to install rumdl manually.
272
274
 
275
+ ## CI/CD Integration
276
+
277
+ ### GitHub Actions
278
+
279
+ rumdl can output annotations directly in GitHub Actions format, making issues appear inline in pull requests:
280
+
281
+ ```yaml
282
+ - name: Lint Markdown
283
+ run: rumdl check --output-format github .
284
+ ```
285
+
286
+ This produces annotations that GitHub automatically displays in the PR's "Files changed" tab. Supports error/warning severity levels and precise issue locations.
287
+
273
288
  ## Rules
274
289
 
275
290
  rumdl implements 54 lint rules for Markdown files. Here are some key rule categories:
@@ -67,6 +67,8 @@ It offers:
67
67
  - [VS Code Extension](#vs-code-extension)
68
68
  - [Usage](#usage)
69
69
  - [Pre-commit Integration](#pre-commit-integration)
70
+ - [CI/CD Integration](#cicd-integration)
71
+ - [GitHub Actions](#github-actions)
70
72
  - [Rules](#rules)
71
73
  - [Command-line Interface](#command-line-interface)
72
74
  - [Commands](#commands)
@@ -241,6 +243,19 @@ repos:
241
243
 
242
244
  When you run `pre-commit install` or `pre-commit run`, pre-commit will automatically install `rumdl` in an isolated Python environment using pip. You do **not** need to install rumdl manually.
243
245
 
246
+ ## CI/CD Integration
247
+
248
+ ### GitHub Actions
249
+
250
+ rumdl can output annotations directly in GitHub Actions format, making issues appear inline in pull requests:
251
+
252
+ ```yaml
253
+ - name: Lint Markdown
254
+ run: rumdl check --output-format github .
255
+ ```
256
+
257
+ This produces annotations that GitHub automatically displays in the PR's "Files changed" tab. Supports error/warning severity levels and precise issue locations.
258
+
244
259
  ## Rules
245
260
 
246
261
  rumdl implements 54 lint rules for Markdown files. Here are some key rule categories:
@@ -2355,6 +2355,26 @@ fn print_statistics(warnings: &[rumdl::rule::LintWarning]) {
2355
2355
  );
2356
2356
  }
2357
2357
 
2358
+ // Helper function to check if a rule is actually fixable based on configuration
2359
+ fn is_rule_actually_fixable(config: &rumdl_config::Config, rule_name: &str) -> bool {
2360
+ // Check unfixable list
2361
+ if config
2362
+ .global
2363
+ .unfixable
2364
+ .iter()
2365
+ .any(|r| r.eq_ignore_ascii_case(rule_name))
2366
+ {
2367
+ return false;
2368
+ }
2369
+
2370
+ // Check fixable list if specified
2371
+ if !config.global.fixable.is_empty() {
2372
+ return config.global.fixable.iter().any(|r| r.eq_ignore_ascii_case(rule_name));
2373
+ }
2374
+
2375
+ true
2376
+ }
2377
+
2358
2378
  // Process file with output formatter
2359
2379
  #[allow(clippy::too_many_arguments)]
2360
2380
  fn process_file_with_formatter(
@@ -2371,7 +2391,7 @@ fn process_file_with_formatter(
2371
2391
 
2372
2392
  // Call the original process_file_inner to get warnings
2373
2393
  let (all_warnings, mut content, total_warnings, fixable_warnings) =
2374
- process_file_inner(file_path, rules, verbose, quiet);
2394
+ process_file_inner(file_path, rules, verbose, quiet, config);
2375
2395
 
2376
2396
  if total_warnings == 0 {
2377
2397
  return (false, 0, 0, 0, Vec::new());
@@ -2408,14 +2428,25 @@ fn process_file_with_formatter(
2408
2428
  // Create a custom formatter that shows [fixed] instead of [*]
2409
2429
  let mut output = String::new();
2410
2430
  for warning in &all_warnings {
2431
+ let rule_name = warning.rule_name.unwrap_or("unknown");
2432
+
2433
+ // Check if the rule is actually fixable based on configuration
2434
+ let is_fixable = is_rule_actually_fixable(config, rule_name);
2435
+
2411
2436
  let was_fixed = warning.fix.is_some()
2437
+ && is_fixable
2412
2438
  && !remaining_warnings.iter().any(|w| {
2413
2439
  w.line == warning.line && w.column == warning.column && w.rule_name == warning.rule_name
2414
2440
  });
2415
2441
 
2416
- let rule_name = warning.rule_name.unwrap_or("unknown");
2417
- let fix_indicator = if was_fixed {
2418
- " [fixed]".green().to_string()
2442
+ let fix_indicator = if warning.fix.is_some() {
2443
+ if !is_fixable {
2444
+ " [unfixable]".yellow().to_string()
2445
+ } else if was_fixed {
2446
+ " [fixed]".green().to_string()
2447
+ } else {
2448
+ String::new()
2449
+ }
2419
2450
  } else {
2420
2451
  String::new()
2421
2452
  };
@@ -2454,6 +2485,7 @@ fn process_file_inner(
2454
2485
  rules: &[Box<dyn Rule>],
2455
2486
  verbose: bool,
2456
2487
  quiet: bool,
2488
+ config: &rumdl_config::Config,
2457
2489
  ) -> (Vec<rumdl::rule::LintWarning>, String, usize, usize) {
2458
2490
  use std::time::Instant;
2459
2491
 
@@ -2507,8 +2539,11 @@ fn process_file_inner(
2507
2539
 
2508
2540
  let total_warnings = all_warnings.len();
2509
2541
 
2510
- // Count fixable issues
2511
- let fixable_warnings = all_warnings.iter().filter(|w| w.fix.is_some()).count();
2542
+ // Count fixable issues (excluding unfixable rules)
2543
+ let fixable_warnings = all_warnings
2544
+ .iter()
2545
+ .filter(|w| w.fix.is_some() && w.rule_name.is_some_and(|name| is_rule_actually_fixable(config, name)))
2546
+ .count();
2512
2547
 
2513
2548
  let lint_end_time = Instant::now();
2514
2549
  let lint_time = lint_end_time.duration_since(lint_start);
@@ -1,10 +1,13 @@
1
1
  //! GitHub Actions annotation format
2
+ //!
3
+ //! Outputs annotations in GitHub Actions workflow command format for PR annotations.
4
+ //! See: https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions
2
5
 
3
6
  use crate::output::OutputFormatter;
4
- use crate::rule::LintWarning;
7
+ use crate::rule::{LintWarning, Severity};
5
8
 
6
9
  /// GitHub Actions formatter
7
- /// Outputs in the format: ::error file=<file>,line=<line>,col=<col>,title=<rule>::<message>
10
+ /// Outputs in the format: ::<level> file=<file>,line=<line>,col=<col>,endLine=<endLine>,endColumn=<endCol>,title=<rule>::<message>
8
11
  pub struct GitHubFormatter;
9
12
 
10
13
  impl Default for GitHubFormatter {
@@ -17,6 +20,24 @@ impl GitHubFormatter {
17
20
  pub fn new() -> Self {
18
21
  Self
19
22
  }
23
+
24
+ /// Escape special characters according to GitHub Actions specification
25
+ /// Percent-encodes: %, \r, \n, :, ,
26
+ /// Used for property values (file, title, etc.)
27
+ fn escape_property(value: &str) -> String {
28
+ value
29
+ .replace('%', "%25")
30
+ .replace('\r', "%0D")
31
+ .replace('\n', "%0A")
32
+ .replace(':', "%3A")
33
+ .replace(',', "%2C")
34
+ }
35
+
36
+ /// Escape special characters in the message part
37
+ /// Percent-encodes: %, \r, \n
38
+ fn escape_message(value: &str) -> String {
39
+ value.replace('%', "%25").replace('\r', "%0D").replace('\n', "%0A")
40
+ }
20
41
  }
21
42
 
22
43
  impl OutputFormatter for GitHubFormatter {
@@ -26,12 +47,38 @@ impl OutputFormatter for GitHubFormatter {
26
47
  for warning in warnings {
27
48
  let rule_name = warning.rule_name.unwrap_or("unknown");
28
49
 
29
- // GitHub Actions annotation format
30
- // Use "warning" level since these are linting warnings, not errors
31
- let line = format!(
32
- "::warning file={},line={},col={},title={}::{}",
33
- file_path, warning.line, warning.column, rule_name, warning.message
34
- );
50
+ // Map severity to GitHub Actions annotation level
51
+ let level = match warning.severity {
52
+ Severity::Error => "error",
53
+ Severity::Warning => "warning",
54
+ };
55
+
56
+ // Escape special characters in all properties
57
+ let escaped_file = Self::escape_property(file_path);
58
+ let escaped_rule = Self::escape_property(rule_name);
59
+ let escaped_message = Self::escape_message(&warning.message);
60
+
61
+ // GitHub Actions annotation format with optional end position
62
+ let line = if warning.end_line != warning.line || warning.end_column != warning.column {
63
+ // Include end position if different from start
64
+ format!(
65
+ "::{} file={},line={},col={},endLine={},endColumn={},title={}::{}",
66
+ level,
67
+ escaped_file,
68
+ warning.line,
69
+ warning.column,
70
+ warning.end_line,
71
+ warning.end_column,
72
+ escaped_rule,
73
+ escaped_message
74
+ )
75
+ } else {
76
+ // Omit end position if same as start
77
+ format!(
78
+ "::{} file={},line={},col={},title={}::{}",
79
+ level, escaped_file, warning.line, warning.column, escaped_rule, escaped_message
80
+ )
81
+ };
35
82
 
36
83
  output.push_str(&line);
37
84
  output.push('\n');
@@ -88,7 +135,7 @@ mod tests {
88
135
  let output = formatter.format_warnings(&warnings, "README.md");
89
136
  assert_eq!(
90
137
  output,
91
- "::warning file=README.md,line=10,col=5,title=MD001::Heading levels should only increment by one level at a time"
138
+ "::warning file=README.md,line=10,col=5,endLine=10,endColumn=15,title=MD001::Heading levels should only increment by one level at a time"
92
139
  );
93
140
  }
94
141
 
@@ -119,7 +166,7 @@ mod tests {
119
166
  ];
120
167
 
121
168
  let output = formatter.format_warnings(&warnings, "test.md");
122
- let expected = "::warning file=test.md,line=5,col=1,title=MD001::First warning\n::warning file=test.md,line=10,col=3,title=MD013::Second warning";
169
+ let expected = "::warning file=test.md,line=5,col=1,endLine=5,endColumn=10,title=MD001::First warning\n::error file=test.md,line=10,col=3,endLine=10,endColumn=20,title=MD013::Second warning";
123
170
  assert_eq!(output, expected);
124
171
  }
125
172
 
@@ -141,10 +188,10 @@ mod tests {
141
188
  }];
142
189
 
143
190
  let output = formatter.format_warnings(&warnings, "doc.md");
144
- // GitHub format doesn't show fix indicator
191
+ // GitHub format doesn't show fix indicator but includes end position
145
192
  assert_eq!(
146
193
  output,
147
- "::warning file=doc.md,line=15,col=1,title=MD022::Headings should be surrounded by blank lines"
194
+ "::warning file=doc.md,line=15,col=1,endLine=15,endColumn=10,title=MD022::Headings should be surrounded by blank lines"
148
195
  );
149
196
  }
150
197
 
@@ -165,7 +212,7 @@ mod tests {
165
212
  let output = formatter.format_warnings(&warnings, "file.md");
166
213
  assert_eq!(
167
214
  output,
168
- "::warning file=file.md,line=1,col=1,title=unknown::Unknown rule warning"
215
+ "::warning file=file.md,line=1,col=1,endLine=1,endColumn=5,title=unknown::Unknown rule warning"
169
216
  );
170
217
  }
171
218
 
@@ -188,7 +235,7 @@ mod tests {
188
235
  let output = formatter.format_warnings(&warnings, "large.md");
189
236
  assert_eq!(
190
237
  output,
191
- "::warning file=large.md,line=99999,col=12345,title=MD999::Edge case warning"
238
+ "::error file=large.md,line=99999,col=12345,endLine=100000,endColumn=12350,title=MD999::Edge case warning"
192
239
  );
193
240
  }
194
241
 
@@ -207,10 +254,32 @@ mod tests {
207
254
  }];
208
255
 
209
256
  let output = formatter.format_warnings(&warnings, "test.md");
210
- // Note: GitHub Actions should handle special characters in messages
257
+ // Newline should be escaped as %0A
258
+ assert_eq!(
259
+ output,
260
+ "::warning file=test.md,line=1,col=1,endLine=1,endColumn=5,title=MD001::Warning with \"quotes\" and 'apostrophes' and %0A newline"
261
+ );
262
+ }
263
+
264
+ #[test]
265
+ fn test_percent_encoding() {
266
+ let formatter = GitHubFormatter::new();
267
+ let warnings = vec![LintWarning {
268
+ line: 1,
269
+ column: 1,
270
+ end_line: 1,
271
+ end_column: 1,
272
+ rule_name: Some("MD001"),
273
+ message: "100% complete\r\nNew line".to_string(),
274
+ severity: Severity::Warning,
275
+ fix: None,
276
+ }];
277
+
278
+ let output = formatter.format_warnings(&warnings, "test%.md");
279
+ // %, \r, and \n should be encoded
211
280
  assert_eq!(
212
281
  output,
213
- "::warning file=test.md,line=1,col=1,title=MD001::Warning with \"quotes\" and 'apostrophes' and \n newline"
282
+ "::warning file=test%25.md,line=1,col=1,title=MD001::100%25 complete%0D%0ANew line"
214
283
  );
215
284
  }
216
285
 
@@ -231,7 +300,7 @@ mod tests {
231
300
  let output = formatter.format_warnings(&warnings, "path/with spaces/and-dashes.md");
232
301
  assert_eq!(
233
302
  output,
234
- "::warning file=path/with spaces/and-dashes.md,line=1,col=1,title=MD001::Test"
303
+ "::warning file=path/with spaces/and-dashes.md,line=1,col=1,endLine=1,endColumn=5,title=MD001::Test"
235
304
  );
236
305
  }
237
306
 
@@ -256,15 +325,17 @@ mod tests {
256
325
  assert!(output.contains("file=test.md"));
257
326
  assert!(output.contains("line=42"));
258
327
  assert!(output.contains("col=7"));
328
+ assert!(output.contains("endLine=42"));
329
+ assert!(output.contains("endColumn=10"));
259
330
  assert!(output.contains("title=MD010"));
260
331
  assert!(output.ends_with("::Hard tabs"));
261
332
  }
262
333
 
263
334
  #[test]
264
- fn test_severity_always_warning() {
335
+ fn test_severity_mapping() {
265
336
  let formatter = GitHubFormatter::new();
266
337
 
267
- // Test that all severities are output as "warning" in GitHub format
338
+ // Test that severities are properly mapped
268
339
  let warnings = vec![
269
340
  LintWarning {
270
341
  line: 1,
@@ -291,16 +362,16 @@ mod tests {
291
362
  let output = formatter.format_warnings(&warnings, "test.md");
292
363
  let lines: Vec<&str> = output.lines().collect();
293
364
 
294
- // Both should use ::warning regardless of severity
365
+ // Warning should use ::warning, Error should use ::error
295
366
  assert!(lines[0].starts_with("::warning "));
296
- assert!(lines[1].starts_with("::warning "));
367
+ assert!(lines[1].starts_with("::error "));
297
368
  }
298
369
 
299
370
  #[test]
300
371
  fn test_commas_in_parameters() {
301
372
  let formatter = GitHubFormatter::new();
302
373
 
303
- // Test that commas in the title don't break the format
374
+ // Test that commas in the title and file path are properly escaped
304
375
  let warnings = vec![LintWarning {
305
376
  line: 1,
306
377
  column: 1,
@@ -313,10 +384,80 @@ mod tests {
313
384
  }];
314
385
 
315
386
  let output = formatter.format_warnings(&warnings, "file,with,commas.md");
316
- // The format should still be parseable by GitHub Actions
387
+ // Commas in properties should be escaped as %2C
388
+ assert_eq!(
389
+ output,
390
+ "::warning file=file%2Cwith%2Ccommas.md,line=1,col=1,endLine=1,endColumn=5,title=MD%2C001::Test message, with comma"
391
+ );
392
+ }
393
+
394
+ #[test]
395
+ fn test_colons_in_parameters() {
396
+ let formatter = GitHubFormatter::new();
397
+
398
+ // Test that colons in file path and rule name are properly escaped
399
+ let warnings = vec![LintWarning {
400
+ line: 1,
401
+ column: 1,
402
+ end_line: 1,
403
+ end_column: 5,
404
+ rule_name: Some("MD:001"), // Unlikely but test edge case
405
+ message: "Test message: with colon".to_string(),
406
+ severity: Severity::Warning,
407
+ fix: None,
408
+ }];
409
+
410
+ let output = formatter.format_warnings(&warnings, "file:with:colons.md");
411
+ // Colons in properties should be escaped as %3A, but not in message
412
+ assert_eq!(
413
+ output,
414
+ "::warning file=file%3Awith%3Acolons.md,line=1,col=1,endLine=1,endColumn=5,title=MD%3A001::Test message: with colon"
415
+ );
416
+ }
417
+
418
+ #[test]
419
+ fn test_same_start_end_position() {
420
+ let formatter = GitHubFormatter::new();
421
+
422
+ // When start and end are the same, end position should be omitted
423
+ let warnings = vec![LintWarning {
424
+ line: 5,
425
+ column: 10,
426
+ end_line: 5,
427
+ end_column: 10,
428
+ rule_name: Some("MD001"),
429
+ message: "Single position warning".to_string(),
430
+ severity: Severity::Warning,
431
+ fix: None,
432
+ }];
433
+
434
+ let output = formatter.format_warnings(&warnings, "test.md");
435
+ // Should not include endLine and endColumn when they're the same as line and column
436
+ assert_eq!(
437
+ output,
438
+ "::warning file=test.md,line=5,col=10,title=MD001::Single position warning"
439
+ );
440
+ }
441
+
442
+ #[test]
443
+ fn test_error_severity() {
444
+ let formatter = GitHubFormatter::new();
445
+
446
+ let warnings = vec![LintWarning {
447
+ line: 1,
448
+ column: 1,
449
+ end_line: 1,
450
+ end_column: 5,
451
+ rule_name: Some("MD001"),
452
+ message: "Error level issue".to_string(),
453
+ severity: Severity::Error,
454
+ fix: None,
455
+ }];
456
+
457
+ let output = formatter.format_warnings(&warnings, "test.md");
317
458
  assert_eq!(
318
459
  output,
319
- "::warning file=file,with,commas.md,line=1,col=1,title=MD,001::Test message, with comma"
460
+ "::error file=test.md,line=1,col=1,endLine=1,endColumn=5,title=MD001::Error level issue"
320
461
  );
321
462
  }
322
463
  }
@@ -81,6 +81,17 @@ pub enum RuleCategory {
81
81
  Other,
82
82
  }
83
83
 
84
+ /// Capability of a rule to fix issues
85
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
86
+ pub enum FixCapability {
87
+ /// Rule can automatically fix all violations it detects
88
+ FullyFixable,
89
+ /// Rule can fix some violations based on context
90
+ ConditionallyFixable,
91
+ /// Rule cannot fix violations (by design)
92
+ Unfixable,
93
+ }
94
+
84
95
  /// Remove marker /// TRAIT_MARKER_V1
85
96
  pub trait Rule: DynClone + Send + Sync {
86
97
  fn name(&self) -> &'static str;
@@ -148,6 +159,11 @@ pub trait Rule: DynClone + Send + Sync {
148
159
  None
149
160
  }
150
161
 
162
+ /// Declares the fix capability of this rule
163
+ fn fix_capability(&self) -> FixCapability {
164
+ FixCapability::FullyFixable // Safe default for backward compatibility
165
+ }
166
+
151
167
  /// Factory: create a rule from config (if present), or use defaults.
152
168
  fn from_config(_config: &crate::config::Config) -> Box<dyn Rule>
153
169
  where