147 lines
4.1 KiB
JavaScript
147 lines
4.1 KiB
JavaScript
#!/usr/bin/env node
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import process from "node:process";
|
|
import YAML from "yaml";
|
|
|
|
const root = path.resolve(import.meta.dirname, "..");
|
|
const recipesDir = path.join(root, "culinary", "recipes");
|
|
|
|
const autofix = process.argv.includes("--fix") || process.argv.includes("--autofix");
|
|
|
|
const gerundMap = {
|
|
"mixing": "Mix",
|
|
"combining": "Combine",
|
|
"adding": "Add",
|
|
"whisking": "Whisk",
|
|
"stirring": "Stir",
|
|
"baking": "Bake",
|
|
"cooking": "Cook",
|
|
"heating": "Heat",
|
|
"pouring": "Pour",
|
|
"placing": "Place",
|
|
"cutting": "Cut",
|
|
"dicing": "Dice",
|
|
"chopping": "Chop",
|
|
"kneading": "Knead",
|
|
"rolling": "Roll",
|
|
"folding": "Fold",
|
|
"preheating": "Preheat",
|
|
"seasoning": "Season",
|
|
"simmering": "Simmer",
|
|
"boiling": "Boil",
|
|
"cooling": "Cool",
|
|
"refrigerating": "Refrigerate",
|
|
"freezing": "Freeze",
|
|
"storing": "Store",
|
|
"serving": "Serve",
|
|
"garnishing": "Garnish",
|
|
};
|
|
|
|
function standardizeInstruction(text) {
|
|
let clean = text.trim();
|
|
if (!clean) return clean;
|
|
|
|
// Check if it's an inline note: (Note: ...) or (...)
|
|
if (clean.startsWith("(") && clean.endsWith(")")) {
|
|
return clean;
|
|
}
|
|
|
|
// Check if it's a section heading: ends with colon
|
|
if (clean.endsWith(":")) {
|
|
// Capitalize first character
|
|
clean = clean.charAt(0).toUpperCase() + clean.slice(1);
|
|
return clean;
|
|
}
|
|
|
|
// Check for common gerund starts
|
|
const words = clean.split(/\s+/);
|
|
const firstWordLower = words[0].toLowerCase();
|
|
if (gerundMap[firstWordLower]) {
|
|
words[0] = gerundMap[firstWordLower];
|
|
clean = words.join(" ");
|
|
}
|
|
|
|
// Capitalize first letter
|
|
clean = clean.charAt(0).toUpperCase() + clean.slice(1);
|
|
|
|
// Replace trailing comma, semicolon, or dash with period
|
|
clean = clean.replace(/[,;\-\s]+$/, "");
|
|
|
|
// Ensure terminal punctuation if not ending with : or )
|
|
if (!clean.endsWith(".") && !clean.endsWith("!") && !clean.endsWith("?") && !clean.endsWith(":") && !clean.endsWith(")")) {
|
|
clean += ".";
|
|
}
|
|
|
|
return clean;
|
|
}
|
|
|
|
function lintRecipeFile(filePath) {
|
|
const content = fs.readFileSync(filePath, "utf8");
|
|
const data = YAML.parse(content);
|
|
if (!data || !Array.isArray(data.steps)) return { warnings: [], errors: [], changed: false };
|
|
|
|
const issues = [];
|
|
let changed = false;
|
|
|
|
const newSteps = data.steps.map((step, index) => {
|
|
const original = step.instruction ?? "";
|
|
const standardized = standardizeInstruction(original);
|
|
|
|
if (original !== standardized) {
|
|
issues.push({
|
|
stepOrder: step.order ?? index + 1,
|
|
original,
|
|
standardized,
|
|
});
|
|
if (autofix) {
|
|
changed = true;
|
|
return { ...step, instruction: standardized };
|
|
}
|
|
}
|
|
return step;
|
|
});
|
|
|
|
if (changed && autofix) {
|
|
data.steps = newSteps;
|
|
fs.writeFileSync(filePath, YAML.stringify(data, { indent: 2, lineWidth: 0 }), "utf8");
|
|
}
|
|
|
|
return { issues, changed };
|
|
}
|
|
|
|
function main() {
|
|
const files = fs.readdirSync(recipesDir).filter((f) => f.endsWith(".yaml")).sort();
|
|
let totalIssues = 0;
|
|
let filesModified = 0;
|
|
|
|
console.log(`Auditing ${files.length} recipe instruction files against Microsoft procedural guidelines...`);
|
|
|
|
for (const file of files) {
|
|
const filePath = path.join(recipesDir, file);
|
|
const { issues, changed } = lintRecipeFile(filePath);
|
|
if (issues.length > 0) {
|
|
totalIssues += issues.length;
|
|
if (changed) filesModified++;
|
|
console.log(`\n📄 ${file} (${issues.length} issue${issues.length > 1 ? "s" : ""}):`);
|
|
for (const issue of issues) {
|
|
console.log(` Step ${issue.stepOrder}:`);
|
|
console.log(` - Current: "${issue.original}"`);
|
|
console.log(` + Standard: "${issue.standardized}"`);
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log("\n--------------------------------------------------");
|
|
if (autofix) {
|
|
console.log(`✅ Standardized ${totalIssues} instructions across ${filesModified} recipe files.`);
|
|
} else {
|
|
console.log(`Found ${totalIssues} non-standard instructions.`);
|
|
if (totalIssues > 0) {
|
|
console.log("Run with --fix to apply automated standardization.");
|
|
}
|
|
}
|
|
}
|
|
|
|
main();
|