UNPKG

shelving

Version:

Toolkit for using data in JavaScript.

49 lines (48 loc) 2.36 kB
import { mergeElements, walkElements } from "../util/element.js"; import { anyMatch } from "../util/regexp.js"; import { ThroughExtractor } from "./ThroughExtractor.js"; /** * Default index file patterns. * - Matched case-insensitively (all entries stored lowercase). * - The first child of a directory that matches any pattern is absorbed. */ const DEFAULT_INDEX = [/^readme\.txt$/i, /^readme\.md$/i, /^index\.md$/i, /^index\.ts$/i, /^index\.tsx$/i]; /** * Through extractor that walks a `DirectoryElement` tree and absorbs each directory's index file into the directory itself. * - For each directory: finds the first child whose `key` matches any `index` pattern. * - The matched child's `title`, `description`, `content`, and `children` are folded into the parent directory. * - The matched child is removed from the parent's children list. * - Recurses into subdirectories before absorbing — the deepest level happens first. */ export class IndexFileExtractor extends ThroughExtractor { _index; constructor(source, { index = DEFAULT_INDEX } = {}) { super(source); this._index = index; } async extract(input) { const root = await this.source.extract(input); return _absorbIndex(root, this._index); } } /** Recursively absorb the index file in `dir` and all nested directories. */ function _absorbIndex(dir, index) { // Recurse first so nested directories absorb their own indexes before we look at this level. const recursed = Array.from(walkElements(dir.props.children)).map(child => child.type === "tree-directory" ? _absorbIndex(child, index) : child); // Find the index child by key. const indexChild = recursed.find(child => anyMatch(child.key, ...index)); if (!indexChild) return { ...dir, props: { ...dir.props, children: recursed } }; // Fold the index child into the directory, and drop it from children. const remaining = recursed.filter(child => child !== indexChild); return { ...dir, props: { ...dir.props, title: dir.props.title ?? indexChild.props.title, description: dir.props.description ?? indexChild.props.description, content: dir.props.content ?? indexChild.props.content, children: mergeElements(indexChild.props.children, remaining), }, }; }