Newer
Older
gnexus-ui-kit / scripts / check-demo-sections.mjs
@Eugene Sukhodolskiy Eugene Sukhodolskiy 1 day ago 2 KB Add static demo section sync check
#!/usr/bin/env node
// Static demo-sync check: the @@include section lists of demo/index.html
// (vanilla) and demo/vue.html must be identical, every included partial
// must exist in both demo/partials/ and demo/partials/vue/, and no
// partial may be orphaned (present on disk but included by neither demo).
// Catches section drift before the build, without a running server.

import { readdirSync, readFileSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";

const root = join(dirname(fileURLToPath(import.meta.url)), "..");
const partialsDir = join(root, "demo/partials");
const vueDir = join(root, "demo/partials/vue");

const sections = file => {
	const matches = [...readFileSync(join(root, file), "utf8").matchAll(/@@include\("partials(?:\/vue)?\/([a-z-]+)\.html"\)/g)];
	return matches.map(match => match[1]);
};

const vanilla = sections("demo/index.html");
const vue = sections("demo/vue.html");

let failed = false;
const fail = message => {
	failed = true;
	console.error(`[demo-sections] ${message}`);
};

const max = Math.max(vanilla.length, vue.length);
for(let index = 0; index < max; index++) {
	if(vanilla[index] !== vue[index]) {
		fail(`section order mismatch at position ${index}: vanilla="${vanilla[index]}" vue="${vue[index]}"`);
	}
}

if(vanilla.length !== vue.length) {
	fail(`section count differs: vanilla=${vanilla.length} vue=${vue.length}`);
}

const listFiles = dir =>
	readdirSync(dir)
		.filter(name => name.endsWith(".html"))
		.map(name => name.replace(/\.html$/, ""));

const vanillaFiles = new Set(listFiles(partialsDir));
const vueFiles = new Set(listFiles(vueDir));

for(const name of new Set([...vanilla, ...vue])) {
	if(!vanillaFiles.has(name)) {
		fail(`partials/${name}.html is included but missing on disk`);
	}
	if(!vueFiles.has(name)) {
		fail(`partials/vue/${name}.html is included but missing on disk`);
	}
}

for(const name of vanillaFiles) {
	if(!vanilla.includes(name)) {
		fail(`partials/${name}.html is not included in demo/index.html (orphan)`);
	}
}
for(const name of vueFiles) {
	if(!vue.includes(name)) {
		fail(`partials/vue/${name}.html is not included in demo/vue.html (orphan)`);
	}
}

if(failed) {
	process.exit(1);
}
console.log(`[demo-sections] ${vanilla.length} sections in sync, ${vanillaFiles.size} partials on disk`);