Skip to content

Commit c8f3de4

Browse files
authored
Merge pull request #12 from amercier/skip-empty-directories
skipEmptyDirectories option
2 parents 55dad09 + ce20011 commit c8f3de4

File tree

7 files changed

+114
-3
lines changed

7 files changed

+114
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format
55

66
## [Unreleased]
77

8-
(nothing)
8+
- `skipEmptyDirectories` option - [#12]
99

1010
## [v0.3.0] - 2018-12-02
1111

@@ -56,6 +56,7 @@ All notable changes to this project will be documented in this file. The format
5656
[#8]: https://github.com/amercier/files-by-directory/pull/8
5757
[#9]: https://github.com/amercier/files-by-directory/pull/9
5858
[#11]: https://github.com/amercier/files-by-directory/pull/11
59+
[#12]: https://github.com/amercier/files-by-directory/pull/12
5960
[v0.1.0]: https://github.com/amercier/files-by-directory/compare/v0.0.0...v0.1.0
6061
[v0.1.1]: https://github.com/amercier/files-by-directory/compare/v0.1.0...v0.1.1
6162
[v0.1.2]: https://github.com/amercier/files-by-directory/compare/v0.1.1...v0.1.2

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,53 @@ for await (const [directory, ...files] of filesByDirectory(['level1'], { showDir
218218

219219
</details>
220220

221+
<details>
222+
<summary><code>options.skipEmptyDirectories</code> (default: <code>true</code>)</summary>
223+
224+
When set to `false`, includes empty files lists.
225+
226+
```bash
227+
# Directory structure:
228+
level1
229+
├── level2a (only directories)
230+
│ └── level3
231+
│ └── file3a
232+
├── level2b
233+
│ └── (empty)
234+
└── file1a
235+
```
236+
237+
```js
238+
for await (const files of filesByDirectory(['level1']/*, { skipEmptyDirectories: true }*/} )) {
239+
console.log(files);
240+
}
241+
// [ 'level1/file1a' ]
242+
// [ 'level1/level2a/level3/file3a' ]
243+
244+
for await (const files of filesByDirectory(['level1'], { skipEmptyDirectories: false } )) {
245+
console.log(files);
246+
}
247+
// [ 'level1/file1a' ]
248+
// []
249+
// [ 'level1/level2a/level3/file3a' ]
250+
// []
251+
```
252+
253+
**Note:** this can be useful when combined with `showDirectories` option:
254+
255+
```js
256+
const options = { skipEmptyDirectories: false, showDirectories: true };
257+
for await (const [directory, ...files] of filesByDirectory(['level1'], options)) {
258+
console.log(directory, files);
259+
}
260+
// level1 [ 'level1/file1a' ]
261+
// level1/level2a []
262+
// level1/level2a/level3 [ 'level1/level2a/level3/file3a' ]
263+
// level1/empty-directory []
264+
```
265+
266+
</details>
267+
221268
## Asynchronous iteration
222269

223270
[Asynchronous iteration] using `for-await-of` syntax requires Node 10+. For older version of NodeJS, either use:

fixture/index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { existsSync, mkdirSync } from 'fs';
12
import { join, relative } from 'path';
23

34
const cwd = process.cwd();
@@ -24,3 +25,10 @@ export const level1 = fixture('level1');
2425
export const file1a = fixture('level1/file1a');
2526
export const unexistingFile = fixture('level1/unexisting-file');
2627
export const linkToUnexistingFile = fixture('level1/link-to-unexisting-file');
28+
29+
export const emptyDirectory = fixture('empty-directory');
30+
31+
// Must create `emptyDirectory` on-the-fly because Git doesn't allow empty directories
32+
if (!existsSync(emptyDirectory)) {
33+
mkdirSync(emptyDirectory);
34+
}

src/__snapshots__/files-by-directory.spec.js.snap

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,3 +598,22 @@ Array [
598598
],
599599
]
600600
`;
601+
602+
exports[`filesByDirectory options skipEmptyDirectories includes empty directories when skipEmptyDirectories is false 1`] = `
603+
Array [
604+
Array [],
605+
Array [
606+
"fixture/level1/level2/level3/file3a",
607+
"fixture/level1/level2/level3/file3b",
608+
],
609+
]
610+
`;
611+
612+
exports[`filesByDirectory options skipEmptyDirectories skips empty directories when skipEmptyDirectories is true 1`] = `
613+
Array [
614+
Array [
615+
"fixture/level1/level2/level3/file3a",
616+
"fixture/level1/level2/level3/file3b",
617+
],
618+
]
619+
`;

src/files-by-directory.spec.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,15 @@ import '@babel/polyfill'; // Required for NodeJS < 10
22
import { values } from './async';
33
import getFilesByDirectory from './files-by-directory';
44
import defaults from './options';
5-
import { file1a, level1, level2, level2Files, level3, level3Files } from '../fixture';
5+
import {
6+
file1a,
7+
level1,
8+
level2,
9+
level2Files,
10+
level3,
11+
level3Files,
12+
emptyDirectory,
13+
} from '../fixture';
614

715
/** @test {filesByDirectory} */
816
describe('filesByDirectory', () => {
@@ -123,5 +131,31 @@ describe('filesByDirectory', () => {
123131
).toMatchSnapshot();
124132
});
125133
});
134+
135+
describe('skipEmptyDirectories', () => {
136+
it('is true by default', () => {
137+
expect(defaults.skipEmptyDirectories).toBe(true);
138+
});
139+
140+
it('skips empty directories when skipEmptyDirectories is true', async () => {
141+
expect(
142+
await values(
143+
getFilesByDirectory([emptyDirectory, level3], {
144+
skipEmptyDirectories: true,
145+
}),
146+
),
147+
).toMatchSnapshot();
148+
});
149+
150+
it('includes empty directories when skipEmptyDirectories is false', async () => {
151+
expect(
152+
await values(
153+
getFilesByDirectory([emptyDirectory, level3], {
154+
skipEmptyDirectories: false,
155+
}),
156+
),
157+
).toMatchSnapshot();
158+
});
159+
});
126160
});
127161
});

src/options.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
* @property {boolean} directoriesFirst Whether to list directories before files.
77
* @property {boolean} showDirectories Whether to include directories as the first entry of the
88
* @property {boolean} followSymlinks Whether to follow symbolic links or not.
9+
* @property {boolean} skipEmptyDirectories Whether to skip empty directories, or include them.
910
* result arrays.
1011
*/
1112
const defaults = {
1213
excludeSymlinks: false,
1314
directoriesFirst: false,
1415
showDirectories: false,
1516
followSymlinks: false,
17+
skipEmptyDirectories: true,
1618
};
1719

1820
export default defaults;

src/walker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export default class Walker {
7575
}
7676

7777
// Process regular files, if any
78-
if (regularFiles.length > 0) {
78+
if (regularFiles.length > 0 || !this.skipEmptyDirectories) {
7979
yield* filesCallback(regularFiles);
8080
}
8181

0 commit comments

Comments
 (0)