Address issue #110: Watch local resources and refresh on change#305
Closed
schuyler wants to merge 5 commits into
Closed
Address issue #110: Watch local resources and refresh on change#305schuyler wants to merge 5 commits into
schuyler wants to merge 5 commits into
Conversation
Add file watching for local images, video, audio, and other resources referenced in the markdown preview. When a watched file changes on disk, append a cache-busting timestamp to its URL and re-render the preview. - MPFileWatcher: reusable single-file watcher (extracts dispatch source pattern from MPDocument) - MPResourceWatcherSet: manages a diffable set of file watchers - MPHTMLResourceURLs: extract local file paths from HTML and apply cache-busting query parameters - Refactor MPDocument to use MPFileWatcher for document auto-reload - Integrate resource watching into the render pipeline Related to #110
Atomic writes (atomically:YES) create a temp file and rename it, which triggers DISPATCH_VNODE_RENAME instead of DISPATCH_VNODE_WRITE. Use atomically:NO so the in-place write triggers the expected event. Related to #110
Remove redundant testHandlerReceivesCorrectPath (it still had atomically:YES and duplicated testHandlerCalledOnFileWrite). Increase dispatch_after delays to 0.2s and timeouts to 5s for CI runners under load. Related to #110
- Move updateWatchedPaths call before the DOM replacement / full reload split so newly added image references are watched immediately - Handle directory base URLs (unsaved documents) correctly in MPResolveLocalPath — check hasDirectoryPath before stripping filename - Add test for directory base URL case Related to #110
Contributor
Code Coverage ReportCurrent Coverage: 55.14% Coverage Details (Summary) |
Owner
Author
|
Superseded by #327, which rebases this branch onto current main to resolve the merge conflicts. |
schuyler
added a commit
that referenced
this pull request
Feb 26, 2026
## Summary - **MPFileWatcher**: Reusable single-file watcher using GCD dispatch sources (`DISPATCH_SOURCE_TYPE_VNODE`), extracted from inline code in MPDocument - **MPResourceWatcherSet**: Manages a set of MPFileWatcher instances with set-diffing to add/remove only changed watchers - **MPHTMLResourceURLs**: Pure utility functions that parse rendered HTML for local resource paths (img, video, audio, source, iframe src + link href) and apply cache-busting `?t=<timestamp>` query parameters - **MPRenderer integration**: Stores per-path timestamps and applies cache-busting before wrapping HTML output - **MPDocument integration**: Refactored existing document file watcher to use MPFileWatcher; added MPResourceWatcherSet that updates watched paths on every render and triggers a re-render on change When a local resource (image, video, audio, CSS) referenced in the Markdown preview is modified on disk, the preview now automatically refreshes to show the updated content. ## Related Issue Related to #110 Supersedes #305 (rebased to resolve merge conflicts with main) ## Manual Testing Plan 1. Create a Markdown file referencing a local image: `` 2. Open in MacDown and verify the image displays in the preview 3. Modify `photo.png` externally (e.g., in Preview or with an image editor) 4. Verify the preview updates within ~1 second without manual action 5. Test with other resource types: `<video src="clip.mp4">`, `<audio src="sound.mp3">`, `<link href="style.css">` 6. Test with subdirectory paths: `` 7. Test with absolute paths: `` 8. Verify remote images (`https://...`) do not trigger file watching 9. Switch to a different Markdown document and verify old watchers are cleaned up 10. Delete a watched resource file and verify no crash or error ## Review Notes - Full TDD test coverage: 20 tests for MPHTMLResourceURLs, 11 tests for MPResourceWatcherSet, 8 tests for MPFileWatcher - All tests pass on macOS 14, 15, 15-intel, and 26
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
DISPATCH_SOURCE_TYPE_VNODE), extracted from inline code in MPDocument?t=<timestamp>query parametersWhen a local resource (image, video, audio, CSS) referenced in the Markdown preview is modified on disk, the preview now automatically refreshes to show the updated content.
Related Issue
Related to #110
Manual Testing Plan
photo.pngexternally (e.g., in Preview or with an image editor)<video src="clip.mp4">,<audio src="sound.mp3">,<link href="style.css">https://...) do not trigger file watchingReview Notes