From cc6551123209ae398f23dd5283562c6d5bf10258 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Sat, 13 Dec 2025 02:48:46 +0100 Subject: [PATCH 1/2] fix!: make `dirname` and `basename` behave like PHP and Node There were some unexpected behavior (when expecting the same as Node.js or PHP do) in both methods. Those were "documented" in the tests but never fixed. Adjusted both functions to behave like Node.js and also in most cases like PHP. Signed-off-by: Ferdinand Thiessen --- lib/index.ts | 17 ++++++++++++++--- test/basename.test.ts | 9 ++------- test/dirname.test.ts | 24 ++++++++---------------- tsconfig.json | 4 ++-- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/lib/index.ts b/lib/index.ts index 6c42fed..5bb19ac 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -28,6 +28,7 @@ export function encodePath(path: string): string { export function basename(path: string): string { return path .replace(/\\/g, '/') + .replace(/\/+$/g, '') .replace(/.*\//, '') } @@ -38,9 +39,19 @@ export function basename(path: string): string { * @param path - The path to get the directory of */ export function dirname(path: string): string { - return path - .replace(/\\/g, '/') - .replace(/\/[^/]*$/, '') + path = path.replaceAll(/\\/g, '/') + const sections = path.split('/') + if (sections.length <= 1) { + // there was no slash in the path + return '.' + } + + sections.pop() + if (sections.length === 1 && sections[0] === '') { + return '/' + } + + return sections.join('/') } /** diff --git a/test/basename.test.ts b/test/basename.test.ts index d2ff6b4..c391503 100644 --- a/test/basename.test.ts +++ b/test/basename.test.ts @@ -37,15 +37,10 @@ describe('basename', function() { it('Returns dot if file name is dot', function() { expect(basename('/subdir/.')).toEqual('.') }) - // TODO: fix the source to make it work like PHP's basename it('Returns the dir itself if no file name given', function() { - // TODO: fix the source to make it work like PHP's dirname - // expect(basename('subdir/')).toEqual('subdir'); - expect(basename('subdir/')).toEqual('') + expect(basename('subdir/')).toEqual('subdir') }) it('Returns the dir itself if no file name given with root', function() { - // TODO: fix the source to make it work like PHP's dirname - // expect(basename('/subdir/')).toEqual('subdir'); - expect(basename('/subdir/')).toEqual('') + expect(basename('/subdir/')).toEqual('subdir') }) }) diff --git a/test/dirname.test.ts b/test/dirname.test.ts index b007b45..fe1d966 100644 --- a/test/dirname.test.ts +++ b/test/dirname.test.ts @@ -8,33 +8,25 @@ import { dirname } from '../lib/index.ts' describe('dirname', function() { it('Returns the nothing if no file name given', function() { - expect(dirname('')).toEqual('') + expect(dirname('')).toEqual('.') }) it('Returns the root if dir is root', function() { - // TODO: fix the source to make it work like PHP's dirname - // expect(dirname('/')).toEqual('/'); - expect(dirname('/')).toEqual('') + expect(dirname('/')).toEqual('/') }) it('Returns the root if dir is double root', function() { - // TODO: fix the source to make it work like PHP's dirname - // expect(dirname('//')).toEqual('/'); - expect(dirname('//')).toEqual('/') // oh no... + expect(dirname('//')).toEqual('/') }) it('Returns dot if dir is dot', function() { expect(dirname('.')).toEqual('.') }) it('Returns dot if no root given', function() { - // TODO: fix the source to make it work like PHP's dirname - // expect(dirname('some dir')).toEqual('.'); - expect(dirname('some dir')).toEqual('some dir') // oh no... + expect(dirname('some dir')).toEqual('.') }) it('Returns the dir name if file name and root path given', function() { - // TODO: fix the source to make it work like PHP's dirname - // expect(dirname('/some name.txt')).toEqual('/'); - expect(dirname('/some name.txt')).toEqual('') + expect(dirname('/some name.txt')).toEqual('/') }) it('Returns the dir name if double root path given', function() { - expect(dirname('//some name.txt')).toEqual('/') // how lucky... + expect(dirname('//some name.txt')).toEqual('/') }) it('Returns the dir name if subdir given without root', function() { expect(dirname('subdir/some name.txt')).toEqual('subdir') @@ -43,9 +35,9 @@ describe('dirname', function() { expect(dirname('/subdir/some name.txt')).toEqual('/subdir') }) it('Returns the dir name if subdir given with double root', function() { - // TODO: fix the source to make it work like PHP's dirname + // TODO: currently it behaves like Node's dirname, but for PHP it would be: // expect(dirname('//subdir/some name.txt')).toEqual('/subdir'); - expect(dirname('//subdir/some name.txt')).toEqual('//subdir') // oh... + expect(dirname('//subdir/some name.txt')).toEqual('//subdir') }) it('Returns the dir name if subdir has dot', function() { expect(dirname('/subdir.dat/some name.txt')).toEqual('/subdir.dat') diff --git a/tsconfig.json b/tsconfig.json index aad1c5e..bc0edb6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,8 +12,8 @@ "erasableSyntaxOnly": true, "rewriteRelativeImportExtensions": true, "lib": [ - "es6", - "dom" + "ESNext", + "DOM" ], } } \ No newline at end of file From eccf0f76fcd66bbf34f91a0471f095f9ad9588bc Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Tue, 16 Dec 2025 13:08:48 +0100 Subject: [PATCH 2/2] test: adjust test description Signed-off-by: Ferdinand Thiessen --- test/dirname.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dirname.test.ts b/test/dirname.test.ts index fe1d966..68e504e 100644 --- a/test/dirname.test.ts +++ b/test/dirname.test.ts @@ -7,7 +7,7 @@ import { describe, expect, it } from 'vitest' import { dirname } from '../lib/index.ts' describe('dirname', function() { - it('Returns the nothing if no file name given', function() { + it('Returns current folder if no file name given', function() { expect(dirname('')).toEqual('.') }) it('Returns the root if dir is root', function() {