From a5652b3f4d11addb04b3a620542e1bdfb967895f Mon Sep 17 00:00:00 2001 From: Test Date: Fri, 3 Apr 2026 23:33:04 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20path=20display=20below=20title=20?= =?UTF-8?q?=E2=80=94=20focus-only=20visibility=20+=20robust=20path=20compu?= =?UTF-8?q?tation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Filename hint now only shows when title is focused (was always visible when slug ≠ filename, causing "path always shown" bug). 2. Vault-relative path computation handles trailing slashes and symlink-resolved paths via lastIndexOf fallback on vault directory name. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/components/TitleField.test.tsx | 19 ++++++++++++++++++- src/components/TitleField.tsx | 20 +++++++++++++++----- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/components/TitleField.test.tsx b/src/components/TitleField.test.tsx index 8299d285..8b51116e 100644 --- a/src/components/TitleField.test.tsx +++ b/src/components/TitleField.test.tsx @@ -36,8 +36,12 @@ describe('TitleField', () => { expect(input).toHaveValue('Keep This') }) - it('shows filename indicator when slug differs from current filename', () => { + it('shows filename indicator when slug differs and title is focused', () => { render( {}} />) + // Not shown when unfocused + expect(screen.queryByTestId('title-field-filename')).not.toBeInTheDocument() + // Shown when focused + fireEvent.focus(screen.getByTestId('title-field-input')) expect(screen.getByTestId('title-field-filename')).toHaveTextContent('my-note.md') }) @@ -148,4 +152,17 @@ describe('TitleField', () => { fireEvent.focus(screen.getByTestId('title-field-input')) expect(screen.queryByTestId('title-field-path')).not.toBeInTheDocument() }) + + it('resolves vault-relative path when paths differ by symlink prefix', () => { + // vaultPath uses symlink /Users/luca/... but notePath is canonical /Volumes/Jupiter/... + render( {}} />) + fireEvent.focus(screen.getByTestId('title-field-input')) + expect(screen.getByTestId('title-field-path')).toHaveTextContent('docs/adr/0001-tauri-stack') + }) + + it('handles vaultPath with trailing slash', () => { + render( {}} />) + fireEvent.focus(screen.getByTestId('title-field-input')) + expect(screen.getByTestId('title-field-path')).toHaveTextContent('docs/adr/0001-tauri-stack') + }) }) diff --git a/src/components/TitleField.tsx b/src/components/TitleField.tsx index 146d679f..df7feb46 100644 --- a/src/components/TitleField.tsx +++ b/src/components/TitleField.tsx @@ -119,15 +119,25 @@ export function TitleField({ title, filename, editable = true, notePath, vaultPa const currentStem = filename.replace(/\.md$/, '') // Compute vault-relative path (only for notes in subdirectories) - const relativePath = notePath && vaultPath - ? notePath.replace(vaultPath + '/', '').replace(/\.md$/, '') - : null + const relativePath = (() => { + if (!notePath || !vaultPath) return null + const vp = vaultPath.replace(/\/+$/, '') + const np = notePath.replace(/\.md$/, '') + if (np.startsWith(vp + '/')) return np.slice(vp.length + 1) + // Fallback: match by vault directory name for symlink-resolved paths + const vaultName = vp.split('/').pop() + if (!vaultName) return null + const segments = np.split('/') + const idx = segments.lastIndexOf(vaultName) + if (idx >= 0) return segments.slice(idx + 1).join('/') + return null + })() const isSubdirectory = relativePath != null && relativePath.includes('/') // Show path only when title is focused and note is in a subdirectory const showRelativePath = isFocused && isSubdirectory - // Show filename hint when slug differs, but suppress when path is already visible - const showFilename = !showRelativePath && (isEditing || currentStem !== expectedSlug) + // Show filename hint when slug differs, but only when focused (not always) + const showFilename = isFocused && !showRelativePath && (isEditing || currentStem !== expectedSlug) return (