mirror of
https://github.com/iconify/iconify.git
synced 2024-10-24 09:32:02 +00:00
128 lines
2.7 KiB
TypeScript
128 lines
2.7 KiB
TypeScript
|
import type { IconifyIcon } from '@iconify/types';
|
||
|
import type { FullIconCustomisations } from '@iconify/utils/lib/customisations';
|
||
|
import {
|
||
|
defaults,
|
||
|
mergeCustomisations,
|
||
|
} from '@iconify/utils/lib/customisations';
|
||
|
import {
|
||
|
flipFromString,
|
||
|
alignmentFromString,
|
||
|
} from '@iconify/utils/lib/customisations/shorthand';
|
||
|
import { rotateFromString } from '@iconify/utils/lib/customisations/rotate';
|
||
|
import { iconToSVG } from '@iconify/utils/lib/svg/build';
|
||
|
import { replaceIDs } from '@iconify/utils/lib/svg/id';
|
||
|
import type { IconifyIconCustomisations, IconifyIconProps } from './props';
|
||
|
|
||
|
/**
|
||
|
* Render result
|
||
|
*/
|
||
|
export interface RenderResult {
|
||
|
width: string | number;
|
||
|
height: string | number;
|
||
|
viewBox: string;
|
||
|
preserveAspectRatio: string;
|
||
|
style?: string;
|
||
|
className: string;
|
||
|
body: string;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render icon
|
||
|
*/
|
||
|
export const render = (
|
||
|
// Icon must be validated before calling this function
|
||
|
icon: Required<IconifyIcon>,
|
||
|
|
||
|
// Partial properties
|
||
|
props: IconifyIconProps,
|
||
|
|
||
|
// Class name
|
||
|
className: string
|
||
|
): RenderResult => {
|
||
|
// Get all customisations
|
||
|
const customisations = mergeCustomisations(
|
||
|
defaults,
|
||
|
props as IconifyIconCustomisations
|
||
|
) as FullIconCustomisations;
|
||
|
|
||
|
// Create empty style
|
||
|
let style = '';
|
||
|
|
||
|
// Get element properties
|
||
|
for (let key in props) {
|
||
|
const value = props[key];
|
||
|
if (value === void 0) {
|
||
|
continue;
|
||
|
}
|
||
|
switch (key) {
|
||
|
// Properties to ignore
|
||
|
case 'icon':
|
||
|
case 'onLoad':
|
||
|
break;
|
||
|
|
||
|
// Boolean attributes
|
||
|
case 'inline':
|
||
|
case 'hFlip':
|
||
|
case 'vFlip':
|
||
|
customisations[key] =
|
||
|
value === true || value === 'true' || value === 1;
|
||
|
break;
|
||
|
|
||
|
// Flip as string: 'horizontal,vertical'
|
||
|
case 'flip':
|
||
|
if (typeof value === 'string') {
|
||
|
flipFromString(customisations, value);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Alignment as string
|
||
|
case 'align':
|
||
|
if (typeof value === 'string') {
|
||
|
alignmentFromString(customisations, value);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Color: copy to style
|
||
|
case 'color':
|
||
|
style += 'color: ' + value + ';';
|
||
|
break;
|
||
|
|
||
|
// Rotation as string
|
||
|
case 'rotate':
|
||
|
if (typeof value === 'string') {
|
||
|
customisations[key] = rotateFromString(value);
|
||
|
} else if (typeof value === 'number') {
|
||
|
customisations[key] = value;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
// Ignore other properties
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Generate icon
|
||
|
const item = iconToSVG(icon, customisations);
|
||
|
|
||
|
// Counter for ids based on "id" property to render icons consistently on server and client
|
||
|
let localCounter = 0;
|
||
|
const id = props.id;
|
||
|
|
||
|
// Create body
|
||
|
const body = replaceIDs(
|
||
|
item.body,
|
||
|
id ? () => id + '-' + localCounter++ : 'iconify-ember-'
|
||
|
);
|
||
|
|
||
|
// Add inline
|
||
|
if (item.inline) {
|
||
|
style += 'vertical-align: -0.125em;';
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
...item.attributes,
|
||
|
style: style === '' ? void 0 : style,
|
||
|
className,
|
||
|
body,
|
||
|
};
|
||
|
};
|