rumdl 0.0.100__tar.gz → 0.0.102__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.
- {rumdl-0.0.100 → rumdl-0.0.102}/CHANGELOG.md +25 -1
- {rumdl-0.0.100 → rumdl-0.0.102}/Cargo.lock +1 -1
- {rumdl-0.0.100 → rumdl-0.0.102}/Cargo.toml +1 -1
- {rumdl-0.0.100 → rumdl-0.0.102}/PKG-INFO +1 -1
- {rumdl-0.0.100 → rumdl-0.0.102}/src/main.rs +37 -1
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md005_list_indent.rs +133 -26
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md006_start_bullets.rs +102 -26
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md007_ul_indent.rs +168 -44
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md009_trailing_spaces.rs +7 -14
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md010_no_hard_tabs.rs +2 -7
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md011_no_reversed_links.rs +0 -1
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md013_line_length.rs +3 -24
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md020_no_missing_space_closed_atx.rs +3 -10
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md025_single_title.rs +36 -18
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md026_no_trailing_punctuation.rs +10 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md029_ordered_list_prefix.rs +4 -5
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md031_blanks_around_fences.rs +0 -6
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md032_blanks_around_lists.rs +1 -1
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md034_no_bare_urls.rs +3 -9
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md035_hr_style.rs +3 -11
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md036_no_emphasis_only_first.rs +6 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md037_spaces_around_emphasis.rs +3 -9
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md041_first_line_heading.rs +2 -9
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md044_proper_names.rs +13 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md045_no_alt_text.rs +11 -9
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md046_code_block_style.rs +0 -6
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md048_code_fence_style.rs +6 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md051_link_fragments.rs +6 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md052_reference_links_images.rs +6 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md053_link_image_reference_definitions.rs +6 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md055_table_pipe_style.rs +5 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md056_table_column_count.rs +5 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md058_blanks_around_tables.rs +5 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/regex_cache.rs +35 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/list_rules_integration_test.rs +7 -7
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md005_test.rs +21 -8
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md005_unicode_test.rs +1 -1
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md007_test.rs +45 -17
- {rumdl-0.0.100 → rumdl-0.0.102}/.config/nextest.toml +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/.mise.toml +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/.pre-commit-config.yaml +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/.rumdl.toml +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/.rustfmt.toml +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/LICENSE +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/MANIFEST.in +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/Makefile +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/README.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/assets/logo.png +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/benches/fix_performance.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/benches/range_performance.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/benches/range_utils_benchmark.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/benches/rule_performance.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/benches/simple_fix_bench.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/RULES.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/global-settings.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md001.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md002.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md003.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md004.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md005.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md006.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md007.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md009.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md010.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md011.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md012.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md013.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md014.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md018.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md019.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md020.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md021.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md022.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md023.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md024.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md025.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md026.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md027.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md028.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md029.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md030.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md031.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md032.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md033.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md034.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md035.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md036.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md037.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md038.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md039.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md040.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md041.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md042.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md043.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md044.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md045.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md046.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md047.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md048.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md049.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md050.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md051.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md052.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md053.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md054.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md055.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md056.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md057.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/md058.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/docs/vscode-extension.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/parity_check.py +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/pyproject.toml +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/python/MANIFEST.in +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/python/PYTHON-README.md +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/python/rumdl/__init__.py +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/python/rumdl/__main__.py +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/python/rumdl/py.typed +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/rumdl.toml.example +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/rust-toolchain.toml +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/scripts/extract-changelog.sh +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/scripts/prepare-release.sh +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/scripts/setup-pre-commit.sh +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/scripts/update-pre-commit-docs.sh +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/bin/benchmark.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/bin/benchmark_rule.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/bin/file_parallel_benchmark.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/bin/measure_code_span_performance.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/exit_codes.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/init.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/inline_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/lib.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/lint_context.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/lsp/mod.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/lsp/server.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/lsp/types.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/markdownlint_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/output/formatters/azure.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/output/formatters/concise.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/output/formatters/github.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/output/formatters/gitlab.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/output/formatters/grouped.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/output/formatters/json.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/output/formatters/json_lines.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/output/formatters/junit.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/output/formatters/mod.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/output/formatters/pylint.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/output/formatters/sarif.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/output/formatters/text.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/output/mod.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/parallel.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/performance.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/profiling.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/python.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rule.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rule_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rule_config_serde.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/blockquote_utils.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/code_block_utils.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/code_fence_utils.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/emphasis_style.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/front_matter_utils.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/heading_utils.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/list_utils.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md001_heading_increment.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md002_first_heading_h1/md002_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md002_first_heading_h1.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md003_heading_style/md003_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md003_heading_style.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md004_unordered_list_style/md004_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md004_unordered_list_style.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md007_ul_indent/md007_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md009_trailing_spaces/md009_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md010_no_hard_tabs/md010_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md012_no_multiple_blanks/md012_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md012_no_multiple_blanks.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md013_line_length/md013_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md014_commands_show_output/md014_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md014_commands_show_output.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md018_no_missing_space_atx.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md019_no_multiple_space_atx.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md022_blanks_around_headings/md022_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md022_blanks_around_headings.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md023_heading_start_left.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md024_no_duplicate_heading/md024_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md024_no_duplicate_heading.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md025_single_title/md025_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md026_no_trailing_punctuation/md026_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md027_multiple_spaces_blockquote.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md028_no_blanks_blockquote.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md030_list_marker_space/md030_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md030_list_marker_space.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md033_no_inline_html/md033_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md033_no_inline_html.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md035_hr_style/md035_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md036_no_emphasis_only_first/md036_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md038_no_space_in_code.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md039_no_space_in_links.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md040_fenced_code_language.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md042_no_empty_links.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md043_required_headings.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md044_proper_names/md044_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md045_no_alt_text/md045_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md046_code_block_style/md046_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md047_single_trailing_newline.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md048_code_fence_style/md048_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md049_emphasis_style/md049_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md049_emphasis_style.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md050_strong_style/md050_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md050_strong_style.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md054_link_image_style/md054_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md054_link_image_style.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md055_table_pipe_style/md055_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md057_existing_relative_links/md057_config.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/md057_existing_relative_links.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/mod.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/rules/strong_style.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/ast_utils.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/code_block_utils.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/document_structure.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/early_returns.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/element_cache.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/emphasis_utils.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/fix_utils.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/markdown_elements.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/mod.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/range_utils.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/string_interner.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/table_utils.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/utils/text_reflow.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/src/vscode.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/advanced_integration_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/character_ranges/additional_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/character_ranges/basic_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/character_ranges/comprehensive_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/character_ranges/extended_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/character_ranges/mod.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/character_ranges/unicode_utils.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/cli_duplication_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/cli_explain_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/cli_flag_precedence_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/cli_integration_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/cli_lsp_fix_consistency.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/cli_statistics_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/commonmark_compliance_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/comprehensive_integration_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/comprehensive_output_format_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/config_application_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/config_file_command_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/config_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/configuration_inheritance_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/consistency_regression_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/cross_platform_compatibility_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/deeply_nested_lists_performance_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/escaped_brackets_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/final_confidence_assessment.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/init_command_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/init_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/inline_config_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/integration_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/json_output_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/lib.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/lsp_editor_integration_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/lsp_integration_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/lsp_memory_leak_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/lsp_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/malformed_markdown_stress_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/markdownlint_cli_integration.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/markdownlint_config_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/markdownlintignore_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/md013_reflow_integration_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/nested_code_block_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/output_format_integration_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/output_format_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/perf_check.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/performance_validation_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/pyproject_config_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/python_bindings_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/real_world_repository_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/regression_prevention_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/emphasis_edge_cases_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/heading_edge_cases_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/inline_content_edge_cases_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/link_edge_cases_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md001_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md001_unicode_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md002_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md003_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md004_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md006_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md006_unicode_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md009_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md010_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md011_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md012_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md013_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md014_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md018_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md019_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md020_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md021_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md022_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md023_extended_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md023_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md024_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md025_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md026_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md027_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md028_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md029_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md029_unicode_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md030_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md031_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md032_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md033_extended_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md033_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md034_ipv6_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md034_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md035_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md036_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md037_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md038_nested_backticks_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md038_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md039_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md040_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md041_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md042_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md043_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md044_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md045_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md046_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md047_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md048_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md049_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md050_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md051_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md051_unicode_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md052_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md053_additional_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md053_proptest.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md053_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md054_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md054_unicode_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md055_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md056_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md057_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/md058_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules/mod.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/rules_mod_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/thread_safety_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/unicode_edge_case_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/utils/blockquote_utils_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/utils/code_block_utils_extended_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/utils/code_block_utils_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/utils/core_utils_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/utils/front_matter_utils_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/utils/line_index_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/utils/mod.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/utils_markdown_edge_cases.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/utils_tests.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/vscode_extension_fixes.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/vscode_test.rs +0 -0
- {rumdl-0.0.100 → rumdl-0.0.102}/tests/vscode_tests.rs +0 -0
|
@@ -7,8 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.0.102] - 2025-07-24
|
|
11
|
+
|
|
12
|
+
## [0.0.101] - 2025-07-23
|
|
13
|
+
|
|
10
14
|
## [0.0.100] - 2025-07-22
|
|
11
15
|
|
|
16
|
+
### Performance Improvements
|
|
17
|
+
- **MD032**: Eliminated redundant DocumentStructure creation through optimization interface delegation
|
|
18
|
+
- Refactored check() method to delegate to check_with_structure() for shared parsing
|
|
19
|
+
- Added fix_with_structure() helper method for optimized fixing operations
|
|
20
|
+
- **List Processing**: Major refactoring of complex list block merging logic for better maintainability
|
|
21
|
+
- Extracted merge_adjacent_list_blocks into clean ListBlockMerger struct
|
|
22
|
+
- Introduced BlockSpacing enum for clear categorization of list spacing types
|
|
23
|
+
- Separated compatibility checking, spacing analysis, and merging logic into focused methods
|
|
24
|
+
- **Memory Management**: Added comprehensive performance stress tests for deeply nested lists
|
|
25
|
+
- Created benchmarks for up to 20 levels of nesting with measurable performance baselines
|
|
26
|
+
- Established performance thresholds: <3ms parsing, <4ms rule checking for extreme nesting
|
|
27
|
+
- Added memory stress testing to prevent performance regressions
|
|
28
|
+
|
|
29
|
+
### Code Quality
|
|
30
|
+
- Improved separation of concerns in list processing logic
|
|
31
|
+
- Enhanced code maintainability through better structured algorithms
|
|
32
|
+
- Added comprehensive test coverage for pathological markdown structures
|
|
33
|
+
|
|
12
34
|
## [0.0.99] - 2025-07-22
|
|
13
35
|
|
|
14
36
|
### Fixed
|
|
@@ -225,7 +247,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
225
247
|
|
|
226
248
|
- Initial implementation of remaining rules for markdownlint parity
|
|
227
249
|
|
|
228
|
-
[Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.
|
|
250
|
+
[Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.102...HEAD
|
|
251
|
+
[0.0.102]: https://github.com/rvben/rumdl/compare/v0.0.101...v0.0.102
|
|
252
|
+
[0.0.101]: https://github.com/rvben/rumdl/compare/v0.0.100...v0.0.101
|
|
229
253
|
[0.0.100]: https://github.com/rvben/rumdl/compare/v0.0.99...v0.0.100
|
|
230
254
|
[0.0.99]: https://github.com/rvben/rumdl/compare/v0.0.98...v0.0.99
|
|
231
255
|
[0.0.98]: https://github.com/rvben/rumdl/compare/v0.0.97...v0.0.98
|
|
@@ -609,6 +609,37 @@ fn find_markdown_files(
|
|
|
609
609
|
// Add support for .markdownlintignore file
|
|
610
610
|
walk_builder.add_custom_ignore_filename(".markdownlintignore");
|
|
611
611
|
|
|
612
|
+
// --- Pre-check for explicit file paths ---
|
|
613
|
+
// If not in discovery mode, validate that specified paths exist
|
|
614
|
+
if !is_discovery_mode {
|
|
615
|
+
for path_str in paths {
|
|
616
|
+
let path = Path::new(path_str);
|
|
617
|
+
if !path.exists() {
|
|
618
|
+
return Err(format!("File not found: {path_str}").into());
|
|
619
|
+
}
|
|
620
|
+
// If it's a file, check if it's a markdown file and add it directly
|
|
621
|
+
if path.is_file() {
|
|
622
|
+
if let Some(ext) = path.extension() {
|
|
623
|
+
if ext == "md" || ext == "markdown" {
|
|
624
|
+
let cleaned_path = if let Some(stripped) = path_str.strip_prefix("./") {
|
|
625
|
+
stripped.to_string()
|
|
626
|
+
} else {
|
|
627
|
+
path_str.clone()
|
|
628
|
+
};
|
|
629
|
+
file_paths.push(cleaned_path);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// If we found files directly, skip the walker
|
|
636
|
+
if !file_paths.is_empty() {
|
|
637
|
+
file_paths.sort();
|
|
638
|
+
file_paths.dedup();
|
|
639
|
+
return Ok(file_paths);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
612
643
|
// --- Execute Walk ---
|
|
613
644
|
|
|
614
645
|
for result in walk_builder.build() {
|
|
@@ -628,7 +659,12 @@ fn find_markdown_files(
|
|
|
628
659
|
file_paths.push(cleaned_path);
|
|
629
660
|
}
|
|
630
661
|
}
|
|
631
|
-
Err(err) =>
|
|
662
|
+
Err(err) => {
|
|
663
|
+
// Only show generic walking errors for directories, not for missing files
|
|
664
|
+
if is_discovery_mode {
|
|
665
|
+
eprintln!("Error walking directory: {err}");
|
|
666
|
+
}
|
|
667
|
+
}
|
|
632
668
|
}
|
|
633
669
|
}
|
|
634
670
|
|
|
@@ -7,29 +7,63 @@ use crate::utils::range_utils::{LineIndex, calculate_match_range};
|
|
|
7
7
|
|
|
8
8
|
use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule, RuleCategory, Severity};
|
|
9
9
|
use crate::utils::document_structure::DocumentStructure;
|
|
10
|
-
|
|
11
|
-
use regex::Regex;
|
|
10
|
+
// No regex patterns needed for this rule
|
|
12
11
|
use std::collections::HashMap;
|
|
13
12
|
use toml;
|
|
14
13
|
|
|
15
|
-
lazy_static! {
|
|
16
|
-
// Regex to match blockquote prefixes (one or more '>' with optional spaces)
|
|
17
|
-
static ref BLOCKQUOTE_PREFIX: Regex = Regex::new(r"^(\s*>\s*)+").unwrap();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
14
|
/// Rule MD005: Inconsistent indentation for list items at the same level
|
|
21
15
|
#[derive(Clone)]
|
|
22
16
|
pub struct MD005ListIndent;
|
|
23
17
|
|
|
24
18
|
impl MD005ListIndent {
|
|
25
|
-
// Determine the expected indentation for a list item
|
|
19
|
+
// Determine the expected indentation for a list item
|
|
20
|
+
// Each nested item should align with the text content of its parent
|
|
26
21
|
#[inline]
|
|
27
|
-
fn get_expected_indent(level: usize) -> usize {
|
|
22
|
+
fn get_expected_indent(level: usize, parent_text_position: Option<usize>) -> usize {
|
|
28
23
|
if level == 1 {
|
|
29
24
|
0 // Top level items should be at the start of the line
|
|
25
|
+
} else if let Some(pos) = parent_text_position {
|
|
26
|
+
// Align with parent's text content
|
|
27
|
+
pos
|
|
30
28
|
} else {
|
|
31
|
-
|
|
29
|
+
// Fallback to standard nested indentation: 2 spaces per level
|
|
30
|
+
2 * (level - 1)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// Get parent info for any list item to determine proper text alignment
|
|
35
|
+
/// Returns parent_text_position where the child should align
|
|
36
|
+
fn get_parent_text_position(
|
|
37
|
+
&self,
|
|
38
|
+
ctx: &crate::lint_context::LintContext,
|
|
39
|
+
current_line: usize,
|
|
40
|
+
current_indent: usize,
|
|
41
|
+
) -> Option<usize> {
|
|
42
|
+
// Look backward from current line to find parent item
|
|
43
|
+
for line_idx in (1..current_line).rev() {
|
|
44
|
+
if let Some(line_info) = ctx.line_info(line_idx) {
|
|
45
|
+
if let Some(list_item) = &line_info.list_item {
|
|
46
|
+
// Found a list item - check if it's at a lower indentation (parent level)
|
|
47
|
+
if list_item.marker_column < current_indent {
|
|
48
|
+
// This is a parent item - calculate where child should align
|
|
49
|
+
if list_item.is_ordered {
|
|
50
|
+
// For ordered lists, align with text start
|
|
51
|
+
let text_start_pos = list_item.marker_column + list_item.marker.len() + 1; // +1 for space after marker
|
|
52
|
+
return Some(text_start_pos);
|
|
53
|
+
} else {
|
|
54
|
+
// For unordered lists, align with text start
|
|
55
|
+
let text_start_pos = list_item.marker_column + 2; // "* " or "- " or "+ "
|
|
56
|
+
return Some(text_start_pos);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// If we encounter non-blank, non-list content at column 0, stop looking
|
|
61
|
+
else if !line_info.is_blank && line_info.indent == 0 {
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
32
65
|
}
|
|
66
|
+
None
|
|
33
67
|
}
|
|
34
68
|
|
|
35
69
|
/// Group related list blocks that should be treated as one logical list structure
|
|
@@ -144,7 +178,19 @@ impl MD005ListIndent {
|
|
|
144
178
|
// Sort by line number to process in order
|
|
145
179
|
group.sort_by_key(|(line_num, _, _)| *line_num);
|
|
146
180
|
|
|
147
|
-
|
|
181
|
+
// Get parent text position for proper alignment
|
|
182
|
+
let parent_text_position = if level > 1 {
|
|
183
|
+
// Get parent info from the first item in the group
|
|
184
|
+
if let Some((line_num, indent, _)) = group.first() {
|
|
185
|
+
self.get_parent_text_position(ctx, *line_num, *indent)
|
|
186
|
+
} else {
|
|
187
|
+
None
|
|
188
|
+
}
|
|
189
|
+
} else {
|
|
190
|
+
None
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
let expected_indent = Self::get_expected_indent(level, parent_text_position);
|
|
148
194
|
|
|
149
195
|
// Check if items in this level have consistent indentation
|
|
150
196
|
let indents: std::collections::HashSet<usize> = group.iter().map(|(_, indent, _)| *indent).collect();
|
|
@@ -401,11 +447,13 @@ mod tests {
|
|
|
401
447
|
let content = "\
|
|
402
448
|
1. Item 1
|
|
403
449
|
2. Item 2
|
|
404
|
-
|
|
405
|
-
|
|
450
|
+
1. Nested 1
|
|
451
|
+
2. Nested 2
|
|
406
452
|
3. Item 3";
|
|
407
453
|
let ctx = LintContext::new(content);
|
|
408
454
|
let result = rule.check(&ctx).unwrap();
|
|
455
|
+
// With dynamic alignment, nested items should align with parent's text content
|
|
456
|
+
// Ordered items starting with "1. " have text at column 3, so nested items need 3 spaces
|
|
409
457
|
assert!(result.is_empty());
|
|
410
458
|
}
|
|
411
459
|
|
|
@@ -418,9 +466,11 @@ mod tests {
|
|
|
418
466
|
* Nested 1";
|
|
419
467
|
let ctx = LintContext::new(content);
|
|
420
468
|
let result = rule.check(&ctx).unwrap();
|
|
421
|
-
|
|
469
|
+
// With dynamic alignment, line 3 correctly aligns with line 2's text position
|
|
470
|
+
// Only line 2 is incorrectly indented
|
|
471
|
+
assert_eq!(result.len(), 1);
|
|
422
472
|
let fixed = rule.fix(&ctx).unwrap();
|
|
423
|
-
assert_eq!(fixed, "* Item 1\n * Item 2\n
|
|
473
|
+
assert_eq!(fixed, "* Item 1\n * Item 2\n * Nested 1");
|
|
424
474
|
}
|
|
425
475
|
|
|
426
476
|
#[test]
|
|
@@ -434,7 +484,10 @@ mod tests {
|
|
|
434
484
|
let result = rule.check(&ctx).unwrap();
|
|
435
485
|
assert_eq!(result.len(), 1);
|
|
436
486
|
let fixed = rule.fix(&ctx).unwrap();
|
|
437
|
-
|
|
487
|
+
// With dynamic alignment, ordered items align with parent's text content
|
|
488
|
+
// Line 1 text starts at col 3, so line 2 should have 3 spaces
|
|
489
|
+
// Line 3 already correctly aligns with line 2's text position
|
|
490
|
+
assert_eq!(fixed, "1. Item 1\n 2. Item 2\n 1. Nested 1");
|
|
438
491
|
}
|
|
439
492
|
|
|
440
493
|
#[test]
|
|
@@ -461,12 +514,15 @@ mod tests {
|
|
|
461
514
|
let result = rule.check(&ctx).unwrap();
|
|
462
515
|
assert_eq!(result.len(), 2);
|
|
463
516
|
let fixed = rule.fix(&ctx).unwrap();
|
|
517
|
+
// With dynamic alignment:
|
|
518
|
+
// Level 2 aligns with Level 1's text (2 spaces)
|
|
519
|
+
// Level 3 aligns with Level 2's text (5 spaces: 2 + "* " + 1)
|
|
464
520
|
assert_eq!(
|
|
465
521
|
fixed,
|
|
466
522
|
"\
|
|
467
523
|
* Level 1
|
|
468
524
|
* Level 2
|
|
469
|
-
|
|
525
|
+
* Level 3"
|
|
470
526
|
);
|
|
471
527
|
}
|
|
472
528
|
|
|
@@ -525,11 +581,14 @@ Even more text";
|
|
|
525
581
|
* Back to 1";
|
|
526
582
|
let ctx = LintContext::new(content);
|
|
527
583
|
let result = rule.check(&ctx).unwrap();
|
|
528
|
-
|
|
584
|
+
// With dynamic alignment, fewer items need correction
|
|
585
|
+
// Lines 2,4: should align with Level 1's text (2 spaces)
|
|
586
|
+
// Line 5: should align with "Back to 2"'s text (5 spaces)
|
|
587
|
+
assert_eq!(result.len(), 3);
|
|
529
588
|
let fixed = rule.fix(&ctx).unwrap();
|
|
530
589
|
assert_eq!(
|
|
531
590
|
fixed,
|
|
532
|
-
"* Level 1\n * Level 2\n
|
|
591
|
+
"* Level 1\n * Level 2\n * Level 3\n * Back to 2\n 1. Ordered 3\n 2. Still 3\n* Back to 1"
|
|
533
592
|
);
|
|
534
593
|
}
|
|
535
594
|
|
|
@@ -692,16 +751,14 @@ Even more text";
|
|
|
692
751
|
* Wrong 4";
|
|
693
752
|
let ctx = LintContext::new(content);
|
|
694
753
|
let fixed = rule.fix(&ctx).unwrap();
|
|
695
|
-
//
|
|
754
|
+
// With dynamic alignment, items align with their parent's text content
|
|
696
755
|
let lines: Vec<&str> = fixed.lines().collect();
|
|
697
756
|
assert_eq!(lines[0], "* Item 1");
|
|
698
757
|
assert_eq!(lines[1], " * Wrong 1");
|
|
699
|
-
assert_eq!(lines[2], "
|
|
700
|
-
assert_eq!(lines[3], "
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
assert_eq!(lines[4], " * Correct");
|
|
704
|
-
assert_eq!(lines[5], " * Wrong 4");
|
|
758
|
+
assert_eq!(lines[2], " * Wrong 2"); // Aligns with line 2's text
|
|
759
|
+
assert_eq!(lines[3], " * Wrong 3"); // Aligns with line 3's text
|
|
760
|
+
assert_eq!(lines[4], " * Correct"); // Back to level 2, aligns with line 1's text
|
|
761
|
+
assert_eq!(lines[5], " * Wrong 4"); // Same level as "Correct"
|
|
705
762
|
}
|
|
706
763
|
|
|
707
764
|
#[test]
|
|
@@ -791,6 +848,56 @@ Even more text";
|
|
|
791
848
|
assert!(result.iter().any(|w| w.line == 2 && w.message.contains("found 3")));
|
|
792
849
|
}
|
|
793
850
|
|
|
851
|
+
#[test]
|
|
852
|
+
fn test_nested_bullets_under_numbered_items() {
|
|
853
|
+
let rule = MD005ListIndent;
|
|
854
|
+
let content = "\
|
|
855
|
+
1. **Active Directory/LDAP**
|
|
856
|
+
- User authentication and directory services
|
|
857
|
+
- LDAP for user information and validation
|
|
858
|
+
|
|
859
|
+
2. **Oracle Unified Directory (OUD)**
|
|
860
|
+
- Extended user directory services
|
|
861
|
+
- Verification of project account presence and changes";
|
|
862
|
+
let ctx = LintContext::new(content);
|
|
863
|
+
let result = rule.check(&ctx).unwrap();
|
|
864
|
+
// Should have no warnings - 3 spaces is correct for bullets under numbered items
|
|
865
|
+
assert!(
|
|
866
|
+
result.is_empty(),
|
|
867
|
+
"Expected no warnings for bullets with 3 spaces under numbered items, got: {result:?}"
|
|
868
|
+
);
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
#[test]
|
|
872
|
+
fn test_nested_bullets_under_numbered_items_wrong_indent() {
|
|
873
|
+
let rule = MD005ListIndent;
|
|
874
|
+
let content = "\
|
|
875
|
+
1. **Active Directory/LDAP**
|
|
876
|
+
- Wrong: only 2 spaces
|
|
877
|
+
- Correct: 3 spaces";
|
|
878
|
+
let ctx = LintContext::new(content);
|
|
879
|
+
let result = rule.check(&ctx).unwrap();
|
|
880
|
+
// Should flag the 2-space indentation as wrong
|
|
881
|
+
assert_eq!(result.len(), 2); // Both items flagged due to inconsistency
|
|
882
|
+
assert!(result.iter().any(|w| w.line == 2 && w.message.contains("found 2")));
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
#[test]
|
|
886
|
+
fn test_regular_nested_bullets_still_work() {
|
|
887
|
+
let rule = MD005ListIndent;
|
|
888
|
+
let content = "\
|
|
889
|
+
* Top level
|
|
890
|
+
* Second level (2 spaces is correct for bullets under bullets)
|
|
891
|
+
* Third level (4 spaces)";
|
|
892
|
+
let ctx = LintContext::new(content);
|
|
893
|
+
let result = rule.check(&ctx).unwrap();
|
|
894
|
+
// Should have no warnings - regular bullet nesting still uses 2-space increments
|
|
895
|
+
assert!(
|
|
896
|
+
result.is_empty(),
|
|
897
|
+
"Expected no warnings for regular bullet nesting, got: {result:?}"
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
|
|
794
901
|
#[test]
|
|
795
902
|
fn test_fix_range_accuracy() {
|
|
796
903
|
let rule = MD005ListIndent;
|
|
@@ -2,8 +2,7 @@ use crate::utils::range_utils::LineIndex;
|
|
|
2
2
|
|
|
3
3
|
use crate::rule::{Fix, LintError, LintResult, LintWarning, Rule, RuleCategory, Severity};
|
|
4
4
|
use crate::utils::document_structure::{DocumentStructure, DocumentStructureExtensions};
|
|
5
|
-
use
|
|
6
|
-
use regex::Regex;
|
|
5
|
+
use crate::utils::regex_cache::UNORDERED_LIST_MARKER_REGEX;
|
|
7
6
|
|
|
8
7
|
/// Rule MD006: Consider starting bulleted lists at the leftmost column
|
|
9
8
|
///
|
|
@@ -16,15 +15,33 @@ use regex::Regex;
|
|
|
16
15
|
#[derive(Clone)]
|
|
17
16
|
pub struct MD006StartBullets;
|
|
18
17
|
|
|
19
|
-
lazy_static! {
|
|
20
|
-
// Pattern to match bullet list items: captures indentation, marker, and space after marker
|
|
21
|
-
static ref BULLET_PATTERN: Regex = Regex::new(r"^(\s*)([*+-])(\s+)").unwrap();
|
|
22
|
-
|
|
23
|
-
// Pattern to match code fence markers
|
|
24
|
-
static ref CODE_FENCE_PATTERN: Regex = Regex::new(r"^(\s*)(```|~~~)").unwrap();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
18
|
impl MD006StartBullets {
|
|
19
|
+
/// Check if a bullet is nested under an ordered list item
|
|
20
|
+
fn is_nested_under_ordered_item(
|
|
21
|
+
&self,
|
|
22
|
+
ctx: &crate::lint_context::LintContext,
|
|
23
|
+
current_line: usize,
|
|
24
|
+
current_indent: usize,
|
|
25
|
+
) -> bool {
|
|
26
|
+
// Look backward from current line to find parent item
|
|
27
|
+
for line_idx in (1..current_line).rev() {
|
|
28
|
+
if let Some(line_info) = ctx.line_info(line_idx) {
|
|
29
|
+
if let Some(list_item) = &line_info.list_item {
|
|
30
|
+
// Found a list item - check if it's at a lower indentation (parent level)
|
|
31
|
+
if list_item.marker_column < current_indent {
|
|
32
|
+
// This is a parent item - check if it's ordered
|
|
33
|
+
return list_item.is_ordered;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// If we encounter non-blank, non-list content at column 0, stop looking
|
|
37
|
+
else if !line_info.is_blank && line_info.indent == 0 {
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
false
|
|
43
|
+
}
|
|
44
|
+
|
|
28
45
|
/// Optimized check using centralized list blocks
|
|
29
46
|
fn check_optimized(&self, ctx: &crate::lint_context::LintContext) -> LintResult {
|
|
30
47
|
let content = ctx.content;
|
|
@@ -56,21 +73,26 @@ impl MD006StartBullets {
|
|
|
56
73
|
// Top-level items are always valid
|
|
57
74
|
is_valid = true;
|
|
58
75
|
} else {
|
|
59
|
-
// Check if this is
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
// Check if this is nested under an ordered item with correct indentation (3 spaces)
|
|
77
|
+
if indent == 3 && self.is_nested_under_ordered_item(ctx, item_line, indent) {
|
|
78
|
+
is_valid = true;
|
|
79
|
+
} else {
|
|
80
|
+
// Check if this is a valid nested item under another bullet
|
|
81
|
+
match Self::find_relevant_previous_bullet(&lines, line_idx) {
|
|
82
|
+
Some((prev_idx, prev_indent)) => {
|
|
83
|
+
match prev_indent.cmp(&indent) {
|
|
84
|
+
std::cmp::Ordering::Less | std::cmp::Ordering::Equal => {
|
|
85
|
+
// Valid nesting or sibling if previous item was valid
|
|
86
|
+
is_valid = valid_bullet_lines[prev_idx];
|
|
87
|
+
}
|
|
88
|
+
std::cmp::Ordering::Greater => {
|
|
89
|
+
// remains invalid
|
|
90
|
+
}
|
|
69
91
|
}
|
|
70
92
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
93
|
+
None => {
|
|
94
|
+
// Indented item with no previous bullet remains invalid
|
|
95
|
+
}
|
|
74
96
|
}
|
|
75
97
|
}
|
|
76
98
|
}
|
|
@@ -84,7 +106,7 @@ impl MD006StartBullets {
|
|
|
84
106
|
|
|
85
107
|
// For the fix, we need to replace the highlighted part with just the bullet marker
|
|
86
108
|
let trimmed = line.trim_start();
|
|
87
|
-
let bullet_part = if let Some(captures) =
|
|
109
|
+
let bullet_part = if let Some(captures) = UNORDERED_LIST_MARKER_REGEX.captures(trimmed) {
|
|
88
110
|
let marker = captures.get(2).map_or("*", |m| m.as_str());
|
|
89
111
|
format!("{marker} ")
|
|
90
112
|
} else {
|
|
@@ -123,7 +145,7 @@ impl MD006StartBullets {
|
|
|
123
145
|
}
|
|
124
146
|
/// Checks if a line is a bullet list item and returns its indentation level
|
|
125
147
|
fn is_bullet_list_item(line: &str) -> Option<usize> {
|
|
126
|
-
if let Some(captures) =
|
|
148
|
+
if let Some(captures) = UNORDERED_LIST_MARKER_REGEX.captures(line) {
|
|
127
149
|
if let Some(indent) = captures.get(1) {
|
|
128
150
|
return Some(indent.as_str().len());
|
|
129
151
|
}
|
|
@@ -338,7 +360,7 @@ impl Rule for MD006StartBullets {
|
|
|
338
360
|
let line = lines[line_idx];
|
|
339
361
|
let trimmed = line.trim_start();
|
|
340
362
|
// Extract just the bullet marker and normalize to single space
|
|
341
|
-
let bullet_part = if let Some(captures) =
|
|
363
|
+
let bullet_part = if let Some(captures) = UNORDERED_LIST_MARKER_REGEX.captures(trimmed) {
|
|
342
364
|
format!("{} ", captures.get(2).unwrap().as_str()) // Always use single space
|
|
343
365
|
} else {
|
|
344
366
|
"* ".to_string() // fallback
|
|
@@ -453,4 +475,58 @@ mod tests {
|
|
|
453
475
|
"Standard nesting (* Item -> * Item) should NOT generate warnings, found: {result:?}"
|
|
454
476
|
);
|
|
455
477
|
}
|
|
478
|
+
|
|
479
|
+
#[test]
|
|
480
|
+
fn test_bullets_nested_under_numbered_items() {
|
|
481
|
+
let rule = MD006StartBullets;
|
|
482
|
+
let content = "\
|
|
483
|
+
1. **Active Directory/LDAP**
|
|
484
|
+
- User authentication and directory services
|
|
485
|
+
- LDAP for user information and validation
|
|
486
|
+
|
|
487
|
+
2. **Oracle Unified Directory (OUD)**
|
|
488
|
+
- Extended user directory services";
|
|
489
|
+
let ctx = crate::lint_context::LintContext::new(content);
|
|
490
|
+
let result = rule.check(&ctx).unwrap();
|
|
491
|
+
// Should have no warnings - 3 spaces is valid for bullets under numbered items
|
|
492
|
+
assert!(
|
|
493
|
+
result.is_empty(),
|
|
494
|
+
"Expected no warnings for bullets with 3 spaces under numbered items, got: {result:?}"
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
#[test]
|
|
499
|
+
fn test_bullets_nested_under_numbered_items_wrong_indent() {
|
|
500
|
+
let rule = MD006StartBullets;
|
|
501
|
+
let content = "\
|
|
502
|
+
1. **Active Directory/LDAP**
|
|
503
|
+
- Wrong: only 2 spaces
|
|
504
|
+
- Also wrong: 4 spaces";
|
|
505
|
+
let ctx = crate::lint_context::LintContext::new(content);
|
|
506
|
+
let result = rule.check(&ctx).unwrap();
|
|
507
|
+
// Should flag the incorrect indentations
|
|
508
|
+
assert_eq!(
|
|
509
|
+
result.len(),
|
|
510
|
+
2,
|
|
511
|
+
"Expected warnings for bullets with incorrect spacing under numbered items"
|
|
512
|
+
);
|
|
513
|
+
assert!(result.iter().any(|w| w.line == 2));
|
|
514
|
+
assert!(result.iter().any(|w| w.line == 3));
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
#[test]
|
|
518
|
+
fn test_regular_bullet_nesting_still_works() {
|
|
519
|
+
let rule = MD006StartBullets;
|
|
520
|
+
let content = "\
|
|
521
|
+
* Top level
|
|
522
|
+
* Nested bullet (2 spaces is correct)
|
|
523
|
+
* Deeply nested (4 spaces)";
|
|
524
|
+
let ctx = crate::lint_context::LintContext::new(content);
|
|
525
|
+
let result = rule.check(&ctx).unwrap();
|
|
526
|
+
// Should have no warnings - standard bullet nesting still works
|
|
527
|
+
assert!(
|
|
528
|
+
result.is_empty(),
|
|
529
|
+
"Expected no warnings for standard bullet nesting, got: {result:?}"
|
|
530
|
+
);
|
|
531
|
+
}
|
|
456
532
|
}
|