Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,32 @@

[![Version](https://img.shields.io/npm/v/lsfnd?logo=npm&label=lsfnd)](https://npmjs.com/package/lsfnd)
![Min. Node](https://img.shields.io/node/v-lts/lsfnd/latest?logo=node.js&label=node)
[![Bundle size (minified)](https://img.shields.io/bundlephobia/min/lsfnd)](https://npmjs.com/package/lsfnd)<br>
[![Bundle size (minified)](https://img.shields.io/bundlephobia/min/lsfnd)](https://npmjs.com/package/lsfnd)<br />
[![Test CI](https://github.com/mitsuki31/lsfnd/actions/workflows/test.yml/badge.svg)](https://github.com/mitsuki31/lsfnd/actions/workflows/test.yml)
[![License](https://img.shields.io/github/license/mitsuki31/lsfnd?logo=github&logoColor=f9f9f9&label=License&labelColor=yellow&color=white)](https://github.com/mitsuki31/lsfnd/tree/master/LICENSE)
[![License](https://img.shields.io/github/license/mitsuki31/lsfnd?logo=readme&logoColor=f9f9f9&label=License&labelColor=yellow&color=white)](https://github.com/mitsuki31/lsfnd/tree/master/LICENSE)

**LSFND** is an abbreviation for _list (ls) files (f) and (n) directories (d)_,
a lightweight Node.js library designed to make listing files and directories more convenient.
It offers an efficient and simple way to explore through your directory structures
and retrieves the names of files and/or directories leveraging a configurable options
to modify the listing behavior, such as recursive searches and regular expression filters.

This library's **primary benefit** is that every implemented API runs asynchronously,
This library's **primary benefit** is that every implemented API within main module runs asynchronously,
guaranteeing that they will **NEVER** disrupt the execution of any other processes.

> [!IMPORTANT]\
> Currently this library only focus on CommonJS (CJS) and ECMAScript Modules (ESM).
> [!IMPORTANT]
>
> As of version 1.0.0, this library has supported TypeScript projects with various
> ### v1.2.0
> Added synchronous version for `ls`, `lsFiles`, and `lsDirs`.
> Can be imported from submodule `/sync` as such below:
> ```js
> const { lsFiles } = require('lsfnd/sync');
> // Or:
> import { lsFiles } from 'lsfnd/sync';
> ```
>
> ### v1.0.0
> This library has supported TypeScript projects with various
> module types (i.e., `node16`, `es6`, and many more). Previously, it was only supports
> TypeScript projects with module type of `commonjs`. All type declarations in this
> library also has been enhanced to more robust and strict, thus improving type safety.
Expand Down
1 change: 1 addition & 0 deletions build.prop.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = {
files: [
'dist/index.js',
'dist/lsfnd.js',
'dist/lsfnd-sync.js',
'dist/lsTypes.js'
]
},
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,21 @@
"exports": {
".": "./dist/index.js",
"./lsfnd": "./dist/lsfnd.js",
"./sync": "./dist/lsfnd-sync.js",
"./types": "./types/index.d.ts",
"./package.json": "./package.json"
},
"scripts": {
"dev": "tsx scripts/build.ts",
"build": "tsx scripts/build.ts --minify",
"postbuild": "tsx scripts/postbuild.ts",
"docs": "npm run-script build:docs",
"build:docs": "typedoc --options typedoc.config.js",
"test": "npm run test:cjs && npm run test:mjs",
"test:cjs": "node test/lsfnd.spec.cjs",
"test:mjs": "node test/lsfnd.spec.mjs",
"test:cjs": "node test/lsfnd.spec.cjs && node test/lsfnd-sync.spec.cjs",
"test:mjs": "node test/lsfnd.spec.mjs && node test/lsfnd-sync.spec.mjs",
"prepublishOnly": "npm run build",
"prepack": "npm test"
"prepack": "npm test && npm pkg delete devDependencies peerDependencies"
},
"repository": {
"type": "git",
Expand Down
71 changes: 71 additions & 0 deletions scripts/postbuild.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import * as fs from 'node:fs';
import * as buildProp from '../build.prop';

const includedFiles = buildProp.minify.files;

/**
* Remove consecutive multiline comments (/* ... *\/) immediately after the
* first `"use strict"` or `'use strict'` directive in the given JS source.
*
* @param source - JavaScript source text
* @returns modified source
*/
function removeMultilineCommentsAfterUseStrict(source: string) {
// Find first "use strict" or 'use strict'
const m = /(['"])use strict\1\s*;?/.exec(source);
if (!m) return source;

// index right after the matched directive
let pos = m.index + m[0].length;

// Walk forward skipping whitespace/newlines and removing /* ... */ blocks
let changed = false;
while (true) {
// Skip whitespace and newlines
const wsMatch = /^[\t\v\f\r\n ]+/.exec(source.slice(pos));
if (wsMatch) pos += wsMatch[0].length;

// If next chars start a block comment, remove it
if (source.startsWith('/*', pos)) {
const end = source.indexOf('*/', pos + 2);
if (end === -1) {
// unterminated block comment — be conservative: stop
break;
}
// Remove from pos to end+2
source = source.slice(0, pos) + source.slice(end + 2);
changed = true;
// continue loop from same pos (since content changed and there may be more)
continue;
}
break; // else nothing to remove; break
}

return changed ? source : source;
}

async function run() {
const modifiedFiles = includedFiles.reduce((acc, val) => {
acc[val] = false;
return acc;
}, {} as Record<(typeof includedFiles)[number], boolean>);

const postbuildPromises = includedFiles.map(async file => {
const raw = await fs.promises.readFile(file, 'utf8');

// Remove comments
const modified = removeMultilineCommentsAfterUseStrict(raw);
if (modified !== raw) {
await fs.promises.writeFile(file, modified, 'utf8');
modifiedFiles[file] = true;
}
});

void await Promise.all(postbuildPromises);

// Summary
console.log('[postbuild] Modified files are included:');
console.table(modifiedFiles);
}

run();
34 changes: 34 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { DefaultLsOptions } from '../types';

/**
* A regular expression pattern to parse the file URL path,
* following the WHATWG URL Standard.
*
* @see {@link https://url.spec.whatwg.org/ WHATWG URL Standard}
* @internal
*/
export const FILE_URL_PATTERN: RegExp = /^file:\/\/\/?(?:[A-Za-z]:)?(?:\/[^\s\\]+)*(?:\/)?/;

/**
* A regular expression pattern to parse and detect the Windows path.
*
* @internal
*/
export const WIN32_PATH_PATTERN: RegExp = /^[A-Za-z]:?(?:\\|\/)(?:[^\\/:*?"<>|\r\n]+(?:\\|\/))*[^\\/:*?"<>|\r\n]*$/;

/**
* An object containing all default values of {@link LsOptions `LsOptions`} type.
*
* @since 1.0.0
* @see {@link DefaultLsOptions}
* @see {@link LsOptions}
*/
export const defaultLsOptions: DefaultLsOptions = {
encoding: 'utf8',
recursive: false,
match: /.+/,
exclude: undefined,
rootDir: process.cwd(),
absolute: false,
basename: false
} satisfies DefaultLsOptions;
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ export type {
LsEntries,
LsResult
} from '../types';
export { defaultLsOptions } from './constants';
Loading