diff --git a/src/js/utils/pathHelpers.js b/src/js/utils/pathHelpers.js index ecf0a26..1eb3b37 100644 --- a/src/js/utils/pathHelpers.js +++ b/src/js/utils/pathHelpers.js @@ -55,10 +55,23 @@ export function resolveRelativePath(basePath, relativePath) { export function normalizePath(path) { if (!path) return ''; - return path + const cleanPath = path .replace(/\\/g, '/') // Convert backslashes to forward slashes .replace(/\/+/g, '/') // Collapse multiple slashes .replace(/^\/|\/$/g, ''); // Remove leading/trailing slashes + + const segments = cleanPath.split('/'); + const stack = []; + + for (const segment of segments) { + if (segment === '..') { + stack.pop(); + } else if (segment !== '.' && segment !== '') { + stack.push(segment); + } + } + + return stack.join('/'); } /** diff --git a/tests/unit/services/LinkNavigationService.test.js b/tests/unit/services/LinkNavigationService.test.js index 7409590..42f0480 100644 --- a/tests/unit/services/LinkNavigationService.test.js +++ b/tests/unit/services/LinkNavigationService.test.js @@ -224,6 +224,7 @@ describe('LinkNavigationService', () => { name: 'test.md', path: 'docs/test.md', handle: mockFileHandle, + anchor: null, }); }); @@ -253,6 +254,7 @@ describe('LinkNavigationService', () => { name: 'test.md', path: 'docs/test.md', handle: mockFileHandle, + anchor: null, }); }); diff --git a/tests/unit/utils/pathHelpers.test.js b/tests/unit/utils/pathHelpers.test.js index 47b7122..7445736 100644 --- a/tests/unit/utils/pathHelpers.test.js +++ b/tests/unit/utils/pathHelpers.test.js @@ -236,10 +236,7 @@ describe('pathHelpers', () => { }); it('should handle normalized paths that resolve outside root', () => { - // Normalization converts 'docs/../secret' to 'secret' - // The implementation normalizes the path but doesn't prevent paths that resolved outside root - // It only checks if the normalized path starts with '..' or is empty - expect(isWithinRoot('docs/../secret', 'docs')).toBe(true); // 'secret' is valid normalized path + expect(isWithinRoot('docs/../secret', 'docs')).toBe(false); }); it('should allow nested paths within root', () => {