2023-06-04 16:59:38 +02:00
|
|
|
import fs from 'fs';
|
|
|
|
|
import path from 'path';
|
|
|
|
|
import { readSvgDirectory } from './helpers.mjs';
|
|
|
|
|
|
|
|
|
|
const currentDir = process.cwd();
|
|
|
|
|
const ICONS_DIR = path.resolve(currentDir, '../icons');
|
|
|
|
|
const svgFiles = readSvgDirectory(ICONS_DIR, '.json');
|
|
|
|
|
|
|
|
|
|
const location = path.resolve(currentDir, '.vitepress/data', 'relatedIcons.json');
|
|
|
|
|
|
|
|
|
|
if (fs.existsSync(location)) {
|
|
|
|
|
fs.unlinkSync(location);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const nameWeight = 5;
|
|
|
|
|
const tagWeight = 4;
|
|
|
|
|
const categoryWeight = 3;
|
|
|
|
|
|
2024-02-01 22:38:21 +09:00
|
|
|
const MAX_RELATED_ICONS = 4 * 17; // grid of 4x17 icons, = 68 icons
|
2023-06-15 14:44:43 +02:00
|
|
|
|
2023-06-04 16:59:38 +02:00
|
|
|
const arrayMatches = (a, b) => {
|
|
|
|
|
// let matches = 0;
|
|
|
|
|
// for (let i = 0; i < a.length; ++i) {
|
|
|
|
|
// if (b.indexOf(a[i]) != -1) {
|
|
|
|
|
// matches++;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// return matches;
|
2024-02-01 22:38:21 +09:00
|
|
|
return a.filter((item) => b.includes(item)).length;
|
|
|
|
|
};
|
2023-06-04 16:59:38 +02:00
|
|
|
|
2024-02-01 22:38:21 +09:00
|
|
|
const nameParts = (icon) =>
|
2024-05-22 13:08:34 +02:00
|
|
|
[
|
|
|
|
|
icon.name,
|
|
|
|
|
...(icon.aliases?.map((alias) => (typeof alias === 'string' ? alias : alias.name)) ?? []),
|
|
|
|
|
]
|
2023-06-04 16:59:38 +02:00
|
|
|
.join('-')
|
|
|
|
|
.split('-')
|
2024-02-01 22:38:21 +09:00
|
|
|
.filter((word) => word.length > 2);
|
2023-06-04 16:59:38 +02:00
|
|
|
|
|
|
|
|
const getRelatedIcons = (currentIcon, icons) => {
|
|
|
|
|
const iconSimilarity = (item) =>
|
2024-02-01 22:38:21 +09:00
|
|
|
nameWeight * arrayMatches(nameParts(item), nameParts(currentIcon)) +
|
|
|
|
|
categoryWeight * arrayMatches(item.categories, currentIcon.categories) +
|
|
|
|
|
tagWeight * arrayMatches(item.tags, currentIcon.tags);
|
2023-06-04 16:59:38 +02:00
|
|
|
return icons
|
2024-02-01 22:38:21 +09:00
|
|
|
.filter((i) => i.name !== currentIcon.name)
|
|
|
|
|
.map((icon) => ({ icon, similarity: iconSimilarity(icon) }))
|
|
|
|
|
.filter((a) => a.similarity > 0) // @todo: maybe require a minimal non-zero similarity
|
2023-06-04 16:59:38 +02:00
|
|
|
.sort((a, b) => b.similarity - a.similarity)
|
2024-02-01 22:38:21 +09:00
|
|
|
.map((i) => i.icon)
|
|
|
|
|
.slice(0, MAX_RELATED_ICONS);
|
|
|
|
|
};
|
2023-06-04 16:59:38 +02:00
|
|
|
|
|
|
|
|
const iconsMetaDataPromises = svgFiles.map(async (iconName) => {
|
|
|
|
|
// eslint-disable-next-line import/no-dynamic-require, global-require
|
|
|
|
|
const metaData = await import(`../icons/${iconName}`, {
|
2024-02-01 22:38:21 +09:00
|
|
|
assert: { type: 'json' },
|
2023-06-04 16:59:38 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const name = iconName.replace('.json', '');
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
name,
|
2024-02-01 22:38:21 +09:00
|
|
|
...metaData.default,
|
2023-06-04 16:59:38 +02:00
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const iconsMetaData = await Promise.all(iconsMetaDataPromises);
|
|
|
|
|
|
2024-02-01 22:38:21 +09:00
|
|
|
const relatedIcons = iconsMetaData.map((icon) => {
|
2023-06-04 16:59:38 +02:00
|
|
|
const iconRelatedIcons = getRelatedIcons(icon, iconsMetaData);
|
2024-02-01 22:38:21 +09:00
|
|
|
return [icon.name, iconRelatedIcons.map((i) => i.name)];
|
2023-06-04 16:59:38 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
fs.promises
|
|
|
|
|
.writeFile(location, JSON.stringify(Object.fromEntries(relatedIcons), null, 2), 'utf-8')
|
|
|
|
|
.then(() => {
|
|
|
|
|
console.log('Successfully written relatedIcons.json file');
|
|
|
|
|
})
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
throw new Error(`Something went wrong generating iconNode files,\n ${error}`);
|
|
|
|
|
});
|