Ajoute un outil de gestion interactive des liens morts
This commit is contained in:
92
tools/lib/url_replacements.js
Normal file
92
tools/lib/url_replacements.js
Normal file
@@ -0,0 +1,92 @@
|
||||
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<Array<{ filePath: string, occurrences: number }>>}
|
||||
*/
|
||||
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,
|
||||
};
|
||||
Reference in New Issue
Block a user