2
0
mirror of https://github.com/iconify/iconify.git synced 2024-09-20 01:09:04 +00:00

feat(next): add trim for custom svg icons

This commit is contained in:
Joaquín Sánchez Jiménez 2022-03-21 18:28:10 +01:00
parent f0e78f4c8f
commit e506d76843
6 changed files with 22 additions and 4 deletions

View File

@ -5,6 +5,7 @@ import type {
InlineCollection, InlineCollection,
} from './types'; } from './types';
import { mergeIconProps } from './utils'; import { mergeIconProps } from './utils';
import { trimSVG } from '../svg/trim';
const debug = createDebugger('@iconify-loader:custom'); const debug = createDebugger('@iconify-loader:custom');
@ -40,6 +41,7 @@ export async function getCustomIcon(
typeof transform === 'function' ? await transform(result) : result, typeof transform === 'function' ? await transform(result) : result,
collection, collection,
icon, icon,
true,
options, options,
undefined undefined
); );

View File

@ -33,6 +33,7 @@ export async function searchForIcon(
`<svg >${body}</svg>`, `<svg >${body}</svg>`,
collection, collection,
id, id,
false,
options, options,
() => attributes () => attributes
); );

View File

@ -33,6 +33,7 @@ export type IconCustomizer = (
* - apply `customize` with default customizations, if provided * - apply `customize` with default customizations, if provided
* - apply `iconCustomizer` with `customize` customizations, if provided * - apply `iconCustomizer` with `customize` customizations, if provided
* - apply `additionalProps` with `iconCustomizer` customizations, if provided * - apply `additionalProps` with `iconCustomizer` customizations, if provided
* - apply `trimSVG` to the final `SVG` only when using custom icon collection and `trimCustomSvg` enabled
*/ */
export type IconCustomizations = { export type IconCustomizations = {
/** /**
@ -63,6 +64,14 @@ export type IconCustomizations = {
* All properties without value will not be applied. * All properties without value will not be applied.
*/ */
additionalProps?: Record<string, string | undefined>; additionalProps?: Record<string, string | undefined>;
/**
* Should optimize the custom `svg` icon?.
*
* Enable this flag when using custom `SVG` on `CSS`.
*
* @default `false`.
*/
trimCustomSvg?: boolean;
}; };
/** /**

View File

@ -1,5 +1,6 @@
import type { Awaitable } from '@antfu/utils'; import type { Awaitable } from '@antfu/utils';
import type { IconifyLoaderOptions } from './types'; import type { IconifyLoaderOptions } from './types';
import { trimSVG } from '../svg/trim';
const svgWidthRegex = /width\s*=\s*["'](\w+)["']/; const svgWidthRegex = /width\s*=\s*["'](\w+)["']/;
const svgHeightRegex = /height\s*=\s*["'](\w+)["']/; const svgHeightRegex = /height\s*=\s*["'](\w+)["']/;
@ -38,6 +39,7 @@ export async function mergeIconProps(
svg: string, svg: string,
collection: string, collection: string,
icon: string, icon: string,
customSvg: boolean,
options?: IconifyLoaderOptions, options?: IconifyLoaderOptions,
propsProvider?: () => Awaitable<Record<string, string>> propsProvider?: () => Awaitable<Record<string, string>>
): Promise<string> { ): Promise<string> {
@ -81,7 +83,7 @@ export async function mergeIconProps(
svg = svg.replace('<svg ', `<svg ${propsToAdd.join(' ')} `); svg = svg.replace('<svg ', `<svg ${propsToAdd.join(' ')} `);
} }
if (svg && options) { if (options) {
const { defaultStyle, defaultClass } = options; const { defaultStyle, defaultClass } = options;
// additional props and iconCustomizer takes precedence // additional props and iconCustomizer takes precedence
if (defaultClass && !svg.includes(' class=')) { if (defaultClass && !svg.includes(' class=')) {
@ -107,5 +109,5 @@ export async function mergeIconProps(
} }
} }
return svg; return customSvg && options?.customizations?.trimCustomSvg === true ? trimSVG(svg) : svg;
} }

View File

@ -1,4 +1,8 @@
// https://bl.ocks.org/jennyknuth/222825e315d45a738ed9d6e04c7a88d0 /**
* Encode the `SVG` to be used on `CSS`: https://bl.ocks.org/jennyknuth/222825e315d45a738ed9d6e04c7a88d0.
*
* @param svg The `SVG` source.
*/
export function encodeSvgForCss(svg: string): string { export function encodeSvgForCss(svg: string): string {
let useSvg = svg.startsWith('<svg>') ? svg.replace('<svg>', '<svg >') : svg; let useSvg = svg.startsWith('<svg>') ? svg.replace('<svg>', '<svg >') : svg;
if (!useSvg.includes(' xmlns:xlink=') && useSvg.includes(' xlink:')) { if (!useSvg.includes(' xmlns:xlink=') && useSvg.includes(' xlink:')) {

View File

@ -5,7 +5,7 @@ export function trimSVG(str: string): string {
return ( return (
str str
// Replace new line only after one of allowed characters that are not part of common attributes // Replace new line only after one of allowed characters that are not part of common attributes
.replace(/(["';{}}><])\s*\n\s*/g, '$1') .replace(/(["';{}><])\s*\n\s*/g, '$1')
// Keep one space in case it is inside attribute // Keep one space in case it is inside attribute
.replace(/\s*\n\s*/g, ' ') .replace(/\s*\n\s*/g, ' ')
// Trim attribute values // Trim attribute values