rumdl 0.0.118__tar.gz → 0.0.119__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 (387) hide show
  1. {rumdl-0.0.118 → rumdl-0.0.119}/CHANGELOG.md +18 -3
  2. {rumdl-0.0.118 → rumdl-0.0.119}/Cargo.lock +1 -1
  3. {rumdl-0.0.118 → rumdl-0.0.119}/Cargo.toml +2 -1
  4. {rumdl-0.0.118 → rumdl-0.0.119}/PKG-INFO +1 -1
  5. {rumdl-0.0.118 → rumdl-0.0.119}/src/lint_context.rs +26 -2
  6. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md007_ul_indent.rs +1 -25
  7. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md051_link_fragments.rs +194 -150
  8. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md057_existing_relative_links.rs +0 -13
  9. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/document_structure.rs +0 -8
  10. rumdl-0.0.119/src/utils/header_id_utils.rs +349 -0
  11. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/kramdown_utils.rs +73 -156
  12. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/mod.rs +1 -0
  13. rumdl-0.0.119/tests/rules/md051_issue_39_regression_test.rs +232 -0
  14. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md051_test.rs +382 -25
  15. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md051_unicode_test.rs +13 -14
  16. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/mod.rs +1 -0
  17. {rumdl-0.0.118 → rumdl-0.0.119}/.config/nextest.toml +0 -0
  18. {rumdl-0.0.118 → rumdl-0.0.119}/.mise.toml +0 -0
  19. {rumdl-0.0.118 → rumdl-0.0.119}/.pre-commit-config.yaml +0 -0
  20. {rumdl-0.0.118 → rumdl-0.0.119}/.rumdl.toml +0 -0
  21. {rumdl-0.0.118 → rumdl-0.0.119}/.rustfmt.toml +0 -0
  22. {rumdl-0.0.118 → rumdl-0.0.119}/LICENSE +0 -0
  23. {rumdl-0.0.118 → rumdl-0.0.119}/MANIFEST.in +0 -0
  24. {rumdl-0.0.118 → rumdl-0.0.119}/Makefile +0 -0
  25. {rumdl-0.0.118 → rumdl-0.0.119}/README.md +0 -0
  26. {rumdl-0.0.118 → rumdl-0.0.119}/assets/logo.png +0 -0
  27. {rumdl-0.0.118 → rumdl-0.0.119}/benches/fix_performance.rs +0 -0
  28. {rumdl-0.0.118 → rumdl-0.0.119}/benches/range_performance.rs +0 -0
  29. {rumdl-0.0.118 → rumdl-0.0.119}/benches/range_utils_benchmark.rs +0 -0
  30. {rumdl-0.0.118 → rumdl-0.0.119}/benches/rule_performance.rs +0 -0
  31. {rumdl-0.0.118 → rumdl-0.0.119}/benches/simple_fix_bench.rs +0 -0
  32. {rumdl-0.0.118 → rumdl-0.0.119}/benchmark/bin/bench_lint_context.rs +0 -0
  33. {rumdl-0.0.118 → rumdl-0.0.119}/benchmark/bin/benchmark.rs +0 -0
  34. {rumdl-0.0.118 → rumdl-0.0.119}/benchmark/bin/benchmark_rule.rs +0 -0
  35. {rumdl-0.0.118 → rumdl-0.0.119}/benchmark/bin/file_parallel_benchmark.rs +0 -0
  36. {rumdl-0.0.118 → rumdl-0.0.119}/benchmark/bin/measure_code_span_performance.rs +0 -0
  37. {rumdl-0.0.118 → rumdl-0.0.119}/docs/RULES.md +0 -0
  38. {rumdl-0.0.118 → rumdl-0.0.119}/docs/global-settings.md +0 -0
  39. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md001.md +0 -0
  40. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md002.md +0 -0
  41. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md003.md +0 -0
  42. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md004.md +0 -0
  43. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md005.md +0 -0
  44. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md006.md +0 -0
  45. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md007.md +0 -0
  46. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md009.md +0 -0
  47. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md010.md +0 -0
  48. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md011.md +0 -0
  49. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md012.md +0 -0
  50. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md013.md +0 -0
  51. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md014.md +0 -0
  52. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md018.md +0 -0
  53. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md019.md +0 -0
  54. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md020.md +0 -0
  55. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md021.md +0 -0
  56. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md022.md +0 -0
  57. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md023.md +0 -0
  58. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md024.md +0 -0
  59. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md025.md +0 -0
  60. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md026.md +0 -0
  61. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md027.md +0 -0
  62. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md028.md +0 -0
  63. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md029.md +0 -0
  64. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md030.md +0 -0
  65. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md031.md +0 -0
  66. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md032.md +0 -0
  67. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md033.md +0 -0
  68. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md034.md +0 -0
  69. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md035.md +0 -0
  70. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md036.md +0 -0
  71. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md037.md +0 -0
  72. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md038.md +0 -0
  73. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md039.md +0 -0
  74. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md040.md +0 -0
  75. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md041.md +0 -0
  76. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md042.md +0 -0
  77. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md043.md +0 -0
  78. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md044.md +0 -0
  79. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md045.md +0 -0
  80. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md046.md +0 -0
  81. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md047.md +0 -0
  82. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md048.md +0 -0
  83. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md049.md +0 -0
  84. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md050.md +0 -0
  85. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md051.md +0 -0
  86. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md052.md +0 -0
  87. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md053.md +0 -0
  88. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md054.md +0 -0
  89. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md055.md +0 -0
  90. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md056.md +0 -0
  91. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md057.md +0 -0
  92. {rumdl-0.0.118 → rumdl-0.0.119}/docs/md058.md +0 -0
  93. {rumdl-0.0.118 → rumdl-0.0.119}/docs/vscode-extension.md +0 -0
  94. {rumdl-0.0.118 → rumdl-0.0.119}/parity_check.py +0 -0
  95. {rumdl-0.0.118 → rumdl-0.0.119}/pyproject.toml +0 -0
  96. {rumdl-0.0.118 → rumdl-0.0.119}/python/MANIFEST.in +0 -0
  97. {rumdl-0.0.118 → rumdl-0.0.119}/python/PYTHON-README.md +0 -0
  98. {rumdl-0.0.118 → rumdl-0.0.119}/python/rumdl/__init__.py +0 -0
  99. {rumdl-0.0.118 → rumdl-0.0.119}/python/rumdl/__main__.py +0 -0
  100. {rumdl-0.0.118 → rumdl-0.0.119}/python/rumdl/py.typed +0 -0
  101. {rumdl-0.0.118 → rumdl-0.0.119}/rumdl.toml.example +0 -0
  102. {rumdl-0.0.118 → rumdl-0.0.119}/rust-toolchain.toml +0 -0
  103. {rumdl-0.0.118 → rumdl-0.0.119}/scripts/extract-changelog.sh +0 -0
  104. {rumdl-0.0.118 → rumdl-0.0.119}/scripts/generate-downloads-table.sh +0 -0
  105. {rumdl-0.0.118 → rumdl-0.0.119}/scripts/pre-release.sh +0 -0
  106. {rumdl-0.0.118 → rumdl-0.0.119}/scripts/prepare-release.sh +0 -0
  107. {rumdl-0.0.118 → rumdl-0.0.119}/scripts/setup-pre-commit.sh +0 -0
  108. {rumdl-0.0.118 → rumdl-0.0.119}/scripts/update-pre-commit-docs.sh +0 -0
  109. {rumdl-0.0.118 → rumdl-0.0.119}/src/config.rs +0 -0
  110. {rumdl-0.0.118 → rumdl-0.0.119}/src/exit_codes.rs +0 -0
  111. {rumdl-0.0.118 → rumdl-0.0.119}/src/inline_config.rs +0 -0
  112. {rumdl-0.0.118 → rumdl-0.0.119}/src/lib.rs +0 -0
  113. {rumdl-0.0.118 → rumdl-0.0.119}/src/lsp/mod.rs +0 -0
  114. {rumdl-0.0.118 → rumdl-0.0.119}/src/lsp/server.rs +0 -0
  115. {rumdl-0.0.118 → rumdl-0.0.119}/src/lsp/types.rs +0 -0
  116. {rumdl-0.0.118 → rumdl-0.0.119}/src/main.rs +0 -0
  117. {rumdl-0.0.118 → rumdl-0.0.119}/src/markdownlint_config.rs +0 -0
  118. {rumdl-0.0.118 → rumdl-0.0.119}/src/output/formatters/azure.rs +0 -0
  119. {rumdl-0.0.118 → rumdl-0.0.119}/src/output/formatters/concise.rs +0 -0
  120. {rumdl-0.0.118 → rumdl-0.0.119}/src/output/formatters/github.rs +0 -0
  121. {rumdl-0.0.118 → rumdl-0.0.119}/src/output/formatters/gitlab.rs +0 -0
  122. {rumdl-0.0.118 → rumdl-0.0.119}/src/output/formatters/grouped.rs +0 -0
  123. {rumdl-0.0.118 → rumdl-0.0.119}/src/output/formatters/json.rs +0 -0
  124. {rumdl-0.0.118 → rumdl-0.0.119}/src/output/formatters/json_lines.rs +0 -0
  125. {rumdl-0.0.118 → rumdl-0.0.119}/src/output/formatters/junit.rs +0 -0
  126. {rumdl-0.0.118 → rumdl-0.0.119}/src/output/formatters/mod.rs +0 -0
  127. {rumdl-0.0.118 → rumdl-0.0.119}/src/output/formatters/pylint.rs +0 -0
  128. {rumdl-0.0.118 → rumdl-0.0.119}/src/output/formatters/sarif.rs +0 -0
  129. {rumdl-0.0.118 → rumdl-0.0.119}/src/output/formatters/text.rs +0 -0
  130. {rumdl-0.0.118 → rumdl-0.0.119}/src/output/mod.rs +0 -0
  131. {rumdl-0.0.118 → rumdl-0.0.119}/src/parallel.rs +0 -0
  132. {rumdl-0.0.118 → rumdl-0.0.119}/src/performance.rs +0 -0
  133. {rumdl-0.0.118 → rumdl-0.0.119}/src/profiling.rs +0 -0
  134. {rumdl-0.0.118 → rumdl-0.0.119}/src/python.rs +0 -0
  135. {rumdl-0.0.118 → rumdl-0.0.119}/src/rule.rs +0 -0
  136. {rumdl-0.0.118 → rumdl-0.0.119}/src/rule_config.rs +0 -0
  137. {rumdl-0.0.118 → rumdl-0.0.119}/src/rule_config_serde.rs +0 -0
  138. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/blockquote_utils.rs +0 -0
  139. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/code_block_utils.rs +0 -0
  140. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/code_fence_utils.rs +0 -0
  141. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/emphasis_style.rs +0 -0
  142. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/front_matter_utils.rs +0 -0
  143. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/heading_utils.rs +0 -0
  144. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/list_utils.rs +0 -0
  145. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md001_heading_increment.rs +0 -0
  146. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md002_first_heading_h1/md002_config.rs +0 -0
  147. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md002_first_heading_h1.rs +0 -0
  148. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md003_heading_style/md003_config.rs +0 -0
  149. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md003_heading_style.rs +0 -0
  150. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md004_unordered_list_style/md004_config.rs +0 -0
  151. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md004_unordered_list_style.rs +0 -0
  152. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md005_list_indent.rs +0 -0
  153. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md006_start_bullets.rs +0 -0
  154. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md007_ul_indent/md007_config.rs +0 -0
  155. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md009_trailing_spaces/md009_config.rs +0 -0
  156. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md009_trailing_spaces.rs +0 -0
  157. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md010_no_hard_tabs/md010_config.rs +0 -0
  158. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md010_no_hard_tabs.rs +0 -0
  159. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md011_no_reversed_links.rs +0 -0
  160. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md012_no_multiple_blanks/md012_config.rs +0 -0
  161. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md012_no_multiple_blanks.rs +0 -0
  162. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md013_line_length/md013_config.rs +0 -0
  163. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md013_line_length.rs +0 -0
  164. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md014_commands_show_output/md014_config.rs +0 -0
  165. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md014_commands_show_output.rs +0 -0
  166. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md018_no_missing_space_atx.rs +0 -0
  167. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md019_no_multiple_space_atx.rs +0 -0
  168. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md020_no_missing_space_closed_atx.rs +0 -0
  169. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
  170. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md022_blanks_around_headings/md022_config.rs +0 -0
  171. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md022_blanks_around_headings.rs +0 -0
  172. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md023_heading_start_left.rs +0 -0
  173. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md024_no_duplicate_heading/md024_config.rs +0 -0
  174. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md024_no_duplicate_heading.rs +0 -0
  175. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md025_single_title/md025_config.rs +0 -0
  176. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md025_single_title.rs +0 -0
  177. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md026_no_trailing_punctuation/md026_config.rs +0 -0
  178. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md026_no_trailing_punctuation.rs +0 -0
  179. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md027_multiple_spaces_blockquote.rs +0 -0
  180. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md028_no_blanks_blockquote.rs +0 -0
  181. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md029_ordered_list_prefix/md029_config.rs +0 -0
  182. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md029_ordered_list_prefix.rs +0 -0
  183. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md030_list_marker_space/md030_config.rs +0 -0
  184. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md030_list_marker_space.rs +0 -0
  185. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md031_blanks_around_fences.rs +0 -0
  186. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md032_blanks_around_lists.rs +0 -0
  187. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md033_no_inline_html/md033_config.rs +0 -0
  188. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md033_no_inline_html.rs +0 -0
  189. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md034_no_bare_urls.rs +0 -0
  190. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md035_hr_style/md035_config.rs +0 -0
  191. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md035_hr_style.rs +0 -0
  192. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md036_no_emphasis_only_first/md036_config.rs +0 -0
  193. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md036_no_emphasis_only_first.rs +0 -0
  194. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md037_spaces_around_emphasis.rs +0 -0
  195. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md038_no_space_in_code.rs +0 -0
  196. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md039_no_space_in_links.rs +0 -0
  197. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md040_fenced_code_language.rs +0 -0
  198. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md041_first_line_heading.rs +0 -0
  199. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md042_no_empty_links.rs +0 -0
  200. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md043_required_headings.rs +0 -0
  201. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md044_proper_names/md044_config.rs +0 -0
  202. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md044_proper_names.rs +0 -0
  203. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md045_no_alt_text/md045_config.rs +0 -0
  204. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md045_no_alt_text.rs +0 -0
  205. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md046_code_block_style/md046_config.rs +0 -0
  206. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md046_code_block_style.rs +0 -0
  207. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md047_single_trailing_newline.rs +0 -0
  208. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md048_code_fence_style/md048_config.rs +0 -0
  209. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md048_code_fence_style.rs +0 -0
  210. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md049_emphasis_style/md049_config.rs +0 -0
  211. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md049_emphasis_style.rs +0 -0
  212. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md050_strong_style/md050_config.rs +0 -0
  213. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md050_strong_style.rs +0 -0
  214. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md052_reference_links_images.rs +0 -0
  215. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md053_link_image_reference_definitions.rs +0 -0
  216. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md054_link_image_style/md054_config.rs +0 -0
  217. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md054_link_image_style.rs +0 -0
  218. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md055_table_pipe_style/md055_config.rs +0 -0
  219. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md055_table_pipe_style.rs +0 -0
  220. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md056_table_column_count.rs +0 -0
  221. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md057_existing_relative_links/md057_config.rs +0 -0
  222. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/md058_blanks_around_tables.rs +0 -0
  223. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/mod.rs +0 -0
  224. {rumdl-0.0.118 → rumdl-0.0.119}/src/rules/strong_style.rs +0 -0
  225. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/ast_utils.rs +0 -0
  226. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/code_block_utils.rs +0 -0
  227. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/early_returns.rs +0 -0
  228. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/element_cache.rs +0 -0
  229. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/emphasis_utils.rs +0 -0
  230. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/fix_utils.rs +0 -0
  231. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/markdown_elements.rs +0 -0
  232. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/range_utils.rs +0 -0
  233. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/regex_cache.rs +0 -0
  234. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/skip_context.rs +0 -0
  235. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/string_interner.rs +0 -0
  236. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/table_utils.rs +0 -0
  237. {rumdl-0.0.118 → rumdl-0.0.119}/src/utils/text_reflow.rs +0 -0
  238. {rumdl-0.0.118 → rumdl-0.0.119}/src/vscode.rs +0 -0
  239. {rumdl-0.0.118 → rumdl-0.0.119}/tests/advanced_integration_tests.rs +0 -0
  240. {rumdl-0.0.118 → rumdl-0.0.119}/tests/character_ranges/additional_tests.rs +0 -0
  241. {rumdl-0.0.118 → rumdl-0.0.119}/tests/character_ranges/basic_tests.rs +0 -0
  242. {rumdl-0.0.118 → rumdl-0.0.119}/tests/character_ranges/comprehensive_tests.rs +0 -0
  243. {rumdl-0.0.118 → rumdl-0.0.119}/tests/character_ranges/extended_tests.rs +0 -0
  244. {rumdl-0.0.118 → rumdl-0.0.119}/tests/character_ranges/mod.rs +0 -0
  245. {rumdl-0.0.118 → rumdl-0.0.119}/tests/character_ranges/unicode_utils.rs +0 -0
  246. {rumdl-0.0.118 → rumdl-0.0.119}/tests/cli_duplication_test.rs +0 -0
  247. {rumdl-0.0.118 → rumdl-0.0.119}/tests/cli_explain_test.rs +0 -0
  248. {rumdl-0.0.118 → rumdl-0.0.119}/tests/cli_flag_precedence_test.rs +0 -0
  249. {rumdl-0.0.118 → rumdl-0.0.119}/tests/cli_integration_tests.rs +0 -0
  250. {rumdl-0.0.118 → rumdl-0.0.119}/tests/cli_lsp_fix_consistency.rs +0 -0
  251. {rumdl-0.0.118 → rumdl-0.0.119}/tests/cli_statistics_test.rs +0 -0
  252. {rumdl-0.0.118 → rumdl-0.0.119}/tests/common/cli_test_utils.rs +0 -0
  253. {rumdl-0.0.118 → rumdl-0.0.119}/tests/common/fixtures.rs +0 -0
  254. {rumdl-0.0.118 → rumdl-0.0.119}/tests/common/mod.rs +0 -0
  255. {rumdl-0.0.118 → rumdl-0.0.119}/tests/common/test_utils.rs +0 -0
  256. {rumdl-0.0.118 → rumdl-0.0.119}/tests/commonmark_compliance_tests.rs +0 -0
  257. {rumdl-0.0.118 → rumdl-0.0.119}/tests/comprehensive_integration_tests.rs +0 -0
  258. {rumdl-0.0.118 → rumdl-0.0.119}/tests/comprehensive_output_format_tests.rs +0 -0
  259. {rumdl-0.0.118 → rumdl-0.0.119}/tests/config_application_tests.rs +0 -0
  260. {rumdl-0.0.118 → rumdl-0.0.119}/tests/config_file_command_test.rs +0 -0
  261. {rumdl-0.0.118 → rumdl-0.0.119}/tests/config_tests.rs +0 -0
  262. {rumdl-0.0.118 → rumdl-0.0.119}/tests/configuration_inheritance_tests.rs +0 -0
  263. {rumdl-0.0.118 → rumdl-0.0.119}/tests/consistency_regression_tests.rs +0 -0
  264. {rumdl-0.0.118 → rumdl-0.0.119}/tests/cross_platform_compatibility_tests.rs +0 -0
  265. {rumdl-0.0.118 → rumdl-0.0.119}/tests/deeply_nested_lists_performance_test.rs +0 -0
  266. {rumdl-0.0.118 → rumdl-0.0.119}/tests/escaped_brackets_test.rs +0 -0
  267. {rumdl-0.0.118 → rumdl-0.0.119}/tests/final_confidence_assessment.rs +0 -0
  268. {rumdl-0.0.118 → rumdl-0.0.119}/tests/fixable_unfixable_config_test.rs +0 -0
  269. {rumdl-0.0.118 → rumdl-0.0.119}/tests/init_command_test.rs +0 -0
  270. {rumdl-0.0.118 → rumdl-0.0.119}/tests/init_tests.rs +0 -0
  271. {rumdl-0.0.118 → rumdl-0.0.119}/tests/inline_config_blocks_test.rs +0 -0
  272. {rumdl-0.0.118 → rumdl-0.0.119}/tests/inline_config_test.rs +0 -0
  273. {rumdl-0.0.118 → rumdl-0.0.119}/tests/integration_tests.rs +0 -0
  274. {rumdl-0.0.118 → rumdl-0.0.119}/tests/json_output_test.rs +0 -0
  275. {rumdl-0.0.118 → rumdl-0.0.119}/tests/kramdown_integration_test.rs +0 -0
  276. {rumdl-0.0.118 → rumdl-0.0.119}/tests/lib.rs +0 -0
  277. {rumdl-0.0.118 → rumdl-0.0.119}/tests/lsp_editor_integration_tests.rs +0 -0
  278. {rumdl-0.0.118 → rumdl-0.0.119}/tests/lsp_integration_tests.rs +0 -0
  279. {rumdl-0.0.118 → rumdl-0.0.119}/tests/lsp_memory_leak_tests.rs +0 -0
  280. {rumdl-0.0.118 → rumdl-0.0.119}/tests/lsp_tests.rs +0 -0
  281. {rumdl-0.0.118 → rumdl-0.0.119}/tests/malformed_markdown_stress_tests.rs +0 -0
  282. {rumdl-0.0.118 → rumdl-0.0.119}/tests/markdownlint_cli_integration.rs +0 -0
  283. {rumdl-0.0.118 → rumdl-0.0.119}/tests/markdownlint_config_test.rs +0 -0
  284. {rumdl-0.0.118 → rumdl-0.0.119}/tests/markdownlintignore_test.rs +0 -0
  285. {rumdl-0.0.118 → rumdl-0.0.119}/tests/md013_reflow_integration_test.rs +0 -0
  286. {rumdl-0.0.118 → rumdl-0.0.119}/tests/nested_code_block_test.rs +0 -0
  287. {rumdl-0.0.118 → rumdl-0.0.119}/tests/output_format_integration_tests.rs +0 -0
  288. {rumdl-0.0.118 → rumdl-0.0.119}/tests/output_format_tests.rs +0 -0
  289. {rumdl-0.0.118 → rumdl-0.0.119}/tests/perf_check.rs +0 -0
  290. {rumdl-0.0.118 → rumdl-0.0.119}/tests/performance_validation_tests.rs +0 -0
  291. {rumdl-0.0.118 → rumdl-0.0.119}/tests/pyproject_config_tests.rs +0 -0
  292. {rumdl-0.0.118 → rumdl-0.0.119}/tests/python_bindings_test.rs +0 -0
  293. {rumdl-0.0.118 → rumdl-0.0.119}/tests/real_world_repository_tests.rs +0 -0
  294. {rumdl-0.0.118 → rumdl-0.0.119}/tests/regression_prevention_tests.rs +0 -0
  295. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/emphasis_edge_cases_test.rs +0 -0
  296. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/heading_edge_cases_test.rs +0 -0
  297. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/inline_content_edge_cases_test.rs +0 -0
  298. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/link_edge_cases_test.rs +0 -0
  299. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/list_rules_integration_test.rs +0 -0
  300. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md001_test.rs +0 -0
  301. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md001_unicode_test.rs +0 -0
  302. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md002_test.rs +0 -0
  303. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md003_test.rs +0 -0
  304. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md004_test.rs +0 -0
  305. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md005_test.rs +0 -0
  306. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md005_unicode_test.rs +0 -0
  307. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md006_test.rs +0 -0
  308. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md006_unicode_test.rs +0 -0
  309. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md007_test.rs +0 -0
  310. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md009_test.rs +0 -0
  311. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md010_test.rs +0 -0
  312. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md011_test.rs +0 -0
  313. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md012_test.rs +0 -0
  314. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md013_test.rs +0 -0
  315. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md014_test.rs +0 -0
  316. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md018_test.rs +0 -0
  317. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md019_test.rs +0 -0
  318. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md020_test.rs +0 -0
  319. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md021_test.rs +0 -0
  320. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md022_test.rs +0 -0
  321. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md023_extended_test.rs +0 -0
  322. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md023_test.rs +0 -0
  323. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md024_test.rs +0 -0
  324. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md025_test.rs +0 -0
  325. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md026_kramdown_test.rs +0 -0
  326. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md026_test.rs +0 -0
  327. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md027_test.rs +0 -0
  328. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md028_test.rs +0 -0
  329. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md029_issue42_test.rs +0 -0
  330. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md029_test.rs +0 -0
  331. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md029_unicode_test.rs +0 -0
  332. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md030_test.rs +0 -0
  333. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md031_kramdown_test.rs +0 -0
  334. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md031_test.rs +0 -0
  335. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md032_test.rs +0 -0
  336. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md033_extended_test.rs +0 -0
  337. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md033_kramdown_test.rs +0 -0
  338. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md033_test.rs +0 -0
  339. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md034_ipv6_test.rs +0 -0
  340. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md034_test.rs +0 -0
  341. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md035_test.rs +0 -0
  342. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md036_test.rs +0 -0
  343. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md037_kramdown_test.rs +0 -0
  344. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md037_test.rs +0 -0
  345. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md038_nested_backticks_test.rs +0 -0
  346. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md038_test.rs +0 -0
  347. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md039_test.rs +0 -0
  348. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md040_test.rs +0 -0
  349. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md041_test.rs +0 -0
  350. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md042_test.rs +0 -0
  351. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md043_test.rs +0 -0
  352. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md044_test.rs +0 -0
  353. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md045_test.rs +0 -0
  354. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md046_test.rs +0 -0
  355. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md047_test.rs +0 -0
  356. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md048_test.rs +0 -0
  357. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md049_test.rs +0 -0
  358. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md050_test.rs +0 -0
  359. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md052_test.rs +0 -0
  360. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md053_additional_test.rs +0 -0
  361. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md053_proptest.rs +0 -0
  362. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md053_test.rs +0 -0
  363. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md054_test.rs +0 -0
  364. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md054_unicode_test.rs +0 -0
  365. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md055_test.rs +0 -0
  366. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md056_test.rs +0 -0
  367. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md057_test.rs +0 -0
  368. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md058_kramdown_test.rs +0 -0
  369. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules/md058_test.rs +0 -0
  370. {rumdl-0.0.118 → rumdl-0.0.119}/tests/rules_mod_test.rs +0 -0
  371. {rumdl-0.0.118 → rumdl-0.0.119}/tests/skip_context_tests.rs +0 -0
  372. {rumdl-0.0.118 → rumdl-0.0.119}/tests/thread_safety_tests.rs +0 -0
  373. {rumdl-0.0.118 → rumdl-0.0.119}/tests/unicode_edge_case_tests.rs +0 -0
  374. {rumdl-0.0.118 → rumdl-0.0.119}/tests/utils/blockquote_utils_test.rs +0 -0
  375. {rumdl-0.0.118 → rumdl-0.0.119}/tests/utils/code_block_utils_extended_test.rs +0 -0
  376. {rumdl-0.0.118 → rumdl-0.0.119}/tests/utils/code_block_utils_test.rs +0 -0
  377. {rumdl-0.0.118 → rumdl-0.0.119}/tests/utils/core_utils_test.rs +0 -0
  378. {rumdl-0.0.118 → rumdl-0.0.119}/tests/utils/front_matter_utils_test.rs +0 -0
  379. {rumdl-0.0.118 → rumdl-0.0.119}/tests/utils/line_index_test.rs +0 -0
  380. {rumdl-0.0.118 → rumdl-0.0.119}/tests/utils/mod.rs +0 -0
  381. {rumdl-0.0.118 → rumdl-0.0.119}/tests/utils_markdown_edge_cases.rs +0 -0
  382. {rumdl-0.0.118 → rumdl-0.0.119}/tests/utils_tests.rs +0 -0
  383. {rumdl-0.0.118 → rumdl-0.0.119}/tests/vscode_extension_fixes.rs +0 -0
  384. {rumdl-0.0.118 → rumdl-0.0.119}/tests/vscode_test.rs +0 -0
  385. {rumdl-0.0.118 → rumdl-0.0.119}/tests/vscode_tests.rs +0 -0
  386. {rumdl-0.0.118 → rumdl-0.0.119}/tests/vscode_windows_comprehensive_test.rs +0 -0
  387. {rumdl-0.0.118 → rumdl-0.0.119}/tests/vscode_windows_test.rs +0 -0
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.0.119] - 2025-08-15
11
+
12
+ ### Fixed
13
+ - **MD051**: Fixed GitHub anchor generation algorithm to correctly handle consecutive spaces
14
+ - "Test & Heading!" now correctly generates "test--heading" instead of "test-heading"
15
+ - Improved compliance with GitHub's official anchor generation behavior
16
+ - Fixed whitespace normalization bug that was collapsing multiple spaces to single spaces
17
+
18
+ ### Improved
19
+ - **Code Quality**: Removed all `#[allow(dead_code)]` violations in codebase
20
+ - Removed unused `InternalCodeBlockState` enum from document_structure.rs
21
+ - Removed unused `extract_url_from_link` function from md057_existing_relative_links.rs
22
+ - Removed unused `is_in_code_block` function from md007_ul_indent.rs
23
+
10
24
  ## [0.0.118] - 2025-08-14
