rumdl 0.0.89__tar.gz → 0.0.90__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.89 → rumdl-0.0.90}/CHANGELOG.md +4 -1
- {rumdl-0.0.89 → rumdl-0.0.90}/Cargo.lock +1 -1
- {rumdl-0.0.89 → rumdl-0.0.90}/Cargo.toml +1 -1
- {rumdl-0.0.89 → rumdl-0.0.90}/PKG-INFO +11 -2
- {rumdl-0.0.89 → rumdl-0.0.90}/README.md +10 -1
- {rumdl-0.0.89 → rumdl-0.0.90}/src/lib.rs +1 -1
- {rumdl-0.0.89 → rumdl-0.0.90}/src/lint_context.rs +22 -369
- {rumdl-0.0.89 → rumdl-0.0.90}/src/main.rs +12 -1
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rule.rs +1 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md009_trailing_spaces.rs +1 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md010_no_hard_tabs.rs +1 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md012_no_multiple_blanks.rs +1 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md037_spaces_around_emphasis.rs +6 -249
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md047_single_trailing_newline.rs +1 -0
- rumdl-0.0.90/src/rules/md049_emphasis_style.rs +266 -0
- rumdl-0.0.90/src/utils/emphasis_utils.rs +374 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/utils/mod.rs +1 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md034_test.rs +5 -5
- rumdl-0.0.89/src/rules/md049_emphasis_style.rs +0 -278
- {rumdl-0.0.89 → rumdl-0.0.90}/.config/nextest.toml +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/.mise.toml +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/.rumdl.toml +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/.rustfmt.toml +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/LICENSE +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/MANIFEST.in +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/Makefile +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/assets/logo.png +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/benches/fix_performance.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/benches/range_performance.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/benches/range_utils_benchmark.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/benches/rule_performance.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/benches/simple_fix_bench.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/RULES.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/global-settings.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md001.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md002.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md003.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md004.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md005.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md006.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md007.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md009.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md010.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md011.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md012.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md013.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md014.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md018.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md019.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md020.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md021.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md022.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md023.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md024.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md025.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md026.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md027.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md028.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md029.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md030.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md031.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md032.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md033.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md034.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md035.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md036.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md037.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md038.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md039.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md040.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md041.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md042.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md043.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md044.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md045.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md046.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md047.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md048.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md049.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md050.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md051.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md052.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md053.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md054.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md055.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md056.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md057.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/md058.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/docs/vscode-extension.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/issues/plan-rule-parity-with-markdownlint.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/parity_check.py +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/pyproject.toml +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/python/MANIFEST.in +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/python/PYTHON-README.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/python/rumdl/__init__.py +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/python/rumdl/__main__.py +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/python/rumdl/py.typed +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/rumdl.toml.example +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/rust-toolchain.toml +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/scripts/extract-changelog.sh +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/scripts/prepare-release.sh +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/bin/benchmark.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/bin/file_parallel_benchmark.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/bin/measure_code_span_performance.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/init.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/inline_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/lsp/mod.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/lsp/server.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/lsp/types.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/markdownlint_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/output/formatters/azure.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/output/formatters/concise.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/output/formatters/github.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/output/formatters/gitlab.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/output/formatters/grouped.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/output/formatters/json.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/output/formatters/json_lines.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/output/formatters/junit.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/output/formatters/mod.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/output/formatters/pylint.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/output/formatters/sarif.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/output/formatters/text.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/output/mod.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/parallel.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/performance.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/profiling.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/python.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rule_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rule_config_serde.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/blockquote_utils.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/code_block_utils.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/code_fence_utils.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/emphasis_style.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/front_matter_utils.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/heading_utils.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/list_utils.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md001_heading_increment.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md002_first_heading_h1/md002_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md002_first_heading_h1.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md003_heading_style/md003_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md003_heading_style.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md004_unordered_list_style/md004_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md004_unordered_list_style.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md005_list_indent.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md006_start_bullets.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md007_ul_indent/md007_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md007_ul_indent.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md009_trailing_spaces/md009_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md010_no_hard_tabs/md010_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md011_no_reversed_links.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md012_no_multiple_blanks/md012_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md013_line_length/md013_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md013_line_length.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md014_commands_show_output/md014_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md014_commands_show_output.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md018_no_missing_space_atx.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md019_no_multiple_space_atx.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md020_no_missing_space_closed_atx.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md021_no_multiple_space_closed_atx.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md022_blanks_around_headings/md022_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md022_blanks_around_headings.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md023_heading_start_left.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md024_no_duplicate_heading/md024_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md024_no_duplicate_heading.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md025_single_title/md025_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md025_single_title.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md026_no_trailing_punctuation/md026_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md026_no_trailing_punctuation.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md027_multiple_spaces_blockquote.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md028_no_blanks_blockquote.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md029_ordered_list_prefix.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md030_list_marker_space/md030_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md030_list_marker_space.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md031_blanks_around_fences.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md032_blanks_around_lists.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md033_no_inline_html/md033_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md033_no_inline_html.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md034_no_bare_urls.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md035_hr_style/md035_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md035_hr_style.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md036_no_emphasis_only_first/md036_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md036_no_emphasis_only_first.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md038_no_space_in_code.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md039_no_space_in_links.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md040_fenced_code_language.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md041_first_line_heading.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md042_no_empty_links.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md043_required_headings.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md044_proper_names/md044_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md044_proper_names.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md045_no_alt_text.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md046_code_block_style/md046_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md046_code_block_style.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md048_code_fence_style/md048_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md048_code_fence_style.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md049_emphasis_style/md049_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md050_strong_style/md050_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md050_strong_style.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md051_link_fragments.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md052_reference_links_images.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md053_link_image_reference_definitions.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md054_link_image_style/md054_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md054_link_image_style.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md055_table_pipe_style/md055_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md055_table_pipe_style.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md056_table_column_count.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md057_existing_relative_links/md057_config.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md057_existing_relative_links.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/md058_blanks_around_tables.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/mod.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/rules/strong_style.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/utils/ast_utils.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/utils/code_block_utils.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/utils/document_structure.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/utils/early_returns.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/utils/element_cache.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/utils/fix_utils.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/utils/markdown_elements.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/utils/range_utils.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/utils/regex_cache.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/utils/string_interner.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/utils/table_utils.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/src/vscode.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/advanced_integration_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/character_ranges/additional_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/character_ranges/basic_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/character_ranges/comprehensive_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/character_ranges/extended_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/character_ranges/mod.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/character_ranges/unicode_utils.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/cli_duplication_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/cli_integration_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/cli_lsp_fix_consistency.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/cli_statistics_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/commonmark_compliance_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/comprehensive_integration_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/comprehensive_output_format_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/config_application_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/config_file_command_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/config_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/configuration_inheritance_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/consistency_regression_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/cross_platform_compatibility_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/final_confidence_assessment.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/init_command_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/init_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/inline_config_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/integration_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/json_output_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/lib.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/lsp_editor_integration_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/lsp_integration_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/lsp_memory_leak_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/lsp_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/malformed_markdown_stress_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/markdownlint_cli_integration.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/markdownlint_config_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/markdownlintignore_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/md030_edge_cases.md +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/output_format_integration_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/output_format_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/perf_check.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/performance_validation_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/pyproject_config_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/real_world_repository_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/regression_prevention_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md001_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md001_unicode_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md002_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md003_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md004_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md005_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md006_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md006_unicode_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md007_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md009_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md010_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md011_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md012_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md013_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md014_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md018_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md019_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md020_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md021_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md022_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md023_extended_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md023_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md024_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md025_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md026_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md027_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md028_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md029_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md030_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md031_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md032_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md033_extended_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md033_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md035_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md036_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md037_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md038_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md039_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md040_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md041_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md042_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md043_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md044_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md045_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md046_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md047_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md048_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md049_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md050_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md051_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md052_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md053_additional_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md053_proptest.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md053_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md054_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md054_unicode_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md055_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md056_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md057_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/md058_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/rules/mod.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/thread_safety_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/unicode_edge_case_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/utils/blockquote_utils_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/utils/code_block_utils_extended_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/utils/code_block_utils_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/utils/core_utils_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/utils/front_matter_utils_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/utils/line_index_test.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/utils/mod.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/utils_markdown_edge_cases.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/utils_tests.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/vscode_extension_fixes.rs +0 -0
- {rumdl-0.0.89 → rumdl-0.0.90}/tests/vscode_test.rs +0 -0
|
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.0.90] - 2025-07-01
|
|
11
|
+
|
|
10
12
|
## [0.0.89] - 2025-07-01
|
|
11
13
|
|
|
12
14
|
### Added
|
|
@@ -107,7 +109,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
107
109
|
### Added
|
|
108
110
|
- Initial implementation of remaining rules for markdownlint parity
|
|
109
111
|
|
|
110
|
-
[Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.
|
|
112
|
+
[Unreleased]: https://github.com/rvben/rumdl/compare/v0.0.90...HEAD
|
|
113
|
+
[0.0.90]: https://github.com/rvben/rumdl/compare/v0.0.89...v0.0.90
|
|
111
114
|
[0.0.89]: https://github.com/rvben/rumdl/compare/v0.0.88...v0.0.89
|
|
112
115
|
[0.0.88]: https://github.com/rvben/rumdl/compare/v0.0.87...v0.0.88
|
|
113
116
|
[0.0.87]: https://github.com/rvben/rumdl/compare/v0.0.86...v0.0.87
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rumdl
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.90
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Environment :: Console
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -55,6 +55,7 @@ Project-URL: Repository, https://github.com/rvben/rumdl.git
|
|
|
55
55
|
- [Table of Contents](#table-of-contents)
|
|
56
56
|
- [Quick Start](#quick-start)
|
|
57
57
|
- [Overview](#overview)
|
|
58
|
+
- [Performance](#performance)
|
|
58
59
|
- [Installation](#installation)
|
|
59
60
|
- [Using Cargo (Rust)](#using-cargo-rust)
|
|
60
61
|
- [Using pip (Python)](#using-pip-python)
|
|
@@ -102,7 +103,7 @@ rumdl init
|
|
|
102
103
|
|
|
103
104
|
rumdl is a high-performance Markdown linter and fixer that helps ensure consistency and best practices in your Markdown files. It offers:
|
|
104
105
|
|
|
105
|
-
- ⚡️ **Built for speed** with Rust
|
|
106
|
+
- ⚡️ **Built for speed** with Rust - significantly faster than alternatives
|
|
106
107
|
- 🔍 **54 lint rules** covering common Markdown issues
|
|
107
108
|
- 🛠️ **Automatic fixing** with `--fix` for most rules
|
|
108
109
|
- 📦 **Zero dependencies** - single binary with no runtime requirements
|
|
@@ -112,6 +113,14 @@ rumdl is a high-performance Markdown linter and fixer that helps ensure consiste
|
|
|
112
113
|
- 📏 **Modern CLI** with detailed error reporting
|
|
113
114
|
- 🔄 **CI/CD friendly** with non-zero exit code on errors
|
|
114
115
|
|
|
116
|
+
## Performance
|
|
117
|
+
|
|
118
|
+
rumdl is designed for speed and efficiency:
|
|
119
|
+
|
|
120
|
+

|
|
121
|
+
|
|
122
|
+
rumdl is **4.3x faster** on average than markdownlint for typical markdown files, with performance improvements ranging from 3.4x to 5.4x depending on project size.
|
|
123
|
+
|
|
115
124
|
## Installation
|
|
116
125
|
|
|
117
126
|
Choose the installation method that works best for you:
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
- [Table of Contents](#table-of-contents)
|
|
25
25
|
- [Quick Start](#quick-start)
|
|
26
26
|
- [Overview](#overview)
|
|
27
|
+
- [Performance](#performance)
|
|
27
28
|
- [Installation](#installation)
|
|
28
29
|
- [Using Cargo (Rust)](#using-cargo-rust)
|
|
29
30
|
- [Using pip (Python)](#using-pip-python)
|
|
@@ -71,7 +72,7 @@ rumdl init
|
|
|
71
72
|
|
|
72
73
|
rumdl is a high-performance Markdown linter and fixer that helps ensure consistency and best practices in your Markdown files. It offers:
|
|
73
74
|
|
|
74
|
-
- ⚡️ **Built for speed** with Rust
|
|
75
|
+
- ⚡️ **Built for speed** with Rust - significantly faster than alternatives
|
|
75
76
|
- 🔍 **54 lint rules** covering common Markdown issues
|
|
76
77
|
- 🛠️ **Automatic fixing** with `--fix` for most rules
|
|
77
78
|
- 📦 **Zero dependencies** - single binary with no runtime requirements
|
|
@@ -81,6 +82,14 @@ rumdl is a high-performance Markdown linter and fixer that helps ensure consiste
|
|
|
81
82
|
- 📏 **Modern CLI** with detailed error reporting
|
|
82
83
|
- 🔄 **CI/CD friendly** with non-zero exit code on errors
|
|
83
84
|
|
|
85
|
+
## Performance
|
|
86
|
+
|
|
87
|
+
rumdl is designed for speed and efficiency:
|
|
88
|
+
|
|
89
|
+

|
|
90
|
+
|
|
91
|
+
rumdl is **4.3x faster** on average than markdownlint for typical markdown files, with performance improvements ranging from 3.4x to 5.4x depending on project size.
|
|
92
|
+
|
|
84
93
|
## Installation
|
|
85
94
|
|
|
86
95
|
Choose the installation method that works best for you:
|
|
@@ -23,7 +23,7 @@ pub mod python;
|
|
|
23
23
|
pub use rules::heading_utils::{Heading, HeadingStyle};
|
|
24
24
|
pub use rules::*;
|
|
25
25
|
|
|
26
|
-
pub use crate::lint_context::{
|
|
26
|
+
pub use crate::lint_context::{LineInfo, LintContext, ListItemInfo};
|
|
27
27
|
use crate::rule::{LintResult, Rule, RuleCategory};
|
|
28
28
|
use crate::utils::document_structure::DocumentStructure;
|
|
29
29
|
use std::time::Instant;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
use crate::utils::code_block_utils::CodeBlockUtils;
|
|
2
2
|
use lazy_static::lazy_static;
|
|
3
|
-
use markdown::{mdast::Node, to_mdast, ParseOptions};
|
|
4
3
|
use regex::Regex;
|
|
5
|
-
use std::panic;
|
|
6
4
|
|
|
7
5
|
lazy_static! {
|
|
8
6
|
// Comprehensive link pattern that captures both inline and reference links
|
|
@@ -223,24 +221,6 @@ pub struct BlockquoteInfo {
|
|
|
223
221
|
pub needs_md028_fix: bool,
|
|
224
222
|
}
|
|
225
223
|
|
|
226
|
-
/// Information about a bare URL or email
|
|
227
|
-
#[derive(Debug, Clone)]
|
|
228
|
-
pub struct BareUrl {
|
|
229
|
-
/// Line number (1-indexed)
|
|
230
|
-
pub line: usize,
|
|
231
|
-
/// Start column (0-indexed) in the line
|
|
232
|
-
pub start_col: usize,
|
|
233
|
-
/// End column (0-indexed) in the line
|
|
234
|
-
pub end_col: usize,
|
|
235
|
-
/// Byte offset in document
|
|
236
|
-
pub byte_offset: usize,
|
|
237
|
-
/// End byte offset in document
|
|
238
|
-
pub byte_end: usize,
|
|
239
|
-
/// The URL or email text
|
|
240
|
-
pub text: String,
|
|
241
|
-
/// Whether this is an email (true) or URL (false)
|
|
242
|
-
pub is_email: bool,
|
|
243
|
-
}
|
|
244
224
|
|
|
245
225
|
/// Information about a list block
|
|
246
226
|
#[derive(Debug, Clone)]
|
|
@@ -263,7 +243,6 @@ pub struct ListBlock {
|
|
|
263
243
|
|
|
264
244
|
pub struct LintContext<'a> {
|
|
265
245
|
pub content: &'a str,
|
|
266
|
-
pub ast: Node, // The root of the AST
|
|
267
246
|
pub line_offsets: Vec<usize>,
|
|
268
247
|
pub code_blocks: Vec<(usize, usize)>, // Cached code block ranges (not including inline code spans)
|
|
269
248
|
pub lines: Vec<LineInfo>, // Pre-computed line information
|
|
@@ -272,79 +251,10 @@ pub struct LintContext<'a> {
|
|
|
272
251
|
pub reference_defs: Vec<ReferenceDef>, // Reference definitions
|
|
273
252
|
pub code_spans: Vec<CodeSpan>, // Pre-parsed inline code spans
|
|
274
253
|
pub list_blocks: Vec<ListBlock>, // Pre-parsed list blocks
|
|
275
|
-
pub bare_urls: Vec<BareUrl>, // Pre-parsed bare URLs and emails
|
|
276
254
|
}
|
|
277
255
|
|
|
278
256
|
impl<'a> LintContext<'a> {
|
|
279
257
|
pub fn new(content: &'a str) -> Self {
|
|
280
|
-
// Check for problematic patterns that cause the markdown crate to panic
|
|
281
|
-
if content_has_problematic_lists(content) {
|
|
282
|
-
log::debug!("Detected problematic list patterns in LintContext, skipping AST parsing");
|
|
283
|
-
let ast = Node::Root(markdown::mdast::Root {
|
|
284
|
-
children: vec![],
|
|
285
|
-
position: None,
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
let mut line_offsets = vec![0];
|
|
289
|
-
for (i, c) in content.char_indices() {
|
|
290
|
-
if c == '\n' {
|
|
291
|
-
line_offsets.push(i + 1);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// Detect code blocks once and cache them
|
|
296
|
-
let code_blocks = CodeBlockUtils::detect_code_blocks(content);
|
|
297
|
-
|
|
298
|
-
// Pre-compute line information
|
|
299
|
-
let lines = Self::compute_line_info(content, &line_offsets, &code_blocks);
|
|
300
|
-
|
|
301
|
-
// Parse links, images, references, code spans, and list blocks
|
|
302
|
-
let links = Self::parse_links(content, &lines, &code_blocks);
|
|
303
|
-
let images = Self::parse_images(content, &lines, &code_blocks);
|
|
304
|
-
let reference_defs = Self::parse_reference_defs(content, &lines);
|
|
305
|
-
let code_spans = Self::parse_code_spans(content, &lines);
|
|
306
|
-
let list_blocks = Self::parse_list_blocks(&lines);
|
|
307
|
-
let bare_urls = Self::parse_bare_urls(content, &lines, &code_blocks, &links, &images, &reference_defs);
|
|
308
|
-
|
|
309
|
-
return Self {
|
|
310
|
-
content,
|
|
311
|
-
ast,
|
|
312
|
-
line_offsets,
|
|
313
|
-
code_blocks,
|
|
314
|
-
lines,
|
|
315
|
-
links,
|
|
316
|
-
images,
|
|
317
|
-
reference_defs,
|
|
318
|
-
code_spans,
|
|
319
|
-
list_blocks,
|
|
320
|
-
bare_urls,
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Try to parse AST, but handle panics from the markdown crate
|
|
325
|
-
let ast = match panic::catch_unwind(std::panic::AssertUnwindSafe(|| to_mdast(content, &ParseOptions::gfm()))) {
|
|
326
|
-
Ok(Ok(ast)) => {
|
|
327
|
-
// Successfully parsed AST
|
|
328
|
-
ast
|
|
329
|
-
}
|
|
330
|
-
Ok(Err(err)) => {
|
|
331
|
-
// Parsing failed with an error
|
|
332
|
-
log::debug!("Failed to parse markdown AST: {:?}", err);
|
|
333
|
-
Node::Root(markdown::mdast::Root {
|
|
334
|
-
children: vec![],
|
|
335
|
-
position: None,
|
|
336
|
-
})
|
|
337
|
-
}
|
|
338
|
-
Err(_) => {
|
|
339
|
-
// Parsing panicked
|
|
340
|
-
log::debug!("Markdown AST parsing panicked, falling back to empty AST");
|
|
341
|
-
Node::Root(markdown::mdast::Root {
|
|
342
|
-
children: vec![],
|
|
343
|
-
position: None,
|
|
344
|
-
})
|
|
345
|
-
}
|
|
346
|
-
};
|
|
347
|
-
|
|
348
258
|
let mut line_offsets = vec![0];
|
|
349
259
|
for (i, c) in content.char_indices() {
|
|
350
260
|
if c == '\n' {
|
|
@@ -364,11 +274,9 @@ impl<'a> LintContext<'a> {
|
|
|
364
274
|
let reference_defs = Self::parse_reference_defs(content, &lines);
|
|
365
275
|
let code_spans = Self::parse_code_spans(content, &lines);
|
|
366
276
|
let list_blocks = Self::parse_list_blocks(&lines);
|
|
367
|
-
let bare_urls = Self::parse_bare_urls(content, &lines, &code_blocks, &links, &images, &reference_defs);
|
|
368
277
|
|
|
369
278
|
Self {
|
|
370
279
|
content,
|
|
371
|
-
ast,
|
|
372
280
|
line_offsets,
|
|
373
281
|
code_blocks,
|
|
374
282
|
lines,
|
|
@@ -377,7 +285,6 @@ impl<'a> LintContext<'a> {
|
|
|
377
285
|
reference_defs,
|
|
378
286
|
code_spans,
|
|
379
287
|
list_blocks,
|
|
380
|
-
bare_urls,
|
|
381
288
|
}
|
|
382
289
|
}
|
|
383
290
|
|
|
@@ -665,28 +572,30 @@ impl<'a> LintContext<'a> {
|
|
|
665
572
|
|
|
666
573
|
/// Pre-compute line information
|
|
667
574
|
fn compute_line_info(content: &str, line_offsets: &[usize], code_blocks: &[(usize, usize)]) -> Vec<LineInfo> {
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
let unordered_regex = regex::Regex::new(r"^(\s*)([-*+])([ \t]*)(.*)").unwrap();
|
|
673
|
-
let ordered_regex = regex::Regex::new(r"^(\s*)(\d+)([.)])([ \t]*)(.*)").unwrap();
|
|
575
|
+
lazy_static! {
|
|
576
|
+
// Regex for list detection - allow any whitespace including no space (to catch malformed lists)
|
|
577
|
+
static ref UNORDERED_REGEX: regex::Regex = regex::Regex::new(r"^(\s*)([-*+])([ \t]*)(.*)").unwrap();
|
|
578
|
+
static ref ORDERED_REGEX: regex::Regex = regex::Regex::new(r"^(\s*)(\d+)([.)])([ \t]*)(.*)").unwrap();
|
|
674
579
|
|
|
675
|
-
|
|
676
|
-
|
|
580
|
+
// Regex for blockquote prefix
|
|
581
|
+
static ref BLOCKQUOTE_REGEX: regex::Regex = regex::Regex::new(r"^(\s*>\s*)(.*)").unwrap();
|
|
677
582
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
583
|
+
// Regex for heading detection
|
|
584
|
+
static ref ATX_HEADING_REGEX: regex::Regex = regex::Regex::new(r"^(\s*)(#{1,6})(\s*)(.*)$").unwrap();
|
|
585
|
+
static ref SETEXT_UNDERLINE_REGEX: regex::Regex = regex::Regex::new(r"^(\s*)(=+|-+)\s*$").unwrap();
|
|
681
586
|
|
|
682
|
-
|
|
683
|
-
|
|
587
|
+
// Regex for blockquote detection
|
|
588
|
+
static ref BLOCKQUOTE_REGEX_FULL: regex::Regex = regex::Regex::new(r"^(\s*)(>+)(\s*)(.*)$").unwrap();
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
let mut lines = Vec::new();
|
|
592
|
+
let content_lines: Vec<&str> = content.lines().collect();
|
|
684
593
|
|
|
685
594
|
for (i, line) in content_lines.iter().enumerate() {
|
|
686
595
|
let byte_offset = line_offsets.get(i).copied().unwrap_or(0);
|
|
687
596
|
let indent = line.len() - line.trim_start().len();
|
|
688
597
|
// For blank detection, consider blockquote context
|
|
689
|
-
let is_blank = if let Some(caps) =
|
|
598
|
+
let is_blank = if let Some(caps) = BLOCKQUOTE_REGEX.captures(line) {
|
|
690
599
|
// In blockquote context, check if content after prefix is blank
|
|
691
600
|
let after_prefix = caps.get(2).map_or("", |m| m.as_str());
|
|
692
601
|
after_prefix.trim().is_empty()
|
|
@@ -712,7 +621,7 @@ impl<'a> LintContext<'a> {
|
|
|
712
621
|
// Detect list items
|
|
713
622
|
let list_item = if !in_code_block && !is_blank {
|
|
714
623
|
// Strip blockquote prefix if present for list detection
|
|
715
|
-
let (line_for_list_check, blockquote_prefix_len) = if let Some(caps) =
|
|
624
|
+
let (line_for_list_check, blockquote_prefix_len) = if let Some(caps) = BLOCKQUOTE_REGEX.captures(line) {
|
|
716
625
|
let prefix = caps.get(1).unwrap().as_str();
|
|
717
626
|
let content = caps.get(2).unwrap().as_str();
|
|
718
627
|
(content, prefix.len())
|
|
@@ -720,7 +629,7 @@ impl<'a> LintContext<'a> {
|
|
|
720
629
|
(&**line, 0)
|
|
721
630
|
};
|
|
722
631
|
|
|
723
|
-
if let Some(caps) =
|
|
632
|
+
if let Some(caps) = UNORDERED_REGEX.captures(line_for_list_check) {
|
|
724
633
|
let leading_spaces = caps.get(1).map_or("", |m| m.as_str());
|
|
725
634
|
let marker = caps.get(2).map_or("", |m| m.as_str());
|
|
726
635
|
let spacing = caps.get(3).map_or("", |m| m.as_str());
|
|
@@ -766,7 +675,7 @@ impl<'a> LintContext<'a> {
|
|
|
766
675
|
content_column,
|
|
767
676
|
})
|
|
768
677
|
}
|
|
769
|
-
} else if let Some(caps) =
|
|
678
|
+
} else if let Some(caps) = ORDERED_REGEX.captures(line_for_list_check) {
|
|
770
679
|
let leading_spaces = caps.get(1).map_or("", |m| m.as_str());
|
|
771
680
|
let number_str = caps.get(2).map_or("", |m| m.as_str());
|
|
772
681
|
let delimiter = caps.get(3).map_or("", |m| m.as_str());
|
|
@@ -836,7 +745,7 @@ impl<'a> LintContext<'a> {
|
|
|
836
745
|
let line = content_lines[i];
|
|
837
746
|
|
|
838
747
|
// Check for blockquotes (even on blank lines within blockquotes)
|
|
839
|
-
if let Some(caps) =
|
|
748
|
+
if let Some(caps) = BLOCKQUOTE_REGEX_FULL.captures(line) {
|
|
840
749
|
let indent_str = caps.get(1).map_or("", |m| m.as_str());
|
|
841
750
|
let markers = caps.get(2).map_or("", |m| m.as_str());
|
|
842
751
|
let spaces_after = caps.get(3).map_or("", |m| m.as_str());
|
|
@@ -873,7 +782,7 @@ impl<'a> LintContext<'a> {
|
|
|
873
782
|
}
|
|
874
783
|
|
|
875
784
|
// Check for ATX headings
|
|
876
|
-
if let Some(caps) =
|
|
785
|
+
if let Some(caps) = ATX_HEADING_REGEX.captures(line) {
|
|
877
786
|
let leading_spaces = caps.get(1).map_or("", |m| m.as_str());
|
|
878
787
|
let hashes = caps.get(2).map_or("", |m| m.as_str());
|
|
879
788
|
let spaces_after = caps.get(3).map_or("", |m| m.as_str());
|
|
@@ -926,7 +835,7 @@ impl<'a> LintContext<'a> {
|
|
|
926
835
|
// Check for Setext headings (need to look at next line)
|
|
927
836
|
else if i + 1 < content_lines.len() {
|
|
928
837
|
let next_line = content_lines[i + 1];
|
|
929
|
-
if !lines[i + 1].in_code_block &&
|
|
838
|
+
if !lines[i + 1].in_code_block && SETEXT_UNDERLINE_REGEX.is_match(next_line) {
|
|
930
839
|
// Skip if next line is front matter delimiter
|
|
931
840
|
if in_front_matter && i < front_matter_end {
|
|
932
841
|
continue;
|
|
@@ -1287,218 +1196,6 @@ impl<'a> LintContext<'a> {
|
|
|
1287
1196
|
|
|
1288
1197
|
list_blocks
|
|
1289
1198
|
}
|
|
1290
|
-
|
|
1291
|
-
/// Parse all bare URLs and emails in the content
|
|
1292
|
-
fn parse_bare_urls(
|
|
1293
|
-
content: &str,
|
|
1294
|
-
lines: &[LineInfo],
|
|
1295
|
-
code_blocks: &[(usize, usize)],
|
|
1296
|
-
links: &[ParsedLink],
|
|
1297
|
-
images: &[ParsedImage],
|
|
1298
|
-
reference_defs: &[ReferenceDef],
|
|
1299
|
-
) -> Vec<BareUrl> {
|
|
1300
|
-
let mut bare_urls = Vec::new();
|
|
1301
|
-
|
|
1302
|
-
// Quick check - if no URLs or emails, return empty
|
|
1303
|
-
if !content.contains("http://")
|
|
1304
|
-
&& !content.contains("https://")
|
|
1305
|
-
&& !content.contains("ftp://")
|
|
1306
|
-
&& !content.contains('@')
|
|
1307
|
-
{
|
|
1308
|
-
return bare_urls;
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
// Build exclusion ranges from links, images, and angle bracket links
|
|
1312
|
-
let mut excluded_ranges: Vec<(usize, usize)> = Vec::new();
|
|
1313
|
-
|
|
1314
|
-
// Exclude link URLs
|
|
1315
|
-
for link in links {
|
|
1316
|
-
if !link.url.is_empty() {
|
|
1317
|
-
excluded_ranges.push((link.byte_offset, link.byte_end));
|
|
1318
|
-
}
|
|
1319
|
-
}
|
|
1320
|
-
|
|
1321
|
-
// Exclude image URLs
|
|
1322
|
-
for image in images {
|
|
1323
|
-
if !image.url.is_empty() {
|
|
1324
|
-
excluded_ranges.push((image.byte_offset, image.byte_end));
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
// Exclude angle bracket links <url> or <email>
|
|
1329
|
-
for angle_match in ANGLE_BRACKET_PATTERN.find_iter(content) {
|
|
1330
|
-
excluded_ranges.push((angle_match.start(), angle_match.end()));
|
|
1331
|
-
}
|
|
1332
|
-
|
|
1333
|
-
// Sort and merge overlapping ranges
|
|
1334
|
-
excluded_ranges.sort_by_key(|r| r.0);
|
|
1335
|
-
let mut merged: Vec<(usize, usize)> = Vec::new();
|
|
1336
|
-
for (start, end) in excluded_ranges {
|
|
1337
|
-
if let Some((_, last_end)) = merged.last_mut() {
|
|
1338
|
-
if *last_end >= start {
|
|
1339
|
-
*last_end = (*last_end).max(end);
|
|
1340
|
-
continue;
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
merged.push((start, end));
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
// Find bare URLs
|
|
1347
|
-
for url_match in BARE_URL_PATTERN.find_iter(content) {
|
|
1348
|
-
let url_start = url_match.start();
|
|
1349
|
-
let mut url_end = url_match.end();
|
|
1350
|
-
|
|
1351
|
-
// Skip if in code block or code span
|
|
1352
|
-
if CodeBlockUtils::is_in_code_block_or_span(code_blocks, url_start) {
|
|
1353
|
-
continue;
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1356
|
-
// Skip if within any excluded range (link/image)
|
|
1357
|
-
let in_any_range = merged.iter().any(|(start, end)| url_start >= *start && url_end <= *end);
|
|
1358
|
-
if in_any_range {
|
|
1359
|
-
continue;
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
|
-
// Check if it's in a reference definition line
|
|
1363
|
-
let mut is_ref_def = false;
|
|
1364
|
-
for ref_def in reference_defs {
|
|
1365
|
-
if let Some(line_info) = lines.get(ref_def.line - 1) {
|
|
1366
|
-
let line_start = line_info.byte_offset;
|
|
1367
|
-
let line_end = if ref_def.line < lines.len() {
|
|
1368
|
-
lines[ref_def.line].byte_offset
|
|
1369
|
-
} else {
|
|
1370
|
-
content.len()
|
|
1371
|
-
};
|
|
1372
|
-
if url_start >= line_start && url_start < line_end {
|
|
1373
|
-
is_ref_def = true;
|
|
1374
|
-
break;
|
|
1375
|
-
}
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
if is_ref_def {
|
|
1379
|
-
continue;
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
// Trim trailing punctuation
|
|
1383
|
-
let raw_url = &content[url_start..url_end];
|
|
1384
|
-
let trailing_punct = ['.', ',', ';', ':', '!', '?'];
|
|
1385
|
-
while url_end > url_start {
|
|
1386
|
-
if let Some(last_char) = raw_url.chars().last() {
|
|
1387
|
-
if trailing_punct.contains(&last_char) {
|
|
1388
|
-
url_end -= last_char.len_utf8();
|
|
1389
|
-
} else {
|
|
1390
|
-
break;
|
|
1391
|
-
}
|
|
1392
|
-
} else {
|
|
1393
|
-
break;
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
|
-
// Manual boundary check
|
|
1398
|
-
let before = if url_start == 0 {
|
|
1399
|
-
None
|
|
1400
|
-
} else {
|
|
1401
|
-
content.get(url_start - 1..url_start)
|
|
1402
|
-
};
|
|
1403
|
-
let after = content.get(url_end..url_end + 1);
|
|
1404
|
-
let is_valid_boundary = before.is_none_or(|c| !c.chars().next().unwrap().is_alphanumeric() && c != "_")
|
|
1405
|
-
&& after.is_none_or(|c| !c.chars().next().unwrap().is_alphanumeric() && c != "_");
|
|
1406
|
-
if !is_valid_boundary {
|
|
1407
|
-
continue;
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
|
-
// Find which line this URL is on
|
|
1411
|
-
let mut line_num = 1;
|
|
1412
|
-
let mut col_start = url_start;
|
|
1413
|
-
for (idx, line_info) in lines.iter().enumerate() {
|
|
1414
|
-
if url_start >= line_info.byte_offset {
|
|
1415
|
-
line_num = idx + 1;
|
|
1416
|
-
col_start = url_start - line_info.byte_offset;
|
|
1417
|
-
} else {
|
|
1418
|
-
break;
|
|
1419
|
-
}
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
// Calculate end column
|
|
1423
|
-
let mut col_end = col_start + (url_end - url_start);
|
|
1424
|
-
if let Some(line_info) = lines.get(line_num - 1) {
|
|
1425
|
-
// For single-line URLs
|
|
1426
|
-
col_end = url_end - line_info.byte_offset;
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
|
-
bare_urls.push(BareUrl {
|
|
1430
|
-
line: line_num,
|
|
1431
|
-
start_col: col_start,
|
|
1432
|
-
end_col: col_end,
|
|
1433
|
-
byte_offset: url_start,
|
|
1434
|
-
byte_end: url_end,
|
|
1435
|
-
text: content[url_start..url_end].to_string(),
|
|
1436
|
-
is_email: false,
|
|
1437
|
-
});
|
|
1438
|
-
}
|
|
1439
|
-
|
|
1440
|
-
// Find bare emails
|
|
1441
|
-
for email_match in BARE_EMAIL_PATTERN.find_iter(content) {
|
|
1442
|
-
let email_start = email_match.start();
|
|
1443
|
-
let email_end = email_match.end();
|
|
1444
|
-
|
|
1445
|
-
// Skip if in code block or code span
|
|
1446
|
-
if CodeBlockUtils::is_in_code_block_or_span(code_blocks, email_start) {
|
|
1447
|
-
continue;
|
|
1448
|
-
}
|
|
1449
|
-
|
|
1450
|
-
// Skip if within any excluded range (link/image)
|
|
1451
|
-
let in_any_range = merged
|
|
1452
|
-
.iter()
|
|
1453
|
-
.any(|(start, end)| email_start >= *start && email_end <= *end);
|
|
1454
|
-
if in_any_range {
|
|
1455
|
-
continue;
|
|
1456
|
-
}
|
|
1457
|
-
|
|
1458
|
-
// Manual boundary check
|
|
1459
|
-
let before = if email_start == 0 {
|
|
1460
|
-
None
|
|
1461
|
-
} else {
|
|
1462
|
-
content.get(email_start - 1..email_start)
|
|
1463
|
-
};
|
|
1464
|
-
let after = content.get(email_end..email_end + 1);
|
|
1465
|
-
let is_valid_boundary = before.is_none_or(|c| {
|
|
1466
|
-
!c.chars().next().unwrap().is_alphanumeric() && c != "_" && c != "."
|
|
1467
|
-
}) && after.is_none_or(|c| {
|
|
1468
|
-
!c.chars().next().unwrap().is_alphanumeric() && c != "_" && c != "."
|
|
1469
|
-
});
|
|
1470
|
-
if !is_valid_boundary {
|
|
1471
|
-
continue;
|
|
1472
|
-
}
|
|
1473
|
-
|
|
1474
|
-
// Find which line this email is on
|
|
1475
|
-
let mut line_num = 1;
|
|
1476
|
-
let mut col_start = email_start;
|
|
1477
|
-
for (idx, line_info) in lines.iter().enumerate() {
|
|
1478
|
-
if email_start >= line_info.byte_offset {
|
|
1479
|
-
line_num = idx + 1;
|
|
1480
|
-
col_start = email_start - line_info.byte_offset;
|
|
1481
|
-
} else {
|
|
1482
|
-
break;
|
|
1483
|
-
}
|
|
1484
|
-
}
|
|
1485
|
-
|
|
1486
|
-
// Calculate end column
|
|
1487
|
-
let col_end = email_end - lines[line_num - 1].byte_offset;
|
|
1488
|
-
|
|
1489
|
-
bare_urls.push(BareUrl {
|
|
1490
|
-
line: line_num,
|
|
1491
|
-
start_col: col_start,
|
|
1492
|
-
end_col: col_end,
|
|
1493
|
-
byte_offset: email_start,
|
|
1494
|
-
byte_end: email_end,
|
|
1495
|
-
text: content[email_start..email_end].to_string(),
|
|
1496
|
-
is_email: true,
|
|
1497
|
-
});
|
|
1498
|
-
}
|
|
1499
|
-
|
|
1500
|
-
bare_urls
|
|
1501
|
-
}
|
|
1502
1199
|
}
|
|
1503
1200
|
|
|
1504
1201
|
/// Merge adjacent list blocks that should be treated as one
|
|
@@ -1545,48 +1242,15 @@ fn merge_adjacent_list_blocks(list_blocks: &mut Vec<ListBlock>) {
|
|
|
1545
1242
|
}
|
|
1546
1243
|
|
|
1547
1244
|
/// Check if content contains patterns that cause the markdown crate to panic
|
|
1548
|
-
fn content_has_problematic_lists(content: &str) -> bool {
|
|
1549
|
-
let lines: Vec<&str> = content.lines().collect();
|
|
1550
|
-
|
|
1551
|
-
// Look for mixed list markers in consecutive lines (which causes the panic)
|
|
1552
|
-
for window in lines.windows(3) {
|
|
1553
|
-
if window.len() >= 2 {
|
|
1554
|
-
let line1 = window[0].trim_start();
|
|
1555
|
-
let line2 = window[1].trim_start();
|
|
1556
|
-
|
|
1557
|
-
// Check if both lines are list items with different markers
|
|
1558
|
-
let is_list1 = line1.starts_with("* ") || line1.starts_with("+ ") || line1.starts_with("- ");
|
|
1559
|
-
let is_list2 = line2.starts_with("* ") || line2.starts_with("+ ") || line2.starts_with("- ");
|
|
1560
|
-
|
|
1561
|
-
if is_list1 && is_list2 {
|
|
1562
|
-
let marker1 = line1.chars().next().unwrap_or(' ');
|
|
1563
|
-
let marker2 = line2.chars().next().unwrap_or(' ');
|
|
1564
|
-
|
|
1565
|
-
// If different markers, this could cause a panic
|
|
1566
|
-
if marker1 != marker2 {
|
|
1567
|
-
return true;
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
}
|
|
1571
|
-
}
|
|
1572
|
-
|
|
1573
|
-
false
|
|
1574
|
-
}
|
|
1575
1245
|
|
|
1576
1246
|
#[cfg(test)]
|
|
1577
1247
|
mod tests {
|
|
1578
1248
|
use super::*;
|
|
1579
|
-
use markdown::mdast::{Heading, Node};
|
|
1580
1249
|
|
|
1581
1250
|
#[test]
|
|
1582
1251
|
fn test_empty_content() {
|
|
1583
1252
|
let ctx = LintContext::new("");
|
|
1584
1253
|
assert_eq!(ctx.content, "");
|
|
1585
|
-
// Should be a Root node with no children
|
|
1586
|
-
match &ctx.ast {
|
|
1587
|
-
Node::Root(root) => assert!(root.children.is_empty()),
|
|
1588
|
-
_ => panic!("AST root is not Root node"),
|
|
1589
|
-
}
|
|
1590
1254
|
assert_eq!(ctx.line_offsets, vec![0]);
|
|
1591
1255
|
assert_eq!(ctx.offset_to_line_col(0), (1, 1));
|
|
1592
1256
|
assert_eq!(ctx.lines.len(), 0);
|
|
@@ -1596,17 +1260,6 @@ mod tests {
|
|
|
1596
1260
|
fn test_single_line() {
|
|
1597
1261
|
let ctx = LintContext::new("# Hello");
|
|
1598
1262
|
assert_eq!(ctx.content, "# Hello");
|
|
1599
|
-
// Should parse a heading
|
|
1600
|
-
match &ctx.ast {
|
|
1601
|
-
Node::Root(root) => {
|
|
1602
|
-
assert_eq!(root.children.len(), 1);
|
|
1603
|
-
match &root.children[0] {
|
|
1604
|
-
Node::Heading(Heading { depth, .. }) => assert_eq!(*depth, 1),
|
|
1605
|
-
_ => panic!("First child is not a Heading"),
|
|
1606
|
-
}
|
|
1607
|
-
}
|
|
1608
|
-
_ => panic!("AST root is not Root node"),
|
|
1609
|
-
}
|
|
1610
1263
|
assert_eq!(ctx.line_offsets, vec![0]);
|
|
1611
1264
|
assert_eq!(ctx.offset_to_line_col(0), (1, 1));
|
|
1612
1265
|
assert_eq!(ctx.offset_to_line_col(3), (1, 4));
|
|
@@ -1971,7 +1971,18 @@ fn run_check(args: &CheckArgs, global_config_path: Option<&str>, no_config: bool
|
|
|
1971
1971
|
let start_time = Instant::now();
|
|
1972
1972
|
|
|
1973
1973
|
// Choose processing strategy based on file count and fix mode
|
|
1974
|
-
|
|
1974
|
+
// Also check if it's a single small file to avoid parallel overhead
|
|
1975
|
+
let single_small_file = if file_paths.len() == 1 {
|
|
1976
|
+
if let Ok(metadata) = fs::metadata(&file_paths[0]) {
|
|
1977
|
+
metadata.len() < 10_000 // 10KB threshold
|
|
1978
|
+
} else {
|
|
1979
|
+
false
|
|
1980
|
+
}
|
|
1981
|
+
} else {
|
|
1982
|
+
false
|
|
1983
|
+
};
|
|
1984
|
+
|
|
1985
|
+
let use_parallel = file_paths.len() > 1 && !args._fix && !single_small_file; // Don't parallelize fixes or small files
|
|
1975
1986
|
|
|
1976
1987
|
// Collect all warnings for statistics if requested
|
|
1977
1988
|
let mut all_warnings_for_stats = Vec::new();
|
|
@@ -250,6 +250,7 @@ impl Rule for MD009TrailingSpaces {
|
|
|
250
250
|
RuleCategory::Whitespace
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
+
|
|
253
254
|
fn default_config_section(&self) -> Option<(String, toml::Value)> {
|
|
254
255
|
let default_config = MD009Config::default();
|
|
255
256
|
let json_value = serde_json::to_value(&default_config).ok()?;
|