vitepress-jsdoc
Version:
A bridge between Vitepress and JSDoc-style commented codebases for hassle-free documentation.
168 lines • 6.6 kB
JavaScript
import path from 'node:path';
import { NodeDirectoryReader } from './node-directory-reader.js';
import { PatternFilter } from './pattern-filter.js';
/**
* Represents a directory entity with basic information.
* @typedef DirectoryEntity
* @property {Function} isDirectory - Function to check if the entity is a directory.
* @property {string} name - Name of the directory entity.
*/
/**
* Represents a file within a directory with its details.
* @typedef DirectoryFile
* @property {string} [ext] - File extension, if available.
* @property {string} [folder] - Folder containing the file, if available.
* @property {boolean} isDir - Flag to determine if the entity is a directory.
* @property {string} name - Name of the file.
* @property {string} path - Full path to the file.
*/
/**
* Interface for reading directory contents.
* @typedef DirectoryReader
* @property {Function} isDirectory - Checks if the given entry is a directory.
* @property {Function} readDirectory - Reads the directory at the given path and returns its entities.
*/
/**
* Options for listing directory tree contents.
* @typedef DirectoryTreeListOptions
* @property {string[]} [exclude] - Patterns to exclude from the tree.
* @property {string[]} [include] - Patterns to include in the tree.
* @property {string} [mainPath] - Main path for relative calculations.
* @property {string} srcPath - Source path of the directory to list.
* @property {FileTree[]} [tree] - Existing tree to append to, if available.
*/
/**
* Represents a node in a file tree structure.
* @typedef FileTree
* @property {FileTree[]} [children] - Child nodes of the current node.
* @property {string} [ext] - File extension, if available.
* @property {string} [fullPath] - Full path to the file or directory.
* @property {string} name - Name of the file or directory.
* @property {string} [path] - Relative path to the file or directory.
*/
/**
* Strategy for filtering directory contents.
* @typedef FilterStrategy
* @property {Function} shouldInclude - Determines if a given entry should be included based on the strategy.
*/
/**
* @typedef DirectoryTreeResult
* @property {DirectoryFile[]} paths - The paths in the directory.
* @property {FileTree[]} tree - The hierarchical tree structure of the directory.
* @property {DirectoryFile[]} excluded - The files that were excluded based on the provided options.
*/
/**
* The `DirectoryTreeBuilder` class provides functionalities to construct a hierarchical
* representation of a directory and its contents based on the provided options.
* It leverages filtering strategies and directory readers to achieve this.
*/
export class DirectoryTreeBuilder {
filter;
reader;
options;
/**
* Initializes a new instance of the DirectoryTreeBuilder class.
*
* @param {DirectoryTreeListOptions} options - Configuration options for building the directory tree.
*/
constructor(options) {
const { include = [], exclude = [] } = options;
this.filter = new PatternFilter(include, exclude);
this.reader = new NodeDirectoryReader();
this.options = options;
}
/**
* Constructs a hierarchical representation of the directory based on the provided options.
*
* @returns {Promise<DirectoryTreeResult>}
* A promise that resolves to the directory tree, including paths, tree structure, and excluded files.
*/
async build() {
const { srcPath, mainPath = '', tree = [] } = this.options;
const paths = [];
const excluded = [];
const dirs = await this.reader.readDirectory(srcPath);
for (const dirent of dirs) {
const fileDetails = this.getFileDetails(srcPath, dirent);
if (this.shouldSkipFile(fileDetails.name))
continue;
if (this.filter.shouldInclude(dirent, srcPath, mainPath)) {
if (fileDetails.isDir) {
const subTree = [];
this.options.srcPath = fileDetails.path;
this.options.tree = subTree;
// eslint-disable-next-line no-await-in-loop
const result = await this.build();
tree.push({
name: fileDetails.name,
children: subTree,
});
paths.push(...result.paths);
excluded.push(...result.excluded);
}
else {
const treeEntry = this.createTreeEntry(fileDetails);
tree.push(treeEntry);
paths.push(fileDetails);
}
}
else {
excluded.push(fileDetails);
}
}
return { paths, tree, excluded };
}
/**
* Retrieves detailed information about a directory entry.
*
* @param {string} srcPath - The source directory path.
* @param {DirectoryEntity} dirent - The directory entry to retrieve details for.
* @returns {DirectoryFile} Detailed information about the directory entry.
*/
getFileDetails(srcPath, dirent) {
const filePath = path.join(srcPath, dirent.name);
const isDir = dirent.isDirectory();
const ext = path.extname(filePath);
let name = path.basename(filePath, ext);
const folder = path.dirname(filePath);
if (name === 'index') {
name = '__index__';
}
return {
isDir,
name,
path: filePath,
...(isDir ? {} : { ext, folder }),
};
}
/**
* Checks whether a specific file should be omitted from the directory tree.
*
* @param {string} fileName - The name of the file to check.
* @returns {boolean} True if the file should be skipped, otherwise false.
*/
shouldSkipFile(fileName) {
return fileName.toLowerCase() === 'readme';
}
/**
* Creates a tree entry based on the provided file details.
*
* @param {DirectoryFile} file - Details of the file for which to create a tree entry.
* @returns {FileTree} A tree entry representing the file.
*/
createTreeEntry(file) {
if (file.isDir) {
return {
name: file.name,
children: [],
};
}
return {
name: file.name,
path: `/${file.name}`,
fullPath: file.path,
ext: file.ext,
};
}
}
//# sourceMappingURL=directory-tree-builder.js.map