Skip to content

Enable checkbox support by default with interactive toggle#270

Merged
schuyler merged 4 commits intomainfrom
claude/enable-checkbox-support-vqPxR
Jan 13, 2026
Merged

Enable checkbox support by default with interactive toggle#270
schuyler merged 4 commits intomainfrom
claude/enable-checkbox-support-vqPxR

Conversation

@schuyler
Copy link
Copy Markdown
Owner

Summary

This PR implements GitHub issue #269 (Render Check Boxes feature request) with the following enhancements:

  • Enable checkbox rendering by default for all users (new and existing) using a one-time migration pattern similar to the text substitution fix in d1cd8c2
  • Interactive checkbox support: Clicking a checkbox in the preview window now toggles its checked/unchecked state in the source document
  • Documentation update: Updated help.md to reflect the new interactive checkbox capability

Implementation Details

Migration (MPPreferences.m)

One-time migration enables htmlTaskList for users who haven't explicitly disabled it.

Checkbox Indexing (hoedown_html_patch.c)

Added data-checkbox-index attribute to rendered checkboxes. Indices are assigned in depth-first order to match hoedown's nested list rendering behavior.

Click Handling (tasklist.js)

Checkboxes are now clickable. Clicks trigger a custom URL scheme (x-macdown-checkbox://toggle/N) that communicates back to the Objective-C code.

Toggle Logic (MPDocument.m)

The toggleCheckboxAtIndex:inMarkdown: method locates and toggles the specified checkbox in the source document, using depth-first ordering to match the rendered HTML indices.

Test Plan

  • 4 migration tests (MPPreferencesTests.m)
  • 6 checkbox rendering tests (MPMarkdownRenderingTests.m)
  • 25 toggle logic and URL scheme tests (MPCheckboxToggleTests.m)
  • All tests pass on macOS 14, 15, 15-intel, and 26

Code Review Issues Addressed

Fixed critical bug identified during code review: the toggle function originally used document order indexing, but hoedown assigns indices in depth-first order (nested items before parent). This mismatch would have caused the wrong checkbox to be toggled in nested lists.

Related to #269

This commit implements GitHub issue #269, adding:

1. **Enable checkbox/task list by default** - Added one-time migration in
   MPPreferences.m that enables htmlTaskList for all users who haven't
   explicitly set a preference (following the pattern from #268).

2. **Interactive checkboxes** - Clicking a checkbox in the preview now
   toggles its state in the source document:
   - Modified hoedown_html_patch.c to add data-checkbox-index attribute
   - Updated tasklist.js with click handlers using custom URL scheme
   - Added handleCheckboxToggle: and toggleCheckboxAtIndex:inMarkdown:
     methods in MPDocument.m to handle the toggle logic

3. **Comprehensive tests** - Added TDD tests covering:
   - Migration behavior (MPPreferencesTests.m)
   - Checkbox index rendering (MPMarkdownRenderingTests.m)
   - Toggle logic and edge cases (MPCheckboxToggleTests.m)

4. **Updated golden files** - Updated task-lists.html and mixed-complex.html
   to include the new data-checkbox-index attributes.

Related to #269
Updated task-lists.html and mixed-complex.html golden files to use
the correct checkbox indices. Hoedown processes nested lists in
depth-first order (children before parent), so the indices reflect
that: children get lower indices than their parent element.

Related to #269
Code review identified a critical bug: the toggle function used document
order (line by line) but hoedown assigns checkbox indices in depth-first
order (nested children before parent). This meant clicking a nested
checkbox would toggle the wrong one.

Changes:
- Rewrote toggleCheckboxAtIndex: to use depth-first ordering via a
  stack-based algorithm that matches hoedown's rendering behavior
- Changed regex to only match lowercase [x] (hoedown ignores capital X)
- Added thread-safety documentation to the global counter
- Added tests for parent checkbox toggling and depth-first ordering

Related to #269
The help file previously stated that clicking checkboxes in the preview
window was not supported. This is now outdated - the feature has been
implemented as part of issue #269.

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

github-actions bot commented Jan 13, 2026

Code Coverage Report

Current Coverage: 52.22%

Coverage Details (Summary)
Name                                                                                                                                   Coverage            
-------------------------------------------------------------------------------------------------------------------------------------- ------------------- 
MASPreferences.bundle                                                                                                                  0.00% (0/0)         
MacDown 3000.app                                                                                                                       58.28% (7458/12797) 
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Utility/MPMathJaxListener.m                                                0.00% (0/26)        
        -[MPMathJaxListener callbacks]                                                                                                 0.00% (0/5)         
        -[MPMathJaxListener addCallback:forKey:]                                                                                       0.00% (0/3)         
        -[MPMathJaxListener invokeCallbackForKey:]                                                                                     0.00% (0/8)         
        +[MPMathJaxListener isSelectorExcludedFromWebScript:]                                                                          0.00% (0/5)         
        +[MPMathJaxListener isKeyExcludedFromWebScript:]                                                                               0.00% (0/5)         
    /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/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)      
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Extension/hoedown_html_patch.c                                             86.47% (115/133)    
        hoedown_patch_reset_checkbox_index                                                                                             100.00% (3/3)       
        hoedown_patch_get_checkbox_index                                                                                               0.00% (0/3)         
        hoedown_patch_render_blockcode                                                                                                 89.09% (49/55)      
        hoedown_patch_render_listitem                                                                                                  100.00% (44/44)     
        hoedown_patch_render_toc_header                                                                                                67.86% (19/28)      
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Application/MPMainController.m                                             42.91% (106/247)    
        MPOpenBundledFile                                                                                                              96.67% (29/30)      
        __MPOpenBundledFile_block_invoke                                                                                               85.71% (6/7)        
        treat                                                                                                                          20.00% (6/30)       
        __treat_block_invoke                                                                                                           0.00% (0/3)         
        -[MPMainController applicationDidFinishLaunching:]                                                                             100.00% (6/6)       
        -[MPMainController openUrlSchemeAppleEvent:withReplyEvent:]                                                                    0.00% (0/45)        
        __59-[MPMainController openUrlSchemeAppleEvent:withReplyEvent:]_block_invoke                                                   0.00% (0/7)         
        -[MPMainController valueForKey:fromQueryItems:]                                                                                0.00% (0/5)         
        -[MPMainController preferences]                                                                                                100.00% (3/3)       
        -[MPMainController preferencesWindowController]                                                                                0.00% (0/18)        
        -[MPMainController showPreferencesWindow:]                                                                                     0.00% (0/2)         
        -[MPMainController showHelp:]                                                                                                  100.00% (3/3)       
        -[MPMainController showContributing:]                                                                                          100.00% (3/3)       
        -[MPMainController init]                                                                                                       90.91% (10/11)      
        -[MPMainController applicationShouldOpenUntitledFile:]                                                                         80.00% (4/5)        
        -[MPMainController applicationDidBecomeActive:]                                                                                100.00% (5/5)       
        -[MPMainController copyFiles]                                                                                                  63.33% (19/30)      
        -[MPMainController openPendingFiles]                                                                                           29.41% (5/17)       
        -[MPMainController openPendingPipedContent]                                                                                    28.57% (4/14)       
        -[MPMainController showFirstLaunchTips]                                                                                        100.00% (3/3)       
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Utility/MPUtilities.m                                                      65.62% (105/160)    
        MPDataRootDirectory                                                                                                            100.00% (14/14)     
        MPDataDirectory                                                                                                                100.00% (5/5)       
        MPPathToDataFile                                                                                                               100.00% (4/4)       
        MPListEntriesForDirectory                                                                                                      0.00% (0/19)        

... (2438 more lines truncated)

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

@schuyler schuyler merged commit d46b7d5 into main Jan 13, 2026
10 checks passed
@schuyler schuyler deleted the claude/enable-checkbox-support-vqPxR branch January 13, 2026 01:49
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