11
25
 
12
26
  ## [0.0.117] - 2025-08-14
@@ -124,7 +138,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
124
138
  ## [0.0.99] - 2025-07-22
125
139
 
126
140
  ### Fixed
127
- - MD034: Added support for `ftps://` URLs
141
+ - MD034: Added support for `ftps://` URLs
128
142
  - MD034: Fixed detection of URLs in HTML comments (now properly ignored)
129
143
  - MD039: Fixed escaped character handling in link text
130
144
  - MD044: Fixed clippy warnings and improved pattern matching for proper names
@@ -202,7 +216,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
202
216
  ### Performance Improvements
203
217
  - Implemented lazy code span loading - 3.8x speedup for 94% of rules that don't use code spans
204
218
  - MD013: 34.5% faster check operations through aggressive early returns
205
- - MD038: 14% faster by leveraging lazy code span loading
219
+ - MD038: 14% faster by leveraging lazy code span loading
206
220
  - MD044: 93.5% faster with global regex caching
207
221
  - MD047: 8.3% faster using pre-computed line data
208
222
  - MD053: 39.7% faster by leveraging pre-parsed reference definitions
@@ -337,7 +351,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
337
351
 
338
352
  - Initial implementation of remaining rules for markdownlint parity
339
353
 
340
- [Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.118...HEAD
354
+ [Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.119...HEAD
355
+ [0.0.119]: https://github.com/rvben/rumdl/compare/v0.0.118...v0.0.119
341
356
  [0.0.118]: https://github.com/rvben/rumdl/compare/v0.0.117...v0.0.118
342
357
  [0.0.117]: https://github.com/rvben/rumdl/compare/v0.0.116...v0.0.117
343
358
  [0.0.116]: https://github.com/rvben/rumdl/compare/v0.0.115...v0.0.116
@@ -1493,7 +1493,7 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
1493
1493
 
1494
1494
  [[package]]
1495
1495
  name = "rumdl"
1496
- version = "0.0.118"
1496
+ version = "0.0.119"
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.118"
3
+ version = "0.0.119"
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)"
@@ -24,6 +24,7 @@ crate-type = ["cdylib", "rlib"]
24
24
  name = "rumdl"
25
25
  path = "src/main.rs"
26
26
 
27
+
27
28
  # Benchmark binaries - only built when explicitly requested
28
29
  [[bin]]
29
30
  name = "benchmark"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rumdl
3
- Version: 0.0.118
3
+ Version: 0.0.119
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -1154,7 +1154,19 @@ impl<'a> LintContext<'a> {
1154
1154
 
1155
1155
  // Extract custom header ID if present
1156
1156
  let raw_text = text.trim().to_string();
1157
- let (clean_text, custom_id) = crate::utils::kramdown_utils::extract_header_id(&raw_text);
1157
+ let (clean_text, mut custom_id) = crate::utils::header_id_utils::extract_header_id(&raw_text);
1158
+
1159
+ // If no custom ID was found on the header line, check the next line for standalone attr-list
1160
+ if custom_id.is_none() && i + 1 < content_lines.len() && i + 1 < lines.len() {
1161
+ let next_line = content_lines[i + 1];
1162
+ if !lines[i + 1].in_code_block
1163
+ && crate::utils::header_id_utils::is_standalone_attr_list(next_line)
1164
+ && let Some(next_line_id) =
1165
+ crate::utils::header_id_utils::extract_standalone_attr_list_id(next_line)
1166
+ {
1167
+ custom_id = Some(next_line_id);
1168
+ }
1169
+ }
1158
1170
 
1159
1171
  lines[i].heading = Some(HeadingInfo {
1160
1172
  level,
@@ -1188,7 +1200,19 @@ impl<'a> LintContext<'a> {
1188
1200
 
1189
1201
  // Extract custom header ID if present
1190
1202
  let raw_text = line.trim().to_string();
1191
- let (clean_text, custom_id) = crate::utils::kramdown_utils::extract_header_id(&raw_text);
1203
+ let (clean_text, mut custom_id) = crate::utils::header_id_utils::extract_header_id(&raw_text);
1204
+
1205
+ // If no custom ID was found on the header line, check the line after underline for standalone attr-list
1206
+ if custom_id.is_none() && i + 2 < content_lines.len() && i + 2 < lines.len() {
1207
+ let attr_line = content_lines[i + 2];
1208
+ if !lines[i + 2].in_code_block
1209
+ && crate::utils::header_id_utils::is_standalone_attr_list(attr_line)
1210
+ && let Some(attr_line_id) =
1211
+ crate::utils::header_id_utils::extract_standalone_attr_list_id(attr_line)
1212
+ {
1213
+ custom_id = Some(attr_line_id);
1214
+ }
1215
+ }
1192
1216
 
1193
1217
  lines[i].heading = Some(HeadingInfo {
1194
1218
  level,
@@ -5,7 +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 crate::utils::regex_cache::{CODE_FENCE_REGEX, UNORDERED_LIST_MARKER_REGEX};
8
+ use crate::utils::regex_cache::UNORDERED_LIST_MARKER_REGEX;
9
9
  use toml;
10
10
 
11
11
  mod md007_config;
@@ -69,30 +69,6 @@ impl MD007ULIndent {
69
69
  }
70
70
  (false, None)
71
71
  }
72
-
73
- #[allow(dead_code)]
74
- fn is_in_code_block(content: &str, line_idx: usize) -> bool {
75
- // Use centralized code fence pattern
76
-
77
- let lines: Vec<&str> = content.lines().collect();
78
- let mut in_code_block = false;
79
-
80
- for (i, line) in lines.iter().enumerate() {
81
- if i > line_idx {
82
- break;
83
- }
84
-
85
- if CODE_FENCE_REGEX.is_match(line.trim_start()) {
86
- in_code_block = !in_code_block;
87
- }
88
-
89
- if i == line_idx {
90
- return in_code_block;
91
- }
92
- }
93
-
94
- false
95
- }
96
72
  }
97
73
 
98
74
  impl Rule for MD007ULIndent {
@@ -1,4 +1,5 @@
1
1
  use crate::rule::{LintError, LintResult, LintWarning, Rule, Severity};
2
+ use crate::utils::kramdown_utils;
2
3
  use crate::utils::regex_cache::get_cached_regex;
3
4
  use lazy_static::lazy_static;
4
5
  use regex::Regex;
@@ -7,10 +8,10 @@ use std::collections::HashSet;
7
8
  lazy_static! {
8
9
  // Pre-compiled optimized patterns for quick checks
9
10
  static ref QUICK_MARKDOWN_CHECK: Regex = Regex::new(r"[*_`\[\]]").unwrap();
10
- // Match emphasis only when not part of snake_case (requires space or start/end)
11
- static ref EMPHASIS_PATTERN: Regex = Regex::new(r"\*+([^*]+)\*+|\b_([^_]+)_\b").unwrap();
11
+ // GitHub only strips asterisks (*), not underscores (_) - underscores are preserved
12
+ static ref EMPHASIS_PATTERN: Regex = Regex::new(r"\*+([^*]+)\*+").unwrap();
12
13
  static ref CODE_PATTERN: Regex = Regex::new(r"`([^`]+)`").unwrap();
13
- static ref LINK_PATTERN: Regex = Regex::new(r"\[([^\]]+)\]\([^)]+\)|\[([^\]]+)\]\[[^\]]*\]").unwrap();
14
+ static ref LINK_PATTERN: Regex = Regex::new(r"\[([^\]]+)\]\(([^)]+)\)|\[([^\]]+)\]\[[^\]]*\]").unwrap();
14
15
  static ref TOC_SECTION_START: Regex = Regex::new(r"(?i)^#+\s*(table\s+of\s+contents?|contents?|toc)\s*$").unwrap();
15
16
  }
16
17
 
@@ -123,7 +124,7 @@ impl MD051LinkFragments {
123
124
  /// Fragment generation following GitHub's official algorithm
124
125
  /// GitHub preserves most Unicode characters, underscores, and consecutive hyphens
125
126
  #[inline]
126
- fn heading_to_fragment_github(&self, heading: &str) -> String {
127
+ pub fn heading_to_fragment_github(&self, heading: &str) -> String {
127
128
  if heading.is_empty() {
128
129
  return String::new();
129
130
  }
@@ -135,72 +136,36 @@ impl MD051LinkFragments {
135
136
  heading.to_string()
136
137
  };
137
138
 
138
- // Trim whitespace first
139
- let text = text.trim();
140
-
141
- // Follow GitHub's actual algorithm (verified with github-slugger)
142
- // GitHub PRESERVES most Unicode characters including:
143
- // - Accented Latin (café, résumé, über)
144
- // - Chinese, Japanese, Korean
145
- // - Arabic, Hebrew
146
- // - Greek, Cyrillic
147
- // - Hindi and other scripts
148
- // It only removes emoji and certain punctuation
149
- let mut fragment = String::with_capacity(text.len());
150
- let mut last_was_space = false;
151
-
152
- for c in text.to_lowercase().chars() {
153
- // Check if character should be kept
154
- if Self::is_valid_github_char(c) {
155
- fragment.push(c);
156
- last_was_space = false;
157
- } else if c == '-' {
158
- // Always preserve hyphens
159
- fragment.push('-');
160
- last_was_space = false;
161
- } else if c.is_whitespace() {
162
- // Convert whitespace to hyphens, but avoid consecutive spaces becoming multiple hyphens
163
- if !last_was_space {
164
- fragment.push('-');
165
- last_was_space = true;
166
- }
167
- } else {
168
- // Skip emoji, symbols, etc.
169
- // If the last character we added was not a hyphen, and this character
170
- // is skipped (like emoji), we might need to add a hyphen if the next
171
- // character is not whitespace. For now, just skip it.
172
- // This handles cases like "A🎉B" → "a-b" but we don't implement that complexity yet.
173
- }
174
- }
139
+ // NOTE: GitHub does NOT trim whitespace - it preserves leading/trailing spaces
140
+ // and converts them to hyphens. This matches the official github-slugger behavior.
175
141
 
176
- // Remove leading and trailing hyphens
177
- fragment.trim_matches('-').to_string()
178
- }
142
+ // GitHub's EXACT algorithm from github-slugger npm package:
143
+ // function slug(value, maintainCase) {
144
+ // if (typeof value !== 'string') return ''
145
+ // if (!maintainCase) value = value.toLowerCase()
146
+ // return value.replace(regex, '').replace(/ /g, '-')
147
+ // }
179
148
 
180
- /// Check if a character should be preserved in GitHub-style anchors
181
- #[inline]
182
- fn is_valid_github_char(c: char) -> bool {
183
- // First, exclude emoji and symbols even if they're "alphanumeric"
184
- if matches!(c,
185
- '\u{1F300}'..='\u{1F9FF}' | // Emoji & Symbols (includes 🎉 at U+1F389)
186
- '\u{2600}'..='\u{26FF}' | // Miscellaneous Symbols
187
- '\u{2700}'..='\u{27BF}' | // Dingbats
188
- '\u{2000}'..='\u{206F}' | // General punctuation
189
- '\u{2E00}'..='\u{2E7F}' | // Supplemental punctuation
190
- '\u{3000}'..='\u{303F}' | // CJK symbols and punctuation (but keep CJK letters)
191
- '\u{FE00}'..='\u{FE0F}' // Variation selectors
192
- ) {
193
- return false;
194
- }
149
+ // 1. Convert to lowercase (maintainCase = false)
150
+ let text = text.to_lowercase();
151
+
152
+ // 2. Apply GitHub's exact regex pattern to remove punctuation/symbols
153
+ // This is the EXACT regex from github-slugger/regex.js
154
+ // Note: In Rust, we need to use \u{} syntax for Unicode above \uFFFF
155
+ // The original JavaScript regex includes surrogate pairs that we convert to direct Unicode ranges
156
+ let github_regex = get_cached_regex(
157
+ r"[\x00-\x1F!-,\./:-@\[-\^`\{-\xA9\xAB-\xB4\xB6-\xB9\xBB-\xBF\xD7\xF7\u{02C2}-\u{02C5}\u{02D2}-\u{02DF}\u{02E5}-\u{02EB}\u{02ED}\u{02EF}-\u{02FF}\u{0375}\u{0378}\u{0379}\u{037E}\u{0380}-\u{0385}\u{0387}\u{038B}\u{038D}\u{03A2}\u{03F6}\u{0482}\u{0530}\u{0557}\u{0558}\u{055A}-\u{055F}\u{0589}-\u{0590}\u{05BE}\u{05C0}\u{05C3}\u{05C6}\u{05C8}-\u{05CF}\u{05EB}-\u{05EE}\u{05F3}-\u{060F}\u{061B}-\u{061F}\u{066A}-\u{066D}\u{06D4}\u{06DD}\u{06DE}\u{06E9}\u{06FD}\u{06FE}\u{0700}-\u{070F}\u{074B}\u{074C}\u{07B2}-\u{07BF}\u{07F6}-\u{07F9}\u{07FB}\u{07FC}\u{07FE}\u{07FF}\u{082E}-\u{083F}\u{085C}-\u{085F}\u{086B}-\u{089F}\u{08B5}\u{08C8}-\u{08D2}\u{08E2}\u{0964}\u{0965}\u{0970}\u{0984}\u{098D}\u{098E}\u{0991}\u{0992}\u{09A9}\u{09B1}\u{09B3}-\u{09B5}\u{09BA}\u{09BB}\u{09C5}\u{09C6}\u{09C9}\u{09CA}\u{09CF}-\u{09D6}\u{09D8}-\u{09DB}\u{09DE}\u{09E4}\u{09E5}\u{09F2}-\u{09FB}\u{09FD}\u{09FF}\u{0A00}\u{0A04}\u{0A0B}-\u{0A0E}\u{0A11}\u{0A12}\u{0A29}\u{0A31}\u{0A34}\u{0A37}\u{0A3A}\u{0A3B}\u{0A3D}\u{0A43}-\u{0A46}\u{0A49}\u{0A4A}\u{0A4E}-\u{0A50}\u{0A52}-\u{0A58}\u{0A5D}\u{0A5F}-\u{0A65}\u{0A76}-\u{0A80}\u{0A84}\u{0A8E}\u{0A92}\u{0AA9}\u{0AB1}\u{0AB4}\u{0ABA}\u{0ABB}\u{0AC6}\u{0ACA}\u{0ACE}\u{0ACF}\u{0AD1}-\u{0ADF}\u{0AE4}\u{0AE5}\u{0AF0}-\u{0AF8}\u{0B00}\u{0B04}\u{0B0D}\u{0B0E}\u{0B11}\u{0B12}\u{0B29}\u{0B31}\u{0B34}\u{0B3A}\u{0B3B}\u{0B45}\u{0B46}\u{0B49}\u{0B4A}\u{0B4E}-\u{0B54}\u{0B58}-\u{0B5B}\u{0B5E}\u{0B64}\u{0B65}\u{0B70}\u{0B72}-\u{0B81}\u{0B84}\u{0B8B}-\u{0B8D}\u{0B91}\u{0B96}-\u{0B98}\u{0B9B}\u{0B9D}\u{0BA0}-\u{0BA2}\u{0BA5}-\u{0BA7}\u{0BAB}-\u{0BAD}\u{0BBA}-\u{0BBD}\u{0BC3}-\u{0BC5}\u{0BC9}\u{0BCE}\u{0BCF}\u{0BD1}-\u{0BD6}\u{0BD8}-\u{0BE5}\u{0BF0}-\u{0BFF}\u{0C0D}\u{0C11}\u{0C29}\u{0C3A}-\u{0C3C}\u{0C45}\u{0C49}\u{0C4E}-\u{0C54}\u{0C57}\u{0C5B}-\u{0C5F}\u{0C64}\u{0C65}\u{0C70}-\u{0C7F}\u{0C84}\u{0C8D}\u{0C91}\u{0CA9}\u{0CB4}\u{0CBA}\u{0CBB}\u{0CC5}\u{0CC9}\u{0CCE}-\u{0CD4}\u{0CD7}-\u{0CDD}\u{0CDF}\u{0CE4}\u{0CE5}\u{0CF0}\u{0CF3}-\u{0CFF}\u{0D0D}\u{0D11}\u{0D45}\u{0D49}\u{0D4F}-\u{0D53}\u{0D58}-\u{0D5E}\u{0D64}\u{0D65}\u{0D70}-\u{0D79}\u{0D80}\u{0D84}\u{0D97}-\u{0D99}\u{0DB2}\u{0DBC}\u{0DBE}\u{0DBF}\u{0DC7}-\u{0DC9}\u{0DCB}-\u{0DCE}\u{0DD5}\u{0DD7}\u{0DE0}-\u{0DE5}\u{0DF0}\u{0DF1}\u{0DF4}-\u{0E00}\u{0E3B}-\u{0E3F}\u{0E4F}\u{0E5A}-\u{0E80}\u{0E83}\u{0E85}\u{0E8B}\u{0EA4}\u{0EA6}\u{0EBE}\u{0EBF}\u{0EC5}\u{0EC7}\u{0ECE}\u{0ECF}\u{0EDA}\u{0EDB}\u{0EE0}-\u{0EFF}\u{0F01}-\u{0F17}\u{0F1A}-\u{0F1F}\u{0F2A}-\u{0F34}\u{0F36}\u{0F38}\u{0F3A}-\u{0F3D}\u{0F48}\u{0F6D}-\u{0F70}\u{0F85}\u{0F98}\u{0FBD}-\u{0FC5}\u{0FC7}-\u{0FFF}\u{104A}-\u{104F}\u{109E}\u{109F}\u{10C6}\u{10C8}-\u{10CC}\u{10CE}\u{10CF}\u{10FB}\u{1249}\u{124E}\u{124F}\u{1257}\u{1259}\u{125E}\u{125F}\u{1289}\u{128E}\u{128F}\u{12B1}\u{12B6}\u{12B7}\u{12BF}\u{12C1}\u{12C6}\u{12C7}\u{12D7}\u{1311}\u{1316}\u{1317}\u{135B}\u{135C}\u{1360}-\u{137F}\u{1390}-\u{139F}\u{13F6}\u{13F7}\u{13FE}-\u{1400}\u{166D}\u{166E}\u{1680}\u{169B}-\u{169F}\u{16EB}-\u{16ED}\u{16F9}-\u{16FF}\u{170D}\u{1715}-\u{171F}\u{1735}-\u{173F}\u{1754}-\u{175F}\u{176D}\u{1771}\u{1774}-\u{177F}\u{17D4}-\u{17D6}\u{17D8}-\u{17DB}\u{17DE}\u{17DF}\u{17EA}-\u{180A}\u{180E}\u{180F}\u{181A}-\u{181F}\u{1879}-\u{187F}\u{18AB}-\u{18AF}\u{18F6}-\u{18FF}\u{191F}\u{192C}-\u{192F}\u{193C}-\u{1945}\u{196E}\u{196F}\u{1975}-\u{197F}\u{19AC}-\u{19AF}\u{19CA}-\u{19CF}\u{19DA}-\u{19FF}\u{1A1C}-\u{1A1F}\u{1A5F}\u{1A7D}\u{1A7E}\u{1A8A}-\u{1A8F}\u{1A9A}-\u{1AA6}\u{1AA8}-\u{1AAF}\u{1AC1}-\u{1AFF}\u{1B4C}-\u{1B4F}\u{1B5A}-\u{1B6A}\u{1B74}-\u{1B7F}\u{1BF4}-\u{1BFF}\u{1C38}-\u{1C3F}\u{1C4A}-\u{1C4C}\u{1C7E}\u{1C7F}\u{1C89}-\u{1C8F}\u{1CBB}\u{1CBC}\u{1CC0}-\u{1CCF}\u{1CD3}\u{1CFB}-\u{1CFF}\u{1DFA}\u{1F16}\u{1F17}\u{1F1E}\u{1F1F}\u{1F46}\u{1F47}\u{1F4E}\u{1F4F}\u{1F58}\u{1F5A}\u{1F5C}\u{1F5E}\u{1F7E}\u{1F7F}\u{1FB5}\u{1FBD}\u{1FBF}-\u{1FC1}\u{1FC5}\u{1FCD}-\u{1FCF}\u{1FD4}\u{1FD5}\u{1FDC}-\u{1FDF}\u{1FED}-\u{1FF1}\u{1FF5}\u{1FFD}-\u{203E}\u{2041}-\u{2053}\u{2055}-\u{2070}\u{2072}-\u{207E}\u{2080}-\u{208F}\u{209D}-\u{20CF}\u{20F1}-\u{2101}\u{2103}-\u{2106}\u{2108}\u{2109}\u{2114}\u{2116}-\u{2118}\u{211E}-\u{2123}\u{2125}\u{2127}\u{2129}\u{212E}\u{213A}\u{213B}\u{2140}-\u{2144}\u{214A}-\u{214D}\u{214F}-\u{215F}\u{2189}-\u{24B5}\u{24EA}-\u{2BFF}\u{2C2F}\u{2C5F}\u{2CE5}-\u{2CEA}\u{2CF4}-\u{2CFF}\u{2D26}\u{2D28}-\u{2D2C}\u{2D2E}\u{2D2F}\u{2D68}-\u{2D6E}\u{2D70}-\u{2D7E}\u{2D97}-\u{2D9F}\u{2DA7}\u{2DAF}\u{2DB7}\u{2DBF}\u{2DC7}\u{2DCF}\u{2DD7}\u{2DDF}\u{2E00}-\u{2E2E}\u{2E30}-\u{3004}\u{3008}-\u{3020}\u{3030}\u{3036}\u{3037}\u{303D}-\u{3040}\u{3097}\u{3098}\u{309B}\u{309C}\u{30A0}\u{30FB}\u{3100}-\u{3104}\u{3130}\u{318F}-\u{319F}\u{31C0}-\u{31EF}\u{3200}-\u{33FF}\u{4DC0}-\u{4DFF}\u{9FFD}-\u{9FFF}\u{A48D}-\u{A4CF}\u{A4FE}\u{A4FF}\u{A60D}-\u{A60F}\u{A62C}-\u{A63F}\u{A673}\u{A67E}\u{A6F2}-\u{A716}\u{A720}\u{A721}\u{A789}\u{A78A}\u{A7C0}\u{A7C1}\u{A7CB}-\u{A7F4}\u{A828}-\u{A82B}\u{A82D}-\u{A83F}\u{A874}-\u{A87F}\u{A8C6}-\u{A8CF}\u{A8DA}-\u{A8DF}\u{A8F8}-\u{A8FA}\u{A8FC}\u{A92E}\u{A92F}\u{A954}-\u{A95F}\u{A97D}-\u{A97F}\u{A9C1}-\u{A9CE}\u{A9DA}-\u{A9DF}\u{A9FF}\u{AA37}-\u{AA3F}\u{AA4E}\u{AA4F}\u{AA5A}-\u{AA5F}\u{AA77}-\u{AA79}\u{AAC3}-\u{AADA}\u{AADE}\u{AADF}\u{AAF0}\u{AAF1}\u{AAF7}-\u{AB00}\u{AB07}\u{AB08}\u{AB0F}\u{AB10}\u{AB17}-\u{AB1F}\u{AB27}\u{AB2F}\u{AB5B}\u{AB6A}-\u{AB6F}\u{ABEB}\u{ABEE}\u{ABEF}\u{ABFA}-\u{ABFF}\u{D7A4}-\u{D7AF}\u{D7C7}-\u{D7CA}\u{D7FC}-\u{D7FF}\u{E000}-\u{F8FF}\u{FA6E}\u{FA6F}\u{FADA}-\u{FAFF}\u{FB07}-\u{FB12}\u{FB18}-\u{FB1C}\u{FB29}\u{FB37}\u{FB3D}\u{FB3F}\u{FB42}\u{FB45}\u{FBB2}-\u{FBD2}\u{FD3E}-\u{FD4F}\u{FD90}\u{FD91}\u{FDC8}-\u{FDEF}\u{FDFC}-\u{FDFF}\u{FE10}-\u{FE1F}\u{FE30}-\u{FE32}\u{FE35}-\u{FE4C}\u{FE50}-\u{FE6F}\u{FE75}\u{FEFD}-\u{FF0F}\u{FF1A}-\u{FF20}\u{FF3B}-\u{FF3E}\u{FF40}\u{FF5B}-\u{FF65}\u{FFBF}-\u{FFC1}\u{FFC8}\u{FFC9}\u{FFD0}\u{FFD1}\u{FFD8}\u{FFD9}\u{FFDD}-\u{FFFF}\u{1000C}\u{10027}\u{1003B}\u{1003E}\u{1004E}\u{1004F}\u{1005E}-\u{1007F}\u{100FB}-\u{1013F}\u{10175}-\u{101FC}\u{101FE}-\u{1027F}\u{1029D}-\u{1029F}\u{102D1}-\u{102DF}\u{102E1}-\u{102FF}\u{10320}-\u{1032C}\u{1034B}-\u{1034F}\u{1037B}-\u{1037F}\u{1039E}\u{1039F}\u{103C4}-\u{103C7}\u{103D0}\u{103D6}-\u{103FF}\u{1049E}\u{1049F}\u{104AA}-\u{104AF}\u{104D4}-\u{104D7}\u{104FC}-\u{104FF}\u{10528}-\u{1052F}\u{10564}-\u{105FF}\u{10737}-\u{1073F}\u{10756}-\u{1075F}\u{10768}-\u{107FF}\u{10806}\u{10807}\u{10809}\u{10836}\u{10839}-\u{1083B}\u{1083D}\u{1083E}\u{10856}-\u{1085F}\u{10877}-\u{1087F}\u{1089F}-\u{108DF}\u{108F3}\u{108F6}-\u{108FF}\u{10916}-\u{1091F}\u{1093A}-\u{1097F}\u{109B8}-\u{109BD}\u{109C0}-\u{109FF}\u{10A04}\u{10A07}-\u{10A0B}\u{10A14}\u{10A18}\u{10A36}\u{10A37}\u{10A3B}-\u{10A3E}\u{10A40}-\u{10A5F}\u{10A7D}-\u{10A7F}\u{10A9D}-\u{10ABF}\u{10AC8}\u{10AE7}-\u{10AFF}\u{10B36}-\u{10B3F}\u{10B56}-\u{10B5F}\u{10B73}-\u{10B7F}\u{10B92}-\u{10BFF}\u{10C49}-\u{10C7F}\u{10CB3}-\u{10CBF}\u{10CF3}-\u{10CFF}\u{10D28}-\u{10D2F}\u{10D3A}-\u{10E7F}\u{10EAA}\u{10EAD}-\u{10EAF}\u{10EB2}-\u{10EFF}\u{10F1D}-\u{10F26}\u{10F28}-\u{10F2F}\u{10F51}-\u{10FAF}\u{10FC5}-\u{10FDF}\u{10FF7}-\u{10FFF}\u{11047}-\u{11065}\u{11070}-\u{1107E}\u{110BB}-\u{110CF}\u{110E9}-\u{110EF}\u{110FA}-\u{110FF}\u{11135}\u{11140}-\u{11143}\u{11148}-\u{1114F}\u{11174}\u{11175}\u{11177}-\u{1117F}\u{111C5}-\u{111C8}\u{111CD}\u{111DB}\u{111DD}-\u{111FF}\u{11212}\u{11238}-\u{1123D}\u{1123F}-\u{1127F}\u{11287}\u{11289}\u{1128E}\u{1129E}\u{112A9}-\u{112AF}\u{112EB}-\u{112EF}\u{112FA}-\u{112FF}\u{11304}\u{1130D}\u{1130E}\u{11311}\u{11312}\u{11329}\u{11331}\u{11334}\u{1133A}\u{11345}\u{11346}\u{11349}\u{1134A}\u{1134E}\u{1134F}\u{11351}-\u{11356}\u{11358}-\u{1135C}\u{11364}\u{11365}\u{1136D}-\u{1136F}\u{11375}-\u{113FF}\u{1144B}-\u{1144F}\u{1145A}-\u{1145D}\u{1145F}-\u{1147F}\u{114C6}\u{114C8}-\u{114CF}\u{114DA}-\u{1157F}\u{115B6}\u{115B7}\u{115C1}-\u{115D7}\u{115DE}-\u{115FF}\u{11641}-\u{11643}\u{11645}-\u{1164F}\u{1165A}-\u{1167F}\u{116B9}-\u{116BF}\u{116CA}-\u{116FF}\u{1171B}-\u{1171C}\u{1172C}-\u{1172F}\u{1173A}-\u{117FF}\u{1183B}-\u{1189F}\u{118EA}-\u{118FE}\u{11900}-\u{1199F}\u{119A8}\u{119A9}\u{119D8}\u{119D9}\u{119E2}\u{119E5}-\u{119FF}\u{11A3F}-\u{11A46}\u{11A48}-\u{11A4F}\u{11A9A}-\u{11A9C}\u{11A9E}-\u{11ABF}\u{11AF9}-\u{11BFF}\u{11C09}\u{11C37}\u{11C41}-\u{11C4F}\u{11C5A}-\u{11C71}\u{11C90}\u{11C91}\u{11CA8}\u{11CB7}-\u{11CFF}\u{11D07}\u{11D0A}\u{11D37}-\u{11D39}\u{11D3B}\u{11D3E}\u{11D48}-\u{11D4F}\u{11D5A}-\u{11D5F}\u{11D66}\u{11D69}\u{11D8F}\u{11D92}\u{11D99}-\u{11D9F}\u{11DAA}-\u{11EDF}\u{11EF7}-\u{11FAF}\u{11FB1}-\u{11FFF}\u{1239A}-\u{123FF}\u{1246F}-\u{1247F}\u{12544}-\u{12FFF}\u{1342F}-\u{143FF}\u{14647}-\u{167FF}\u{16A39}-\u{16A3F}\u{16A5F}\u{16A6A}-\u{16ACF}\u{16AEE}\u{16AEF}\u{16AF5}-\u{16AFF}\u{16B37}-\u{16B3F}\u{16B44}-\u{16B4F}\u{16B5A}-\u{16B62}\u{16B78}-\u{16B7C}\u{16B90}-\u{16EFF}\u{16F4B}-\u{16F4E}\u{16F88}-\u{16F8E}\u{16FA0}-\u{16FDF}\u{16FE2}\u{16FE5}-\u{16FEF}\u{16FF2}-\u{16FFF}\u{187F8}-\u{187FF}\u{18CD6}-\u{18CFF}\u{18D09}-\u{1AFFF}\u{1B11F}-\u{1B14F}\u{1B153}-\u{1B163}\u{1B168}-\u{1B16F}\u{1B2FC}-\u{1BBFF}\u{1BC6B}-\u{1BC6F}\u{1BC7D}-\u{1BC7F}\u{1BC89}-\u{1BC8F}\u{1BC9A}-\u{1BC9C}\u{1BC9F}-\u{1CFFF}\u{1D0F6}-\u{1D0FF}\u{1D127}-\u{1D128}\u{1D173}-\u{1D17A}\u{1D1E9}-\u{1D1FF}\u{1D246}-\u{1D2DF}\u{1D2F4}-\u{1D2FF}\u{1D357}-\u{1D35F}\u{1D379}-\u{1D3FF}\u{1D455}\u{1D49D}\u{1D4A0}\u{1D4A1}\u{1D4A3}\u{1D4A4}\u{1D4A7}\u{1D4A8}\u{1D4AD}\u{1D4BA}\u{1D4BC}\u{1D4C4}\u{1D506}\u{1D50B}\u{1D50C}\u{1D515}\u{1D51D}\u{1D53A}\u{1D53F}\u{1D545}\u{1D547}-\u{1D549}\u{1D551}\u{1D6A6}\u{1D6A7}\u{1D6C1}\u{1D6DB}\u{1D6FB}\u{1D715}\u{1D735}\u{1D74F}\u{1D76F}\u{1D789}\u{1D7A9}\u{1D7C3}\u{1D7CC}\u{1D7CD}\u{1D800}-\u{1D9FF}\u{1DA37}-\u{1DA3A}\u{1DA6D}-\u{1DA74}\u{1DA76}-\u{1DA83}\u{1DA85}-\u{1DA9A}\u{1DAA0}\u{1DAB0}-\u{1DFFF}\u{1E007}\u{1E019}\u{1E01A}\u{1E022}\u{1E025}\u{1E02B}-\u{1E0FF}\u{1E12D}-\u{1E12F}\u{1E13E}\u{1E13F}\u{1E14A}-\u{1E14D}\u{1E14F}-\u{1E2BF}\u{1E2FA}-\u{1E2FF}\u{1E4FA}-\u{1E7FF}\u{1E8C5}-\u{1E8CF}\u{1E8D7}-\u{1E8FF}\u{1E94C}-\u{1E94F}\u{1E95A}-\u{1E9FF}\u{1EA00}-\u{1EDFF}\u{1EE04}\u{1EE20}\u{1EE23}\u{1EE25}\u{1EE26}\u{1EE28}\u{1EE33}\u{1EE38}\u{1EE3A}\u{1EE3C}-\u{1EE41}\u{1EE43}-\u{1EE46}\u{1EE48}\u{1EE4A}\u{1EE4C}\u{1EE50}\u{1EE53}\u{1EE55}\u{1EE56}\u{1EE58}\u{1EE5A}\u{1EE5C}\u{1EE5E}\u{1EE60}\u{1EE63}\u{1EE65}\u{1EE66}\u{1EE6B}\u{1EE73}\u{1EE78}\u{1EE7D}\u{1EE7F}\u{1EE8A}\u{1EE9C}-\u{1EEA0}\u{1EEA4}\u{1EEAA}\u{1EEBC}-\u{1EFFF}\u{1F000}-\u{1F02B}\u{1F030}-\u{1F093}\u{1F0A0}-\u{1F0AE}\u{1F0B1}-\u{1F0BF}\u{1F0C1}-\u{1F0CF}\u{1F0D1}-\u{1F0F5}\u{1F100}-\u{1F1AD}\u{1F1E6}-\u{1F202}\u{1F210}-\u{1F23B}\u{1F240}-\u{1F248}\u{1F250}\u{1F251}\u{1F260}-\u{1F265}\u{1F300}-\u{1F6D7}\u{1F6DD}-\u{1F6EC}\u{1F6F0}-\u{1F6FC}\u{1F700}-\u{1F773}\u{1F780}-\u{1F7D8}\u{1F7E0}-\u{1F7EB}\u{1F7F0}\u{1F800}-\u{1F80B}\u{1F810}-\u{1F847}\u{1F850}-\u{1F859}\u{1F860}-\u{1F887}\u{1F890}-\u{1F8AD}\u{1F8B0}\u{1F8B1}\u{1F900}-\u{1F978}\u{1F97A}-\u{1F9CB}\u{1F9CD}-\u{1FA53}\u{1FA60}-\u{1FA6D}\u{1FA70}-\u{1FA74}\u{1FA78}-\u{1FA7C}\u{1FA80}-\u{1FA86}\u{1FA90}-\u{1FAAC}\u{1FAB0}-\u{1FABA}\u{1FAC0}-\u{1FAC5}\u{1FAD0}-\u{1FAD9}\u{1FAE0}-\u{1FAE7}\u{1FAF0}-\u{1FAF6}\u{1FB00}-\u{1FB92}\u{1FB94}-\u{1FBCA}\u{1FBF0}-\u{1FBF9}\u{1FC00}-\u{1FFFF}\u{2A6DE}-\u{2A6FF}\u{2B735}-\u{2B73F}\u{2B81E}\u{2B81F}\u{2CEA2}-\u{2CEAF}\u{2EBE1}-\u{2F7FF}\u{2FA1E}-\u{2FFFF}\u{3134B}-\u{E00FF}\u{E01F0}-\u{10FFFF}]"
158
+ ).expect("Valid GitHub regex pattern");
195
159
 
196
- // Keep ASCII alphanumeric and underscores
197
- c.is_ascii_alphanumeric() || c == '_' ||
198
- // Keep Unicode letters and digits (but not emoji, which we filtered above)
199
- c.is_alphabetic() || c.is_numeric()
160
+ // Remove all punctuation and symbols matched by the regex
161
+ let result = github_regex.replace_all(&text, "");
162
+
163
+ // 3. Replace spaces with hyphens (/ /g, '-')
164
+ result.replace(' ', "-")
200
165
  }
201
166
 
202
167
  /// Fragment generation following kramdown's algorithm
203
- /// kramdown strips diacritics but keeps base letters, removes underscores
168
+ /// Uses the official kramdown implementation from kramdown_utils
204
169
  #[inline]
205
170
  fn heading_to_fragment_kramdown(&self, heading: &str) -> String {
206
171
  if heading.is_empty() {
@@ -214,75 +179,8 @@ impl MD051LinkFragments {
214
179
  heading.to_string()
215
180
  };
216
181
 
217
- // Trim whitespace first
218
- let text = text.trim();
219
-
220
- // Check if this would result in empty/non-Latin content
221
- let has_latin = text
222
- .chars()
223
- .any(|c| c.is_ascii_alphabetic() || (c as u32 >= 0x00C0 && c as u32 <= 0x024F)); // Latin extended
224
-
225
- if !has_latin {
226
- // kramdown generates generic "section" for non-Latin scripts
227
- return "section".to_string();
228
- }
229
-
230
- // Follow kramdown's algorithm
231
- let mut result = String::with_capacity(text.len());
232
- let mut found_letter = false;
233
-
234
- for c in text.chars() {
235
- // Skip leading non-letters
236
- if !found_letter && !Self::is_kramdown_letter(c) {
237
- continue;
238
- }
239
- if Self::is_kramdown_letter(c) {
240
- found_letter = true;
241
- }
242
-
243
- // Process character
244
- if c.is_ascii_alphabetic() {
245
- result.push(c.to_ascii_lowercase());
246
- } else if c.is_ascii_digit() && found_letter {
247
- result.push(c);
248
- } else if c == ' ' || c == '-' {
249
- result.push('-');
250
- } else if let Some(replacement) = Self::kramdown_normalize_char(c) {
251
- // kramdown normalizes accented characters
252
- result.push_str(replacement);
253
- }
254
- // Skip underscores and other characters
255
- }
256
-
257
- // Remove leading and trailing hyphens
258
- result.trim_matches('-').to_string()
259
- }
260
-
261
- /// Check if character is considered a letter by kramdown
262
- #[inline]
263
- fn is_kramdown_letter(c: char) -> bool {
264
- c.is_ascii_alphabetic() ||
265
- // Latin-1 Supplement and Extended Latin
266
- (c as u32 >= 0x00C0 && c as u32 <= 0x024F)
267
- }
268
-
269
- /// Normalize accented characters for kramdown (simplified)
270
- #[inline]
271
- fn kramdown_normalize_char(c: char) -> Option<&'static str> {
272
- match c {
273
- 'À' | 'Á' | 'Â' | 'Ã' | 'Ä' | 'Å' | 'à' | 'á' | 'â' | 'ã' | 'ä' | 'å' => Some("a"),
274
- 'È' | 'É' | 'Ê' | 'Ë' | 'è' | 'é' | 'ê' | 'ë' => Some("e"),
275
- 'Ì' | 'Í' | 'Î' | 'Ï' | 'ì' | 'í' | 'î' | 'ï' => Some("i"),
276
- 'Ò' | 'Ó' | 'Ô' | 'Õ' | 'Ö' | 'Ø' | 'ò' | 'ó' | 'ô' | 'õ' | 'ö' | 'ø' => Some("o"),
277
- 'Ù' | 'Ú' | 'Û' | 'Ü' | 'ù' | 'ú' | 'û' | 'ü' => Some("u"),
278
- 'Ý' | 'ý' | 'ÿ' => Some("y"),
279
- 'Ñ' | 'ñ' => Some("n"),
280
- 'Ç' | 'ç' => Some("c"),
281
- 'ß' => Some("ss"),
282
- 'Æ' | 'æ' => Some("ae"),
283
- 'Œ' | 'œ' => Some("oe"),
284
- _ => None,
285
- }
182
+ // Use the official kramdown algorithm from utils
183
+ kramdown_utils::heading_to_fragment(&text)
286
184
  }
287
185
 
288
186
  /// Fragment generation for Bitbucket style
@@ -310,14 +208,27 @@ impl MD051LinkFragments {
310
208
  heading.to_string()
311
209
  };
312
210
 
313
- // Step 2: Apply deburr (accent removal) - use kramdown normalization
211
+ // Step 2: Apply deburr (accent removal) - basic accent normalization
314
212
  let mut result = String::with_capacity(text.len());
315
213
  for c in text.chars() {
316
- if let Some(replacement) = Self::kramdown_normalize_char(c) {
317
- result.push_str(replacement);
318
- } else {
319
- result.push(c);
320
- }
214
+ let replacement = match c {
215
+ 'À' | 'Á' | 'Â' | 'Ã' | 'Ä' | 'Å' | 'à' | 'á' | 'â' | 'ã' | 'ä' | 'å' => "a",
216
+ 'È' | 'É' | 'Ê' | 'Ë' | 'è' | 'é' | 'ê' | 'ë' => "e",
217
+ 'Ì' | 'Í' | 'Î' | 'Ï' | 'ì' | 'í' | 'î' | 'ï' => "i",
218
+ 'Ò' | 'Ó' | 'Ô' | 'Õ' | 'Ö' | 'Ø' | 'ò' | 'ó' | 'ô' | 'õ' | 'ö' | 'ø' => "o",
219
+ 'Ù' | 'Ú' | 'Û' | 'Ü' | 'ù' | 'ú' | 'û' | 'ü' => "u",
220
+ 'Ý' | 'ý' | 'ÿ' => "y",
221
+ 'Ñ' | 'ñ' => "n",
222
+ 'Ç' | 'ç' => "c",
223
+ 'ß' => "ss",
224
+ 'Æ' | 'æ' => "ae",
225
+ 'Œ' | 'œ' => "oe",
226
+ _ => {
227
+ result.push(c);
228
+ continue;
229
+ }
230
+ };
231
+ result.push_str(replacement);
321
232
  }
322
233
  text = result;
323
234
 
@@ -364,9 +275,9 @@ impl MD051LinkFragments {
364
275
  fn strip_markdown_formatting_fast(&self, text: &str) -> String {
365
276
  let mut result = text.to_string();
366
277
 
367
- // Strip emphasis (bold/italic)
368
- if result.contains('*') || result.contains('_') {
369
- result = EMPHASIS_PATTERN.replace_all(&result, "$1$2").to_string();
278
+ // Strip emphasis (only asterisks, underscores are preserved per GitHub spec)
279
+ if result.contains('*') {
280
+ result = EMPHASIS_PATTERN.replace_all(&result, "$1").to_string();
370
281
  }
371
282
 
372
283
  // Strip inline code
@@ -374,9 +285,9 @@ impl MD051LinkFragments {
374
285
  result = CODE_PATTERN.replace_all(&result, "$1").to_string();
375
286
  }
376
287
 
377
- // Strip links
288
+ // Strip links (GitHub keeps both link text and URL)
378
289
  if result.contains('[') {
379
- result = LINK_PATTERN.replace_all(&result, "$1$2").to_string();
290
+ result = LINK_PATTERN.replace_all(&result, "$1$2$3").to_string();
380
291
  }
381
292
 
382
293
  result
@@ -637,8 +548,8 @@ mod tests {
637
548
  assert_eq!(rule.heading_to_fragment_github("Café"), "café");
638
549
  assert_eq!(rule.heading_to_fragment_github("Über uns"), "über-uns");
639
550
 
640
- // Emojis should be stripped
641
- assert_eq!(rule.heading_to_fragment_github("Emoji 🎉 Party"), "emoji-party");
551
+ // Emojis should be stripped (results in double hyphen)
552
+ assert_eq!(rule.heading_to_fragment_github("Emoji 🎉 Party"), "emoji--party");
642
553
  }
643
554
 
644
555
  #[test]
@@ -661,11 +572,11 @@ mod tests {
661
572
  );
662
573
 
663
574
  // Accented characters normalized
664
- assert_eq!(rule.heading_to_fragment_kramdown("Café"), "cafe");
665
- assert_eq!(rule.heading_to_fragment_kramdown("Über uns"), "uber-uns");
575
+ assert_eq!(rule.heading_to_fragment_kramdown("Café"), "caf");
576
+ assert_eq!(rule.heading_to_fragment_kramdown("Über uns"), "ber-uns");
666
577
 
667
- // Leading/trailing hyphens removed
668
- assert_eq!(rule.heading_to_fragment_kramdown("---test---"), "test");
578
+ // Leading hyphens removed, trailing preserved
579
+ assert_eq!(rule.heading_to_fragment_kramdown("---test---"), "test---");
669
580
  }
670
581
 
671
582
  #[test]
@@ -941,4 +852,137 @@ More content.
941
852
  assert!(!MD051LinkFragments::is_cross_file_link("%}some{%#fragment"));
942
853
  assert!(!MD051LinkFragments::is_cross_file_link("}}text{{#fragment"));
943
854
  }
855
+
856
+ #[test]
857
+ fn test_simplified_github_algorithm_edge_cases() {
858
+ let rule = MD051LinkFragments::new();
859
+
860
+ // Test consecutive punctuation - GitHub removes punctuation, no spaces to convert
861
+ assert_eq!(rule.heading_to_fragment_github("Test:::Multiple"), "testmultiple");
862
+ assert_eq!(rule.heading_to_fragment_github("Step >>> Next"), "step--next"); // Spaces around >>> become hyphens
863
+
864
+ // Test mixed hyphens and punctuation
865
+ assert_eq!(
866
+ rule.heading_to_fragment_github("Double--Hyphen: Test"),
867
+ "double--hyphen-test"
868
+ );
869
+ assert_eq!(
870
+ rule.heading_to_fragment_github("Pre-existing: More--Hyphens"),
871
+ "pre-existing-more--hyphens"
872
+ );
873
+
874
+ // Test multiple whitespace
875
+ assert_eq!(
876
+ rule.heading_to_fragment_github("Multiple Spaces"),
877
+ "multiple---spaces"
878
+ ); // Each space becomes a hyphen
879
+
880
+ // Test leading/trailing punctuation - hyphens are preserved!
881
+ assert_eq!(
882
+ rule.heading_to_fragment_github("---Leading and Trailing---"),
883
+ "---leading-and-trailing---"
884
+ );
885
+ assert_eq!(
886
+ rule.heading_to_fragment_github(":::Mixed:::Punctuation:::"),
887
+ "mixedpunctuation"
888
+ ); // No spaces between colons
889
+
890
+ // Test complex combinations
891
+ assert_eq!(
892
+ rule.heading_to_fragment_github("API::Response > Error--Handling"),
893
+ "apiresponse--error--handling"
894
+ );
895
+ }
896
+
897
+ #[test]
898
+ fn test_github_slugger_comprehensive_compliance() {
899
+ let rule = MD051LinkFragments::new();
900
+
901
+ // Comprehensive test cases generated from the official github-slugger npm package
902
+ // to ensure our implementation exactly matches GitHub's behavior
903
+ let test_cases = vec![
904
+ ("Simple Title", "simple-title"),
905
+ ("Title With Numbers 123", "title-with-numbers-123"),
906
+ ("UPPERCASE TITLE", "uppercase-title"),
907
+ ("lowercase title", "lowercase-title"),
908
+ ("MiXeD CaSe TiTlE", "mixed-case-title"),
909
+ // Issue #39 specific cases
910
+ ("cbrown --> sbrown: --unsafe-paths", "cbrown----sbrown---unsafe-paths"),
911
+ ("cbrown -> sbrown", "cbrown---sbrown"),
912
+ ("Arrow Test <-> bidirectional", "arrow-test---bidirectional"),
913
+ ("Double Arrow ==> Test", "double-arrow--test"),
914
+ // Ampersands and special chars
915
+ ("Testing & Coverage", "testing--coverage"),
916
+ (
917
+ "API Reference: Methods & Properties",
918
+ "api-reference-methods--properties",
919
+ ),
920
+ ("Config: Database & Cache Settings", "config-database--cache-settings"),
921
+ ("PHP $_REQUEST", "php-_request"),
922
+ ("sched_debug", "sched_debug"),
923
+ ("Add ldap_monitor to delegator$", "add-ldap_monitor-to-delegator"),
924
+ // Complex punctuation patterns
925
+ ("Step 1: Setup (Prerequisites)", "step-1-setup-prerequisites"),
926
+ ("Error #404 - Not Found!", "error-404---not-found"),
927
+ ("FAQ: What's Next?", "faq-whats-next"),
928
+ ("Version 2.0.1 - Release Notes", "version-201---release-notes"),
929
+ // Multiple hyphens and spaces
930
+ ("Test --- Multiple Hyphens", "test-----multiple-hyphens"),
931
+ ("Test -- Spaced Hyphens", "test------spaced-hyphens"),
932
+ ("Test - Single - Hyphen", "test---single---hyphen"),
933
+ ("Multiple Spaces", "multiple---spaces"),
934
+ // Leading/trailing punctuation
935
+ ("---Leading Hyphens", "---leading-hyphens"),
936
+ ("Trailing Hyphens---", "trailing-hyphens---"),
937
+ ("---Both Sides---", "---both-sides---"),
938
+ (":::Colons:::", "colons"),
939
+ ("***Asterisks***", "asterisks"),
940
+ ("___Underscores___", "___underscores___"),
941
+ ("...Dots...", "dots"),
942
+ // Unicode preservation
943
+ ("Café René", "café-rené"),
944
+ ("Über uns", "über-uns"),
945
+ ("日本語タイトル", "日本語タイトル"),
946
+ ("Русский заголовок", "русский-заголовок"),
947
+ ("مرحبا بالعالم", "مرحبا-بالعالم"),
948
+ // Emojis are removed
949
+ ("🎉 Emoji Start", "-emoji-start"),
950
+ ("Emoji 🎉 Middle", "emoji--middle"),
951
+ ("End Emoji 🎉", "end-emoji-"),
952
+ ("Multiple 🚀 🎨 Emojis", "multiple---emojis"),
953
+ // Special symbols
954
+ ("Price: $99.99", "price-9999"),
955
+ ("Copyright © 2024", "copyright--2024"),
956
+ ("Temperature: 25°C", "temperature-25c"),
957
+ ("Percentage: 100%", "percentage-100"),
958
+ ("Email: user@example.com", "email-userexamplecom"),
959
+ // Edge cases
960
+ ("", ""),
961
+ (" ", "-"),
962
+ (" ", "---"),
963
+ ("-", "-"),
964
+ ("---", "---"),
965
+ ("_", "_"),
966
+ ("___", "___"),
967
+ ("123", "123"),
968
+ ("!@#$%^&*()", ""),
969
+ // URL and paths
970
+ ("GET /api/v1/users", "get-apiv1users"),
971
+ ("C:\\Windows\\Path", "cwindowspath"),
972
+ ("URL: https://example.com", "url-httpsexamplecom"),
973
+ // Nested brackets
974
+ ("[Bracketed] Content", "bracketed-content"),
975
+ ("(Parenthetical) Remark", "parenthetical-remark"),
976
+ ("{Braced} Text", "braced-text"),
977
+ ("<Angled> Brackets", "angled-brackets"),
978
+ ];
979
+
980
+ for (input, expected) in test_cases {
981
+ let actual = rule.heading_to_fragment_github(input);
982
+ assert_eq!(
983
+ actual, expected,
984
+ "Failed for input: {input:?}\nExpected: {expected:?}\nActual: {actual:?}"
985
+ );
986
+ }
987
+ }
944
988
  }
@@ -195,19 +195,6 @@ impl MD057ExistingRelativeLinks {
195
195
  }
196
196
  }
197
197
  }
198
-
199
- /// Extract a URL from a Markdown link segment
200
- #[allow(dead_code)]
201
- fn extract_url_from_link<'a>(&self, link_text: &'a str) -> Option<(&'a str, usize)> {
202
- // Find the URL part using regex
203
- URL_EXTRACT_REGEX.captures(link_text).and_then(move |caps| {
204
- caps.get(1).map(|url_match| {
205
- let url = url_match.as_str().trim();
206
- let position = url_match.start();
207
- (url, position)
208
- })
209
- })
210
- }
211
198
  }
212
199
 
213
200
  impl Rule for MD057ExistingRelativeLinks {
@@ -120,14 +120,6 @@ pub struct BlockquoteRange {
120
120
  pub end_line: usize,
121
121
  }
122
122
 
123
- /// Code block processing state
124
- #[allow(dead_code)]
125
- enum InternalCodeBlockState {
126
- None,
127
- InFenced,
128
- InIndented,
129
- }
130
-
131
123
  /// OPTIMIZATION 1: Inline code span representation
132
124
  #[derive(Debug, Clone)]
133
125
  pub struct CodeSpan {