From e4c5bd51ebb1f71976cdc4faa5b990bb61ada5a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ademir=20Jos=C3=A9=20Ferreira=20J=C3=BAnior?= Date: Mon, 5 Oct 2026 16:41:53 -0300 Subject: [PATCH] Give associated Markdown files a dedicated document icon --- CHANGELOG.md | 4 ++ docs/architecture.md | 2 + docs/help/file-and-folder-workflows.md | 2 +- docs/specification.md | 1 + src-tauri/icons/document.ico | Bin 0 -> 24553 bytes src-tauri/icons/document/16.svg | 7 +++ src-tauri/icons/document/20.svg | 7 +++ src-tauri/icons/document/24.svg | 7 +++ src-tauri/icons/document/32.svg | 7 +++ src-tauri/icons/document/icon.svg | 7 +++ src-tauri/src/installer_tests.rs | 59 +++++++++++++++++++++++- src-tauri/tauri.conf.json | 3 ++ src-tauri/windows/file-associations.wxs | 2 +- src-tauri/windows/installer-hooks.nsh | 2 +- 14 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 src-tauri/icons/document.ico create mode 100644 src-tauri/icons/document/16.svg create mode 100644 src-tauri/icons/document/20.svg create mode 100644 src-tauri/icons/document/24.svg create mode 100644 src-tauri/icons/document/32.svg create mode 100644 src-tauri/icons/document/icon.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index c84bb80a..1453e765 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ Leafdown uses lightweight [Keep a Changelog](https://keepachangelog.com/en/1.1.0 ## [Unreleased] +### Added + +- Give Markdown files associated with Leafdown a dedicated folded-page icon with the green leaf and Markdown symbol, separate from the application icon. Both Windows installers include it without changing your default app. + ## [0.1.0-alpha.2] - 2026-10-05 ### Added diff --git a/docs/architecture.md b/docs/architecture.md index afb6b09b..31f0535e 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -250,6 +250,8 @@ File associations come from `src-tauri/windows/installer-hooks.nsh` for NSIS and - a `Leafdown.Markdown` value under each extension's `OpenWithProgids`; and - `Capabilities` under the product's registry key, listed in `RegisteredApplications`, so Default apps can offer Leafdown. +The document icon is separate from the application icon. `bundle.resources` maps `src-tauri/icons/document.ico` to `document.ico` beside the installed executable, and both installers point the ProgID's `DefaultIcon` at that quoted path. The source and installed filenames match because the bundled WiX generator retains the source filename when mapping resources. The bundler owns installing and removing this resource; MSI also repairs it. The editable source is `src-tauri/icons/document/icon.svg`, with separate 16, 20, 24, and 32 pixel sources for small-size adjustments. The ICO contains those sizes plus 40, 48, 64, 128, and 256 pixel frames. Application, window, and shortcut icons continue to use the existing leaf artwork. + Neither writes an extension's default value or its `UserChoice`. The MSI's values belong to one component, so Windows Installer restores them on repair and removes them on uninstall and major upgrade. The NSIS installer writes them on every install, and its uninstaller removes them only while the ProgID's command still names its own executable, so uninstalling a stale installation location leaves another location's registration in place. ## Security diff --git a/docs/help/file-and-folder-workflows.md b/docs/help/file-and-folder-workflows.md index d386b8cc..b540bc1d 100644 --- a/docs/help/file-and-folder-workflows.md +++ b/docs/help/file-and-folder-workflows.md @@ -6,7 +6,7 @@ Leafdown keeps the open document and the folder context separate. The folder con **File > Open** opens one Markdown file: `.md`, `.markdown`, `.mdown`, or `.mkd`. If no folder is open, Leafdown also opens its parent folder as context. If a folder is already pinned, opening a file elsewhere leaves that context in place. **File > Open folder** scans the folder for Markdown articles and opens a matching root-level `readme` or `index` file when present. Ignored directories do not appear in the navigator. -On Windows, installing Leafdown adds it to File Explorer's **Open with** menu for these files and to **Settings > Apps > Default apps**, without changing which app opens them by default. Choose Leafdown there to open Markdown files from File Explorer. Each file opened this way starts its own Leafdown window, with the file's folder as context. **File > Open** works either way. +On Windows, installing Leafdown adds it to File Explorer's **Open with** menu for these files and to **Settings > Apps > Default apps**, without changing which app opens them by default. Choose Leafdown there to open Markdown files from File Explorer. Files associated with Leafdown show a folded-page icon with the green leaf and Markdown symbol. Each file opened this way starts its own Leafdown window, with the file's folder as context. **File > Open** works either way. The welcome screen and **File > Open recent** show previously opened files and folders when **Record recent files and folders** is on. You can remove one recent item or clear both lists without deleting files. See [Settings reference](settings-reference.md) for the setting. diff --git a/docs/specification.md b/docs/specification.md index 54824e26..15afd209 100644 --- a/docs/specification.md +++ b/docs/specification.md @@ -507,6 +507,7 @@ Workflows execute upon successful completion of dirty-state checks. If a dirty c ### Open From The Operating System - The Windows installers register Leafdown as able to open each supported Markdown extension, so File Explorer offers it under Open with and Settings lists it under Default apps. Installing, upgrading, repairing, or reinstalling never makes Leafdown the default application: each extension's default and the user's choice stay as they were, and choosing Leafdown is the user's step in Windows. +- Files associated with Leafdown use a document icon showing the green leaf above the Markdown M and down arrow on a folded page. The application and its shortcuts keep the leaf icon. - Opening a file through that registration, or starting Leafdown with a path as its first command-line argument, starts a new Leafdown window with that file, even when another Leafdown window is open. A relative path resolves against the directory Leafdown started in; later arguments are ignored. - The file opens through [Open File](#open-file) once preferences have loaded, so it sets the folder context and records recents as File > Open does. A missing, unreadable, oversized, unsupported, or undecodable file shows its open error, as described in [Error Handling](#error-handling), and leaves the welcome screen. - Upgrading, reinstalling, or repairing points the registration at the installed executable. Uninstalling removes the registration that installation made and nothing else. The NSIS installation registers for the current user and the MSI installation for all users; while both are installed, Windows uses the current user's. diff --git a/src-tauri/icons/document.ico b/src-tauri/icons/document.ico new file mode 100644 index 0000000000000000000000000000000000000000..5e5668e1308615a25fc30e1c0afdb39f5f57cf65 GIT binary patch literal 24553 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 mjfQUz=)(d#J%fBXPH6wHZ+^1lGAPv(ID literal 0 HcmV?d00001 diff --git a/src-tauri/icons/document/16.svg b/src-tauri/icons/document/16.svg new file mode 100644 index 00000000..3a6b4e9b --- /dev/null +++ b/src-tauri/icons/document/16.svg @@ -0,0 +1,7 @@ + + Leafdown document — leaf and Markdown + + + + + diff --git a/src-tauri/icons/document/20.svg b/src-tauri/icons/document/20.svg new file mode 100644 index 00000000..85c953b1 --- /dev/null +++ b/src-tauri/icons/document/20.svg @@ -0,0 +1,7 @@ + + Leafdown document — leaf and Markdown + + + + + diff --git a/src-tauri/icons/document/24.svg b/src-tauri/icons/document/24.svg new file mode 100644 index 00000000..d5f5bf1f --- /dev/null +++ b/src-tauri/icons/document/24.svg @@ -0,0 +1,7 @@ + + Leafdown document — leaf and Markdown + + + + + diff --git a/src-tauri/icons/document/32.svg b/src-tauri/icons/document/32.svg new file mode 100644 index 00000000..35a79e7a --- /dev/null +++ b/src-tauri/icons/document/32.svg @@ -0,0 +1,7 @@ + + Leafdown document — leaf and Markdown + + + + + diff --git a/src-tauri/icons/document/icon.svg b/src-tauri/icons/document/icon.svg new file mode 100644 index 00000000..cc34c950 --- /dev/null +++ b/src-tauri/icons/document/icon.svg @@ -0,0 +1,7 @@ + + Leafdown document — leaf and Markdown + + + + + diff --git a/src-tauri/src/installer_tests.rs b/src-tauri/src/installer_tests.rs index 97dd7f37..f495fb61 100644 --- a/src-tauri/src/installer_tests.rs +++ b/src-tauri/src/installer_tests.rs @@ -1,4 +1,4 @@ -use std::fs; +use std::{collections::BTreeSet, fs}; use crate::document::MARKDOWN_FILE_EXTENSIONS; @@ -58,3 +58,60 @@ fn installers_register_every_listed_extension_without_claiming_its_default() { } } } + +#[test] +fn installers_register_the_bundled_document_icon_without_replacing_the_app_icon() { + let config: serde_json::Value = serde_json::from_str(&read_manifest_file("tauri.conf.json")) + .expect("the Tauri configuration should be valid JSON"); + let source = "icons/document.ico"; + + assert_eq!(config["bundle"]["resources"][source], "document.ico"); + assert!( + config["bundle"]["icon"] + .as_array() + .expect("application icons should be listed") + .iter() + .any(|icon| icon == "icons/icon.ico") + ); + assert!(read_manifest_file("windows/installer-hooks.nsh").contains( + "WriteRegStr SHCTX \"${LEAFDOWN_PROGID_KEY}\\DefaultIcon\" \"\" `\"$INSTDIR\\document.ico\",0`" + )); + assert!(read_manifest_file("windows/file-associations.wxs").contains( + "" + )); + + let icon = fs::read(format!("{}/{source}", env!("CARGO_MANIFEST_DIR"))) + .expect("the bundled document icon should be readable"); + assert_eq!(&icon[..4], &[0, 0, 1, 0]); + let frame_count = usize::from(u16::from_le_bytes([icon[4], icon[5]])); + let mut sizes = BTreeSet::new(); + for index in 0..frame_count { + let entry = &icon[6 + index * 16..6 + (index + 1) * 16]; + let width = if entry[0] == 0 { + 256 + } else { + u32::from(entry[0]) + }; + let height = if entry[1] == 0 { + 256 + } else { + u32::from(entry[1]) + }; + assert_eq!(width, height); + assert!(sizes.insert(width), "icon frame sizes should not repeat"); + + let length = u32::from_le_bytes(entry[8..12].try_into().unwrap()) as usize; + let offset = u32::from_le_bytes(entry[12..16].try_into().unwrap()) as usize; + let image = &icon[offset..offset + length]; + assert_eq!(&image[..8], b"\x89PNG\r\n\x1a\n"); + assert_eq!(u32::from_be_bytes(image[16..20].try_into().unwrap()), width); + assert_eq!( + u32::from_be_bytes(image[20..24].try_into().unwrap()), + height + ); + } + assert_eq!( + sizes, + BTreeSet::from([16, 20, 24, 32, 40, 48, 64, 128, 256]) + ); +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 930327fa..36b14776 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -31,6 +31,9 @@ "bundle": { "active": true, "targets": ["nsis", "msi"], + "resources": { + "icons/document.ico": "document.ico" + }, "windows": { "nsis": { "installerHooks": "windows/installer-hooks.nsh" diff --git a/src-tauri/windows/file-associations.wxs b/src-tauri/windows/file-associations.wxs index 971f0b6b..fdd7a601 100644 --- a/src-tauri/windows/file-associations.wxs +++ b/src-tauri/windows/file-associations.wxs @@ -12,7 +12,7 @@ - + diff --git a/src-tauri/windows/installer-hooks.nsh b/src-tauri/windows/installer-hooks.nsh index 8e3129f4..f8e2b5d9 100644 --- a/src-tauri/windows/installer-hooks.nsh +++ b/src-tauri/windows/installer-hooks.nsh @@ -24,7 +24,7 @@ !macro NSIS_HOOK_POSTINSTALL !insertmacro LEAFDOWN_OPEN_COMMAND $R0 WriteRegStr SHCTX "${LEAFDOWN_PROGID_KEY}" "" "Markdown Document" - WriteRegStr SHCTX "${LEAFDOWN_PROGID_KEY}\DefaultIcon" "" `"$INSTDIR\${MAINBINARYNAME}.exe",0` + WriteRegStr SHCTX "${LEAFDOWN_PROGID_KEY}\DefaultIcon" "" `"$INSTDIR\document.ico",0` WriteRegStr SHCTX "${LEAFDOWN_PROGID_KEY}\shell\open\command" "" $R0 WriteRegStr SHCTX "${MANUPRODUCTKEY}\Capabilities" "ApplicationName" "${PRODUCTNAME}"