rumdl 0.0.71__tar.gz → 0.0.73__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.71 → rumdl-0.0.73}/Cargo.lock +1 -1
- {rumdl-0.0.71 → rumdl-0.0.73}/Cargo.toml +1 -1
- {rumdl-0.0.71 → rumdl-0.0.73}/PKG-INFO +1 -1
- {rumdl-0.0.71 → rumdl-0.0.73}/src/lib.rs +1 -1
- {rumdl-0.0.71 → rumdl-0.0.73}/src/main.rs +7 -10
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md001_heading_increment.rs +1 -1
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md006_start_bullets.rs +19 -8
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md009_trailing_spaces.rs +2 -2
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md011_no_reversed_links.rs +85 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md014_commands_show_output.rs +19 -4
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md022_blanks_around_headings.rs +6 -6
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md025_single_title.rs +58 -1
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md026_no_trailing_punctuation.rs +2 -2
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md028_no_blanks_blockquote.rs +1 -1
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md029_ordered_list_prefix.rs +46 -2
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md032_blanks_around_lists.rs +9 -9
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md033_no_inline_html.rs +20 -26
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md034_no_bare_urls.rs +90 -95
- rumdl-0.0.73/src/rules/md037_spaces_around_emphasis.rs +620 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md039_no_space_in_links.rs +1 -1
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md040_fenced_code_language.rs +3 -2
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md045_no_alt_text.rs +1 -1
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md046_code_block_style.rs +4 -4
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md048_code_fence_style.rs +2 -2
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md055_table_pipe_style.rs +24 -1
- {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/regex_cache.rs +6 -4
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/output_format_tests.rs +2 -2
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md001_test.rs +1 -1
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md001_unicode_test.rs +1 -1
- rumdl-0.0.73/tests/rules/md006_test.rs +243 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md009_test.rs +1 -4
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md032_test.rs +3 -5
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md034_test.rs +72 -5
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md037_test.rs +205 -12
- rumdl-0.0.71/src/rules/md037_spaces_around_emphasis.rs +0 -595
- rumdl-0.0.71/tests/rules/md006_test.rs +0 -143
- {rumdl-0.0.71 → rumdl-0.0.73}/.rumdl.toml +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/MANIFEST.in +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/Makefile +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/README.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/assets/logo.png +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/benches/fix_performance.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/benches/range_performance.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/benches/range_utils_benchmark.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/benches/rule_performance.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/benches/simple_fix_bench.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/RULES.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md001.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md002.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md003.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md004.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md005.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md006.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md007.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md009.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md010.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md011.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md012.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md013.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md014.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md018.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md019.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md020.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md021.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md022.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md023.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md024.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md025.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md026.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md027.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md028.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md029.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md030.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md031.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md032.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md033.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md034.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md035.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md036.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md037.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md038.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md039.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md040.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md041.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md042.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md043.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md044.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md045.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md046.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md047.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md048.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md049.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md050.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md051.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md052.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md053.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md054.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md055.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md056.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md057.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/docs/md058.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/issues/plan-rule-parity-with-markdownlint.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/parity_check.py +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/pyproject.toml +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/python/MANIFEST.in +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/python/PYTHON-README.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/python/rumdl/__init__.py +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/python/rumdl/__main__.py +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/python/rumdl/py.typed +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/rumdl.toml.example +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/config.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/init.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/lint_context.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/lsp/mod.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/lsp/server.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/lsp/types.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/markdownlint_config.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/parallel.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/performance.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/profiling.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/python.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rule.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/blockquote_utils.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/code_block_utils.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/code_fence_utils.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/emphasis_style.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/front_matter_utils.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/heading_utils.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/list_utils.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md002_first_heading_h1.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md003_heading_style.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md004_unordered_list_style.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md005_list_indent.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md007_ul_indent.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md010_no_hard_tabs.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md012_no_multiple_blanks.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md013_line_length.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md018_no_missing_space_atx.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md019_no_multiple_space_atx.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md020_no_missing_space_closed_atx.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md023_heading_start_left.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md024_no_duplicate_heading.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md027_multiple_spaces_blockquote.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md030_list_marker_space.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md031_blanks_around_fences.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md035_hr_style.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md036_no_emphasis_only_first.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md038_no_space_in_code.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md041_first_line_heading.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md042_no_empty_links.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md043_required_headings.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md044_proper_names.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md047_single_trailing_newline.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md049_emphasis_style.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md050_strong_style.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md051_link_fragments.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md052_reference_links_images.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md053_link_image_reference_definitions.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md054_link_image_style.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md056_table_column_count.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md057_existing_relative_links.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/md058_blanks_around_tables.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/mod.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/rules/strong_style.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/ast_utils.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/code_block_utils.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/document_structure.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/early_returns.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/element_cache.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/markdown_elements.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/mod.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/range_utils.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/string_interner.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/src/utils/table_utils.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/advanced_integration_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/character_ranges/additional_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/character_ranges/basic_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/character_ranges/comprehensive_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/character_ranges/extended_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/character_ranges/mod.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/character_ranges/unicode_utils.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/cli_duplication_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/cli_integration_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/commonmark_compliance_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/comprehensive_integration_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/config_application_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/config_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/init_command_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/init_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/integration_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/json_output_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/lib.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/lsp_integration_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/lsp_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/markdownlint_cli_integration.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/markdownlint_config_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/md030_edge_cases.md +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/perf_check.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/pyproject_config_tests.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md002_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md003_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md004_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md005_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md006_unicode_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md007_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md010_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md011_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md012_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md013_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md014_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md018_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md019_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md020_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md021_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md022_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md023_extended_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md023_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md024_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md025_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md026_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md027_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md028_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md029_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md030_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md031_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md033_extended_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md033_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md035_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md036_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md038_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md039_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md040_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md041_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md042_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md043_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md044_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md045_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md046_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md047_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md048_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md049_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md050_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md051_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md052_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md053_additional_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md053_proptest.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md053_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md054_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md054_unicode_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md055_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md056_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md057_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/md058_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/rules/mod.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/blockquote_utils_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/code_block_utils_extended_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/code_block_utils_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/core_utils_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/front_matter_utils_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/line_index_test.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils/mod.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/tests/utils_markdown_edge_cases.rs +0 -0
- {rumdl-0.0.71 → rumdl-0.0.73}/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("![") {
|
|
@@ -1297,16 +1297,13 @@ fn process_stdin(rules: &[Box<dyn Rule>], args: &CheckArgs) {
|
|
|
1297
1297
|
let has_issues = !all_warnings.is_empty();
|
|
1298
1298
|
if has_issues {
|
|
1299
1299
|
for warning in &all_warnings {
|
|
1300
|
+
let rule_name = warning.rule_name.unwrap_or("unknown");
|
|
1300
1301
|
println!(
|
|
1301
|
-
"<stdin>:{}:{}: {}
|
|
1302
|
-
warning.line,
|
|
1303
|
-
warning.column,
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
rumdl::rule::Severity::Warning => "warning".yellow(),
|
|
1307
|
-
},
|
|
1308
|
-
warning.message,
|
|
1309
|
-
warning.rule_name.unwrap_or("unknown")
|
|
1302
|
+
"<stdin>:{}:{}: {} {}",
|
|
1303
|
+
warning.line.to_string().cyan(),
|
|
1304
|
+
warning.column.to_string().cyan(),
|
|
1305
|
+
format!("[{:5}]", rule_name).yellow(), // Align rule names consistently
|
|
1306
|
+
warning.message
|
|
1310
1307
|
);
|
|
1311
1308
|
}
|
|
1312
1309
|
}
|
|
@@ -1611,7 +1608,7 @@ fn process_file(
|
|
|
1611
1608
|
file_path.blue().underline(),
|
|
1612
1609
|
warning.line.to_string().cyan(),
|
|
1613
1610
|
warning.column.to_string().cyan(),
|
|
1614
|
-
format!("[{}]", rule_name).yellow(),
|
|
1611
|
+
format!("[{:5}]", rule_name).yellow(), // Pad rule name to 5 characters for alignment
|
|
1615
1612
|
warning.message,
|
|
1616
1613
|
fix_indicator.green()
|
|
1617
1614
|
);
|
|
@@ -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),
|
|
@@ -66,9 +66,15 @@ impl MD006StartBullets {
|
|
|
66
66
|
if Self::is_bullet_list_item(lines[check_idx]).is_none() {
|
|
67
67
|
// Found non-list content - check if it breaks the list structure
|
|
68
68
|
let content_indent = lines[check_idx].len() - lines[check_idx].trim_start().len();
|
|
69
|
-
|
|
70
|
-
//
|
|
71
|
-
|
|
69
|
+
|
|
70
|
+
// Content is acceptable if:
|
|
71
|
+
// 1. It's indented at least as much as the current item (continuation of parent)
|
|
72
|
+
// 2. OR it's indented more than the previous bullet (continuation of previous item)
|
|
73
|
+
// 3. AND we have a true parent relationship (prev_indent < current_indent)
|
|
74
|
+
let is_continuation = content_indent >= prev_indent.max(2); // At least 2 spaces for continuation
|
|
75
|
+
let is_valid_nesting = prev_indent < current_indent;
|
|
76
|
+
|
|
77
|
+
if !is_continuation || !is_valid_nesting {
|
|
72
78
|
has_breaking_content = true;
|
|
73
79
|
break;
|
|
74
80
|
}
|
|
@@ -78,13 +84,19 @@ impl MD006StartBullets {
|
|
|
78
84
|
if !has_breaking_content {
|
|
79
85
|
return Some((i, prev_indent));
|
|
80
86
|
} else {
|
|
81
|
-
// Content breaks the list structure
|
|
82
|
-
|
|
87
|
+
// Content breaks the list structure, but continue searching for an earlier valid parent
|
|
88
|
+
continue;
|
|
83
89
|
}
|
|
84
90
|
}
|
|
85
91
|
// If prev_indent > current_indent, it's a child of a sibling, ignore it and keep searching.
|
|
86
92
|
} else {
|
|
87
|
-
// Found non-list content -
|
|
93
|
+
// Found non-list content - check if it's a continuation line
|
|
94
|
+
let content_indent = lines[i].len() - lines[i].trim_start().len();
|
|
95
|
+
// If it's indented enough to be a continuation, don't break the search
|
|
96
|
+
if content_indent >= 2 {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
// Otherwise, this breaks the search
|
|
88
100
|
return None;
|
|
89
101
|
}
|
|
90
102
|
}
|
|
@@ -247,8 +259,7 @@ impl Rule for MD006StartBullets {
|
|
|
247
259
|
column: start_col,
|
|
248
260
|
end_line: line_num,
|
|
249
261
|
end_column: end_col,
|
|
250
|
-
message: "List item
|
|
251
|
-
.to_string(),
|
|
262
|
+
message: "List item indentation".to_string(),
|
|
252
263
|
fix: Some(Fix {
|
|
253
264
|
range: line_index.line_col_to_byte_range(line_num, 1),
|
|
254
265
|
replacement,
|
|
@@ -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
|
}
|
|
@@ -254,7 +254,7 @@ impl MD032BlanksAroundLists {
|
|
|
254
254
|
end_column: end_col,
|
|
255
255
|
severity: Severity::Error,
|
|
256
256
|
rule_name: Some(self.name()),
|
|
257
|
-
message: "
|
|
257
|
+
message: "List should be preceded by blank line".to_string(),
|
|
258
258
|
fix: Some(Fix {
|
|
259
259
|
range: line_index.line_col_to_byte_range(start_line, 1),
|
|
260
260
|
replacement: format!("{}\n{}", prefix, lines[start_line - 1]),
|
|
@@ -288,7 +288,7 @@ impl MD032BlanksAroundLists {
|
|
|
288
288
|
end_column: end_col_last,
|
|
289
289
|
severity: Severity::Error,
|
|
290
290
|
rule_name: Some(self.name()),
|
|
291
|
-
message: "
|
|
291
|
+
message: "List should be followed by blank line".to_string(),
|
|
292
292
|
fix: Some(Fix {
|
|
293
293
|
range: line_index.line_col_to_byte_range(end_line + 1, 1),
|
|
294
294
|
replacement: format!("{}\n{}", prefix, lines[end_line]),
|
|
@@ -577,7 +577,7 @@ mod tests {
|
|
|
577
577
|
warnings[0].line, 2,
|
|
578
578
|
"Warning should be on the last line of the list (line 2)"
|
|
579
579
|
);
|
|
580
|
-
assert!(warnings[0].message.contains("followed by
|
|
580
|
+
assert!(warnings[0].message.contains("followed by blank line"));
|
|
581
581
|
|
|
582
582
|
// Test that warning has fix
|
|
583
583
|
check_warnings_have_fixes(content);
|
|
@@ -607,7 +607,7 @@ mod tests {
|
|
|
607
607
|
warnings[0].line, 2,
|
|
608
608
|
"Warning should be on the first line of the list (line 2)"
|
|
609
609
|
);
|
|
610
|
-
assert!(warnings[0].message.contains("preceded by
|
|
610
|
+
assert!(warnings[0].message.contains("preceded by blank line"));
|
|
611
611
|
|
|
612
612
|
// Test that warning has fix
|
|
613
613
|
check_warnings_have_fixes(content);
|
|
@@ -634,9 +634,9 @@ mod tests {
|
|
|
634
634
|
"Expected 2 warnings for list in middle without surrounding blank lines"
|
|
635
635
|
);
|
|
636
636
|
assert_eq!(warnings[0].line, 2, "First warning on line 2 (start)");
|
|
637
|
-
assert!(warnings[0].message.contains("preceded by
|
|
637
|
+
assert!(warnings[0].message.contains("preceded by blank line"));
|
|
638
638
|
assert_eq!(warnings[1].line, 3, "Second warning on line 3 (end)");
|
|
639
|
-
assert!(warnings[1].message.contains("followed by
|
|
639
|
+
assert!(warnings[1].message.contains("followed by blank line"));
|
|
640
640
|
|
|
641
641
|
// Test that warnings have fixes
|
|
642
642
|
check_warnings_have_fixes(content);
|
|
@@ -682,9 +682,9 @@ mod tests {
|
|
|
682
682
|
);
|
|
683
683
|
if warnings.len() == 2 {
|
|
684
684
|
assert_eq!(warnings[0].line, 2, "Warning 1 should be on line 2 (start)");
|
|
685
|
-
assert!(warnings[0].message.contains("preceded by
|
|
685
|
+
assert!(warnings[0].message.contains("preceded by blank line"));
|
|
686
686
|
assert_eq!(warnings[1].line, 5, "Warning 2 should be on line 5 (end)");
|
|
687
|
-
assert!(warnings[1].message.contains("followed by
|
|
687
|
+
assert!(warnings[1].message.contains("followed by blank line"));
|
|
688
688
|
}
|
|
689
689
|
|
|
690
690
|
// Test that warnings have fixes
|
|
@@ -794,7 +794,7 @@ mod tests {
|
|
|
794
794
|
);
|
|
795
795
|
if !warnings.is_empty() {
|
|
796
796
|
assert_eq!(warnings[0].line, 4); // Warning on last line of list
|
|
797
|
-
assert!(warnings[0].message.contains("followed by
|
|
797
|
+
assert!(warnings[0].message.contains("followed by blank line"));
|
|
798
798
|
}
|
|
799
799
|
|
|
800
800
|
// Test that warnings have fixes
|