Skip to content

Address issue #143: Horizontal rule regex edge cases and fragile header detection#185

Merged
schuyler merged 3 commits intomainfrom
claude/resolve-issue-143-01CZ5iyHRbEpHpVRNpWy7Fnx
Nov 25, 2025
Merged

Address issue #143: Horizontal rule regex edge cases and fragile header detection#185
schuyler merged 3 commits intomainfrom
claude/resolve-issue-143-01CZ5iyHRbEpHpVRNpWy7Fnx

Conversation

@schuyler
Copy link
Copy Markdown
Owner

Summary

This PR fixes edge cases in horizontal rule detection and improves scroll synchronization reliability for MacDown 3000. The changes maintain backward compatibility while improving CommonMark compliance.

Changes Made

  1. Updated hrRegex pattern (MPDocument.m:1850)

    • Added support for 0-3 leading spaces per CommonMark spec
    • Pattern: ^[ ]{0,3}(([-][ ]*){3,}|([*][ ]*){3,}|([_][ ]*){3,})$
    • Handles edge cases: spacing variants (- - -), leading whitespace
    • Changed \s* to [ ]* for more precise space matching
  2. Fixed setext header detection bug (MPDocument.m:1886)

    • Removed incorrect !isHorizontalRule check
    • Now correctly detects setext headers like Text\n---
    • dashRegex pattern ^([-]+)$ already ensures only consecutive dashes match
  3. Added comprehensive documentation (MPDocument.m:1745-1916)

    • Documented horizontal rule vs setext header distinction
    • Listed all edge cases with examples
    • Added CommonMark compatibility notes
    • Explained previousLineHadContent flag logic
    • Added detailed inline comments throughout
  4. Added 40 comprehensive tests (MPScrollSyncTests.m:573-1075)

    • Basic HR types (-, *, _)
    • Spacing variants (---, - - -, irregular spacing)
    • Minimum character requirements (2 vs 3+ characters)
    • Setext vs HR context (previousLineHadContent behavior)
    • Leading whitespace (0-3 spaces allowed, 4+ = code)
    • Invalid patterns (mixed characters, trailing text)
    • Complex contexts (interaction with other elements)
    • Edge cases (tabs, emphasis, underscores)
  5. Updated planning documents

    • Test counts: 28 → 68 tests
    • Line counts: ~574 → ~1,075 lines
    • Updated coverage metrics

Related Issue

Related to #143

Manual Testing Plan

See full testing plan in comments. Key scenarios:

Review Notes

  • TDD Methodology: 40 comprehensive tests added first
  • Code Review: Critical bug fixed (setext header detection)
  • Documentation: Planning documents updated
  • Backward Compatibility: All changes maintain existing behavior

The issue will remain open for manual verification.

This commit fixes edge cases in horizontal rule detection and improves
code documentation for the scroll synchronization system.

Changes made:

1. **Updated hrRegex pattern** (MPDocument.m:1850)
   - Now allows 0-3 leading spaces per CommonMark spec
   - Pattern: ^[ ]{0,3}(([-][ ]*){3,}|([*][ ]*){3,}|([_][ ]*){3,})$
   - Handles edge cases: spacing variants, leading whitespace
   - Maintains backward compatibility with MacDown behavior

2. **Added comprehensive documentation** (MPDocument.m:1745-1783)
   - Documented horizontal rule vs setext header distinction
   - Listed all edge cases with examples
   - Added CommonMark compatibility notes
   - Referenced issue #143 for future maintainability

3. **Added detailed inline comments** (MPDocument.m:1829-1910)
   - Explained each regex pattern's purpose
   - Documented previousLineHadContent flag logic
   - Added comments explaining setext header detection
   - Clarified why checks are performed in specific order

4. **Added 40 comprehensive tests** (MPScrollSyncTests.m:573-1075)
   - Tests for all three HR types (-, *, _)
   - Spacing variant tests (---, - - -, irregular spacing)
   - Minimum character requirement tests (2 vs 3+ characters)
   - Setext vs HR context tests (previousLineHadContent behavior)
   - Leading whitespace tests (0-3 spaces allowed, 4+ = code)
   - Invalid pattern tests (mixed characters, trailing text)
   - Complex context tests (interaction with other elements)
   - Edge case tests (tabs, emphasis, underscores)

All tests follow project conventions using XCTAssertNoThrow pattern
appropriate for headless testing without UI context.

Related to #143
Remove incorrect !isHorizontalRule check that prevented setext headers
with 3+ dashes from being detected correctly.

The dashRegex pattern ^([-]+)$ only matches consecutive dashes (---,
not - - -), so the additional !isHorizontalRule check was unnecessary
and incorrectly prevented valid setext headers like "Text\n---" from
being detected.

This ensures:
- "Text\n---" → Detected as setext header ✓
- "\n---" → NOT detected as setext header (no prior content) ✓
- "Text\n- - -" → NOT detected as setext header (spaced, not consecutive) ✓

Identified by code review.

Related to #143
Updated test counts and coverage metrics after adding 40 comprehensive
tests for horizontal rule regex edge cases and setext header detection.

Changes:
- MPScrollSyncTests.m: 574 → 1,075 lines (501 lines added)
- Test count: 28 → 68 tests (40 tests added)
- Total test code: ~1,396 → ~1,897 lines
- Test coverage ratio: ~22 → ~30 lines of tests per source file

Updated files:
- plans/test_coverage_improvement_plan.md
- plans/infrastructure_evaluation.md

Related to #143
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Nov 25, 2025

Code Coverage Report

Current Coverage: 41.74%

