Skip to content

feat: open Markdown files from File Explorer through Windows file associations - #637

Merged
Azganoth merged 2 commits into
mainfrom
feature/file-associations
Oct 5, 2026
Merged

Azganoth merged 2 commits into
mainfrom
feature/file-associations

Conversation

@Azganoth

@Azganoth Azganoth commented Oct 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • The Windows NSIS (per-user) and MSI (per-machine) installers register Leafdown for every built-in Markdown extension, so File Explorer offers it under Open with and Settings lists it under Default apps. They never make it the default: each extension's default value and the user's UserChoice are left alone, and choosing Leafdown is the user's step in Windows.
  • Registration does not use Tauri's bundle.fileAssociations. In the installed bundler (CLI 2.11.4), both the NSIS and WiX templates write each extension's default value, which replaces another application's registration and makes Leafdown the default wherever the user has not chosen one. The NSIS template also leaves the executable path unquoted, and on reinstall it overwrites its _backup of the previous default with its own class. A Leafdown-owned NSIS hook and WiX fragment instead register a Leafdown.Markdown ProgID with a quoted command, an OpenWithProgids value per extension, and Capabilities listed in RegisteredApplications. docs/decisions.md records the choice.
  • build.rs generates both installers' extension lists from markdown-file-extensions.json into the gitignored src-tauri/gen/windows/, so a new built-in extension needs no installer edit.
  • The MSI's values belong to one component, so repair restores them and uninstall and major upgrade remove them. Tauri adds componentRefs to a separate External feature, where referencing the main binary's file key from registry values fails ICE69, so a SetProperty carries the executable path. The NSIS uninstaller removes the registration only while the ProgID command still names its own executable, so uninstalling a stale install location leaves the current one's registration in place.
  • Leafdown records its first command-line argument as an absolute launch path. Once the persisted stores have started and the window shows, the frontend takes it once and opens it through the ordinary Open File workflow, including folder context, recents, watchers, and the usual open errors. Each OS launch is its own process and window; single-instance routing is not introduced.
  • Specification, Architecture (new Packaging section and Launch Workflow), Decisions, file and folder Help, the changelog, the E2E target list, and the release checklist describe the delivered behavior.

Related Issue

Closes #630

Verification

Rust tests cover launch-path parsing (Unicode and spaces, relative paths, no argument, single take). They also check that the generated installer lists match the registry exactly, that both installers iterate those lists, that no installer writes an extension key outside OpenWithProgids, and that tauri.conf.json carries no fileAssociations. Frontend tests cover opening the launch document through the open workflow with recents and folder context, the ordinary unsupported-file and encoding errors, opening only after the window shows, and opening with default settings when preferences fail to load. A new launch-document desktop scenario launches the app with a Unicode path argument and checks the editor, article navigator selection, and recents.

pnpm check, pnpm test:e2e:desktop:runner, and pnpm tauri build (NSIS and MSI) pass. The bundle also succeeds with src-tauri/gen/windows/ deleted beforehand.

Manually verified in Windows 11 with real release installers, against a machine that already had VS Code, Zed, and Typora registrations and a Notepad++ UserChoice for .md, comparing registry snapshots after each step:

  1. NSIS install, same-version reinstall, and upgrade produce identical registration, with the existing defaults, other applications' OpenWithProgids values, and UserChoice unchanged.
  2. Reinstalling NSIS to a second location with a space in its path moves the registration there. Uninstalling the stale location leaves it in place, and uninstalling the current location returns the registry to the baseline.
  3. MSI install, msiexec /fomus repair after deleting owned values, upgrade to a later version, and uninstall restore the values, keep a single product, and return the registry to the baseline.
  4. With both installed, Windows resolves the per-user NSIS registration, and removing NSIS falls back to the MSI's.
  5. Launching through the ProgID verb, as File Explorer does, passes a Unicode path with spaces exactly, opens it with its folder context and recents, and a second launch while the first runs opens its own window. Missing, unsupported, oversized, and permission-denied paths report the ordinary open errors.

Not verified: picking Leafdown in File Explorer's Open with menu and in Settings > Default apps by hand; the error toasts on screen (the error kinds were checked through diagnostics logs); the desktop scenarios, which are left to CI.

Notes

  • An NSIS upgrade that drops a built-in extension would leave that extension's OpenWithProgids value behind; the MSI removes it with the old product.
  • Independent of this change, Tauri's WiX template takes INSTALLDIR from the install-directory key the NSIS uninstaller leaves in HKCU, so an MSI installed after an NSIS uninstall goes into the old NSIS folder.

@Azganoth Azganoth added the Feature New feature or request label Oct 5, 2026
@Azganoth Azganoth self-assigned this Oct 5, 2026
@github-project-automation github-project-automation Bot moved this to Backlog in Leafdown Oct 5, 2026
…ions

# Conflicts:
#	docs/architecture.md
#	src/test/utils/tauriApi.ts
@Azganoth
Azganoth merged commit 5f41353 into main Oct 5, 2026
3 checks passed
@Azganoth
Azganoth deleted the feature/file-associations branch October 5, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

File associations

1 participant