mirror of
https://github.com/lucide-icons/lucide.git
synced 2026-11-15 14:08:49 +00:00
fix(shared): escape attribute values in buildLucideSvg (#4940)
* fix(shared): escape attribute values in buildLucideSvg Attribute values were interpolated into the SVG string as-is, so a value containing a double quote, ampersand or angle bracket (for example in a custom attribute or class name) produced malformed markup. * Use replace(/x/g) instead of replaceAll for broader TS lib compat lucide-react-native's tsconfig doesn't include the ES2021 lib that replaceAll requires, failing typecheck. A global regex replace is functionally identical here and works under any target. * Escape the full set of relevant HTML entities in attribute values Also escape > and ' per review feedback, not just & " <. * Apply suggestion from @karsa-mistmere --------- Co-authored-by: Karsa <contact@karsa.org>
This commit is contained in:
@@ -1,10 +1,21 @@
|
||||
import buildLucideIconNode from './buildLucideIconNode';
|
||||
import type { LucideBuildParams, LucideIconData, LucideIconNode } from './types';
|
||||
|
||||
const entities = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
} as const;
|
||||
|
||||
const escapeAttribute = (value: string) =>
|
||||
value.replace(/[&<>"']/g, (char) => entities[char as keyof typeof entities]);
|
||||
|
||||
const buildDomNode = ([tagName, attributes, children = []]: LucideIconNode): string =>
|
||||
`<${tagName} ${Object.entries(attributes)
|
||||
.filter(([, value]) => value !== undefined && value !== null)
|
||||
.map(([attrName, value]) => `${attrName}="${String(value)}"`)
|
||||
.map(([attrName, value]) => `${attrName}="${escapeAttribute(String(value))}"`)
|
||||
.join(' ')}>${children?.map((child) => buildDomNode(child)).join('')}</${tagName}>`;
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import buildLucideSvg from '../src/build/buildLucideSvg';
|
||||
|
||||
const icon = { name: 'dot', size: 24, node: [['circle', { cx: 12, cy: 12, r: 1 }]] } as const;
|
||||
|
||||
describe('buildLucideSvg', () => {
|
||||
it('should escape special characters in attribute values', () => {
|
||||
const svg = buildLucideSvg(icon as any, {
|
||||
attributes: { 'data-label': 'a\'s "quoted" <b> & c' },
|
||||
});
|
||||
|
||||
expect(svg).toContain('data-label="a's "quoted" <b> & c"');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user