Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix icons/logos with static SVG IDs to use generated IDs #5204

Merged
merged 12 commits into from
Sep 23, 2021
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## [`master`](https://github.com/elastic/eui/tree/master)

No public interface changes since `38.1.0`.
**Bug fixes**

- Fixed logo icons with static SVG IDs causing accessibility errors when multiples of the same logo were present ([#5204](https://github.com/elastic/eui/pull/5204))

## [`38.1.0`](https://github.com/elastic/eui/tree/v38.1.0)

Expand Down
38 changes: 31 additions & 7 deletions scripts/compile-icons.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,24 @@ function pascalCase(x) {
const iconFiles = glob.sync('**/*.svg', { cwd: iconsDir, realpath: true });

iconFiles.forEach(async (filePath) => {
const fileName = path.basename(filePath, '.svg');
const svgSource = fs.readFileSync(filePath);
const svgString = svgSource.toString();

try {
const viewBoxPosition = svgSource.toString().indexOf('viewBox');
if (viewBoxPosition === -1) {
if (!svgString.includes('viewBox')) {
throw new Error(`${filePath} is missing a 'viewBox' attribute`);
}

const jsxSource = await svgr(
const hasIds = svgString.includes('id="');

let jsxSource = await svgr(
svgSource,
{
plugins: ['@svgr/plugin-svgo', '@svgr/plugin-jsx'],
svgoConfig: {
plugins: [
{ cleanupIDs: false },
{ cleanupIDs: true },
{ prefixIds: false },
{ removeViewBox: false },
],
Expand All @@ -43,17 +46,38 @@ iconFiles.forEach(async (filePath) => {
{ template },
opts,
{ imports, componentName, props, jsx }
) => template.ast`
) =>
hasIds
? template.ast`
${imports}
import { htmlIdGenerator } from '../../../services';
const ${componentName} = (${props}) => {
const generateId = htmlIdGenerator('${fileName}');
return (
${jsx}
);
};
export const icon = ${componentName};
`
: template.ast`
${imports}
const ${componentName} = (${props}) => ${jsx}
export const icon = ${componentName};
`,
`,
},
{
componentName: `EuiIcon${pascalCase(path.basename(filePath, '.svg'))}`,
componentName: `EuiIcon${pascalCase(fileName)}`,
}
);

// Replace static SVGs IDs with dynamic JSX that uses the htmlIdGenerator
if (hasIds) {
jsxSource = jsxSource
.replace(/id="(\S+)"/gi, "id={generateId('$1')}")
.replace(/"url\(#(\S+)\)"/gi, "{`url(#${generateId('$1')})`}")
.replace(/xlinkHref="#(\S+)"/gi, "xlinkHref={`#${generateId('$1')}`}");
}

const outputFilePath = filePath.replace(/\.svg$/, '.js');
const comment = '// THIS IS A GENERATED FILE. DO NOT MODIFY MANUALLY\n\n';
fs.writeFileSync(outputFilePath, comment + jsxSource);
Expand Down
Loading