From cb85fc253866d4a5db3a2fc7474b6a0eaa0c88b9 Mon Sep 17 00:00:00 2001 From: Davide Ficano Date: Sat, 25 Jul 2026 07:35:24 +0200 Subject: [PATCH 1/7] docs: improve trusted paths guidance --- trustedPaths.md | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/trustedPaths.md b/trustedPaths.md index 8da8601..0451183 100755 --- a/trustedPaths.md +++ b/trustedPaths.md @@ -19,24 +19,37 @@ VisualDiffer prompts a file panel when it can't access a file due to a permissio [Using VisualDiffer as external diff tool with sandbox](#using_visualdiffer_as_external_diff_tool_with_sandbox) ===================================================== -VisualDiffer can be used to compare files using other applications, for example to compare a remote file version with the local one. +Other applications can use VisualDiffer to compare files, for example, to compare a remote version of a file with its local version. -Applications like Dreamweaver save the remote version to a temporary file and then pass the generated full path to VisualDiffer, but this path isn't trusted, so VisualDiffer shows the file panel every time. +An application can save the remote version to a temporary file and then pass its full path to VisualDiffer. However, the path is not trusted, so VisualDiffer displays the file panel every time. -This behaviour generates a very frustrating user experience because the user must select the file from the panel again and again. +This behavior can be frustrating because you must select the file from the panel repeatedly. [Use Trusted Paths](#use_trusted_paths) ================= -Trusted paths resolve this problem because applications save files in their own specific temporary folders; for example SourceTree can generate the following path: +Trusted paths solve this problem because applications save files in their own temporary folders. For example, an application can generate the following path: /var/folders/mr/5dfd6w717cj5j374q24fdxsh0000gn/T/2PhpDQ_UnifiedDiff.m -but trusting it works only once because the path component **5dfd6w717cj5j374q24fdxsh0000gn/T/** is randomly generated and changes every time. +Trusting this path works only once because the **5dfd6w717cj5j374q24fdxsh0000gn/T/** path component is generated randomly and changes every time. -We can trust **/var/folders**, which is the root used by SourceTree to save temporary files. +Instead, you can trust **/var/folders**, the root directory used to save temporary files. -Trusting **/var/folders** ensures every path generated inside it (at any deeper subfolder level) doesn't require any additional user permission and the file panel prompts no longer appear. +Trusting **/var/folders** ensures that paths generated anywhere inside it do not require additional permission, preventing further file panel prompts. + +[Trust the File System from the Root (`/`)?](#trust_high_level) +============================= + +Integrating VisualDiffer with [Finder](finder.html) through Services or Quick Actions can make the user experience even more frustrating. The items you want to compare can be located anywhere, either on the main disk or on external disks under `/Volumes/`, causing the file selection panel to appear repeatedly. + +You may wonder, “I have just selected this path in Finder, so why am I being asked to open it?” This behavior is required by the sandbox. Finder and VisualDiffer are separate processes, and trusted paths cannot be transferred between them. + +### [Workaround](#trusted_workaround) + +⚠️ This workaround is not a complete solution. You can manually add a high-level directory, such as `/Volumes` or `/`, to Trusted Paths. Every path below that directory will then be accessible without requiring you to select it. + +Use this workaround only if you understand that it grants VisualDiffer access to everything below the selected directory. VisualDiffer does not send or index data, and it performs file operations only when explicitly initiated by the user, so this approach can be considered “safe.” [Where to configure Trusted Paths](#where_configure_trusted_paths) ============================= From 1a46acdc4d951441c3e599504caa8477f7cdd19a Mon Sep 17 00:00:00 2001 From: Davide Ficano Date: Sat, 25 Jul 2026 07:38:29 +0200 Subject: [PATCH 2/7] style: resize image when width changes --- .claude/settings.local.json | 8 ++++++++ AGENTS.md | 8 ++++++++ CLAUDE.md | 1 + css/input.css | 8 +++++++- css/theme.css | 7 ++++++- 5 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 .claude/settings.local.json create mode 100644 AGENTS.md create mode 120000 CLAUDE.md diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..19152a5 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,8 @@ +{ + "permissions": { + "allow": [ + "Bash(git *)", + "Bash(pbcopy)" + ] + } +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..59b58dd --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,8 @@ +# Text Guidelines + +- Check the grammar of any text and adjust if necessary. Text must ALWAYS be written in ENGLISH. +- Write the text using user-manual style language: clear, simple, and accessible, avoiding unnecessary technical jargon, while retaining all technical details explicitly documented in the source, without omitting or oversimplifying them. + +# Versioning + +Do not ask to commit, operations like `commit`, `add`, `push` are done manually by the user diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/css/input.css b/css/input.css index 2dc284d..e73d455 100644 --- a/css/input.css +++ b/css/input.css @@ -160,13 +160,19 @@ td.copy-cmd.copied::after { } img.wiki-img { - max-width: 50%; + max-width: 100%; border: 1px solid #94a3b8; border-radius: 4px; background-color: #fff; padding: 3px; } +@media (min-width: 768px) { + img.wiki-img { + max-width: 50%; + } +} + table.file-legend tr td { padding: 6px 10px; } diff --git a/css/theme.css b/css/theme.css index b2f4ddf..44e7cc3 100644 --- a/css/theme.css +++ b/css/theme.css @@ -1584,12 +1584,17 @@ td.copy-cmd.copied::after { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23059669' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E"); } img.wiki-img { - max-width: 50%; + max-width: 100%; border: 1px solid #94a3b8; border-radius: 4px; background-color: #fff; padding: 3px; } +@media (min-width: 768px) { + img.wiki-img { + max-width: 50%; + } +} table.file-legend tr td { padding: 6px 10px; } From dcc2138d01cc6675aba1212c1acd868bbbd199af Mon Sep 17 00:00:00 2001 From: Davide Ficano Date: Tue, 4 Aug 2026 05:43:34 +0200 Subject: [PATCH 3/7] fix: remove incorrect documentation --- fileDiff.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fileDiff.md b/fileDiff.md index 1bf31c5..e188125 100644 --- a/fileDiff.md +++ b/fileDiff.md @@ -82,7 +82,7 @@ A *section* is a contiguous block of differing lines. Two shortcuts in the Edit # [Show Details](#show_details) -**View → Show Details** opens a panel below the diff tables that shows the selected line at character level, highlighting exactly which characters differ. Hide it again from the same menu item or from the right-click menu inside the panel. +**View → Show Details** opens a panel below the diff tables that shows the selected line. Hide it again from the same menu item or from the right-click menu inside the panel. > **Line-ending characters are always shown in the Details panel**, even when Show Whitespace is off. Unix lines end with **¶**, DOS lines end with **¤**. This makes it easy to identify the source of a difference that looks identical at first glance. From 683bac981099ea993dd403cc6d12ee4839e9db35 Mon Sep 17 00:00:00 2001 From: Davide Ficano Date: Tue, 18 Aug 2026 10:28:23 +0200 Subject: [PATCH 4/7] docs: explain how to install custom color schemes --- hiddenSettings.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/hiddenSettings.md b/hiddenSettings.md index b712845..3d5d042 100644 --- a/hiddenSettings.md +++ b/hiddenSettings.md @@ -114,3 +114,24 @@ Click any row in the **Example** column to copy the full command to the clipboar + +# [How to Use a Custom Color Scheme](#install_theme) + +**Installation** + +Use the [Color Scheme Editor](https://visualdiffer.com/colors.html) to create a custom color scheme, then download the JSON file. For example, save the file as `~/Downloads/my-scheme.json`. + +Open Terminal and run the following commands. The first command copies the file to a directory that the VisualDiffer sandbox can access. + +```sh +cp ~/Downloads/my-scheme.json ~/Library/Application\ Scripts/com.visualdiffer +defaults write com.visualdiffer colorsConfigPath ~/Library/Application\ Scripts/com.visualdiffer/my-scheme.json +``` + +**Restore the Default Setting** + +To stop using the custom color scheme, run the following command: + +```sh +defaults delete com.visualdiffer colorsConfigPath +``` From 84d8f68c99ed60a158533fd2a5806b47f422a9ed Mon Sep 17 00:00:00 2001 From: Davide Ficano Date: Tue, 18 Aug 2026 10:51:09 +0200 Subject: [PATCH 5/7] docs: explain restart --- hiddenSettings.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hiddenSettings.md b/hiddenSettings.md index 3d5d042..bbcceff 100644 --- a/hiddenSettings.md +++ b/hiddenSettings.md @@ -128,6 +128,8 @@ cp ~/Downloads/my-scheme.json ~/Library/Application\ Scripts/com.visualdiffer defaults write com.visualdiffer colorsConfigPath ~/Library/Application\ Scripts/com.visualdiffer/my-scheme.json ``` +Changes to the color scheme take effect only after you restart VisualDiffer. + **Restore the Default Setting** To stop using the custom color scheme, run the following command: From 3b757e611f3adc34220ec9a63ebcf9ca6b7807e4 Mon Sep 17 00:00:00 2001 From: Davide Ficano Date: Thu, 20 Aug 2026 07:09:18 +0200 Subject: [PATCH 6/7] docs: improve custom color scheme documentation --- css/input.css | 51 +++++++++++++++++++++++++++++++++++++++++++- css/theme.css | 41 +++++++++++++++++++++++++++++++++++ hiddenSettings.md | 11 +++++++++- js/copy-cmd.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 154 insertions(+), 3 deletions(-) diff --git a/css/input.css b/css/input.css index e73d455..ca19462 100644 --- a/css/input.css +++ b/css/input.css @@ -159,6 +159,55 @@ td.copy-cmd.copied::after { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23059669' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E"); } +#main .code-block { + position: relative; + margin: 1.7142857em 0; +} + +#main .code-block pre { + margin: 0; + padding-right: 3rem; +} + +.copy-code-button { + position: absolute; + top: 0.625rem; + right: 0.625rem; + width: 20px; + height: 20px; + padding: 0; + border: 0; + background-color: transparent; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e2e8f0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='9' y='9' width='13' height='13' rx='2' ry='2'/%3E%3Cpath d='M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1'/%3E%3C/svg%3E"); + background-position: center; + background-repeat: no-repeat; + background-size: contain; + cursor: pointer; + opacity: 0; + transition: opacity 0.15s; +} + +.code-block:hover .copy-code-button, +.copy-code-button:focus-visible { + opacity: 1; +} + +.copy-code-button:focus-visible { + outline: 2px solid #e2e8f0; + outline-offset: 2px; +} + +.copy-code-button.copied { + opacity: 1; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e2e8f0' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E"); +} + +@media (hover: none) { + .copy-code-button { + opacity: 1; + } +} + img.wiki-img { max-width: 100%; border: 1px solid #94a3b8; @@ -270,4 +319,4 @@ table.file-legend tr td { .finder-callout a:hover { color: var(--color-brand-800); } -} \ No newline at end of file +} diff --git a/css/theme.css b/css/theme.css index 44e7cc3..382f266 100644 --- a/css/theme.css +++ b/css/theme.css @@ -1583,6 +1583,47 @@ td.copy-cmd.copied::after { opacity: 1; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23059669' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E"); } +#main .code-block { + position: relative; + margin: 1.7142857em 0; +} +#main .code-block pre { + margin: 0; + padding-right: 3rem; +} +.copy-code-button { + position: absolute; + top: 0.625rem; + right: 0.625rem; + width: 20px; + height: 20px; + padding: 0; + border: 0; + background-color: transparent; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e2e8f0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='9' y='9' width='13' height='13' rx='2' ry='2'/%3E%3Cpath d='M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1'/%3E%3C/svg%3E"); + background-position: center; + background-repeat: no-repeat; + background-size: contain; + cursor: pointer; + opacity: 0; + transition: opacity 0.15s; +} +.code-block:hover .copy-code-button, .copy-code-button:focus-visible { + opacity: 1; +} +.copy-code-button:focus-visible { + outline: 2px solid #e2e8f0; + outline-offset: 2px; +} +.copy-code-button.copied { + opacity: 1; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e2e8f0' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E"); +} +@media (hover: none) { + .copy-code-button { + opacity: 1; + } +} img.wiki-img { max-width: 100%; border: 1px solid #94a3b8; diff --git a/hiddenSettings.md b/hiddenSettings.md index bbcceff..7ccb472 100644 --- a/hiddenSettings.md +++ b/hiddenSettings.md @@ -121,15 +121,24 @@ Click any row in the **Example** column to copy the full command to the clipboar Use the [Color Scheme Editor](https://visualdiffer.com/colors.html) to create a custom color scheme, then download the JSON file. For example, save the file as `~/Downloads/my-scheme.json`. -Open Terminal and run the following commands. The first command copies the file to a directory that the VisualDiffer sandbox can access. +Open Terminal and run the following commands. + +Copy the file to a directory that the VisualDiffer sandbox can access. ```sh cp ~/Downloads/my-scheme.json ~/Library/Application\ Scripts/com.visualdiffer +``` + +Set the `colorsConfigPath` property to the full path of the copied file. + +```sh defaults write com.visualdiffer colorsConfigPath ~/Library/Application\ Scripts/com.visualdiffer/my-scheme.json ``` Changes to the color scheme take effect only after you restart VisualDiffer. +Custom color schemes do not respond to changes between Light and Dark appearances. If you switch the appearance, the custom color scheme remains active. + **Restore the Default Setting** To stop using the custom color scheme, run the following command: diff --git a/js/copy-cmd.js b/js/copy-cmd.js index 015d34b..72e61d6 100644 --- a/js/copy-cmd.js +++ b/js/copy-cmd.js @@ -1,10 +1,62 @@ document.addEventListener('DOMContentLoaded', function () { + function copyText(text) { + if (navigator.clipboard && window.isSecureContext) { + return navigator.clipboard.writeText(text); + } + + return new Promise(function (resolve, reject) { + var textArea = document.createElement('textarea'); + textArea.value = text; + textArea.setAttribute('readonly', ''); + textArea.style.position = 'fixed'; + textArea.style.opacity = '0'; + document.body.appendChild(textArea); + textArea.select(); + + try { + if (!document.execCommand('copy')) { + throw new Error('Copy command failed'); + } + resolve(); + } catch (error) { + reject(error); + } finally { + textArea.remove(); + } + }); + } + document.querySelectorAll('.copy-cmd').forEach(function (cell) { cell.addEventListener('click', function () { - navigator.clipboard.writeText(cell.dataset.cmd).then(function () { + copyText(cell.dataset.cmd).then(function () { cell.classList.add('copied'); setTimeout(function () { cell.classList.remove('copied'); }, 1500); }); }); }); + + document.querySelectorAll('#main pre').forEach(function (codeBlock) { + var wrapper = document.createElement('div'); + var button = document.createElement('button'); + + wrapper.className = 'code-block'; + codeBlock.parentNode.insertBefore(wrapper, codeBlock); + wrapper.appendChild(codeBlock); + + button.className = 'copy-code-button'; + button.type = 'button'; + button.setAttribute('aria-label', 'Copy code to clipboard'); + wrapper.appendChild(button); + + button.addEventListener('click', function () { + copyText(codeBlock.textContent).then(function () { + button.setAttribute('aria-label', 'Code copied'); + button.classList.add('copied'); + setTimeout(function () { + button.setAttribute('aria-label', 'Copy code to clipboard'); + button.classList.remove('copied'); + }, 1500); + }); + }); + }); }); From 265959a32b0c7cdf878b5f26c3959dffb1958207 Mon Sep 17 00:00:00 2001 From: Davide Ficano Date: Fri, 21 Aug 2026 10:11:51 +0200 Subject: [PATCH 7/7] docs: add link to the "Color Scheme Editor" --- colors.html | 1975 +++++++++++++++++++++++++++++++++++++++++++++ hiddenSettings.md | 4 +- index.md | 1 + 3 files changed, 1978 insertions(+), 2 deletions(-) create mode 100644 colors.html diff --git a/colors.html b/colors.html new file mode 100644 index 0000000..e7c32c2 --- /dev/null +++ b/colors.html @@ -0,0 +1,1975 @@ + + + + + + +VisualDiffer — Color Scheme Editor + + + + + + + + + +
+
+ +
+

VisualDiffer — Color Scheme Editor

+

Start with a built-in color scheme, adjust it in the live previews, then download the colors.json file.

+
+
+ +
+ + + +
+ Preview appearance +
+ + +
+
+ + + +
+
+ + + +
+ + +
+
+
+

Folder differ

+

Icons are omitted from this text-only preview. Select any colored element to locate its setting.

+
+
+
+
+ Folder rows retain the canvas background. Only file and filtered rows use a fill color. + Folder sizes use the Folder size color. +
+
+
+ +
+
+

File differ

+

Preview line numbers, the gutter separator, hatched missing lines, inline highlights, and the thumbnail position box.

+
+
+
+
+ Selected rows retain their status text color. + Thumbnail blocks use the text color from each side. +
+
+
+ +
+

Console log

+
+
+
+
+ +
+
+

colors.json

+

Uses the same structure as the bundled files.

+
+
+

+                
+ + + Values can use hexadecimal #rgb, #rrggbb, or #rrggbbaa notation, or the dynamic textForeground and textBackground values. +
+
+
+
+
+ + + + + + diff --git a/hiddenSettings.md b/hiddenSettings.md index 7ccb472..42ee175 100644 --- a/hiddenSettings.md +++ b/hiddenSettings.md @@ -115,11 +115,11 @@ Click any row in the **Example** column to copy the full command to the clipboar -# [How to Use a Custom Color Scheme](#install_theme) +# [How to Use a Custom Color Scheme](#how_to_use_a_custom_color_scheme) **Installation** -Use the [Color Scheme Editor](https://visualdiffer.com/colors.html) to create a custom color scheme, then download the JSON file. For example, save the file as `~/Downloads/my-scheme.json`. +Use the Color Scheme Editor to create a custom color scheme, then download the JSON file. For example, save the file as `~/Downloads/my-scheme.json`. Open Terminal and run the following commands. diff --git a/index.md b/index.md index aaa5294..68cc8b7 100644 --- a/index.md +++ b/index.md @@ -30,6 +30,7 @@ Integration & Settings Extra Features ============== +* [Color Scheme Editor](colors.html) * [visdiff — Command-Line Tool](unixshell.html) * [Hidden Settings](hiddenSettings.html) * [Frequently Asked Questions](faq.html)