2
0
mirror of https://github.com/iconify/iconify.git synced 2024-12-04 18:23:17 +00:00

chore: fix transformations in generated css

This commit is contained in:
Vjacheslav Trushkin 2024-08-23 18:48:22 +03:00
parent b6c141ea14
commit 52ab55a112
4 changed files with 84 additions and 12 deletions

View File

@ -3,7 +3,7 @@
"type": "module",
"description": "Common functions for working with Iconify icon sets used by various packages.",
"author": "Vjacheslav Trushkin",
"version": "2.1.31",
"version": "2.1.32",
"license": "MIT",
"bugs": "https://github.com/iconify/iconify/issues",
"homepage": "https://iconify.design/docs/libraries/utils/",

View File

@ -7,7 +7,8 @@ import type {
IconCSSItemOptions,
IconContentItemOptions,
} from './types';
import { makeIconSquare } from '../icon/square';
import { makeViewBoxSquare } from '../icon/square';
import { iconToSVG } from '../svg/build';
/**
* Generates common CSS rules for multiple icons, rendered as background/mask
@ -61,24 +62,28 @@ export function generateItemCSSRules(
const result = {} as Record<string, string>;
const varName = options.varName;
// Build icon
const buildResult = iconToSVG(icon);
let viewBox = buildResult.viewBox;
// Calculate width
if (icon.width !== icon.height) {
if (viewBox[2] !== viewBox[3]) {
if (options.forceSquare) {
// Change viewBox
icon = makeIconSquare(icon);
viewBox = makeViewBoxSquare(viewBox);
} else {
// Change width in result
result['width'] = calculateSize('1em', icon.width / icon.height);
result['width'] = calculateSize('1em', viewBox[2] / viewBox[3]);
}
}
// Get SVG
const svg = iconToHTML(
icon.body.replace(/currentColor/g, options.color || 'black'),
buildResult.body.replace(/currentColor/g, options.color || 'black'),
{
viewBox: `${icon.left} ${icon.top} ${icon.width} ${icon.height}`,
width: icon.width.toString(),
height: icon.height.toString(),
viewBox: `${viewBox[0]} ${viewBox[1]} ${viewBox[2]} ${viewBox[3]}`,
width: `${viewBox[2]}`,
height: `${viewBox[3]}`,
}
);
@ -110,16 +115,20 @@ export function generateItemContent(
icon: Required<IconifyIcon>,
options: IconContentItemOptions
): string {
// Build icon
const buildResult = iconToSVG(icon);
const viewBox = buildResult.viewBox;
// Get dimensions
const height = options.height;
const width =
options.width ?? calculateSize(height, icon.width / icon.height);
options.width ?? calculateSize(height, viewBox[2] / viewBox[3]);
// Get SVG
const svg = iconToHTML(
icon.body.replace(/currentColor/g, options.color || 'black'),
buildResult.body.replace(/currentColor/g, options.color || 'black'),
{
viewBox: `${icon.left} ${icon.top} ${icon.width} ${icon.height}`,
viewBox: `${viewBox[0]} ${viewBox[1]} ${viewBox[2]} ${viewBox[3]}`,
width: width.toString(),
height: height.toString(),
}

View File

@ -1,4 +1,5 @@
import type { IconifyIcon } from '@iconify/types';
import { SVGViewBox } from '../svg/viewbox';
/**
* Make icon square
@ -19,3 +20,15 @@ export function makeIconSquare(
}
return icon;
}
/**
* Make icon viewBox square
*/
export function makeViewBoxSquare(viewBox: SVGViewBox): SVGViewBox {
const [left, top, width, height] = viewBox;
if (width !== height) {
const max = Math.max(width, height);
return [left - (max - width) / 2, top - (max - height) / 2, max, max];
}
return viewBox;
}

View File

@ -28,6 +28,32 @@ describe('Testing CSS for icon', () => {
`);
});
test('Background with transformations', () => {
const icon: IconifyIcon = {
body: '<path d="M0 0h16v16z" fill="#f80" />',
rotate: 1,
width: 24,
height: 16,
};
const expectedURL = svgToURL(
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 24" width="16" height="24"><g transform="rotate(90 8 8)">${icon.body}</g></svg>`
);
expect(
getIconCSS(icon, {
format: 'expanded',
})
).toBe(`.icon {
display: inline-block;
width: 0.67em;
height: 1em;
background-repeat: no-repeat;
background-size: 100% 100%;
background-image: ${expectedURL};
}
`);
});
test('Background with options', () => {
const icon: IconifyIcon = {
body: '<path d="M0 0h16v16z" fill="#f80" />',
@ -218,6 +244,30 @@ describe('Testing CSS for icon', () => {
visibility: visible;
content: ${expectedURL};
}
`);
});
test('Transformations with getIconContentCSS', () => {
const icon: IconifyIcon = {
body: '<path d="M0 0h16v16z" fill="currentColor" stroke="currentColor" stroke-width="1" />',
hFlip: true,
};
const expectedURL = svgToURL(
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="24" height="24"><g transform="translate(16 0) scale(-1 1)">${icon.body.replace(
/currentColor/g,
'black'
)}</g></svg>`
);
expect(
getIconContentCSS(icon, {
height: 24,
format: 'expanded',
iconSelector: '.test-icon::before',
})
).toBe(`.test-icon::before {
content: ${expectedURL};
}
`);
});
});