Files
2024-08-06 14:00:40 +03:00

108 lines
3.9 KiB
JavaScript

const process = require('node:process');
const Ajv = require('ajv');
const addFormats = require('ajv-formats');
const fs = require('fs');
const path = require('path');
const sizeOf = require('image-size');
const schema = require('./token-schema.json');
const ajv = new Ajv();
addFormats(ajv);
const validate = ajv.compile(schema);
const dataDirectoryPath = path.resolve(process.cwd(), 'data');
const iconsDirectoryPath = path.resolve(dataDirectoryPath, 'icons');
async function validateJsonFile(filePath, iconUsage) {
// exclude file "list.json"
if (path.basename(filePath) === 'list.json') {
return;
}
const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
const valid = validate(data);
if (valid) {
console.log(`File ${path.basename(filePath)} is valid.`);
const iconFileName = data.iconFileName.toLowerCase();
const iconFilePath = path.join(iconsDirectoryPath, iconFileName);
if (!fs.existsSync(iconFilePath)) {
throw new Error(`File ${path.basename(filePath)} is invalid: Icon file ${iconFileName} does not exist.`);
}
if (iconUsage[iconFileName]) {
iconUsage[iconFileName]++;
} else {
iconUsage[iconFileName] = 1;
}
} else {
throw new Error(`File ${path.basename(filePath)} is invalid: ${JSON.stringify(validate.errors)}`);
}
}
function validatePngFile(filePath, iconUsage) {
if (path.extname(filePath) !== '.png') {
throw new Error(`File ${path.basename(filePath)} is invalid: Image must be in PNG format.`);
}
const dimensions = sizeOf(filePath);
const fileName = path.basename(filePath).toLowerCase();
const MIN_SIZE = 128;
const MAX_SIZE = 1024;
if (dimensions.width !== dimensions.height || dimensions.width < MIN_SIZE || dimensions.width > MAX_SIZE) {
throw new Error(`File ${fileName} is invalid: Image must be square and at least ${MIN_SIZE}x${MIN_SIZE} pixels, Your image is ${dimensions.width}x${dimensions.height} pixels.`);
} else if (!iconUsage[fileName] || iconUsage[fileName] > 1) {
throw new Error(`File ${fileName} is invalid: Icon must be used in exactly one JSON file.`);
} else {
console.log(`File ${fileName} is valid.`);
}
}
function validateAllFilesInDirectory(directoryPath, extension, validationFunction, iconUsage) {
const files = fs.readdirSync(directoryPath);
const fileNames = new Set();
files.forEach(file => {
const filePath = path.join(directoryPath, file);
const fileName = path.basename(file, extension).toLowerCase();
if (fileNames.has(fileName)) {
throw new Error(`File ${file} is invalid: Duplicate file name (case insensitive).`);
} else {
fileNames.add(fileName);
if (path.extname(file) === extension) {
validationFunction(filePath, iconUsage);
}
}
});
}
async function validateJsonFiles(iconUsage) {
const files = fs.readdirSync(dataDirectoryPath);
const fileNames = new Set();
for (const file of files) {
const filePath = path.join(dataDirectoryPath, file);
const fileName = path.basename(file, '.json').toLowerCase();
if (fileNames.has(fileName)) {
throw new Error(`File ${file} is invalid: Duplicate file name (case insensitive).`);
} else {
fileNames.add(fileName);
if (path.extname(file) === '.json') {
await validateJsonFile(filePath, iconUsage);
}
}
}
}
function validatePngFiles(iconUsage) {
validateAllFilesInDirectory(iconsDirectoryPath, '.png', validatePngFile, iconUsage);
}
(async () => {
const iconUsage = {};
try {
await validateJsonFiles(iconUsage);
validatePngFiles(iconUsage);
console.log('\x1b[32m%s\x1b[0m', 'All files are valid.');
} catch (error) {
console.error(error.message);
process.exit(1);
}
})();