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

View File

@ -7,7 +7,8 @@ import type {
IconCSSItemOptions, IconCSSItemOptions,
IconContentItemOptions, IconContentItemOptions,
} from './types'; } 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 * 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 result = {} as Record<string, string>;
const varName = options.varName; const varName = options.varName;
// Build icon
const buildResult = iconToSVG(icon);
let viewBox = buildResult.viewBox;
// Calculate width // Calculate width
if (icon.width !== icon.height) { if (viewBox[2] !== viewBox[3]) {
if (options.forceSquare) { if (options.forceSquare) {
// Change viewBox // Change viewBox
icon = makeIconSquare(icon); viewBox = makeViewBoxSquare(viewBox);
} else { } else {
// Change width in result // Change width in result
result['width'] = calculateSize('1em', icon.width / icon.height); result['width'] = calculateSize('1em', viewBox[2] / viewBox[3]);
} }
} }
// Get SVG // Get SVG
const svg = iconToHTML( 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: icon.width.toString(), width: `${viewBox[2]}`,
height: icon.height.toString(), height: `${viewBox[3]}`,
} }
); );
@ -110,16 +115,20 @@ export function generateItemContent(
icon: Required<IconifyIcon>, icon: Required<IconifyIcon>,
options: IconContentItemOptions options: IconContentItemOptions
): string { ): string {
// Build icon
const buildResult = iconToSVG(icon);
const viewBox = buildResult.viewBox;
// Get dimensions // Get dimensions
const height = options.height; const height = options.height;
const width = const width =
options.width ?? calculateSize(height, icon.width / icon.height); options.width ?? calculateSize(height, viewBox[2] / viewBox[3]);
// Get SVG // Get SVG
const svg = iconToHTML( 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(), width: width.toString(),
height: height.toString(), height: height.toString(),
} }

View File

@ -1,4 +1,5 @@
import type { IconifyIcon } from '@iconify/types'; import type { IconifyIcon } from '@iconify/types';
import { SVGViewBox } from '../svg/viewbox';
/** /**
* Make icon square * Make icon square
@ -19,3 +20,15 @@ export function makeIconSquare(
} }
return icon; 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', () => { test('Background with options', () => {
const icon: IconifyIcon = { const icon: IconifyIcon = {
body: '<path d="M0 0h16v16z" fill="#f80" />', body: '<path d="M0 0h16v16z" fill="#f80" />',
@ -218,6 +244,30 @@ describe('Testing CSS for icon', () => {
visibility: visible; visibility: visible;
content: ${expectedURL}; 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};
}
`); `);
}); });
}); });