mirror of
https://github.com/iconify/iconify.git
synced 2024-11-09 14:50:56 +00:00
feat: parse svg in utils, handle defs correctly
This commit is contained in:
parent
957a9eda66
commit
c5f818ecab
@ -342,6 +342,11 @@
|
||||
"import": "./lib/svg/build.mjs",
|
||||
"types": "./lib/svg/build.d.ts"
|
||||
},
|
||||
"./lib/svg/defs": {
|
||||
"require": "./lib/svg/defs.cjs",
|
||||
"import": "./lib/svg/defs.mjs",
|
||||
"types": "./lib/svg/defs.d.ts"
|
||||
},
|
||||
"./lib/svg/encode-svg-for-css": {
|
||||
"require": "./lib/svg/encode-svg-for-css.cjs",
|
||||
"import": "./lib/svg/encode-svg-for-css.mjs",
|
||||
@ -362,6 +367,11 @@
|
||||
"import": "./lib/svg/inner-html.mjs",
|
||||
"types": "./lib/svg/inner-html.d.ts"
|
||||
},
|
||||
"./lib/svg/parse": {
|
||||
"require": "./lib/svg/parse.cjs",
|
||||
"import": "./lib/svg/parse.mjs",
|
||||
"types": "./lib/svg/parse.d.ts"
|
||||
},
|
||||
"./lib/svg/size": {
|
||||
"require": "./lib/svg/size.cjs",
|
||||
"import": "./lib/svg/size.mjs",
|
||||
@ -376,6 +386,11 @@
|
||||
"require": "./lib/svg/url.cjs",
|
||||
"import": "./lib/svg/url.mjs",
|
||||
"types": "./lib/svg/url.d.ts"
|
||||
},
|
||||
"./lib/svg/viewbox": {
|
||||
"require": "./lib/svg/viewbox.cjs",
|
||||
"import": "./lib/svg/viewbox.mjs",
|
||||
"types": "./lib/svg/viewbox.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
|
@ -4,6 +4,8 @@ import {
|
||||
IconifyIconCustomisations,
|
||||
} from '../customisations/defaults';
|
||||
import { calculateSize } from './size';
|
||||
import { SVGViewBox } from './viewbox';
|
||||
import { wrapSVGContent } from './defs';
|
||||
|
||||
/**
|
||||
* Interface for getSVGData() result
|
||||
@ -16,6 +18,9 @@ export interface IconifyIconBuildResult {
|
||||
viewBox: string;
|
||||
};
|
||||
|
||||
// viewBox as numbers
|
||||
viewBox: SVGViewBox;
|
||||
|
||||
// Content
|
||||
body: string;
|
||||
}
|
||||
@ -163,12 +168,11 @@ export function iconToSVG(
|
||||
}
|
||||
|
||||
if (transformations.length) {
|
||||
body =
|
||||
'<g transform="' +
|
||||
transformations.join(' ') +
|
||||
'">' +
|
||||
body +
|
||||
'</g>';
|
||||
body = wrapSVGContent(
|
||||
body,
|
||||
'<g transform="' + transformations.join(' ') + '">',
|
||||
'</g>'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@ -211,17 +215,12 @@ export function iconToSVG(
|
||||
setAttr('width', width);
|
||||
setAttr('height', height);
|
||||
|
||||
attributes.viewBox =
|
||||
box.left.toString() +
|
||||
' ' +
|
||||
box.top.toString() +
|
||||
' ' +
|
||||
boxWidth.toString() +
|
||||
' ' +
|
||||
boxHeight.toString();
|
||||
const viewBox: SVGViewBox = [box.left, box.top, boxWidth, boxHeight];
|
||||
attributes.viewBox = viewBox.join(' ');
|
||||
|
||||
return {
|
||||
attributes,
|
||||
viewBox,
|
||||
body,
|
||||
};
|
||||
}
|
||||
|
50
packages/utils/src/svg/defs.ts
Normal file
50
packages/utils/src/svg/defs.ts
Normal file
@ -0,0 +1,50 @@
|
||||
interface SplitSVGDefsResult {
|
||||
defs: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract definitions from SVG
|
||||
*/
|
||||
export function splitSVGDefs(content: string): SplitSVGDefsResult {
|
||||
let defs = '';
|
||||
const index = content.indexOf('<defs');
|
||||
while (index >= 0) {
|
||||
const start = content.indexOf('>', index);
|
||||
const end = content.indexOf('</defs');
|
||||
if (start === -1 || end === -1) {
|
||||
// Fail
|
||||
break;
|
||||
}
|
||||
const endEnd = content.indexOf('>', end);
|
||||
if (endEnd === -1) {
|
||||
break;
|
||||
}
|
||||
defs += content.slice(start + 1, end).trim();
|
||||
content = content.slice(0, index).trim() + content.slice(endEnd + 1);
|
||||
}
|
||||
|
||||
return {
|
||||
defs,
|
||||
content,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge defs and content
|
||||
*/
|
||||
export function mergeDefsAndContent(defs: string, content: string): string {
|
||||
return '<defs>' + defs + '</defs>' + content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap SVG content, without wrapping definitions
|
||||
*/
|
||||
export function wrapSVGContent(
|
||||
body: string,
|
||||
start: string,
|
||||
end: string
|
||||
): string {
|
||||
const { defs, content } = splitSVGDefs(body);
|
||||
return (defs ? '<defs>' + defs + '</defs>' : '') + start + content + end;
|
||||
}
|
92
packages/utils/src/svg/parse.ts
Normal file
92
packages/utils/src/svg/parse.ts
Normal file
@ -0,0 +1,92 @@
|
||||
import { IconifyIconBuildResult } from './build';
|
||||
import { wrapSVGContent } from './defs';
|
||||
import { getSVGViewBox } from './viewbox';
|
||||
|
||||
/**
|
||||
* Parsed SVG content
|
||||
*/
|
||||
export interface ParsedSVGContent {
|
||||
// Attributes for SVG element
|
||||
attribs: Record<string, string>;
|
||||
|
||||
// Content
|
||||
body: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract attributes and content from SVG
|
||||
*/
|
||||
export function parseSVGContent(content: string): ParsedSVGContent | undefined {
|
||||
// Split SVG attributes and body
|
||||
const match = content
|
||||
.trim()
|
||||
.match(
|
||||
/(?:<(?:\?xml|!DOCTYPE)[^>]+>\s*)*<svg([^>]+)>([\s\S]+)<\/svg[^>]*>/
|
||||
);
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
const body = match[2].trim();
|
||||
|
||||
// Split attributes
|
||||
const attribsList = match[1].match(/[\w:-]+="[^"]*"/g);
|
||||
const attribs = Object.create(null) as Record<string, string>;
|
||||
attribsList?.forEach((row) => {
|
||||
const match = row.match(/([\w:-]+)="([^"]*)"/);
|
||||
if (match) {
|
||||
attribs[match[1]] = match[2];
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
attribs,
|
||||
body,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert parsed SVG to IconifyIconBuildResult
|
||||
*/
|
||||
export function buildParsedSVG(
|
||||
data: ParsedSVGContent
|
||||
): IconifyIconBuildResult | undefined {
|
||||
const attribs = data.attribs;
|
||||
const viewBox = getSVGViewBox(attribs['viewBox'] ?? '');
|
||||
if (!viewBox) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Split presentation attributes
|
||||
const groupAttributes: string[] = [];
|
||||
for (const key in attribs) {
|
||||
if (
|
||||
key === 'style' ||
|
||||
key.startsWith('fill') ||
|
||||
key.startsWith('stroke')
|
||||
) {
|
||||
groupAttributes.push(`${key}="${attribs[key]}"`);
|
||||
}
|
||||
}
|
||||
|
||||
let body = data.body;
|
||||
if (groupAttributes.length) {
|
||||
// Wrap content in group, except for defs
|
||||
body = wrapSVGContent(
|
||||
body,
|
||||
'<g ' + groupAttributes.join(' ') + '>',
|
||||
'</g>'
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
attributes: {
|
||||
// Copy dimensions if exist
|
||||
width: attribs.width,
|
||||
height: attribs.height,
|
||||
// Merge viewBox
|
||||
viewBox: viewBox.join(' '),
|
||||
},
|
||||
viewBox,
|
||||
body,
|
||||
};
|
||||
}
|
17
packages/utils/src/svg/viewbox.ts
Normal file
17
packages/utils/src/svg/viewbox.ts
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* SVG viewBox: x, y, width, height
|
||||
*/
|
||||
export type SVGViewBox = [x: number, y: number, width: number, height: number];
|
||||
|
||||
/**
|
||||
* Get viewBox from string
|
||||
*/
|
||||
export function getSVGViewBox(value: string): SVGViewBox | undefined {
|
||||
const result = value.trim().split(/\s+/).map(Number);
|
||||
if (
|
||||
result.length === 4 &&
|
||||
result.reduce((prev, value) => prev && !isNaN(value), true)
|
||||
) {
|
||||
return result as SVGViewBox;
|
||||
}
|
||||
}
|
191
packages/utils/tests/parse-svg-test.ts
Normal file
191
packages/utils/tests/parse-svg-test.ts
Normal file
@ -0,0 +1,191 @@
|
||||
import { IconifyIconBuildResult } from '../lib/svg/build';
|
||||
import { parseSVGContent, buildParsedSVG } from '../lib/svg/parse';
|
||||
import { splitSVGDefs } from '../lib/svg/defs';
|
||||
import { getSVGViewBox } from '../lib/svg/viewbox';
|
||||
import { readFileSync } from 'node:fs';
|
||||
|
||||
const fixturesDir = './tests/fixtures';
|
||||
|
||||
describe('Testing parsing SVG content', () => {
|
||||
test('Getting viewBox', () => {
|
||||
// Valid numbers
|
||||
expect(getSVGViewBox('1 2 3 4')).toEqual([1, 2, 3, 4]);
|
||||
expect(getSVGViewBox('-1 0 25.5 -123.5')).toEqual([
|
||||
-1, 0, 25.5, -123.5,
|
||||
]);
|
||||
expect(getSVGViewBox(' 1\t2 3\n4\t ')).toEqual([1, 2, 3, 4]);
|
||||
|
||||
// Bad numbers
|
||||
expect(getSVGViewBox('1 2 3')).toBeUndefined();
|
||||
expect(getSVGViewBox('1 2 3 4 5')).toBeUndefined();
|
||||
expect(getSVGViewBox('a 1 2 3')).toBeUndefined();
|
||||
expect(getSVGViewBox('0 1 2 b')).toBeUndefined();
|
||||
expect(getSVGViewBox('1 2 3 4b')).toBeUndefined();
|
||||
});
|
||||
|
||||
test('Simple SVG', () => {
|
||||
const body =
|
||||
'<path d="M12,21L15.6,16.2C14.6,15.45 13.35,15 12,15C10.65,15 9.4,15.45 8.4,16.2L12,21" opacity="0"><animate id="spinner_jbAr" begin="0;spinner_8ff3.end+0.2s" attributeName="opacity" calcMode="discrete" dur="0.25s" values="0;1" fill="freeze"/><animate id="spinner_8ff3" begin="spinner_aTlH.end+0.5s" attributeName="opacity" dur="0.001s" values="1;0" fill="freeze"/></path><path d="M12,9C9.3,9 6.81,9.89 4.8,11.4L6.6,13.8C8.1,12.67 9.97,12 12,12C14.03,12 15.9,12.67 17.4,13.8L19.2,11.4C17.19,9.89 14.7,9 12,9Z" opacity="0"><animate id="spinner_dof4" begin="spinner_jbAr.end" attributeName="opacity" calcMode="discrete" dur="0.25s" values="0;1" fill="freeze"/><animate begin="spinner_aTlH.end+0.5s" attributeName="opacity" dur="0.001s" values="1;0" fill="freeze"/></path><path d="M12,3C7.95,3 4.21,4.34 1.2,6.6L3,9C5.5,7.12 8.62,6 12,6C15.38,6 18.5,7.12 21,9L22.8,6.6C19.79,4.34 16.05,3 12,3" opacity="0"><animate id="spinner_aTlH" begin="spinner_dof4.end" attributeName="opacity" calcMode="discrete" dur="0.25s" values="0;1" fill="freeze"/><animate begin="spinner_aTlH.end+0.5s" attributeName="opacity" dur="0.001s" values="1;0" fill="freeze"/></path>';
|
||||
const svg = `<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">${body}</svg>`;
|
||||
|
||||
// Parse
|
||||
const parsed = parseSVGContent(svg);
|
||||
expect(parsed).toBeTruthy();
|
||||
if (!parsed) {
|
||||
return;
|
||||
}
|
||||
expect(parsed.attribs).toEqual({
|
||||
width: '24',
|
||||
height: '24',
|
||||
viewBox: '0 0 24 24',
|
||||
xmlns: 'http://www.w3.org/2000/svg',
|
||||
});
|
||||
expect(parsed.body).toEqual(body);
|
||||
|
||||
// Build
|
||||
const built = buildParsedSVG(parsed);
|
||||
const expected: IconifyIconBuildResult = {
|
||||
attributes: {
|
||||
width: '24',
|
||||
height: '24',
|
||||
viewBox: '0 0 24 24',
|
||||
},
|
||||
viewBox: [0, 0, 24, 24],
|
||||
body,
|
||||
};
|
||||
expect(built).toEqual(expected);
|
||||
|
||||
// Defs
|
||||
expect(splitSVGDefs(body)).toEqual({
|
||||
defs: '',
|
||||
content: body,
|
||||
});
|
||||
});
|
||||
|
||||
test('SVG with XML heading', () => {
|
||||
const svg = readFileSync(
|
||||
fixturesDir + '/circle-xml-preface.svg',
|
||||
'utf8'
|
||||
);
|
||||
const body = '<circle cx="60" cy="60" r="50"/>';
|
||||
|
||||
// Parse
|
||||
const parsed = parseSVGContent(svg);
|
||||
expect(parsed).toBeTruthy();
|
||||
if (!parsed) {
|
||||
return;
|
||||
}
|
||||
expect(parsed?.attribs).toEqual({
|
||||
viewBox: '0 0 120 120',
|
||||
xmlns: 'http://www.w3.org/2000/svg',
|
||||
});
|
||||
expect(parsed.body).toEqual(body);
|
||||
|
||||
// Build
|
||||
const built = buildParsedSVG(parsed);
|
||||
const expected: IconifyIconBuildResult = {
|
||||
attributes: {
|
||||
viewBox: '0 0 120 120',
|
||||
},
|
||||
viewBox: [0, 0, 120, 120],
|
||||
body,
|
||||
};
|
||||
expect(built).toEqual(expected);
|
||||
|
||||
// Defs
|
||||
expect(splitSVGDefs(body)).toEqual({
|
||||
defs: '',
|
||||
content: body,
|
||||
});
|
||||
});
|
||||
|
||||
test('SVG with style and junk', () => {
|
||||
const body1 =
|
||||
'<metadata id="metadata8"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>';
|
||||
const defs1 =
|
||||
'<clipPath id="clipPath16" clipPathUnits="userSpaceOnUse"><path id="path18" d="M 0,38 38,38 38,0 0,0 0,38 Z"/></clipPath>';
|
||||
const body2 =
|
||||
'<g transform="matrix(1.25,0,0,-1.25,0,47.5)" id="g10"><g id="g12"><g clip-path="url(#clipPath16)" id="g14"><g transform="translate(37,3)" id="g20"><path id="path22" style="fill:#ffcc4d;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 0,0 c 0,-1.104 -0.896,-2 -2,-2 l -32,0 c -1.104,0 -2,0.896 -2,2 l 0,19 c 0,1.104 0.896,2 2,2 l 32,0 c 1.104,0 2,-0.896 2,-2 L 0,0 Z"/></g><g transform="translate(35,24)" id="g24"><path id="path26" style="fill:#6d6e71;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 0,0 -32,0 c -1.104,0 -2,-0.896 -2,-2 L 2,-2 C 2,-0.896 1.104,0 0,0"/></g><path id="path28" style="fill:#3b88c3;fill-opacity:1;fill-rule:nonzero;stroke:none" d="M 35,9 3,9 3,13 35,13 35,9 Z"/><path id="path30" style="fill:#3b88c3;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 35,15 -32,0 0,4 32,0 0,-4 z"/><path id="path32" style="fill:#3b88c3;fill-opacity:1;fill-rule:nonzero;stroke:none" d="M 35,3 3,3 3,7 35,7 35,3 Z"/><path id="path34" style="fill:#ffcc4d;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 31,2 -2,0 0,18 2,0 0,-18 z"/><g transform="translate(23,37)" id="g36"><path id="path38" style="fill:#ffe8b6;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 0,0 -16,0 c -1.104,0 -2,-0.896 -2,-2 l 0,-34 20,0 0,34 C 2,-0.896 1.104,0 0,0"/></g><g transform="translate(23,37)" id="g40"><path id="path42" style="fill:#808285;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 0,0 -16,0 c -1.104,0 -2,-0.896 -2,-2 L 2,-2 C 2,-0.896 1.104,0 0,0"/></g><path id="path44" style="fill:#55acee;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 23,15 -16,0 0,4 16,0 0,-4 z"/><path id="path46" style="fill:#55acee;fill-opacity:1;fill-rule:nonzero;stroke:none" d="M 23,9 7,9 7,13 23,13 23,9 Z"/><path id="path48" style="fill:#55acee;fill-opacity:1;fill-rule:nonzero;stroke:none" d="M 23,3 7,3 7,7 23,7 23,3 Z"/><path id="path50" style="fill:#ffe8b6;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 13,1 -2,0 0,29 2,0 0,-29 z"/><path id="path52" style="fill:#ffe8b6;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 19,1 -2,0 0,29 2,0 0,-29 z"/><path id="path54" style="fill:#226699;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 17,1 -4,0 0,6 4,0 0,-6 z"/><g transform="translate(21,28)" id="g56"><path id="path58" style="fill:#a7a9ac;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 0,0 c 0,-3.313 -2.687,-6 -6,-6 -3.313,0 -6,2.687 -6,6 0,3.313 2.687,6 6,6 3.313,0 6,-2.687 6,-6"/></g><g transform="translate(19,28)" id="g60"><path id="path62" style="fill:#e6e7e8;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 0,0 c 0,-2.209 -1.791,-4 -4,-4 -2.209,0 -4,1.791 -4,4 0,2.209 1.791,4 4,4 2.209,0 4,-1.791 4,-4"/></g><g transform="translate(18,27)" id="g64"><path id="path66" style="fill:#a0041e;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 0,0 -3,0 c -0.552,0 -1,0.448 -1,1 l 0,5 c 0,0.552 0.448,1 1,1 0.552,0 1,-0.448 1,-1 L -2,2 0,2 C 0.552,2 1,1.552 1,1 1,0.448 0.552,0 0,0"/></g></g></g></g>';
|
||||
const body = `${body1}<defs id="defs6">${defs1}</defs>${body2}`;
|
||||
const svg = `
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 47.5 47.5" style="enable-background:new 0 0 47.5 47.5;" xml:space="preserve" version="1.1" id="svg2">
|
||||
${body}
|
||||
</svg>`;
|
||||
|
||||
// Parse
|
||||
const parsed = parseSVGContent(svg);
|
||||
expect(parsed).toBeTruthy();
|
||||
if (!parsed) {
|
||||
return;
|
||||
}
|
||||
expect(parsed?.attribs).toEqual({
|
||||
'xmlns:dc': 'http://purl.org/dc/elements/1.1/',
|
||||
'xmlns:cc': 'http://creativecommons.org/ns#',
|
||||
'xmlns:rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
|
||||
'xmlns:svg': 'http://www.w3.org/2000/svg',
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'viewBox': '0 0 47.5 47.5',
|
||||
'style': 'enable-background:new 0 0 47.5 47.5;',
|
||||
'xml:space': 'preserve',
|
||||
'version': '1.1',
|
||||
'id': 'svg2',
|
||||
});
|
||||
expect(parsed.body).toEqual(body);
|
||||
|
||||
// Build
|
||||
const built = buildParsedSVG(parsed);
|
||||
const expected: IconifyIconBuildResult = {
|
||||
attributes: {
|
||||
viewBox: '0 0 47.5 47.5',
|
||||
},
|
||||
viewBox: [0, 0, 47.5, 47.5],
|
||||
body: `<defs>${defs1}</defs><g style="enable-background:new 0 0 47.5 47.5;">${body1}${body2}</g>`,
|
||||
};
|
||||
expect(built).toEqual(expected);
|
||||
|
||||
// Defs
|
||||
expect(splitSVGDefs(body)).toEqual({
|
||||
defs: defs1,
|
||||
content: body1 + body2,
|
||||
});
|
||||
});
|
||||
|
||||
test('SVG with fill', () => {
|
||||
const body = `<g filter="url(#filter0_iii_18_1526)">
|
||||
<path d="M14.0346 3.55204L18.2991 10.8362L12.2834 12.5469C8.12828 11.172 5.68075 8.52904 4.20532 5.8125C3.58307 4.66681 3.58813 2.5625 6.06108 2.5625H12.3087C13.0189 2.5625 13.6758 2.93914 14.0346 3.55204Z" fill="#4686EC"/>
|
||||
<path d="M14.0346 3.55204L18.2991 10.8362L12.2834 12.5469C8.12828 11.172 5.68075 8.52904 4.20532 5.8125C3.58307 4.66681 3.58813 2.5625 6.06108 2.5625H12.3087C13.0189 2.5625 13.6758 2.93914 14.0346 3.55204Z" fill="url(#paint0_radial_18_1526)"/>
|
||||
<path d="M14.0346 3.55204L18.2991 10.8362L12.2834 12.5469C8.12828 11.172 5.68075 8.52904 4.20532 5.8125C3.58307 4.66681 3.58813 2.5625 6.06108 2.5625H12.3087C13.0189 2.5625 13.6758 2.93914 14.0346 3.55204Z" fill="url(#paint1_linear_18_1526)"/>
|
||||
</g>
|
||||
`;
|
||||
const svg = `<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">${body}</svg>`;
|
||||
|
||||
// Parse
|
||||
const parsed = parseSVGContent(svg);
|
||||
expect(parsed).toBeTruthy();
|
||||
if (!parsed) {
|
||||
return;
|
||||
}
|
||||
expect(parsed?.attribs).toEqual({
|
||||
width: '32',
|
||||
height: '32',
|
||||
viewBox: '0 0 32 32',
|
||||
fill: 'none',
|
||||
xmlns: 'http://www.w3.org/2000/svg',
|
||||
});
|
||||
expect(parsed.body).toEqual(body.trim());
|
||||
|
||||
// Build
|
||||
const built = buildParsedSVG(parsed);
|
||||
const expected: IconifyIconBuildResult = {
|
||||
attributes: {
|
||||
width: '32',
|
||||
height: '32',
|
||||
viewBox: '0 0 32 32',
|
||||
},
|
||||
viewBox: [0, 0, 32, 32],
|
||||
body: `<g fill="none">${body.trim()}</g>`,
|
||||
};
|
||||
expect(built).toEqual(expected);
|
||||
});
|
||||
});
|
@ -13,6 +13,7 @@ describe('Testing iconToSVG', () => {
|
||||
height: '1em',
|
||||
viewBox: '0 0 16 16',
|
||||
},
|
||||
viewBox: [0, 0, 16, 16],
|
||||
body: '',
|
||||
};
|
||||
|
||||
@ -39,6 +40,7 @@ describe('Testing iconToSVG', () => {
|
||||
height: '16',
|
||||
viewBox: '0 0 16 16',
|
||||
},
|
||||
viewBox: [0, 0, 16, 16],
|
||||
body: '<path d="" />',
|
||||
};
|
||||
|
||||
@ -70,6 +72,7 @@ describe('Testing iconToSVG', () => {
|
||||
height: '16',
|
||||
viewBox: '0 0 16 16',
|
||||
},
|
||||
viewBox: [0, 0, 16, 16],
|
||||
body: '<path d="" />',
|
||||
};
|
||||
|
||||
@ -92,6 +95,7 @@ describe('Testing iconToSVG', () => {
|
||||
height: '16',
|
||||
viewBox: '0 0 20 16',
|
||||
},
|
||||
viewBox: [0, 0, 20, 16],
|
||||
body: '<path d="..." />',
|
||||
};
|
||||
|
||||
@ -115,6 +119,7 @@ describe('Testing iconToSVG', () => {
|
||||
width: '20',
|
||||
viewBox: '0 0 20 16',
|
||||
},
|
||||
viewBox: [0, 0, 20, 16],
|
||||
body: '<path d="..." />',
|
||||
};
|
||||
|
||||
@ -137,6 +142,7 @@ describe('Testing iconToSVG', () => {
|
||||
attributes: {
|
||||
viewBox: '0 0 20 16',
|
||||
},
|
||||
viewBox: [0, 0, 20, 16],
|
||||
body: '<path d="..." />',
|
||||
};
|
||||
|
||||
@ -160,6 +166,7 @@ describe('Testing iconToSVG', () => {
|
||||
height: '40px',
|
||||
viewBox: '0 0 16 20',
|
||||
},
|
||||
viewBox: [0, 0, 16, 20],
|
||||
body: '<g transform="rotate(90 8 8)"><path d="..." /></g>',
|
||||
};
|
||||
|
||||
@ -183,6 +190,7 @@ describe('Testing iconToSVG', () => {
|
||||
height: '40px',
|
||||
viewBox: '0 0 16 20',
|
||||
},
|
||||
viewBox: [0, 0, 16, 20],
|
||||
body: '<g transform="rotate(-90 10 10)"><path d="..." /></g>',
|
||||
};
|
||||
|
||||
@ -206,6 +214,7 @@ describe('Testing iconToSVG', () => {
|
||||
height: '32',
|
||||
viewBox: '0 0 20 16',
|
||||
},
|
||||
viewBox: [0, 0, 20, 16],
|
||||
body: '<g transform="translate(20 0) scale(-1 1)"><path d="..." /></g>',
|
||||
};
|
||||
|
||||
@ -229,6 +238,7 @@ describe('Testing iconToSVG', () => {
|
||||
height: '1em',
|
||||
viewBox: '0 0 16 20',
|
||||
},
|
||||
viewBox: [0, 0, 16, 20],
|
||||
body: '<g transform="rotate(90 8 8) translate(20 0) scale(-1 1)"><path d="..." /></g>',
|
||||
};
|
||||
|
||||
@ -255,6 +265,7 @@ describe('Testing iconToSVG', () => {
|
||||
height: '1em',
|
||||
viewBox: '0 0 16 20',
|
||||
},
|
||||
viewBox: [0, 0, 16, 20],
|
||||
body: '<g transform="translate(16 0) scale(-1 1)"><g transform="rotate(90 8 8)"><path d="..." /></g></g>',
|
||||
};
|
||||
|
||||
@ -281,6 +292,7 @@ describe('Testing iconToSVG', () => {
|
||||
height: '16',
|
||||
viewBox: '0 0 20 16',
|
||||
},
|
||||
viewBox: [0, 0, 20, 16],
|
||||
body: '<path d="..." />',
|
||||
};
|
||||
|
||||
@ -304,6 +316,7 @@ describe('Testing iconToSVG', () => {
|
||||
height: '1em',
|
||||
viewBox: '0 0 128 128',
|
||||
},
|
||||
viewBox: [0, 0, 128, 128],
|
||||
body:
|
||||
'<g transform="translate(128 0) scale(-1 1)">' +
|
||||
iconBody +
|
||||
|
Loading…
Reference in New Issue
Block a user