Skip to content

Commit fe73cbd

Browse files
committed
fix(core): read backslashes as separators in globParent
`fs.globSync` reads backslashes as path separators, never as escapes, on every platform, so `doc\api\*.md` finds `doc/api`'s files, but `globParent` only split on `/` and returned `.` for it. glob-parent converted backslashes on Windows, so this matches it again. Also covers `?` (glob syntax, which glob-parent missed) and `(b|c)` (matched literally by `fs.globSync`, which glob-parent treated as glob). Assisted-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent fd5420a commit fe73cbd

2 files changed

Lines changed: 15 additions & 3 deletions

File tree

‎packages/core/src/utils/__tests__/glob.test.mjs‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ describe('globParent', () => {
6262
assert.strictEqual(globParent('a/{b,c}/*.md'), 'a');
6363
assert.strictEqual(globParent('a/b/[x-y]*.md'), 'a/b');
6464
assert.strictEqual(globParent('a/+(b|c)/*.md'), 'a');
65+
assert.strictEqual(globParent('a/b?d/*.md'), 'a');
66+
});
67+
68+
it('should treat as plain what fs.globSync matches literally', () => {
69+
assert.strictEqual(globParent('a/(b|c)/*.md'), 'a/(b|c)');
70+
assert.strictEqual(globParent('a/b+c/*.md'), 'a/b+c');
71+
});
72+
73+
it('should read backslashes as separators, like fs.globSync', () => {
74+
assert.strictEqual(globParent('doc\\api\\*.md'), 'doc/api');
75+
assert.strictEqual(globParent('C:\\docs\\*.md'), 'C:/docs');
6576
});
6677

6778
it('should return the parent directory of a plain path', () => {

‎packages/core/src/utils/glob.mjs‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ export const findFiles = (patterns, { cwd = process.cwd(), ignore } = {}) => {
2828
/**
2929
* Returns the directory part of a glob pattern before its first glob segment,
3030
* e.g. `doc/api` for `doc/api/*.md`, or the parent directory of a plain path.
31+
* Like `fs.globSync`, it reads backslashes as separators, never as escapes.
3132
*
32-
* @param {string} pattern - A glob pattern with POSIX separators
33+
* @param {string} pattern - A glob pattern
3334
* @returns {string}
3435
*/
3536
export const globParent = pattern => {
36-
const segments = pattern.split('/');
37+
const segments = pattern.replaceAll('\\', '/').split('/');
3738
const index = segments.findIndex(segment => GLOB_SEGMENT.test(segment));
3839
const parent = segments.slice(0, index === -1 ? -1 : index).join('/');
3940

40-
return parent || (pattern.startsWith('/') ? '/' : '.');
41+
return parent || (segments[0] === '' ? '/' : '.');
4142
};

0 commit comments

Comments
 (0)