Files
flaticon-uicons/update-icon-list.js
T
ubunteroz ae66c2e34c Initial commit: Flaticon UIcons package with local font build system
Add 50,000+ icon font package sourced from Flaticon API with local
webfonts and interactive icon explorer.

Features:
- 50,492 icons across 15 style variations (weight × corner)
- Self-hosted webfonts (TTF, WOFF, WOFF2)
- Interactive icon explorer with search and filters
- FontForge-based build pipeline for generating fonts from SVGs
- Drop-in CSS with class-based icon usage

Build scripts:
- scripts/build-font.py - Standalone FontForge Python script
- build-fonts.js - Node.js orchestrator for font generation
- update-icon-list.js - Fetch icon metadata from Flaticon API
- build-icons-js.js - Generate browser-ready icon dataset

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Z.ai GLM 4.7 <noreply@z.ai>
2026-01-24 10:58:23 +08:00

121 lines
3.6 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const https = require('https');
const buildIconsJs = require('./build-icons-js');
const API_URL = 'https://www.flaticon.com/ajax/icon-fonts-most-downloaded/';
const HEADERS = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Sec-Ch-Ua': '"Not A(Brand";v="99", "Google Chrome";v="121"',
'Sec-Ch-Ua-Mobile': '?0',
'Sec-Ch-Ua-Platform': '"macOS"',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none'
};
function parseArgs(argv) {
const args = {};
for (let i = 0; i < argv.length; i += 1) {
const arg = argv[i];
if (!arg.startsWith('--')) continue;
const key = arg.slice(2);
const value = argv[i + 1] && !argv[i + 1].startsWith('--') ? argv[i + 1] : true;
if (value !== true) i += 1;
args[key] = value;
}
return args;
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function fetchJson(page) {
const url = `${API_URL}${page}`;
return new Promise((resolve, reject) => {
const request = https.request(url, { headers: HEADERS }, response => {
let data = '';
response.on('data', chunk => {
data += chunk;
});
response.on('end', () => {
try {
resolve(JSON.parse(data));
} catch (error) {
reject(error);
}
});
});
request.on('error', reject);
request.end();
});
}
async function run() {
const args = parseArgs(process.argv.slice(2));
const start = Number(args.start || 1);
let end = Number(args.end || 0);
const delay = Number(args.delay || 100);
if (Number.isNaN(start) || start < 1) {
throw new Error('Invalid --start value');
}
console.log(`Fetching icons starting at page ${start}...`);
const first = await fetchJson(start);
if (!first || !Array.isArray(first.items)) {
throw new Error('Unexpected response from Flaticon API');
}
if (!end || Number.isNaN(end)) {
end = Number(first.pages || start);
}
const itemsById = new Map();
const addItems = items => {
(items || []).forEach(item => {
if (item && item.id) {
itemsById.set(item.id, item);
}
});
};
addItems(first.items);
console.log(`Page ${start}/${end}: ${first.items.length} items`);
for (let page = start + 1; page <= end; page += 1) {
const payload = await fetchJson(page);
addItems(payload.items);
if (page % 25 === 0 || page === end) {
console.log(`Page ${page}/${end}: ${payload.items.length} items`);
}
if (delay > 0) {
await sleep(delay);
}
}
const outputDir = path.join(__dirname, 'data');
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const allIcons = Array.from(itemsById.values());
const outputPath = path.join(outputDir, 'all_icons.json');
fs.writeFileSync(outputPath, JSON.stringify(allIcons), 'utf8');
console.log(`Wrote ${outputPath} (${allIcons.length} icons)`);
buildIconsJs({
inputPath: outputPath,
outputPath: path.join(outputDir, 'all_icons.js')
});
}
run().catch(error => {
console.error(error.message || error);
process.exit(1);
});