Skip to content

Support user-provided Prism syntax highlighting themes#324

Merged
schuyler merged 3 commits into
mainfrom
claude/resolve-issue-311-G4Ecx
Feb 20, 2026
Merged

Support user-provided Prism syntax highlighting themes#324
schuyler merged 3 commits into
mainfrom
claude/resolve-issue-311-G4Ecx

Conversation

@schuyler

Copy link
Copy Markdown
Owner

Summary

  • Add support for loading custom Prism syntax highlighting themes from ~/Library/Application Support/MacDown 3000/Prism/themes/
  • User-provided themes override bundled themes on name conflict, following the same pattern used by HTML Stylesheets and Editor Themes
  • Add Reveal/Reload segmented control in the HTML Preferences pane next to the syntax highlighting theme dropdown
  • Update QuickLook renderer to also check Application Support for user themes

Related to #311

Changes

Core Utilities (MPUtilities.h/m)

  • New kMPPrismThemesDirectoryName constant ("Prism/themes")
  • New MPHighlightingThemeURLForNameInPaths() — checks user directory first, then bundle, with default fallback
  • New MPListHighlightingThemesInPaths() — merges themes from both sources, deduplicates, sorts alphabetically
  • Refactored existing MPHighlightingThemeURLForName() to delegate to the new path-parameterized function

Preferences UI (MPHtmlPreferencesViewController.m/.xib)

  • Refactored loadHighlightingThemes to use MPListHighlightingThemesInPaths
  • Added highlightingThemeFunctions segmented control with Reveal and Reload buttons
  • Reveal creates the Prism/themes/ directory if needed, then opens in Finder
  • Segmented control enabled state bound to htmlSyntaxHighlighting preference

QuickLook Renderer (MPQuickLookRenderer.m)

  • Updated local MPHighlightingThemeURLForName() to check Application Support before bundle resources

Tests (MPUtilityTests.m)

  • 11 new unit tests covering URL resolution and theme listing:
    • User theme present, bundle fallback, user overrides bundle, default fallback, CSS extension handling
    • Bundled theme listing, user theme inclusion, deduplication, non-CSS filtering, empty handling, sorting

Test plan

  • All 12 MPUtilityTests pass (11 new + 1 existing)
  • CI passes on all 4 macOS runners (14, 15, 15-intel, 26)
  • 100% test coverage on MPUtilityTests.m
  • Manual: Place a custom .css theme in ~/Library/Application Support/MacDown 3000/Prism/themes/
  • Manual: Verify custom theme appears in the Rendering preferences dropdown
  • Manual: Verify Reveal button opens the Prism/themes directory in Finder
  • Manual: Verify Reload button refreshes the theme list
  • Manual: Verify selecting a custom theme applies it to the preview

https://claude.ai/code/session_018hqL5LCNBvbJoPbMXsJoG2

Related to #311

Tests for MPHighlightingThemeURLForNameInPaths():
- User theme takes precedence when present
- Falls back to bundle theme when no user theme exists
- User overrides bundle on name conflict
- Falls back to default prism.css for unknown names
- Handles .css extension in theme name

Tests for MPListHighlightingThemesInPaths():
- Returns bundled themes
- Includes user-provided themes
- Deduplicates on name conflict
- Ignores non-CSS files
- Returns empty array when no themes exist
- Returns themes sorted alphabetically

Stub implementations return nil/empty to ensure tests fail (TDD).

https://claude.ai/code/session_018hqL5LCNBvbJoPbMXsJoG2
Related to #311

Core changes:
- Add kMPPrismThemesDirectoryName constant for "Prism/themes" path
- Implement MPHighlightingThemeURLForNameInPaths() to check Application
  Support first, then bundle, with default fallback
- Implement MPListHighlightingThemesInPaths() to merge and deduplicate
  themes from both sources, sorted alphabetically
- Refactor MPHighlightingThemeURLForName() to delegate to the new
  path-parameterized function

