Skip to content

Add MutationObserver to viz.init.js for live-edit Graphviz re-rendering#357

Merged
schuyler merged 1 commit into
mainfrom
claude/issue-332-graphviz-mutation-observer
Apr 8, 2026
Merged

Add MutationObserver to viz.init.js for live-edit Graphviz re-rendering#357
schuyler merged 1 commit into
mainfrom
claude/issue-332-graphviz-mutation-observer

Conversation

@schuyler

@schuyler schuyler commented Apr 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • viz.init.js: adds a rendering guard flag and a MutationObserver that watches for .language-{engine} elements across all 6 Graphviz engines; calls init() when any are found after body.innerHTML replacement. Loop prevention is structural — doGraphviz() replaces the triggering <code> element with SVG before the observer can fire again.
  • MPGraphvizRenderingTests.m: new test file mirroring MPMermaidRenderingTests.m; 15 tests covering code block rendering, script inclusion/exclusion, preference change detection, style changes, multiple diagrams, mixed content, edge cases, and graphviz+mermaid coexistence.
  • project.pbxproj: registers new test file in the MacDownTests target.

This is the same class of bug fixed for Mermaid in #331 / PR #333.

Test plan

  • All four CI runners passed (macos-14, macos-15, macos-15-intel, macos-26)
  • Manual: open a doc with a dot fence, edit it — diagram re-renders without full reload

Related to #332

Related to #332

window.load doesn't fire when MPDocument.m replaces body.innerHTML
during live editing, so Graphviz diagrams never rendered after the
initial page load. This is the same class of bug fixed for Mermaid
in #331 / PR #333.

Changes:
- viz.init.js: add rendering guard flag and MutationObserver that
  watches for .language-{engine} elements across all 6 Graphviz
  engines (circo, dot, fdp, neato, osage, twopi); calls init() when
  any are found. Loop prevention is natural: doGraphviz() replaces
  the code element with SVG, so the trigger element disappears before
  the observer can fire again.
- MPGraphvizRenderingTests.m: new test file mirroring
  MPMermaidRenderingTests.m; covers code block rendering, script
  inclusion/exclusion, preference change detection, multiple diagrams,
  mixed content, edge cases, and graphviz+mermaid coexistence.
- project.pbxproj: register MPGraphvizRenderingTests.m in
  MacDownTests target.
@github-actions

github-actions Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Report

Current Coverage: 57.74%

Coverage Details (Summary)
Name                                                                                                                                   Coverage            
-------------------------------------------------------------------------------------------------------------------------------------- ------------------- 
MASPreferences.bundle                                                                                                                  0.00% (0/0)         
MacDown 3000.app                                                                                                                       59.88% (8280/13828) 
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Document/MPDocument.m                                                      53.29% (1133/2126)  
        MPEditorPreferenceKeyWithValueKey                                                                                              85.71% (6/7)        
        MPEditorKeysToObserve                                                                                                          100.00% (15/15)     
        __MPEditorKeysToObserve_block_invoke                                                                                           100.00% (10/10)     
        MPEditorPreferencesToObserve                                                                                                   100.00% (14/14)     
        __MPEditorPreferencesToObserve_block_invoke                                                                                    100.00% (9/9)       
        MPRectStringForAutosaveName                                                                                                    100.00% (6/6)       
        MPAreNilableStringsEqual                                                                                                       100.00% (3/3)       
        MPGetWebViewBackgroundColor                                                                                                    0.00% (0/9)         
        -[NSURL(Convert) absoluteBaseURLString]                                                                                        0.00% (0/6)         
        -[WebView(Shortcut) enclosingScrollView]                                                                                       100.00% (3/3)       
        -[MPPreferences(Hoedown) extensionFlags]                                                                                       78.57% (22/28)      
        -[MPPreferences(Hoedown) rendererFlags]                                                                                        75.00% (9/12)       
        MPGetPreviewLoadingCompletionHandler                                                                                           100.00% (26/26)     
        __MPGetPreviewLoadingCompletionHandler_block_invoke                                                                            100.00% (23/23)     
        -[MPDocument preferences]                                                                                                      100.00% (3/3)       
        -[MPDocument markdown]                                                                                                         100.00% (3/3)       
        -[MPDocument setMarkdown:]                                                                                                     100.00% (3/3)       
        -[MPDocument html]                                                                                                             0.00% (0/3)         
        -[MPDocument toolbarVisible]                                                                                                   0.00% (0/3)         
        -[MPDocument previewVisible]                                                                                                   100.00% (3/3)       
        -[MPDocument editorVisible]                                                                                                    100.00% (3/3)       
        -[MPDocument needsHtml]                                                                                                        80.00% (4/5)        
        -[MPDocument setTotalWords:]                                                                                                   0.00% (0/7)         
        -[MPDocument setTotalCharacters:]                                                                                              0.00% (0/7)         
        -[MPDocument setTotalCharactersNoSpaces:]                                                                                      0.00% (0/8)         
        -[MPDocument setAutosaveName:]                                                                                                 100.00% (4/4)       
        -[MPDocument init]                                                                                                             90.00% (9/10)       
        -[MPDocument windowNibName]                                                                                                    100.00% (3/3)       
        -[MPDocument windowControllerDidLoadNib:]                                                                                      100.00% (99/99)     
        __41-[MPDocument windowControllerDidLoadNib:]_block_invoke                                                                     100.00% (3/3)       
        __41-[MPDocument windowControllerDidLoadNib:]_block_invoke.249                                                                 100.00% (6/6)       
        -[MPDocument reloadFromLoadedString]                                                                                           100.00% (8/8)       
        -[MPDocument close]                                                                                                            13.33% (4/30)       
        +[MPDocument autosavesInPlace]                                                                                                 100.00% (3/3)       
        +[MPDocument writableTypes]                                                                                                    100.00% (3/3)       
        -[MPDocument isDocumentEdited]                                                                                                 100.00% (5/5)       
        -[MPDocument writeToURL:ofType:error:]                                                                                         0.00% (0/28)        
        __38-[MPDocument writeToURL:ofType:error:]_block_invoke                                                                        0.00% (0/2)         
        __38-[MPDocument writeToURL:ofType:error:]_block_invoke_2                                                                      0.00% (0/3)         
        -[MPDocument dataOfType:error:]                                                                                                100.00% (3/3)       
        -[MPDocument readFromData:ofType:error:]                                                                                       100.00% (8/8)       
        -[MPDocument prepareSavePanel:]                                                                                                76.92% (30/39)      
        __31-[MPDocument prepareSavePanel:]_block_invoke                                                                               100.00% (12/12)     
        -[MPDocument printInfo]                                                                                                        0.00% (0/8)         
        -[MPDocument printOperationWithSettings:error:]                                                                                0.00% (0/7)         

... (2900 more lines truncated)

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

@schuyler schuyler merged commit 95179c1 into main Apr 8, 2026
9 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.

1 participant