Coverage Details (Summary)
Name                                                                                                                                   Coverage            
-------------------------------------------------------------------------------------------------------------------------------------- ------------------- 
MASPreferences.bundle                                                                                                                  0.00% (0/0)         
MacDown 3000.app                                                                                                                       53.90% (6711/12450) 
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Extension/NSColor+HTML.m                                                   94.05% (332/353)    
        +[NSColor(HTML) colorWithHexString:]                                                                                           94.12% (16/17)      
        +[NSColor(HTML) colorWithHTMLName:]                                                                                            89.13% (164/184)    
        __35+[NSColor(HTML) colorWithHTMLName:]_block_invoke                                                                           100.00% (152/152)   
    /Users/runner/work/macdown3000/macdown3000/Dependency/peg-markdown-highlight/HGMarkdownHighlighter.m                               75.31% (421/559)    
        styleparsing_error_callback                                                                                                    0.00% (0/10)        
        -[HGMarkdownHighlighter init]                                                                                                  92.86% (13/14)      
        -[HGMarkdownHighlighter initWithTextView:]                                                                                     83.33% (5/6)        
        -[HGMarkdownHighlighter initWithTextView:waitInterval:]                                                                        83.33% (5/6)        
        -[HGMarkdownHighlighter initWithTextView:waitInterval:styles:]                                                                 0.00% (0/6)         
        -[HGMarkdownHighlighter parseText:]                                                                                            100.00% (9/9)       
        -[HGMarkdownHighlighter convertOffsets:text:]                                                                                  26.19% (11/42)      
        -[HGMarkdownHighlighter requestParsing]                                                                                        100.00% (15/15)     
        __39-[HGMarkdownHighlighter requestParsing]_block_invoke                                                                       100.00% (12/12)     
        __39-[HGMarkdownHighlighter requestParsing]_block_invoke.55                                                                    100.00% (3/3)       
        __39-[HGMarkdownHighlighter requestParsing]_block_invoke.67                                                                    100.00% (4/4)       
        -[HGMarkdownHighlighter getClearFontTraitMask:]                                                                                88.89% (16/18)      
        -[HGMarkdownHighlighter clearHighlightingForRange:]                                                                            100.00% (31/31)     
        __51-[HGMarkdownHighlighter clearHighlightingForRange:]_block_invoke                                                           50.00% (4/8)        
        -[HGMarkdownHighlighter readClearTextStylesFromTextView]                                                                       100.00% (17/17)     
        -[HGMarkdownHighlighter applyHighlighting:withRange:]                                                                          80.00% (60/75)      
        __53-[HGMarkdownHighlighter applyHighlighting:withRange:]_block_invoke                                                         92.31% (12/13)      
        -[HGMarkdownHighlighter applyVisibleRangeHighlighting]                                                                         100.00% (16/16)     
        -[HGMarkdownHighlighter clearHighlighting]                                                                                     100.00% (3/3)       
        -[HGMarkdownHighlighter cacheElementList:]                                                                                     100.00% (6/6)       
        -[HGMarkdownHighlighter clearElementsCache]                                                                                    100.00% (2/2)       
        -[HGMarkdownHighlighter textViewTextDidChange:]                                                                                0.00% (0/11)        
        __47-[HGMarkdownHighlighter textViewTextDidChange:]_block_invoke                                                               0.00% (0/3)         
        -[HGMarkdownHighlighter textViewDidScroll:]                                                                                    27.27% (3/11)       
        __43-[HGMarkdownHighlighter textViewDidScroll:]_block_invoke                                                                   0.00% (0/6)         
        __43-[HGMarkdownHighlighter textViewDidScroll:]_block_invoke_2                                                                 0.00% (0/3)         
        -[HGMarkdownHighlighter getDefaultStyles]                                                                                      100.00% (27/27)     
        -[HGMarkdownHighlighter applyStyleDependenciesToTargetTextView]                                                                85.71% (12/14)      
        -[HGMarkdownHighlighter setStyles:]                                                                                            75.00% (6/8)        
        -[HGMarkdownHighlighter getDefaultSelectedTextAttributes]                                                                      100.00% (7/7)       
        -[HGMarkdownHighlighter handleStyleParsingError:]                                                                              0.00% (0/12)        
        -[HGMarkdownHighlighter applyStylesFromStylesheet:withErrorHandler:]                                                           81.40% (70/86)      
        -[HGMarkdownHighlighter setTargetTextView:]                                                                                    85.71% (6/7)        
        -[HGMarkdownHighlighter parseAndHighlightNow]                                                                                  100.00% (3/3)       
        -[HGMarkdownHighlighter highlightNow]                                                                                          100.00% (3/3)       
        -[HGMarkdownHighlighter activate]                                                                                              91.67% (22/24)      
        -[HGMarkdownHighlighter deactivate]                                                                                            100.00% (18/18)     
    /Users/runner/work/macdown3000/macdown3000/Dependency/peg-markdown-highlight/HGMarkdownHighlightingStyle.m                         87.69% (57/65)      
        +[HGMarkdownHighlightingStyle colorFromARGBColor:]                                                                             100.00% (6/6)       
        -[HGMarkdownHighlightingStyle initWithType:attributesToAdd:toRemove:fontTraitsToAdd:]                                          88.89% (8/9)        
        -[HGMarkdownHighlightingStyle initWithStyleAttributes:baseFont:]                                                               86.00% (43/50)      

... (2099 more lines truncated)

📊 **Full coverage report available in workflow artifacts**

@schuyler schuyler merged commit e075eed into main Nov 25, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants