rumdl 0.0.72__tar.gz → 0.0.74__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.72 → rumdl-0.0.74}/Cargo.lock +1 -1
- {rumdl-0.0.72 → rumdl-0.0.74}/Cargo.toml +1 -1
- {rumdl-0.0.72 → rumdl-0.0.74}/PKG-INFO +1 -1
- {rumdl-0.0.72 → rumdl-0.0.74}/src/main.rs +7 -10
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md006_start_bullets.rs +19 -8
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md032_blanks_around_lists.rs +36 -2
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md034_no_bare_urls.rs +81 -92
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md042_no_empty_links.rs +7 -49
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md051_link_fragments.rs +74 -51
- {rumdl-0.0.72 → rumdl-0.0.74}/src/utils/document_structure.rs +70 -68
- rumdl-0.0.74/tests/rules/md006_test.rs +243 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md033_test.rs +321 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md034_test.rs +69 -2
- rumdl-0.0.74/tests/rules/md042_test.rs +291 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md051_test.rs +128 -0
- rumdl-0.0.72/tests/rules/md006_test.rs +0 -143
- rumdl-0.0.72/tests/rules/md042_test.rs +0 -84
- {rumdl-0.0.72 → rumdl-0.0.74}/.rumdl.toml +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/MANIFEST.in +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/Makefile +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/README.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/assets/logo.png +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/benches/fix_performance.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/benches/range_performance.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/benches/range_utils_benchmark.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/benches/rule_performance.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/benches/simple_fix_bench.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/RULES.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md001.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md002.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md003.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md004.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md005.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md006.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md007.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md009.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md010.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md011.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md012.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md013.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md014.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md018.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md019.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md020.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md021.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md022.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md023.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md024.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md025.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md026.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md027.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md028.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md029.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md030.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md031.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md032.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md033.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md034.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md035.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md036.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md037.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md038.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md039.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md040.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md041.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md042.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md043.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md044.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md045.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md046.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md047.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md048.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md049.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md050.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md051.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md052.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md053.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md054.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md055.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md056.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md057.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/docs/md058.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/issues/plan-rule-parity-with-markdownlint.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/parity_check.py +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/pyproject.toml +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/python/MANIFEST.in +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/python/PYTHON-README.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/python/rumdl/__init__.py +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/python/rumdl/__main__.py +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/python/rumdl/py.typed +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/rumdl.toml.example +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/config.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/init.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/lib.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/lint_context.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/lsp/mod.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/lsp/server.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/lsp/types.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/markdownlint_config.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/parallel.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/performance.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/profiling.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/python.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rule.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/blockquote_utils.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/code_block_utils.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/code_fence_utils.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/emphasis_style.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/front_matter_utils.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/heading_utils.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/list_utils.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md001_heading_increment.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md002_first_heading_h1.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md003_heading_style.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md004_unordered_list_style.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md005_list_indent.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md007_ul_indent.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md009_trailing_spaces.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md010_no_hard_tabs.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md011_no_reversed_links.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md012_no_multiple_blanks.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md013_line_length.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md014_commands_show_output.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md018_no_missing_space_atx.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md019_no_multiple_space_atx.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md020_no_missing_space_closed_atx.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md022_blanks_around_headings.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md023_heading_start_left.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md024_no_duplicate_heading.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md025_single_title.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md026_no_trailing_punctuation.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md027_multiple_spaces_blockquote.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md028_no_blanks_blockquote.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md029_ordered_list_prefix.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md030_list_marker_space.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md031_blanks_around_fences.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md033_no_inline_html.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md035_hr_style.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md036_no_emphasis_only_first.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md037_spaces_around_emphasis.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md038_no_space_in_code.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md039_no_space_in_links.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md040_fenced_code_language.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md041_first_line_heading.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md043_required_headings.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md044_proper_names.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md045_no_alt_text.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md046_code_block_style.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md047_single_trailing_newline.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md048_code_fence_style.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md049_emphasis_style.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md050_strong_style.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md052_reference_links_images.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md053_link_image_reference_definitions.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md054_link_image_style.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md055_table_pipe_style.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md056_table_column_count.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md057_existing_relative_links.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/md058_blanks_around_tables.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/mod.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/rules/strong_style.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/utils/ast_utils.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/utils/code_block_utils.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/utils/early_returns.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/utils/element_cache.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/utils/markdown_elements.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/utils/mod.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/utils/range_utils.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/utils/regex_cache.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/utils/string_interner.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/src/utils/table_utils.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/advanced_integration_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/character_ranges/additional_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/character_ranges/basic_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/character_ranges/comprehensive_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/character_ranges/extended_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/character_ranges/mod.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/character_ranges/unicode_utils.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/cli_duplication_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/cli_integration_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/commonmark_compliance_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/comprehensive_integration_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/config_application_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/config_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/init_command_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/init_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/integration_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/json_output_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/lib.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/lsp_integration_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/lsp_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/markdownlint_cli_integration.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/markdownlint_config_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/md030_edge_cases.md +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/output_format_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/perf_check.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/pyproject_config_tests.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md001_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md001_unicode_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md002_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md003_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md004_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md005_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md006_unicode_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md007_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md009_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md010_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md011_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md012_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md013_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md014_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md018_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md019_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md020_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md021_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md022_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md023_extended_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md023_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md024_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md025_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md026_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md027_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md028_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md029_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md030_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md031_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md032_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md033_extended_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md035_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md036_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md037_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md038_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md039_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md040_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md041_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md043_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md044_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md045_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md046_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md047_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md048_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md049_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md050_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md052_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md053_additional_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md053_proptest.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md053_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md054_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md054_unicode_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md055_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md056_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md057_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/md058_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/rules/mod.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/utils/blockquote_utils_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/utils/code_block_utils_extended_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/utils/code_block_utils_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/utils/core_utils_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/utils/front_matter_utils_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/utils/line_index_test.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/utils/mod.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/utils_markdown_edge_cases.rs +0 -0
- {rumdl-0.0.72 → rumdl-0.0.74}/tests/utils_tests.rs +0 -0
|
@@ -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
|
);
|
|
@@ -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,
|
|
@@ -103,8 +103,42 @@ impl MD032BlanksAroundLists {
|
|
|
103
103
|
if structure.is_in_code_block(current_line_idx_1)
|
|
104
104
|
|| structure.is_in_front_matter(current_line_idx_1)
|
|
105
105
|
{
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
// Special case: Even if a line is in a code block (e.g., tab-indented),
|
|
107
|
+
// if it looks like a list item, the user probably intended it as such.
|
|
108
|
+
// We should warn about spacing issues rather than silently ignore it.
|
|
109
|
+
// But only apply this to INDENTED code blocks, not FENCED code blocks.
|
|
110
|
+
if structure.is_in_code_block(current_line_idx_1) {
|
|
111
|
+
// Check if this is an indented code block (starts with tab or 4+ spaces)
|
|
112
|
+
// vs a fenced code block (enclosed in ``` or ~~~)
|
|
113
|
+
let line_trimmed = line_str.trim_start();
|
|
114
|
+
let leading_whitespace = &line_str[..line_str.len() - line_trimmed.len()];
|
|
115
|
+
let is_indented_code = leading_whitespace.contains('\t') ||
|
|
116
|
+
leading_whitespace.chars().filter(|&c| c == ' ').count() >= 4;
|
|
117
|
+
|
|
118
|
+
if is_indented_code {
|
|
119
|
+
// Check if this "indented code block" line actually looks like a list item
|
|
120
|
+
let blockquote_prefix = BLOCKQUOTE_PREFIX_RE
|
|
121
|
+
.find(line_str)
|
|
122
|
+
.map_or(String::new(), |m| m.as_str().to_string());
|
|
123
|
+
let line_content = line_str.trim_start_matches(&blockquote_prefix);
|
|
124
|
+
|
|
125
|
+
// If it matches our list item pattern, treat it as a list item for linting purposes
|
|
126
|
+
if LIST_ITEM_START_REGEX.is_match(line_content) {
|
|
127
|
+
// Don't skip - process it as a potential list item
|
|
128
|
+
} else {
|
|
129
|
+
current_line_idx_0 += 1;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
// Fenced code block - always skip
|
|
134
|
+
current_line_idx_0 += 1;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
// Front matter - always skip
|
|
139
|
+
current_line_idx_0 += 1;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
108
142
|
}
|
|
109
143
|
|
|
110
144
|
// Determine blockquote prefix and content *before* checking for list item
|
|
@@ -96,61 +96,53 @@ impl MD034NoBareUrls {
|
|
|
96
96
|
&url[..end]
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
//
|
|
100
|
-
fn
|
|
99
|
+
// Uses DocumentStructure for code block and code span detection in check_with_structure.
|
|
100
|
+
pub fn check_with_structure(
|
|
101
101
|
&self,
|
|
102
|
-
|
|
103
|
-
line_idx: usize,
|
|
102
|
+
ctx: &crate::lint_context::LintContext,
|
|
104
103
|
structure: &crate::utils::document_structure::DocumentStructure,
|
|
105
|
-
) ->
|
|
106
|
-
let
|
|
107
|
-
|
|
108
|
-
// Early return: empty lines
|
|
109
|
-
if line.trim().is_empty() {
|
|
110
|
-
return warnings;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Fast path - check if line potentially contains a URL
|
|
114
|
-
if !URL_QUICK_CHECK.is_match(line) {
|
|
115
|
-
return warnings;
|
|
116
|
-
}
|
|
104
|
+
) -> LintResult {
|
|
105
|
+
let content = ctx.content;
|
|
117
106
|
|
|
118
|
-
//
|
|
119
|
-
if
|
|
120
|
-
return
|
|
107
|
+
// Early return: skip if no URLs or emails
|
|
108
|
+
if self.should_skip(content) {
|
|
109
|
+
return Ok(vec![]);
|
|
121
110
|
}
|
|
122
111
|
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
return warnings;
|
|
126
|
-
}
|
|
112
|
+
// Process the entire content to handle multi-line markdown links
|
|
113
|
+
let mut warnings = Vec::new();
|
|
127
114
|
|
|
128
|
-
//
|
|
115
|
+
// First, find all markdown link ranges across the entire content
|
|
129
116
|
let mut excluded_ranges: Vec<(usize, usize)> = Vec::new();
|
|
130
|
-
|
|
131
|
-
|
|
117
|
+
|
|
118
|
+
// Markdown links: [text](url) - handle multi-line
|
|
119
|
+
for cap in MARKDOWN_LINK_PATTERN.captures_iter(content) {
|
|
132
120
|
if let Some(dest) = cap.get(1) {
|
|
133
121
|
excluded_ranges.push((dest.start(), dest.end()));
|
|
134
122
|
}
|
|
135
123
|
}
|
|
136
|
-
|
|
137
|
-
|
|
124
|
+
|
|
125
|
+
// Markdown images:  - handle multi-line
|
|
126
|
+
for cap in MARKDOWN_IMAGE_PATTERN.captures_iter(content) {
|
|
138
127
|
if let Some(dest) = cap.get(2) {
|
|
139
128
|
excluded_ranges.push((dest.start(), dest.end()));
|
|
140
129
|
}
|
|
141
130
|
}
|
|
131
|
+
|
|
142
132
|
// Angle-bracket links: <url>
|
|
143
|
-
for cap in ANGLE_LINK_PATTERN.captures_iter(
|
|
133
|
+
for cap in ANGLE_LINK_PATTERN.captures_iter(content) {
|
|
144
134
|
if let Some(m) = cap.get(1) {
|
|
145
135
|
excluded_ranges.push((m.start(), m.end()));
|
|
146
136
|
}
|
|
147
137
|
}
|
|
138
|
+
|
|
148
139
|
// HTML attribute URLs: src="url", href="url", etc.
|
|
149
|
-
for cap in HTML_ATTRIBUTE_URL.captures_iter(
|
|
140
|
+
for cap in HTML_ATTRIBUTE_URL.captures_iter(content) {
|
|
150
141
|
if let Some(url_attr) = cap.get(1) {
|
|
151
142
|
excluded_ranges.push((url_attr.start(), url_attr.end()));
|
|
152
143
|
}
|
|
153
144
|
}
|
|
145
|
+
|
|
154
146
|
// Sort and merge overlapping ranges
|
|
155
147
|
excluded_ranges.sort_by_key(|r| r.0);
|
|
156
148
|
let mut merged: Vec<(usize, usize)> = Vec::new();
|
|
@@ -164,12 +156,13 @@ impl MD034NoBareUrls {
|
|
|
164
156
|
merged.push((start, end));
|
|
165
157
|
}
|
|
166
158
|
|
|
167
|
-
|
|
159
|
+
// Now find all URLs in the content and check if they're excluded
|
|
160
|
+
for url_match in SIMPLE_URL_REGEX.find_iter(content) {
|
|
168
161
|
let url_start = url_match.start();
|
|
169
162
|
let mut url_end = url_match.end();
|
|
170
163
|
|
|
171
164
|
// Trim trailing punctuation that's likely sentence punctuation
|
|
172
|
-
let raw_url = &
|
|
165
|
+
let raw_url = &content[url_start..url_end];
|
|
173
166
|
let trimmed_url = self.trim_trailing_punctuation(raw_url);
|
|
174
167
|
url_end = url_start + trimmed_url.len();
|
|
175
168
|
|
|
@@ -182,9 +175,9 @@ impl MD034NoBareUrls {
|
|
|
182
175
|
let before = if url_start == 0 {
|
|
183
176
|
None
|
|
184
177
|
} else {
|
|
185
|
-
|
|
178
|
+
content.get(url_start - 1..url_start)
|
|
186
179
|
};
|
|
187
|
-
let after =
|
|
180
|
+
let after = content.get(url_end..url_end + 1);
|
|
188
181
|
let is_valid_boundary = before.map_or(true, |c| {
|
|
189
182
|
!c.chars().next().unwrap().is_alphanumeric() && c != "_"
|
|
190
183
|
}) && after.map_or(true, |c| {
|
|
@@ -193,45 +186,67 @@ impl MD034NoBareUrls {
|
|
|
193
186
|
if !is_valid_boundary {
|
|
194
187
|
continue;
|
|
195
188
|
}
|
|
196
|
-
|
|
197
|
-
|
|
189
|
+
|
|
190
|
+
// Convert byte offset to line/column
|
|
191
|
+
let (line_num, col_num) = ctx.offset_to_line_col(url_start);
|
|
192
|
+
|
|
193
|
+
// Skip if this URL is within a code span
|
|
194
|
+
if structure.is_in_code_span(line_num, col_num) {
|
|
198
195
|
continue;
|
|
199
196
|
}
|
|
200
|
-
|
|
197
|
+
|
|
198
|
+
// Skip if this URL is within a code block
|
|
199
|
+
if structure.is_in_code_block(line_num) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Skip if URL is within any excluded range (link/image dest)
|
|
201
204
|
let in_any_range = merged
|
|
202
205
|
.iter()
|
|
203
206
|
.any(|(start, end)| url_start >= *start && url_end <= *end);
|
|
204
207
|
if in_any_range {
|
|
205
208
|
continue;
|
|
206
209
|
}
|
|
210
|
+
|
|
211
|
+
// Skip reference definitions
|
|
212
|
+
let line_start = content[..url_start].rfind('\n').map(|i| i + 1).unwrap_or(0);
|
|
213
|
+
let line_end = content[url_start..].find('\n').map(|i| url_start + i).unwrap_or(content.len());
|
|
214
|
+
let line = &content[line_start..line_end];
|
|
215
|
+
if REFERENCE_DEF_RE.is_match(line) {
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
let url_text = &content[url_start..url_end];
|
|
207
220
|
let (start_line, start_col, end_line, end_col) =
|
|
208
|
-
calculate_url_range(
|
|
221
|
+
calculate_url_range(line_num, line, col_num - 1, url_text.len());
|
|
222
|
+
|
|
209
223
|
warnings.push(LintWarning {
|
|
210
224
|
rule_name: Some(self.name()),
|
|
211
225
|
line: start_line,
|
|
212
226
|
column: start_col,
|
|
213
227
|
end_line,
|
|
214
228
|
end_column: end_col,
|
|
215
|
-
message: format!("Bare URL found
|
|
229
|
+
message: format!("Bare URL found"),
|
|
216
230
|
severity: Severity::Warning,
|
|
217
231
|
fix: Some(Fix {
|
|
218
232
|
range: url_start..url_end,
|
|
219
|
-
replacement: format!("<{}>",
|
|
233
|
+
replacement: format!("<{}>", url_text),
|
|
220
234
|
}),
|
|
221
235
|
});
|
|
222
236
|
}
|
|
223
237
|
|
|
224
238
|
// Check for email addresses - similar logic to URLs
|
|
225
|
-
for email_match in EMAIL_REGEX.find_iter(
|
|
239
|
+
for email_match in EMAIL_REGEX.find_iter(content) {
|
|
226
240
|
let email_start = email_match.start();
|
|
227
241
|
let email_end = email_match.end();
|
|
242
|
+
|
|
228
243
|
// Manual boundary check: not part of a larger word
|
|
229
244
|
let before = if email_start == 0 {
|
|
230
245
|
None
|
|
231
246
|
} else {
|
|
232
|
-
|
|
247
|
+
content.get(email_start - 1..email_start)
|
|
233
248
|
};
|
|
234
|
-
let after =
|
|
249
|
+
let after = content.get(email_end..email_end + 1);
|
|
235
250
|
let is_valid_boundary = before.map_or(true, |c| {
|
|
236
251
|
!c.chars().next().unwrap().is_alphanumeric() && c != "_" && c != "."
|
|
237
252
|
}) && after.map_or(true, |c| {
|
|
@@ -240,10 +255,20 @@ impl MD034NoBareUrls {
|
|
|
240
255
|
if !is_valid_boundary {
|
|
241
256
|
continue;
|
|
242
257
|
}
|
|
243
|
-
|
|
244
|
-
|
|
258
|
+
|
|
259
|
+
// Convert byte offset to line/column
|
|
260
|
+
let (line_num, col_num) = ctx.offset_to_line_col(email_start);
|
|
261
|
+
|
|
262
|
+
// Skip if this email is within a code span
|
|
263
|
+
if structure.is_in_code_span(line_num, col_num) {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Skip if this email is within a code block
|
|
268
|
+
if structure.is_in_code_block(line_num) {
|
|
245
269
|
continue;
|
|
246
270
|
}
|
|
271
|
+
|
|
247
272
|
// Skip if email is within any excluded range (link/image dest)
|
|
248
273
|
let in_any_range = merged
|
|
249
274
|
.iter()
|
|
@@ -251,65 +276,29 @@ impl MD034NoBareUrls {
|
|
|
251
276
|
if in_any_range {
|
|
252
277
|
continue;
|
|
253
278
|
}
|
|
279
|
+
|
|
280
|
+
let email_text = &content[email_start..email_end];
|
|
281
|
+
let line_start = content[..email_start].rfind('\n').map(|i| i + 1).unwrap_or(0);
|
|
282
|
+
let line_end = content[email_start..].find('\n').map(|i| email_start + i).unwrap_or(content.len());
|
|
283
|
+
let line = &content[line_start..line_end];
|
|
254
284
|
let (start_line, start_col, end_line, end_col) =
|
|
255
|
-
calculate_url_range(
|
|
285
|
+
calculate_url_range(line_num, line, col_num - 1, email_text.len());
|
|
286
|
+
|
|
256
287
|
warnings.push(LintWarning {
|
|
257
288
|
rule_name: Some(self.name()),
|
|
258
289
|
line: start_line,
|
|
259
290
|
column: start_col,
|
|
260
291
|
end_line,
|
|
261
292
|
end_column: end_col,
|
|
262
|
-
message: format!(
|
|
263
|
-
"Bare email address found: {}",
|
|
264
|
-
&line[email_start..email_end]
|
|
265
|
-
),
|
|
293
|
+
message: format!("Bare email address found"),
|
|
266
294
|
severity: Severity::Warning,
|
|
267
295
|
fix: Some(Fix {
|
|
268
296
|
range: email_start..email_end,
|
|
269
|
-
replacement: format!("<{}>",
|
|
297
|
+
replacement: format!("<{}>", email_text),
|
|
270
298
|
}),
|
|
271
299
|
});
|
|
272
300
|
}
|
|
273
|
-
warnings
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// Uses DocumentStructure for code block and code span detection in check_with_structure.
|
|
277
|
-
pub fn check_with_structure(
|
|
278
|
-
&self,
|
|
279
|
-
ctx: &crate::lint_context::LintContext,
|
|
280
|
-
structure: &crate::utils::document_structure::DocumentStructure,
|
|
281
|
-
) -> LintResult {
|
|
282
|
-
let content = ctx.content;
|
|
283
301
|
|
|
284
|
-
// Early return: skip if no URLs or emails
|
|
285
|
-
if self.should_skip(content) {
|
|
286
|
-
return Ok(vec![]);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
let mut warnings = Vec::new();
|
|
290
|
-
for (i, line) in content.lines().enumerate() {
|
|
291
|
-
// Fast path: Skip empty lines
|
|
292
|
-
if line.trim().is_empty() {
|
|
293
|
-
continue;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// Fast path: Skip lines without potential URLs or emails
|
|
297
|
-
if !line.contains("http") && !line.contains("ftp") && !line.contains('@') {
|
|
298
|
-
continue;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Skip lines in code blocks
|
|
302
|
-
if structure.is_in_code_block(i + 1) {
|
|
303
|
-
continue;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// Fast path: Skip reference link definitions
|
|
307
|
-
if REFERENCE_DEF_RE.is_match(line) {
|
|
308
|
-
continue;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
warnings.extend(self.find_bare_urls_with_structure(line, i, structure));
|
|
312
|
-
}
|
|
313
302
|
Ok(warnings)
|
|
314
303
|
}
|
|
315
304
|
|
|
@@ -368,7 +357,7 @@ impl MD034NoBareUrls {
|
|
|
368
357
|
column: start_col,
|
|
369
358
|
end_line,
|
|
370
359
|
end_column: end_col,
|
|
371
|
-
message: format!("Bare URL found
|
|
360
|
+
message: format!("Bare URL found"),
|
|
372
361
|
severity: Severity::Warning,
|
|
373
362
|
fix: Some(Fix {
|
|
374
363
|
range: offset..(offset + url_text.len()),
|
|
@@ -466,7 +455,7 @@ impl MD034NoBareUrls {
|
|
|
466
455
|
column: start_col,
|
|
467
456
|
end_line,
|
|
468
457
|
end_column: end_col,
|
|
469
|
-
message: format!("Bare URL found
|
|
458
|
+
message: format!("Bare URL found"),
|
|
470
459
|
severity: Severity::Warning,
|
|
471
460
|
fix: Some(Fix {
|
|
472
461
|
range: offset..(offset + url_text.len()),
|
|
@@ -35,57 +35,15 @@ impl Rule for MD042NoEmptyLinks {
|
|
|
35
35
|
|
|
36
36
|
fn check(&self, ctx: &crate::lint_context::LintContext) -> LintResult {
|
|
37
37
|
let content = ctx.content;
|
|
38
|
-
let line_index = LineIndex::new(content.to_string());
|
|
39
|
-
let mut warnings = Vec::new();
|
|
40
|
-
|
|
41
|
-
lazy_static! {
|
|
42
|
-
static ref EMPTY_LINK_REGEX: Regex =
|
|
43
|
-
Regex::new(r"(?<!\!)\[([^\]]*)\]\(([^\)]*)\)").unwrap();
|
|
44
|
-
}
|
|
45
38
|
|
|
46
|
-
for
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Ok(cap) => cap,
|
|
50
|
-
Err(_) => continue,
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
let full_match = cap.get(0).unwrap();
|
|
54
|
-
let text = cap.get(1).map_or("", |m| m.as_str());
|
|
55
|
-
let url = cap.get(2).map_or("", |m| m.as_str());
|
|
56
|
-
|
|
57
|
-
if text.trim().is_empty() || url.trim().is_empty() {
|
|
58
|
-
let replacement = if text.trim().is_empty() && url.trim().is_empty() {
|
|
59
|
-
"[Link text](https://example.com)".to_string()
|
|
60
|
-
} else if text.trim().is_empty() {
|
|
61
|
-
format!("[Link text]({})", url)
|
|
62
|
-
} else {
|
|
63
|
-
format!("[{}](https://example.com)", text)
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
warnings.push(LintWarning {
|
|
67
|
-
rule_name: Some(self.name()),
|
|
68
|
-
message: format!(
|
|
69
|
-
"Empty link found: [{
|
|
70
|
-
}]({})",
|
|
71
|
-
text, url
|
|
72
|
-
),
|
|
73
|
-
line: line_num + 1,
|
|
74
|
-
column: full_match.start() + 1,
|
|
75
|
-
end_line: line_num + 1,
|
|
76
|
-
end_column: full_match.end() + 1,
|
|
77
|
-
severity: Severity::Warning,
|
|
78
|
-
fix: Some(Fix {
|
|
79
|
-
range: line_index
|
|
80
|
-
.line_col_to_byte_range(line_num + 1, full_match.start() + 1),
|
|
81
|
-
replacement,
|
|
82
|
-
}),
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
}
|
|
39
|
+
// Early return for empty content or content without links
|
|
40
|
+
if content.is_empty() || !content.contains('[') {
|
|
41
|
+
return Ok(Vec::new());
|
|
86
42
|
}
|
|
87
43
|
|
|
88
|
-
|
|
44
|
+
// Use document structure for proper code block and code span detection
|
|
45
|
+
let structure = DocumentStructure::new(content);
|
|
46
|
+
self.check_with_structure(ctx, &structure)
|
|
89
47
|
}
|
|
90
48
|
|
|
91
49
|
/// Optimized check using document structure
|
|
@@ -125,7 +83,7 @@ impl Rule for MD042NoEmptyLinks {
|
|
|
125
83
|
line: link.line,
|
|
126
84
|
column: link.start_col,
|
|
127
85
|
end_line: link.line,
|
|
128
|
-
end_column: link.end_col,
|
|
86
|
+
end_column: link.end_col + 1,
|
|
129
87
|
severity: Severity::Warning,
|
|
130
88
|
fix: Some(Fix {
|
|
131
89
|
range: line_index.line_col_to_byte_range(link.line, link.start_col),
|