rumdl 0.0.70__tar.gz → 0.0.72__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.70 → rumdl-0.0.72}/Cargo.lock +1 -1
- {rumdl-0.0.70 → rumdl-0.0.72}/Cargo.toml +1 -1
- {rumdl-0.0.70 → rumdl-0.0.72}/PKG-INFO +1 -1
- {rumdl-0.0.70 → rumdl-0.0.72}/src/lib.rs +1 -1
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md001_heading_increment.rs +1 -1
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md006_start_bullets.rs +55 -35
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md009_trailing_spaces.rs +2 -2
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md011_no_reversed_links.rs +85 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md014_commands_show_output.rs +19 -4
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md022_blanks_around_headings.rs +6 -6
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md025_single_title.rs +58 -1
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md026_no_trailing_punctuation.rs +2 -2
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md028_no_blanks_blockquote.rs +1 -1
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md029_ordered_list_prefix.rs +46 -2
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md030_list_marker_space.rs +10 -2
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md032_blanks_around_lists.rs +9 -9
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md033_no_inline_html.rs +20 -26
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md034_no_bare_urls.rs +12 -6
- rumdl-0.0.72/src/rules/md037_spaces_around_emphasis.rs +620 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md039_no_space_in_links.rs +1 -1
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md040_fenced_code_language.rs +3 -2
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md045_no_alt_text.rs +1 -1
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md046_code_block_style.rs +4 -4
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md048_code_fence_style.rs +2 -2
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md055_table_pipe_style.rs +24 -1
- {rumdl-0.0.70 → rumdl-0.0.72}/src/utils/regex_cache.rs +6 -4
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/output_format_tests.rs +2 -2
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md001_test.rs +1 -1
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md001_unicode_test.rs +1 -1
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md009_test.rs +1 -4
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md030_test.rs +35 -7
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md032_test.rs +3 -5
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md034_test.rs +3 -3
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md037_test.rs +205 -12
- rumdl-0.0.70/src/rules/md037_spaces_around_emphasis.rs +0 -595
- {rumdl-0.0.70 → rumdl-0.0.72}/.rumdl.toml +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/MANIFEST.in +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/Makefile +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/README.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/assets/logo.png +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/benches/fix_performance.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/benches/range_performance.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/benches/range_utils_benchmark.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/benches/rule_performance.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/benches/simple_fix_bench.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/RULES.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md001.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md002.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md003.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md004.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md005.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md006.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md007.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md009.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md010.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md011.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md012.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md013.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md014.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md018.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md019.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md020.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md021.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md022.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md023.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md024.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md025.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md026.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md027.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md028.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md029.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md030.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md031.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md032.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md033.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md034.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md035.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md036.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md037.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md038.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md039.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md040.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md041.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md042.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md043.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md044.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md045.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md046.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md047.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md048.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md049.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md050.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md051.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md052.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md053.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md054.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md055.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md056.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md057.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/docs/md058.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/issues/plan-rule-parity-with-markdownlint.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/parity_check.py +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/pyproject.toml +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/python/MANIFEST.in +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/python/PYTHON-README.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/python/rumdl/__init__.py +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/python/rumdl/__main__.py +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/python/rumdl/py.typed +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/rumdl.toml.example +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/config.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/init.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/lint_context.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/lsp/mod.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/lsp/server.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/lsp/types.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/main.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/markdownlint_config.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/parallel.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/performance.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/profiling.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/python.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rule.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/blockquote_utils.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/code_block_utils.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/code_fence_utils.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/emphasis_style.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/front_matter_utils.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/heading_utils.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/list_utils.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md002_first_heading_h1.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md003_heading_style.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md004_unordered_list_style.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md005_list_indent.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md007_ul_indent.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md010_no_hard_tabs.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md012_no_multiple_blanks.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md013_line_length.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md018_no_missing_space_atx.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md019_no_multiple_space_atx.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md020_no_missing_space_closed_atx.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md023_heading_start_left.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md024_no_duplicate_heading.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md027_multiple_spaces_blockquote.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md031_blanks_around_fences.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md035_hr_style.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md036_no_emphasis_only_first.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md038_no_space_in_code.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md041_first_line_heading.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md042_no_empty_links.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md043_required_headings.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md044_proper_names.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md047_single_trailing_newline.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md049_emphasis_style.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md050_strong_style.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md051_link_fragments.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md052_reference_links_images.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md053_link_image_reference_definitions.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md054_link_image_style.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md056_table_column_count.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md057_existing_relative_links.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/md058_blanks_around_tables.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/mod.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/rules/strong_style.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/utils/ast_utils.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/utils/code_block_utils.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/utils/document_structure.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/utils/early_returns.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/utils/element_cache.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/utils/markdown_elements.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/utils/mod.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/utils/range_utils.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/utils/string_interner.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/src/utils/table_utils.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/advanced_integration_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/character_ranges/additional_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/character_ranges/basic_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/character_ranges/comprehensive_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/character_ranges/extended_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/character_ranges/mod.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/character_ranges/unicode_utils.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/cli_duplication_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/cli_integration_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/commonmark_compliance_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/comprehensive_integration_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/config_application_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/config_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/init_command_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/init_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/integration_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/json_output_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/lib.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/lsp_integration_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/lsp_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/markdownlint_cli_integration.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/markdownlint_config_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/md030_edge_cases.md +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/perf_check.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/pyproject_config_tests.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md002_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md003_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md004_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md005_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md006_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md006_unicode_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md007_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md010_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md011_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md012_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md013_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md014_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md018_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md019_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md020_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md021_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md022_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md023_extended_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md023_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md024_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md025_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md026_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md027_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md028_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md029_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md031_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md033_extended_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md033_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md035_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md036_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md038_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md039_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md040_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md041_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md042_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md043_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md044_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md045_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md046_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md047_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md048_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md049_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md050_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md051_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md052_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md053_additional_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md053_proptest.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md053_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md054_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md054_unicode_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md055_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md056_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md057_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/md058_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/rules/mod.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/utils/blockquote_utils_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/utils/code_block_utils_extended_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/utils/code_block_utils_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/utils/core_utils_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/utils/front_matter_utils_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/utils/line_index_test.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/utils/mod.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/utils_markdown_edge_cases.rs +0 -0
- {rumdl-0.0.70 → rumdl-0.0.72}/tests/utils_tests.rs +0 -0
|
@@ -70,7 +70,7 @@ impl ContentCharacteristics {
|
|
|
70
70
|
{
|
|
71
71
|
chars.has_lists = true;
|
|
72
72
|
}
|
|
73
|
-
if !chars.has_links && line.contains('[') {
|
|
73
|
+
if !chars.has_links && (line.contains('[') || line.contains("http://") || line.contains("https://") || line.contains("ftp://")) {
|
|
74
74
|
chars.has_links = true;
|
|
75
75
|
}
|
|
76
76
|
if !chars.has_images && line.contains("![") {
|
|
@@ -162,7 +162,7 @@ impl Rule for MD001HeadingIncrement {
|
|
|
162
162
|
column: start_col,
|
|
163
163
|
end_line,
|
|
164
164
|
end_column: end_col,
|
|
165
|
-
message: format!("
|
|
165
|
+
message: format!("Expected heading level {}", prev_level + 1),
|
|
166
166
|
severity: Severity::Warning,
|
|
167
167
|
fix: Some(Fix {
|
|
168
168
|
range: line_index.line_col_to_byte_range(line_num, indentation + 1),
|
|
@@ -25,14 +25,14 @@ lazy_static! {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
impl MD006StartBullets {
|
|
28
|
-
///
|
|
28
|
+
/// Checks if a line is a bullet list item and returns its indentation level
|
|
29
29
|
fn is_bullet_list_item(line: &str) -> Option<usize> {
|
|
30
|
-
if let Some(
|
|
31
|
-
let indent =
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
None
|
|
30
|
+
if let Some(captures) = BULLET_PATTERN.captures(line) {
|
|
31
|
+
if let Some(indent) = captures.get(1) {
|
|
32
|
+
return Some(indent.as_str().len());
|
|
33
|
+
}
|
|
35
34
|
}
|
|
35
|
+
None
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/// Checks if a line is blank (empty or whitespace only)
|
|
@@ -46,7 +46,9 @@ impl MD006StartBullets {
|
|
|
46
46
|
Some(indent) => indent,
|
|
47
47
|
None => return None, // Should not happen if called on a bullet item
|
|
48
48
|
};
|
|
49
|
+
|
|
49
50
|
let mut i = line_idx;
|
|
51
|
+
|
|
50
52
|
while i > 0 {
|
|
51
53
|
i -= 1;
|
|
52
54
|
if Self::is_blank_line(lines[i]) {
|
|
@@ -54,13 +56,36 @@ impl MD006StartBullets {
|
|
|
54
56
|
}
|
|
55
57
|
if let Some(prev_indent) = Self::is_bullet_list_item(lines[i]) {
|
|
56
58
|
if prev_indent <= current_indent {
|
|
57
|
-
|
|
59
|
+
// Found a potential parent or sibling
|
|
60
|
+
// Check if there's any non-list content between this potential parent and current item
|
|
61
|
+
let mut has_breaking_content = false;
|
|
62
|
+
for check_idx in (i + 1)..line_idx {
|
|
63
|
+
if Self::is_blank_line(lines[check_idx]) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if Self::is_bullet_list_item(lines[check_idx]).is_none() {
|
|
67
|
+
// Found non-list content - check if it breaks the list structure
|
|
68
|
+
let content_indent = lines[check_idx].len() - lines[check_idx].trim_start().len();
|
|
69
|
+
// Content is only acceptable if it's indented at least as much as current item
|
|
70
|
+
// AND we have a true parent relationship (prev_indent < current_indent)
|
|
71
|
+
if content_indent < current_indent || prev_indent >= current_indent {
|
|
72
|
+
has_breaking_content = true;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if !has_breaking_content {
|
|
79
|
+
return Some((i, prev_indent));
|
|
80
|
+
} else {
|
|
81
|
+
// Content breaks the list structure
|
|
82
|
+
return None;
|
|
83
|
+
}
|
|
58
84
|
}
|
|
59
85
|
// If prev_indent > current_indent, it's a child of a sibling, ignore it and keep searching.
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
break;
|
|
86
|
+
} else {
|
|
87
|
+
// Found non-list content - this breaks the search
|
|
88
|
+
return None;
|
|
64
89
|
}
|
|
65
90
|
}
|
|
66
91
|
None
|
|
@@ -156,36 +181,25 @@ impl Rule for MD006StartBullets {
|
|
|
156
181
|
doc_structure: &DocumentStructure,
|
|
157
182
|
) -> LintResult {
|
|
158
183
|
let content = _ctx.content;
|
|
159
|
-
|
|
160
|
-
// Early returns for performance
|
|
161
|
-
if content.is_empty() || doc_structure.list_lines.is_empty() {
|
|
184
|
+
if doc_structure.list_lines.is_empty() {
|
|
162
185
|
return Ok(Vec::new());
|
|
163
186
|
}
|
|
164
|
-
|
|
165
|
-
// Quick check for any list markers before processing
|
|
166
187
|
if !content.contains('*') && !content.contains('-') && !content.contains('+') {
|
|
167
188
|
return Ok(Vec::new());
|
|
168
189
|
}
|
|
169
|
-
|
|
170
|
-
// Pre-compute LineIndex once for all operations
|
|
171
190
|
let line_index = LineIndex::new(content.to_string());
|
|
172
191
|
let mut result = Vec::new();
|
|
173
192
|
let lines: Vec<&str> = content.lines().collect();
|
|
174
193
|
let mut valid_bullet_lines = vec![false; lines.len()];
|
|
175
|
-
|
|
176
|
-
// Process list lines in order for better cache locality
|
|
177
194
|
for &line_num in &doc_structure.list_lines {
|
|
178
195
|
let line_idx = line_num - 1;
|
|
179
196
|
if line_idx >= lines.len() {
|
|
180
197
|
continue;
|
|
181
198
|
}
|
|
182
199
|
let line = lines[line_idx];
|
|
183
|
-
|
|
184
|
-
// Skip lines in code blocks
|
|
185
200
|
if doc_structure.is_in_code_block(line_num) {
|
|
186
201
|
continue;
|
|
187
202
|
}
|
|
188
|
-
|
|
189
203
|
if let Some(indent) = Self::is_bullet_list_item(line) {
|
|
190
204
|
let mut is_valid = false; // Assume invalid initially
|
|
191
205
|
if indent == 0 {
|
|
@@ -220,19 +234,25 @@ impl Rule for MD006StartBullets {
|
|
|
220
234
|
} else {
|
|
221
235
|
fixed_line.to_string()
|
|
222
236
|
};
|
|
237
|
+
|
|
238
|
+
// Calculate the range to highlight: from first indentation character to end of list marker
|
|
239
|
+
let start_col = if indent > 0 { 2 } else { 1 }; // Start from first indentation space if indented
|
|
240
|
+
let marker_pos = line.find(|c: char| c == '*' || c == '-' || c == '+').unwrap_or(0);
|
|
241
|
+
let end_col = marker_pos + 3; // +1 for the marker itself, +1 for 1-based indexing, +1 for space after marker
|
|
242
|
+
|
|
223
243
|
result.push(LintWarning {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
244
|
+
rule_name: Some(self.name()),
|
|
245
|
+
severity: Severity::Warning,
|
|
246
|
+
line: line_num,
|
|
247
|
+
column: start_col,
|
|
248
|
+
end_line: line_num,
|
|
249
|
+
end_column: end_col,
|
|
250
|
+
message: "List item should start at the beginning of the line (remove indentation)"
|
|
251
|
+
.to_string(),
|
|
252
|
+
fix: Some(Fix {
|
|
253
|
+
range: line_index.line_col_to_byte_range(line_num, 1),
|
|
254
|
+
replacement,
|
|
255
|
+
}),
|
|
236
256
|
});
|
|
237
257
|
}
|
|
238
258
|
}
|
|
@@ -100,7 +100,7 @@ impl Rule for MD009TrailingSpaces {
|
|
|
100
100
|
column: start_col,
|
|
101
101
|
end_line,
|
|
102
102
|
end_column: end_col,
|
|
103
|
-
message: "Empty line
|
|
103
|
+
message: "Empty line has trailing spaces".to_string(),
|
|
104
104
|
severity: Severity::Warning,
|
|
105
105
|
fix: Some(Fix {
|
|
106
106
|
range: _line_index.line_col_to_byte_range(line_num + 1, 1),
|
|
@@ -134,7 +134,7 @@ impl Rule for MD009TrailingSpaces {
|
|
|
134
134
|
column: start_col,
|
|
135
135
|
end_line,
|
|
136
136
|
end_column: end_col,
|
|
137
|
-
message: "Empty blockquote line
|
|
137
|
+
message: "Empty blockquote line needs a space after >".to_string(),
|
|
138
138
|
severity: Severity::Warning,
|
|
139
139
|
fix: Some(Fix {
|
|
140
140
|
range: _line_index.line_col_to_byte_range(line_num + 1, trimmed.len() + 1),
|
|
@@ -146,3 +146,88 @@ impl Rule for MD011NoReversedLinks {
|
|
|
146
146
|
Box::new(MD011NoReversedLinks)
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
|
+
|
|
150
|
+
#[cfg(test)]
|
|
151
|
+
mod tests {
|
|
152
|
+
use super::*;
|
|
153
|
+
use crate::lint_context::LintContext;
|
|
154
|
+
|
|
155
|
+
#[test]
|
|
156
|
+
fn test_capture_group_order_fix() {
|
|
157
|
+
// This test confirms that the capture group order bug is fixed
|
|
158
|
+
// The regex pattern \(([^)]+)\)\[([^\]]+)\] captures:
|
|
159
|
+
// cap[1] = URL (inside parentheses)
|
|
160
|
+
// cap[2] = text (inside brackets)
|
|
161
|
+
// So (URL)[text] should become [text](URL)
|
|
162
|
+
|
|
163
|
+
let rule = MD011NoReversedLinks;
|
|
164
|
+
|
|
165
|
+
// Test with reversed link syntax
|
|
166
|
+
let content = "Check out (https://example.com)[this link] for more info.";
|
|
167
|
+
let ctx = LintContext::new(content);
|
|
168
|
+
|
|
169
|
+
// This should detect the reversed syntax
|
|
170
|
+
let result = rule.check(&ctx).unwrap();
|
|
171
|
+
assert_eq!(result.len(), 1);
|
|
172
|
+
assert!(result[0].message.contains("Reversed link syntax"));
|
|
173
|
+
|
|
174
|
+
// Verify the fix produces correct output
|
|
175
|
+
let fix = result[0].fix.as_ref().unwrap();
|
|
176
|
+
assert_eq!(fix.replacement, "[this link](https://example.com)");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
#[test]
|
|
180
|
+
fn test_multiple_reversed_links() {
|
|
181
|
+
// Test multiple reversed links in the same content
|
|
182
|
+
let rule = MD011NoReversedLinks;
|
|
183
|
+
|
|
184
|
+
let content = "Visit (https://example.com)[Example] and (https://test.com)[Test Site].";
|
|
185
|
+
let ctx = LintContext::new(content);
|
|
186
|
+
|
|
187
|
+
let result = rule.check(&ctx).unwrap();
|
|
188
|
+
assert_eq!(result.len(), 2);
|
|
189
|
+
|
|
190
|
+
// Verify both fixes are correct
|
|
191
|
+
assert_eq!(result[0].fix.as_ref().unwrap().replacement, "[Example](https://example.com)");
|
|
192
|
+
assert_eq!(result[1].fix.as_ref().unwrap().replacement, "[Test Site](https://test.com)");
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
#[test]
|
|
196
|
+
fn test_normal_links_not_flagged() {
|
|
197
|
+
// Test that normal link syntax is not flagged
|
|
198
|
+
let rule = MD011NoReversedLinks;
|
|
199
|
+
|
|
200
|
+
let content = "This is a normal [link](https://example.com) and another [link](https://test.com).";
|
|
201
|
+
let ctx = LintContext::new(content);
|
|
202
|
+
|
|
203
|
+
let result = rule.check(&ctx).unwrap();
|
|
204
|
+
assert_eq!(result.len(), 0);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
#[test]
|
|
208
|
+
fn debug_capture_groups() {
|
|
209
|
+
// Debug test to understand capture group behavior
|
|
210
|
+
let pattern = r"\(([^)]+)\)\[([^\]]+)\]";
|
|
211
|
+
let regex = Regex::new(pattern).unwrap();
|
|
212
|
+
|
|
213
|
+
let test_text = "(https://example.com)[Click here]";
|
|
214
|
+
|
|
215
|
+
if let Some(cap) = regex.captures(test_text) {
|
|
216
|
+
println!("Full match: {}", &cap[0]);
|
|
217
|
+
println!("cap[1] (first group): {}", &cap[1]);
|
|
218
|
+
println!("cap[2] (second group): {}", &cap[2]);
|
|
219
|
+
|
|
220
|
+
// Current fix format
|
|
221
|
+
let current_fix = format!("[{}]({})", &cap[2], &cap[1]);
|
|
222
|
+
println!("Current fix produces: {}", current_fix);
|
|
223
|
+
|
|
224
|
+
// Test what the actual rule produces
|
|
225
|
+
let rule = MD011NoReversedLinks;
|
|
226
|
+
let ctx = LintContext::new(test_text);
|
|
227
|
+
let result = rule.check(&ctx).unwrap();
|
|
228
|
+
if !result.is_empty() {
|
|
229
|
+
println!("Rule fix produces: {}", result[0].fix.as_ref().unwrap().replacement);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
@@ -70,9 +70,7 @@ impl MD014CommandsShowOutput {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
let mut has_command = false;
|
|
73
|
-
|
|
74
73
|
let mut has_output = false;
|
|
75
|
-
|
|
76
74
|
let mut last_command = String::new();
|
|
77
75
|
|
|
78
76
|
for line in block {
|
|
@@ -88,6 +86,16 @@ impl MD014CommandsShowOutput {
|
|
|
88
86
|
has_command && !has_output && !self.is_no_output_command(&last_command)
|
|
89
87
|
}
|
|
90
88
|
|
|
89
|
+
fn get_command_from_block(&self, block: &[&str]) -> String {
|
|
90
|
+
for line in block {
|
|
91
|
+
let trimmed = line.trim();
|
|
92
|
+
if self.is_command_line(line) {
|
|
93
|
+
return trimmed[1..].trim().to_string();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
String::new()
|
|
97
|
+
}
|
|
98
|
+
|
|
91
99
|
fn fix_command_block(&self, block: &[&str]) -> String {
|
|
92
100
|
block
|
|
93
101
|
.iter()
|
|
@@ -175,14 +183,21 @@ impl Rule for MD014CommandsShowOutput {
|
|
|
175
183
|
match_obj.len(),
|
|
176
184
|
);
|
|
177
185
|
|
|
186
|
+
// Get the command for a more helpful message
|
|
187
|
+
let command = self.get_command_from_block(¤t_block);
|
|
188
|
+
let message = if command.is_empty() {
|
|
189
|
+
"Command should show output (add example output or remove $ prompt)".to_string()
|
|
190
|
+
} else {
|
|
191
|
+
format!("Command '{}' should show output (add example output or remove $ prompt)", command)
|
|
192
|
+
};
|
|
193
|
+
|
|
178
194
|
warnings.push(LintWarning {
|
|
179
195
|
rule_name: Some(self.name()),
|
|
180
196
|
line: start_line,
|
|
181
197
|
column: start_col,
|
|
182
198
|
end_line,
|
|
183
199
|
end_column: end_col,
|
|
184
|
-
message
|
|
185
|
-
.to_string(),
|
|
200
|
+
message,
|
|
186
201
|
severity: Severity::Warning,
|
|
187
202
|
fix: Some(Fix {
|
|
188
203
|
range: _line_index
|
|
@@ -582,7 +582,7 @@ impl Rule for MD022BlanksAroundHeadings {
|
|
|
582
582
|
} else {
|
|
583
583
|
"lines"
|
|
584
584
|
};
|
|
585
|
-
issues.push(format!("
|
|
585
|
+
issues.push(format!("Expected {} blank {} between headings", required_blanks, line_word));
|
|
586
586
|
}
|
|
587
587
|
}
|
|
588
588
|
|
|
@@ -604,7 +604,7 @@ impl Rule for MD022BlanksAroundHeadings {
|
|
|
604
604
|
"lines"
|
|
605
605
|
};
|
|
606
606
|
issues.push(format!(
|
|
607
|
-
"
|
|
607
|
+
"Expected {} blank {} above heading",
|
|
608
608
|
self.lines_above, line_word
|
|
609
609
|
));
|
|
610
610
|
}
|
|
@@ -663,7 +663,7 @@ impl Rule for MD022BlanksAroundHeadings {
|
|
|
663
663
|
"lines"
|
|
664
664
|
};
|
|
665
665
|
issues.push(format!(
|
|
666
|
-
"
|
|
666
|
+
"Expected {} blank {} below heading",
|
|
667
667
|
self.lines_below, line_word
|
|
668
668
|
));
|
|
669
669
|
}
|
|
@@ -784,7 +784,7 @@ impl Rule for MD022BlanksAroundHeadings {
|
|
|
784
784
|
} else {
|
|
785
785
|
"lines"
|
|
786
786
|
};
|
|
787
|
-
issues.push(format!("
|
|
787
|
+
issues.push(format!("Expected {} blank {} between headings", required_blanks, line_word));
|
|
788
788
|
}
|
|
789
789
|
}
|
|
790
790
|
|
|
@@ -806,7 +806,7 @@ impl Rule for MD022BlanksAroundHeadings {
|
|
|
806
806
|
"lines"
|
|
807
807
|
};
|
|
808
808
|
issues.push(format!(
|
|
809
|
-
"
|
|
809
|
+
"Expected {} blank {} above heading",
|
|
810
810
|
self.lines_above, line_word
|
|
811
811
|
));
|
|
812
812
|
}
|
|
@@ -865,7 +865,7 @@ impl Rule for MD022BlanksAroundHeadings {
|
|
|
865
865
|
"lines"
|
|
866
866
|
};
|
|
867
867
|
issues.push(format!(
|
|
868
|
-
"
|
|
868
|
+
"Expected {} blank {} below heading",
|
|
869
869
|
self.lines_below, line_word
|
|
870
870
|
));
|
|
871
871
|
}
|
|
@@ -253,7 +253,13 @@ impl Rule for MD025SingleTitle {
|
|
|
253
253
|
"{} {}",
|
|
254
254
|
"#".repeat(self.level + 1),
|
|
255
255
|
if line_content.trim_start().starts_with('#') {
|
|
256
|
-
|
|
256
|
+
// Add bounds checking to prevent panic
|
|
257
|
+
let slice_start = col + self.level;
|
|
258
|
+
if slice_start < line_content.len() {
|
|
259
|
+
&line_content[slice_start..]
|
|
260
|
+
} else {
|
|
261
|
+
"" // If bounds exceeded, use empty string
|
|
262
|
+
}
|
|
257
263
|
} else {
|
|
258
264
|
line_content.trim() // For Setext, use the whole line
|
|
259
265
|
}
|
|
@@ -357,4 +363,55 @@ mod tests {
|
|
|
357
363
|
"Should not flag a single title after front matter"
|
|
358
364
|
);
|
|
359
365
|
}
|
|
366
|
+
|
|
367
|
+
#[test]
|
|
368
|
+
fn test_bounds_checking_bug() {
|
|
369
|
+
// Test case that could trigger bounds error in fix generation
|
|
370
|
+
// When col + self.level exceeds line_content.len()
|
|
371
|
+
let rule = MD025SingleTitle::default();
|
|
372
|
+
|
|
373
|
+
// Create content with very short second heading
|
|
374
|
+
let content = "# First\n#";
|
|
375
|
+
let ctx = crate::lint_context::LintContext::new(content);
|
|
376
|
+
|
|
377
|
+
// This should not panic
|
|
378
|
+
let result = rule.check(&ctx);
|
|
379
|
+
assert!(result.is_ok());
|
|
380
|
+
|
|
381
|
+
// Test the fix as well
|
|
382
|
+
let fix_result = rule.fix(&ctx);
|
|
383
|
+
assert!(fix_result.is_ok());
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
#[test]
|
|
387
|
+
fn test_bounds_checking_edge_case() {
|
|
388
|
+
// Test case that specifically targets the bounds checking fix
|
|
389
|
+
// Create a heading where col + self.level would exceed line length
|
|
390
|
+
let rule = MD025SingleTitle::default();
|
|
391
|
+
|
|
392
|
+
// Create content where the second heading is just "#" (length 1)
|
|
393
|
+
// col will be 0, self.level is 1, so col + self.level = 1
|
|
394
|
+
// This should not exceed bounds for "#" but tests the edge case
|
|
395
|
+
let content = "# First Title\n#";
|
|
396
|
+
let ctx = crate::lint_context::LintContext::new(content);
|
|
397
|
+
|
|
398
|
+
// This should not panic and should handle the edge case gracefully
|
|
399
|
+
let result = rule.check(&ctx);
|
|
400
|
+
assert!(result.is_ok());
|
|
401
|
+
|
|
402
|
+
if let Ok(warnings) = result {
|
|
403
|
+
if !warnings.is_empty() {
|
|
404
|
+
// Check that the fix doesn't cause a panic
|
|
405
|
+
let fix_result = rule.fix(&ctx);
|
|
406
|
+
assert!(fix_result.is_ok());
|
|
407
|
+
|
|
408
|
+
// The fix should produce valid content
|
|
409
|
+
if let Ok(fixed_content) = fix_result {
|
|
410
|
+
assert!(!fixed_content.is_empty());
|
|
411
|
+
// Should convert the second "#" to "##" (or "## " if there's content)
|
|
412
|
+
assert!(fixed_content.contains("##"));
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
360
417
|
}
|
|
@@ -292,7 +292,7 @@ impl MD026NoTrailingPunctuation {
|
|
|
292
292
|
end_line,
|
|
293
293
|
end_column: end_col,
|
|
294
294
|
message: format!(
|
|
295
|
-
"Heading '{}'
|
|
295
|
+
"Heading '{}' ends with punctuation '{}'",
|
|
296
296
|
heading_text.trim(),
|
|
297
297
|
last_char
|
|
298
298
|
),
|
|
@@ -337,7 +337,7 @@ impl MD026NoTrailingPunctuation {
|
|
|
337
337
|
end_column: end_col,
|
|
338
338
|
message: format!(
|
|
339
339
|
"Heading '{
|
|
340
|
-
}'
|
|
340
|
+
}' ends with punctuation '{}'",
|
|
341
341
|
lines[heading_line - 1].trim(),
|
|
342
342
|
last_char
|
|
343
343
|
),
|
|
@@ -73,7 +73,7 @@ impl Rule for MD028NoBlanksBlockquote {
|
|
|
73
73
|
|
|
74
74
|
warnings.push(LintWarning {
|
|
75
75
|
rule_name: Some(self.name()),
|
|
76
|
-
message: "
|
|
76
|
+
message: "Empty blockquote line should contain '>' marker".to_string(),
|
|
77
77
|
line: start_line,
|
|
78
78
|
column: start_col,
|
|
79
79
|
end_line,
|
|
@@ -307,9 +307,8 @@ impl MD029OrderedListPrefix {
|
|
|
307
307
|
|
|
308
308
|
// Check each item in the group for correct sequence
|
|
309
309
|
for (idx, (line_num, line)) in group.iter().enumerate() {
|
|
310
|
-
if Self::get_list_number(line)
|
|
310
|
+
if let Some(actual_num) = Self::get_list_number(line) {
|
|
311
311
|
let expected_num = self.get_expected_number(idx);
|
|
312
|
-
let actual_num = Self::get_list_number(line).unwrap();
|
|
313
312
|
|
|
314
313
|
if actual_num != expected_num {
|
|
315
314
|
warnings.push(LintWarning {
|
|
@@ -378,4 +377,49 @@ mod tests {
|
|
|
378
377
|
let result = rule.check_with_structure(&ctx, &structure).unwrap();
|
|
379
378
|
assert!(result.is_empty());
|
|
380
379
|
}
|
|
380
|
+
|
|
381
|
+
#[test]
|
|
382
|
+
fn test_redundant_computation_fix() {
|
|
383
|
+
// This test confirms that the redundant computation bug is fixed
|
|
384
|
+
// Previously: get_list_number() was called twice (once for is_some(), once for unwrap())
|
|
385
|
+
// Now: get_list_number() is called once with if let pattern
|
|
386
|
+
|
|
387
|
+
let rule = MD029OrderedListPrefix::default();
|
|
388
|
+
|
|
389
|
+
// Test with mixed valid and edge case content
|
|
390
|
+
let content = "1. First item\n3. Wrong number\n2. Another wrong number";
|
|
391
|
+
let structure = DocumentStructure::new(content);
|
|
392
|
+
let ctx = crate::lint_context::LintContext::new(content);
|
|
393
|
+
|
|
394
|
+
// This should not panic and should produce warnings for incorrect numbering
|
|
395
|
+
let result = rule.check_with_structure(&ctx, &structure).unwrap();
|
|
396
|
+
assert_eq!(result.len(), 2); // Should have warnings for items 3 and 2
|
|
397
|
+
|
|
398
|
+
// Verify the warnings have correct content
|
|
399
|
+
assert!(result[0].message.contains("3 does not match style (expected 2)"));
|
|
400
|
+
assert!(result[1].message.contains("2 does not match style (expected 3)"));
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
#[test]
|
|
404
|
+
fn test_performance_improvement() {
|
|
405
|
+
// This test verifies that the fix improves performance by avoiding redundant calls
|
|
406
|
+
let rule = MD029OrderedListPrefix::default();
|
|
407
|
+
|
|
408
|
+
// Create a larger list to test performance
|
|
409
|
+
let mut content = String::new();
|
|
410
|
+
for i in 1..=100 {
|
|
411
|
+
content.push_str(&format!("{}. Item {}\n", i + 1, i)); // All wrong numbers
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
let structure = DocumentStructure::new(&content);
|
|
415
|
+
let ctx = crate::lint_context::LintContext::new(&content);
|
|
416
|
+
|
|
417
|
+
// This should complete without issues and produce warnings for all items
|
|
418
|
+
let result = rule.check_with_structure(&ctx, &structure).unwrap();
|
|
419
|
+
assert_eq!(result.len(), 100); // Should have warnings for all 100 items
|
|
420
|
+
|
|
421
|
+
// Verify first and last warnings
|
|
422
|
+
assert!(result[0].message.contains("2 does not match style (expected 1)"));
|
|
423
|
+
assert!(result[99].message.contains("101 does not match style (expected 100)"));
|
|
424
|
+
}
|
|
381
425
|
}
|
|
@@ -149,7 +149,11 @@ impl Rule for MD030ListMarkerSpace {
|
|
|
149
149
|
column: start_col,
|
|
150
150
|
end_line,
|
|
151
151
|
end_column: end_col,
|
|
152
|
-
message:
|
|
152
|
+
message: format!(
|
|
153
|
+
"Spaces after list markers (Expected: {}; Actual: {})",
|
|
154
|
+
expected_spaces,
|
|
155
|
+
whitespace.len()
|
|
156
|
+
),
|
|
153
157
|
fix,
|
|
154
158
|
});
|
|
155
159
|
}
|
|
@@ -420,7 +424,11 @@ mod tests {
|
|
|
420
424
|
"Should flag lines with too many spaces after list marker"
|
|
421
425
|
);
|
|
422
426
|
for warning in result {
|
|
423
|
-
|
|
427
|
+
assert!(
|
|
428
|
+
warning.message.starts_with("Spaces after list markers (Expected:") && warning.message.contains("Actual:"),
|
|
429
|
+
"Warning message should include expected and actual values, got: '{}'",
|
|
430
|
+
warning.message
|
|
431
|
+
);
|
|
424
432
|
}
|
|
425
433
|
}
|
|
426
434
|
}
|