UNPKG

@analogjs/vite-plugin-nitro

Version:

A Vite plugin for adding a nitro API server

116 lines 5.06 kB
import { readFileSync } from 'node:fs'; import { join, relative, resolve } from 'node:path'; import { normalizePath } from 'vite'; import { createRequire } from 'node:module'; import { globSync } from 'tinyglobby'; const require = createRequire(import.meta.url); /** * Discovers content files with front matter and extracts metadata for prerendering. * * This function: * 1. Discovers all content files matching the specified glob pattern * 2. Reads each file and parses front matter metadata * 3. Extracts file name, extension, and path information * 4. Returns structured data for prerendering content pages * * @param workspaceRoot The workspace root directory path * @param rootDir The project root directory relative to workspace * @param glob The glob pattern to match content files (e.g., 'content/blog') * @returns Array of PrerenderContentFile objects with metadata and front matter * * Example usage: * const contentFiles = getMatchingContentFilesWithFrontMatter( * '/workspace', * 'apps/my-app', * 'content/blog' * ); * * Sample discovered file paths: * - /workspace/apps/my-app/content/blog/first-post.md * - /workspace/apps/my-app/content/blog/2024/01/hello-world.md * - /workspace/apps/my-app/content/blog/tech/angular-v17.mdx * - /workspace/apps/my-app/content/blog/about/index.md * * Sample output structure: * { * name: 'first-post', * extension: 'md', * path: 'content/blog', * attributes: { title: 'My First Post', date: '2024-01-01', tags: ['intro'] } * } * * tinyglobby vs fast-glob comparison: * - Both support the same glob patterns for file discovery * - Both are efficient for finding content files * - tinyglobby is now used instead of fast-glob * - tinyglobby provides similar functionality with smaller bundle size * - tinyglobby's globSync returns absolute paths when absolute: true is set * * Front matter parsing: * - Uses front-matter library to parse YAML/TOML front matter * - Extracts metadata like title, date, tags, author, etc. * - Supports both YAML (---) and TOML (+++) delimiters * - Returns structured attributes for prerendering * * File path processing: * - Normalizes paths for cross-platform compatibility * - Extracts file name without extension * - Determines file extension for content type handling * - Maintains relative path structure for routing */ export function getMatchingContentFilesWithFrontMatter(workspaceRoot, rootDir, glob, recursive = false) { // Dynamically require front-matter library // eslint-disable-next-line @typescript-eslint/no-var-requires const fm = require('front-matter'); // Normalize the project root path for consistent path handling const root = normalizePath(resolve(workspaceRoot, rootDir)); // Resolve the content directory path relative to the project root const resolvedDir = normalizePath(relative(root, join(root, glob))); // Discover all content files in the specified directory. // Default pattern matches only top-level files; recursive opt-in walks subdirectories. const pattern = recursive ? `${root}/${resolvedDir}/**/*` : `${root}/${resolvedDir}/*`; const contentFiles = globSync([pattern], { dot: true, absolute: true, onlyFiles: true, }); const dirPrefix = `${root}/${resolvedDir}`; // Process each discovered content file to extract metadata and front matter const mappedFilesWithFm = contentFiles.map((f) => { // Read the file contents as UTF-8 text const fileContents = readFileSync(f, 'utf8'); // Parse front matter from the file content const raw = fm(fileContents); // Get the relative file path by removing the root directory const filepath = f.replace(root, ''); // Extract file name and extension using regex // Matches: /filename.ext or /filename (with optional extension) const match = filepath.match(/\/([^/.]+)(\.([^/.]+))?$/); let name = ''; let extension = ''; if (match) { name = match[1]; // File name without extension extension = match[3] || ''; // File extension or empty string if no extension } // Path of the file's directory relative to the configured contentDir. // For top-level files this is an empty string; for nested files it // gives transforms enough context to disambiguate identically-named // files (e.g. docs/a/post.md vs docs/b/post.md). const relativeDir = normalizePath(relative(dirPrefix, f)); const lastSlash = relativeDir.lastIndexOf('/'); const relativePath = lastSlash === -1 ? '' : relativeDir.slice(0, lastSlash); // Return structured content file data for prerendering return { name, extension, path: resolvedDir, attributes: raw.attributes, content: fileContents, relativePath, }; }); return mappedFilesWithFm; } //# sourceMappingURL=get-content-files.js.map