mirror of https://github.com/iconify/api.git
153 lines
4.1 KiB
TypeScript
153 lines
4.1 KiB
TypeScript
import type { FastifyReply, FastifyRequest } from 'fastify';
|
|
import { stringToColor } from '@iconify/utils/lib/colors';
|
|
import { getIconsCSS } from '@iconify/utils/lib/css/icons';
|
|
import { getStoredIconsData } from '../../data/icon-set/utils/get-icons';
|
|
import { iconSets } from '../../data/icon-sets';
|
|
import type { IconCSSIconSetOptions } from '@iconify/utils/lib/css/types';
|
|
import { paramToBoolean } from '../../misc/bool';
|
|
|
|
/**
|
|
* Check selector for weird stuff
|
|
*/
|
|
function checkSelector(value: string | undefined): boolean {
|
|
if (typeof value !== 'string') {
|
|
return false;
|
|
}
|
|
const cleanValue = value.replaceAll('{name}', '').replaceAll('{prefix}', '');
|
|
return cleanValue.indexOf('{') === -1 && cleanValue.indexOf('}') === -1;
|
|
}
|
|
|
|
/**
|
|
* Generate icons style
|
|
*/
|
|
export function generateIconsStyleResponse(prefix: string, query: FastifyRequest['query'], res: FastifyReply) {
|
|
const q = (query || {}) as Record<string, string>;
|
|
const names = q.icons?.split(',');
|
|
|
|
if (!names || !names.length) {
|
|
// Missing or invalid icons parameter
|
|
res.send(404);
|
|
return;
|
|
}
|
|
|
|
// Get icon set
|
|
const iconSet = iconSets[prefix];
|
|
if (!iconSet) {
|
|
// No such icon set
|
|
res.send(404);
|
|
return;
|
|
}
|
|
|
|
// Get icons
|
|
getStoredIconsData(iconSet.item, names, (data) => {
|
|
// Options
|
|
const options: IconCSSIconSetOptions = {};
|
|
const qOptions = q as IconCSSIconSetOptions;
|
|
|
|
if (typeof qOptions.format === 'string') {
|
|
const format = qOptions.format;
|
|
switch (format) {
|
|
case 'compact':
|
|
case 'compressed':
|
|
case 'expanded':
|
|
options.format = format;
|
|
}
|
|
}
|
|
|
|
// 'color': string
|
|
// Sets color for monotone images
|
|
const color = qOptions.color;
|
|
if (typeof color === 'string' && stringToColor(color)) {
|
|
options.color = color;
|
|
}
|
|
|
|
// 'mode': string
|
|
// Forces mode
|
|
// Alias for 'background': 'bg'
|
|
const mode = qOptions.mode;
|
|
if (mode) {
|
|
switch (mode) {
|
|
case 'background':
|
|
case 'mask':
|
|
options.mode = mode;
|
|
|
|
default:
|
|
if ((mode as string) === 'bg') {
|
|
options.mode = 'background';
|
|
}
|
|
}
|
|
}
|
|
|
|
// 'forceSquare': boolean
|
|
// Forces icon to be square, regardless of width/height ratio
|
|
// Aliases: 'square', 'force-square'
|
|
const forceSquare = paramToBoolean(q.square || q.forceSquare || q['force-square'], void 0);
|
|
if (typeof forceSquare === 'boolean') {
|
|
options.forceSquare = forceSquare;
|
|
}
|
|
|
|
// 'pseudoSelector': boolean
|
|
// Adds `content: '';` to common selector. Useful when selector is a pseudo-selector
|
|
// Aliases: 'pseudo', 'pseudo-selector'
|
|
const pseudoSelector = paramToBoolean(q.pseudo || q.pseudoSelector || q['pseudo-selector'], void 0);
|
|
if (typeof pseudoSelector === 'boolean') {
|
|
options.pseudoSelector = pseudoSelector;
|
|
}
|
|
|
|
// 'commonSelector': string
|
|
// Common selector for all requested icons
|
|
// Alias: 'common'
|
|
const commonSelector = qOptions.commonSelector || q.common;
|
|
if (checkSelector(commonSelector)) {
|
|
options.commonSelector = commonSelector;
|
|
}
|
|
|
|
// 'iconSelector': string
|
|
// Icon selector
|
|
// Alias: 'selector'
|
|
const iconSelector = qOptions.iconSelector || q.selector;
|
|
if (checkSelector(iconSelector)) {
|
|
options.iconSelector = iconSelector;
|
|
}
|
|
|
|
// 'overrideSelector': string
|
|
// Selector for rules in icon that override common rules
|
|
// Alias: 'override'
|
|
const overrideSelector = qOptions.overrideSelector || q.override;
|
|
if (checkSelector(overrideSelector)) {
|
|
options.overrideSelector = overrideSelector;
|
|
}
|
|
|
|
// 'varName': string
|
|
// Variable name
|
|
// Alias: 'var'
|
|
const varName = q.varName || q.var;
|
|
if (typeof varName === 'string' && varName.match(/^[a-z0-9_-]*$/)) {
|
|
if (!varName || varName === 'null' || !paramToBoolean(varName, true)) {
|
|
options.varName = null;
|
|
} else {
|
|
options.varName = varName;
|
|
}
|
|
}
|
|
|
|
// Generate css
|
|
const css = getIconsCSS(
|
|
{
|
|
// Data
|
|
...data,
|
|
// Info to detect palette
|
|
info: iconSet.item.info,
|
|
},
|
|
names,
|
|
options
|
|
);
|
|
|
|
// Send CSS, optionally as attachment
|
|
if (q.download) {
|
|
res.header('Content-Disposition', 'attachment; filename="' + prefix + '.css"');
|
|
}
|
|
|
|
res.type('text/css; charset=utf-8').send(css);
|
|
});
|
|
}
|