UNPKG

@mintlify/prebuild

Version:

Helpful functions for Mintlify's prebuild step

63 lines (62 loc) 2.78 kB
import { exec } from 'child_process'; import { promisify } from 'util'; const execAsync = promisify(exec); /** * Gets git blame data for a file, returning a map of line numbers to ISO date strings. * Uses author-time (when the change was originally created) rather than committer-time. * @param filePath - Absolute path to the file * @param repoPath - Path to the git repository root * @returns Record<number, string> mapping line numbers (1-indexed) to ISO date strings */ export const getGitBlame = async (filePath, repoPath) => { try { // Make file path relative to repo root for git blame const relativeFilePath = filePath.startsWith(repoPath) ? filePath.substring(repoPath.length + 1) : filePath; // Use git blame with porcelain format for easier parsing // --line-porcelain gives us detailed info for each line const { stdout } = await execAsync(`git blame --line-porcelain "${relativeFilePath}"`, { cwd: repoPath, maxBuffer: 10 * 1024 * 1024, // 10MB buffer for large files }); const lineBlame = {}; const lines = stdout.split('\n'); for (let i = 0; i < lines.length; i++) { const line = lines[i]; if (!line) continue; // Line starting with commit hash indicates a new blame entry // Format: <commit-hash> <original-line> <final-line> <num-lines> const commitMatch = line.match(/^[0-9a-f]{40}\s+\d+\s+(\d+)/); if (commitMatch && commitMatch[1]) { const lineNumber = parseInt(commitMatch[1], 10); // Look ahead for 'author-time' field (Unix timestamp) let authorTime; for (let j = i + 1; j < lines.length && j < i + 15; j++) { const nextLine = lines[j]; if (!nextLine) continue; if (nextLine.startsWith('author-time ')) { const timestamp = parseInt(nextLine.substring('author-time '.length), 10); authorTime = new Date(timestamp * 1000).toISOString(); break; } // Stop when we hit the content line (starts with tab) if (nextLine.startsWith('\t')) { break; } } if (authorTime) { lineBlame[lineNumber] = authorTime; } } } return lineBlame; } catch (error) { // If git blame fails (e.g., file not in git, no commits), silently return empty blame // Server will use current date as fallback return {}; } };