diff --git a/.github/workflows/auto-cleanup-bot.yml b/.github/workflows/auto-cleanup-bot.yml index 058db6f36e88d38..7143b740ff1961b 100644 --- a/.github/workflows/auto-cleanup-bot.yml +++ b/.github/workflows/auto-cleanup-bot.yml @@ -31,13 +31,12 @@ jobs: yarn content fix-flaws yarn fix:md yarn fix:fm - node scripts/update-moved-file-links.js - name: Create PR with only fixable issues if: success() uses: peter-evans/create-pull-request@v5 with: - commit-message: "chore: auto-fix Markdownlint, Prettier, front-matter, redirects issues" + commit-message: "chore: auto-fix Markdownlint, Prettier, and front-matter issues" branch: markdownlint-auto-cleanup title: "fix: auto-cleanup by bot" author: mdn-bot <108879845+mdn-bot@users.noreply.github.com> @@ -49,7 +48,7 @@ jobs: if: failure() uses: peter-evans/create-pull-request@v5 with: - commit-message: "chore: auto-fix Markdownlint issues" + commit-message: "chore: auto-fix Markdownlint, Prettier, and front-matter issues" branch: markdownlint-auto-cleanup title: "fix: auto-cleanup by bot" author: mdn-bot <108879845+mdn-bot@users.noreply.github.com> diff --git a/.lintstagedrc.json b/.lintstagedrc.json index 9e259f12baf57f8..094d52dba504cc4 100644 --- a/.lintstagedrc.json +++ b/.lintstagedrc.json @@ -3,6 +3,7 @@ "*.md": [ "markdownlint-cli2 --fix", "node scripts/front-matter_linter.js --fix true", + "node scripts/update-moved-file-links.js --check", "prettier --write" ], "tests/**/*.*": "yarn test:front-matter-linter", diff --git a/scripts/update-moved-file-links.js b/scripts/update-moved-file-links.js index 264a9d4aa562ce0..1034440f1d1535d 100644 --- a/scripts/update-moved-file-links.js +++ b/scripts/update-moved-file-links.js @@ -1,12 +1,18 @@ import fs from "node:fs/promises"; import path from "node:path"; -import { execGit, getRootDir, walkSync, isImagePath } from "./utils.js"; +import { + execGit, + getRootDir, + walkSync, + isImagePath, + IMG_RX, + SLUG_RX, +} from "./utils.js"; -const SLUG_RX = /(?<=\nslug: ).*?$/gm; const HELP_MSG = "Usage:\n\t" + "node scripts/update-moved-file-links.js\n\t" + - "node scripts/update-moved-file-links.js [movedFromPath] [movedToPath]\n"; + "node scripts/update-moved-file-links.js --check\n"; /** * Try to get slug for an image from file path @@ -26,43 +32,37 @@ export async function getImageSlug(imagePath, root) { } } -let movedFiles = []; const rootDir = getRootDir(); -const argLength = process.argv.length; +let movedFiles = []; +let isCheckOnly = false; if (process.argv[2] === "--help" || process.argv[2] === "-h") { console.error(HELP_MSG); process.exit(0); -} else if (argLength === 2 && argLength > 3) { - console.error(HELP_MSG); - process.exit(1); -} else if (argLength === 3) { - movedFiles.push({ from: process.argv[2], to: process.argv[3] }); -} else { - // git log --name-status --pretty=format:"" --since "1 day ago" --diff-filter=R - let result = execGit( - [ - "log", - "--name-status", - "--pretty=format:", - '--since="1 day ago"', - "--diff-filter=R", - ], - { cwd: "." }, - ); +} else if (process.argv[2] === "--check") { + isCheckOnly = true; +} - if (result.trim()) { - movedFiles.push( - ...result - .split("\n") - .filter((line) => line.trim() !== "" && line.includes("files/en-us")) - .map((line) => line.replaceAll(/files\/en-us\/|\/index.md/gm, "")) - .map((line) => line.split(/\s/)) - .map((tuple) => { - return { from: tuple[1], to: tuple[2] }; - }), - ); - } +// get staged and unstaged changes +const result = execGit(["status", "--short", "--porcelain"], { cwd: "." }); +if (result.trim()) { + movedFiles.push( + ...result + .split("\n") + .filter( + (line) => + /^\s*RM?\s+/gi.test(line) && + line.includes("files/en-us") && + (IMG_RX.test(line) || line.includes("index.md")), + ) + .map((line) => + line.replaceAll(/^\s*RM?\s+|files\/en-us\/|\/index.md/gm, ""), + ) + .map((line) => line.split(/ -> /)) + .map((tuple) => { + return { from: tuple[0], to: tuple[1] }; + }), + ); } if (movedFiles.length < 1) { @@ -99,7 +99,7 @@ movedFiles = ( ) ).filter((e) => !!e); -console.log(`Number of moved files to consider: ${movedFiles.length}`); +console.log("Moved files:", movedFiles); let totalNo = 0; let updatedNo = 0; @@ -108,7 +108,7 @@ for await (const filePath of walkSync(getRootDir())) { try { totalNo++; const content = await fs.readFile(filePath, "utf-8"); - let updated = new String(content); + let updated = String(content); for (const moved of movedFiles) { // [text](link) updated = updated.replaceAll(`${moved.from})`, `${moved.to})`); @@ -124,7 +124,14 @@ for await (const filePath of walkSync(getRootDir())) { updated = updated.replaceAll(`${moved.from}'`, `${moved.to}'`); } - if (content !== updated) { + if (content !== updated.valueOf()) { + if (isCheckOnly) { + console.error( + "File(s) have been moved. " + + "Run 'node scripts/update-moved-file-links.js' to update references.", + ); + process.exit(1); + } updatedNo++; await fs.writeFile(filePath, updated); } diff --git a/scripts/utils.js b/scripts/utils.js index 3a8bb5e692f4751..e424338a39dcbb7 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -2,7 +2,8 @@ import fs from "node:fs/promises"; import path from "node:path"; import childProcess from "node:child_process"; -const IMG_RX = /(\.png|\.jpg|\.svg|\.gif)$/gim; +export const IMG_RX = /(\.png|\.jpg|\.svg|\.gif)$/gim; +export const SLUG_RX = /(?<=\nslug: ).*?$/gm; export async function* walkSync(dir) { const files = await fs.readdir(dir, { withFileTypes: true });