content / scripts /front-matter_linter.js
AbdulElahGwaith's picture
Upload folder using huggingface_hub
780c9fe verified
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { eachLimit } from "async";
import cliProgress from "cli-progress";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { fdir } from "fdir";
import { getAjvValidator, checkFrontMatter } from "./front-matter_utils.js";
async function resolveDirectory(file) {
const stats = await fs.lstat(file);
if (stats.isDirectory()) {
const api = new fdir()
.withErrors()
.withFullPaths()
.filter((filePath) => filePath.endsWith("index.md"))
.exclude((dirName) => dirName === "conflicting" || dirName === "orphaned")
.crawl(file);
return api.withPromise();
} else if (
stats.isFile() &&
file.endsWith("index.md") &&
!file.includes("/conflicting/") &&
!file.includes("/orphaned/") &&
!file.includes("scripts/filecheck/fixtures/") &&
!file.includes("tests/front-matter_test_files")
) {
return [file];
} else {
return [];
}
}
// lint front matter
async function lintFrontMatter(filesAndDirectories, options) {
const files = (
await Promise.all(filesAndDirectories.map(resolveDirectory))
).flat();
options.config = JSON.parse(await fs.readFile(options.configFile, "utf-8"));
options.validator = getAjvValidator(options.config.schema);
const progressBar = new cliProgress.SingleBar({ etaBuffer: 100 });
progressBar.start(files.length, 0);
const errors = [];
const fixableErrors = [];
await eachLimit(files, os.cpus().length, async (file) => {
try {
const [error, fixableError, content] = await checkFrontMatter(
file,
options,
);
if (content) {
fs.writeFile(file, content);
}
error && errors.push(error);
fixableError && fixableErrors.push(fixableError);
} catch (err) {
errors.push(`${err}\n ${err.stack}`);
} finally {
progressBar.increment();
}
});
progressBar.stop();
console.log(errors.length, fixableErrors.length);
if (errors.length || fixableErrors.length) {
let msg = errors.map((error) => `${error}`).join("\n\n");
if (fixableErrors.length) {
msg += "\n\nFollowing fixable errors can be fixed using '--fix' option\n";
msg += fixableErrors.map((error) => `${error}`).join("\n");
}
throw new Error(msg);
}
}
yargs(hideBin(process.argv))
.command(
"$0 [files...]",
"Lint front matter in markdown files",
(yargs) => {
return yargs
.positional("files", {
type: "string",
array: true,
describe: "List of files and/or directories to check",
default: ["./files/en-us"],
})
.option("fix", {
type: "boolean",
describe: "Save corrected output",
default: false,
})
.option("config-file", {
type: "string",
describe: "Custom configuration file",
default: "./front-matter-config.json",
});
},
async (argv) => {
const cwd = process.cwd();
const files = (argv.files || []).map((f) => path.resolve(cwd, f));
if (!files.length) {
console.info("No files to lint.");
return;
}
// yargs converts dashed flags to camelCase by default.
const options = {
fix: argv.fix,
configFile: argv.configFile,
};
await lintFrontMatter(files, options);
},
)
.help().argv;