Preferences UI:
- Refactor loadHighlightingThemes to use MPListHighlightingThemesInPaths
- Add Reveal/Reload segmented control for Prism themes directory
- Reveal creates ~/Library/Application Support/MacDown 3000/Prism/themes/
  if it doesn't exist, then opens it in Finder

QuickLook renderer:
- Update local MPHighlightingThemeURLForName() to check Application
  Support before bundle resources

XIB:
- Add highlightingThemeFunctions segmented control next to theme dropdown
- Bind enabled state to htmlSyntaxHighlighting preference

https://claude.ai/code/session_018hqL5LCNBvbJoPbMXsJoG2
@github-actions

github-actions Bot commented Feb 20, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Report

Current Coverage: 55.68%

Coverage Details (Summary)
Name                                                                                                                                   Coverage            
-------------------------------------------------------------------------------------------------------------------------------------- ------------------- 
MASPreferences.bundle                                                                                                                  0.00% (0/0)         
MacDown 3000.app                                                                                                                       59.14% (7954/13450) 
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Preferences/MPHtmlPreferencesViewController.m                              0.00% (0/112)       
        MPPrismDefaultThemeName                                                                                                        0.00% (0/2)         
        -[MPHtmlPreferencesViewController viewIdentifier]                                                                              0.00% (0/3)         
        -[MPHtmlPreferencesViewController toolbarItemImage]                                                                            0.00% (0/3)         
        -[MPHtmlPreferencesViewController toolbarItemLabel]                                                                            0.00% (0/2)         
        -[MPHtmlPreferencesViewController viewWillAppear]                                                                              0.00% (0/4)         
        -[MPHtmlPreferencesViewController changeStylesheet:]                                                                           0.00% (0/7)         
        -[MPHtmlPreferencesViewController changeHighlightingTheme:]                                                                    0.00% (0/7)         
        -[MPHtmlPreferencesViewController invokeStylesheetFunction:]                                                                   0.00% (0/23)        
        -[MPHtmlPreferencesViewController invokeHighlightingThemeFunction:]                                                            0.00% (0/33)        
        -[MPHtmlPreferencesViewController loadStylesheets]                                                                             0.00% (0/13)        
        -[MPHtmlPreferencesViewController loadHighlightingThemes]                                                                      0.00% (0/15)        
    /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/MacDown/Code/Utility/FileURLInlining.m                                                  26.60% (25/94)      
        +[FileURLInlining inlineFromIterable:]                                                                                         0.00% (0/11)        
        -[FileURLInlining initWithURL:]                                                                                                0.00% (0/6)         
        -[FileURLInlining init]                                                                                                        100.00% (3/3)       
        -[FileURLInlining inlineContent]                                                                                               0.00% (0/9)         
        -[FileURLInlining imageContent]                                                                                                0.00% (0/12)        
        +[FileURLInlining mimeTypeForFilePath:]                                                                                        100.00% (22/22)     
        -[FileURLInlining clippingContent]                                                                                             0.00% (0/4)         
        +[FileURLInlining isTextClippingAtPath:]                                                                                       0.00% (0/12)        
        +[FileURLInlining textContentFromClipping:]                                                                                    0.00% (0/15)        
    /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                                             41.78% (94/225)     
        MPOpenBundledFile                                                                                                              95.83% (23/24)      
        treat                                                                                                                          20.00% (6/30)       
        __treat_block_invoke                                                                                                           0.00% (0/3)         
        -[MPMainController applicationDidFinishLaunching:]                                                                             100.00% (6/6)       
        -[MPMainController openUrlSchemeAppleEvent:withReplyEvent:]                                                                    0.00% (0/39)        
        -[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)         

... (2680 more lines truncated)

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

@schuyler schuyler merged commit 8a21156 into main Feb 20, 2026
9 checks passed
@schuyler schuyler deleted the claude/resolve-issue-311-G4Ecx branch February 20, 2026 15:18
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