import crypto from 'crypto'; import fs from 'fs/promises'; import path from 'path'; import type {FileRule} from './options'; export function checkFileWithRules(filePath: string, rules: FileRule[] = []): boolean { for (const rule of rules) { if (rule instanceof RegExp) { rule.lastIndex = 0; if (rule.test(filePath)) { return true; } continue; } if (rule(filePath)) { return true; } } return false; } export function getMd5(data: Buffer | string): string { return crypto.createHash('md5').update(data).digest('hex').slice(0, 5); } export function getAssetType(uri: string): 'absolute' | 'base64' | 'relative' { if (/^http/i.test(uri)) { return 'absolute'; } if (/^data:[^;]+;base64,/.test(uri)) { return 'base64'; } return 'relative'; } export async function readFileText(filePath: string): Promise { return fs.readFile(filePath, 'utf8'); } export async function readFileBuffer(filePath: string): Promise { return fs.readFile(filePath); } export async function ensureDir(dirPath: string): Promise { await fs.mkdir(dirPath, {recursive: true}); } export async function writeFile(filePath: string, data: Buffer | string): Promise { await ensureDir(path.dirname(filePath)); await fs.writeFile(filePath, data); } export async function copyFile(from: string, to: string): Promise { await ensureDir(path.dirname(to)); await fs.copyFile(from, to); } export async function copyDir(from: string, to: string): Promise { await ensureDir(to); const entries = await fs.readdir(from, {withFileTypes: true}); for (const entry of entries) { const sourcePath = path.join(from, entry.name); const targetPath = path.join(to, entry.name); if (entry.isDirectory()) { await copyDir(sourcePath, targetPath); } else { await copyFile(sourcePath, targetPath); } } } export async function removeDir(dirPath: string): Promise { await fs.rm(dirPath, {recursive: true, force: true}); } export function bufferToDataUri(buffer: Buffer, mimeType: string): string { return `data:${mimeType || ''};base64,${buffer.toString('base64')}`; } export function cloneJson(input: T): T { return JSON.parse(JSON.stringify(input)); } export function toPosixPath(inputPath: string): string { return inputPath.replace(/\\/g, '/'); } export function getRelativeOutputDir(rootDir: string, sourceDir: string): string { const relativeDir = path.relative(rootDir, sourceDir); if (!relativeDir || relativeDir === '.') { return ''; } if (relativeDir.startsWith('..')) { return path.basename(sourceDir); } return relativeDir; } export function getHashedAssetPath(baseDir: string, uri: string, data: Buffer): string { const parsed = path.posix.parse(toPosixPath(uri)); const segments = parsed.dir ? parsed.dir.split('/') : []; segments.push(parsed.name, getMd5(data)); return path.join(baseDir, `${segments.join('-')}${parsed.ext}`); } export function appendHashToFilename(relativePath: string, data: Buffer): string { const parsed = path.parse(relativePath); return path.join(parsed.dir, `${parsed.name}-${getMd5(data)}${parsed.ext}`); }