📝 Project2MD
Overview
The Project2MD function converts a project directory into a single Markdown (.md) file. It recursively walks through the directory tree, reads file contents, and appends them to a Markdown file with optional formatting. It also generates a summary table of all processed files.
This is useful for creating project documentation, code snapshots, or sharing projects as a single Markdown file.
Installation
1npm install hbh-nodes
Or using yarn:
1yarn add hbh-nodes
Usage
1import { P2PMD } from 'hbh-nodes';3const { Project2MD, SimpleExclude } = P2PMD;5await Project2MD({6 input: './my-project',7 output: './docs/project.md',8 concurrency: 10,9 onprogress: ({ index, relPath }) => {10 console.log(`Processed file #${index}: ${relPath}`);11 },12 onEnd: ({ total }) => {13 console.log(`Finished! Total files processed: ${total}`);14 },15});
Function Signature
1async function Project2MD(opts?: Project2MDOptions): Promise<void>
Parameters
opts – An optional object of type Project2MDOptions.
Options
| Option | Type | Default | Description | |
|---|---|---|---|---|
input |
string |
'./' |
Path to the input directory to convert. | |
output |
string |
'output.md' |
Path of the Markdown file to create. | |
onprogress |
(progress: { index: number; relPath: string }) => void |
() => {} |
Callback called after each file is processed. | |
onEnd |
(summary: { total: number }) => void |
() => {} |
Callback called when processing finishes. | |
filenameFormatter |
`(relPath: string, stats: fs.Stats) => string | Promise |
Returns Markdown header for each file. Default: ###### \${relPath}`` |
Allows customizing the header of each file block. |
summaryFormatter |
`(files: { relPath: string; size: number }[]) => string | Promise |
Generates the summary table at the end. | |
exclude |
string[] |
SimpleExclude.Node |
List of files or directories to exclude (supports globs * and ?). |
|
ignoreHidden |
boolean |
true |
Skip hidden files and directories starting with .. |
|
concurrency |
number |
5 |
Maximum number of files to process concurrently. | |
maxFileSize |
number |
10 * 1024 * 1024 |
Skip files larger than this size (in bytes). | |
stopOnError |
boolean |
false |
If true, stops processing on the first error. |
Predefined Exclude
SimpleExclude is provided to skip common Node.js project files and directories:
1SimpleExclude.Node = ['node_modules', 'package-lock.json', '.gitignore', 'package.json'];
How It Works
-
Resolve Paths Converts
inputandoutputto absolute paths and ensures the output file itself is excluded. -
Directory Walk Recursively walks directories sequentially to avoid concurrency deadlocks.
- Directories are traversed first.
- Files are processed concurrently, respecting the
concurrencylimit.
-
File Processing For each file:
- Skips if hidden, excluded, or exceeds
maxFileSize. - Reads file contents (
utf-8). - Generates a Markdown header using
filenameFormatter. - Wraps the content in a fenced code block with language derived from the file extension.
- Appends content to the output Markdown file.
- Calls
onprogresscallback.
- Skips if hidden, excluded, or exceeds
-
Summary Generation After all files are processed:
- Calls
summaryFormatterwith the list of processed files. - Appends the generated summary to the Markdown file.
- Calls
-
Error Handling
- Wraps file system operations in
safeRunto catch errors without stopping execution unlessstopOnErroristrue. - Logs warnings and errors for files that fail to process.
- Wraps file system operations in
Example Output
Assuming a directory structure:
src/
├─ index.js
├─ utils.js
README.md
Generated output.md could look like:
1###### `src/index.js`3```js4console.log('Hello World');
src/utils.js
1export function add(a, b) { return a + b; }
README.md
1# My Project2This is my project.
Notes
- Files larger than
maxFileSizeare skipped. - Hidden files/directories are ignored if
ignoreHiddenistrue. - Concurrency ensures faster processing but directory traversal is always sequential.
- Markdown language blocks are derived from file extensions; fallback to no language if unknown.
onprogressandonEndallow progress tracking or UI updates.
This function is designed for Node.js environments and uses ESM imports (fs/promises, path).