const fs = require("node:fs/promises"); const path = require("node:path"); const { collectFilesByExtensions } = require("./content"); const DEFAULT_URL_TEXT_EXTENSIONS = Object.freeze([ ".json", ".markdown", ".md", ".yaml", ".yml", ]); /** * Compte les occurrences exactes d'une chaine dans un texte. * @param {string} text Texte a analyser. * @param {string} needle Chaine recherchee. * @returns {number} Nombre d'occurrences trouvees. */ function countOccurrences(text, needle) { if (typeof text !== "string") { return 0; } if (typeof needle !== "string" || !needle) { return 0; } return text.split(needle).length - 1; } /** * Retourne la liste des fichiers textuels contenant une URL donnee. * @param {string} rootDir Racine a parcourir. * @param {string} targetUrl URL a rechercher. * @param {{ extensions?: string[] }} options Options de recherche. * @returns {Promise>} */ async function findUrlOccurrences(rootDir, targetUrl, options = {}) { let extensions = DEFAULT_URL_TEXT_EXTENSIONS; if (Array.isArray(options.extensions)) { extensions = options.extensions; } const files = await collectFilesByExtensions(rootDir, extensions); const matches = []; for (const filePath of files) { const content = await fs.readFile(filePath, "utf8"); const occurrences = countOccurrences(content, targetUrl); if (occurrences <= 0) { continue; } matches.push({ filePath, occurrences }); } return matches; } /** * Remplace toutes les occurrences exactes d'une URL dans une liste de fichiers. * @param {string} rootDir Racine de recherche. * @param {string} targetUrl URL a remplacer. * @param {string} replacementUrl URL de remplacement. * @param {{ extensions?: string[], matches?: Array<{ filePath: string, occurrences: number }> }} options Options d'ecriture. * @returns {Promise<{ changedFiles: string[], totalOccurrences: number }>} */ async function replaceUrlInFiles(rootDir, targetUrl, replacementUrl, options = {}) { let matches = []; if (Array.isArray(options.matches)) { matches = options.matches; } else { matches = await findUrlOccurrences(rootDir, targetUrl, options); } const changedFiles = []; let totalOccurrences = 0; for (const match of matches) { const filePath = path.resolve(match.filePath); const content = await fs.readFile(filePath, "utf8"); const updatedContent = content.split(targetUrl).join(replacementUrl); await fs.writeFile(filePath, updatedContent, "utf8"); changedFiles.push(filePath); totalOccurrences += match.occurrences; } return { changedFiles, totalOccurrences }; } module.exports = { DEFAULT_URL_TEXT_EXTENSIONS, countOccurrences, findUrlOccurrences, replaceUrlInFiles, };