natemoo-re / astro-icon

Inline and sprite-based SVGs in Astro made easy!
https://astroicon.dev
Other
1.07k stars 61 forks source link

Duplicate Icons on Chromium Based Browsers #235

Open iEscapedVim opened 1 month ago

iEscapedVim commented 1 month ago

What version of astro-icon are you using?

v1.1.0

Astro Info

Astro                    v4.13.3
Node                     v22.6.0
System                   Linux (x64)
Package Manager          npm
Output                   static
Adapter                  none
Integrations             @astrojs/tailwind
                         astro-icon

If this issue only occurs in one browser, which browser is a problem?

Chrome, Brave.. my guess on all the chromium based browsers

Describe the Bug

So I faced this weird issue the other day while using the plugin. Where If you use some Icons in together the icon will duplicate/clone itself idk what term to use.

Basically If you have 4 or 5 icons together some of them with show same icons instead of showing the one the svg is used for.. top bar section with multiple icons in chrome/brave image

same section in firefox image

using svg code directly works fine.

What's the expected result?

to see different icons, instead of one of them duplicating/cloning to others.

Link to Minimal Reproducible Example

https://stackblitz.com/edit/duplicate-icons

natemoo-re commented 4 weeks ago

The reproduction replicates the issue only because the SVG source files are identical... can you share an accurate reproduction?

My best guess: the elements might not have a unique ID, so the references don't work? You can use the is:inline directive on <Icon> to work around this if needed.

iEscapedVim commented 4 weeks ago

the SVG source files are identical...

so sorry about that I think I didn't copy the code right while trying to replicate the issue, I recently initiated the switch to neovim from vscode.. . anyway I have updated the original code.. The SVGs are unique now, but the issue is still present.

azhirov commented 1 week ago

The problem is that SVGO optimizes SVG icons by replacing the id values of all elements with simpler ones. Its strategy is sequentially using Latin letters, starting from a (see SVGO cleanupIds docs). However, SVGO processes each icon independently of the others and doesn't know that the same id might have already been assigned in a previous file.

To solve the problem, you can use the prefixIds plugin, which will add a prefix and increment it each time:

// astro.config.mjs

import { defineConfig } from 'astro/config';
import icon from 'astro-icon';

let prefixCounter = 0;

export default defineConfig({
  integrations: [
    icon({
      iconDir: 'src/assets/icons',
      svgoOptions: {
        multipass: true,
        plugins: [
          {
            name: 'cleanupIds', // optional
          },
          {
            name: 'prefixIds',
            params: {
              delim: '',
              prefix: () => prefixCounter++,
            },
          },
        ]
      }
    }),
  ],
});

@natemoo-re, it might be worth adding a note in the documentation or using the mentioned configuration as the default setting.

iEscapedVim commented 1 week ago

The problem is that SVGO optimizes SVG icons by replacing the id values of all elements with simpler ones. Its strategy is sequentially using Latin letters, starting from a (see SVGO cleanupIds docs). However, SVGO processes each icon independently of the others and doesn't know that the same id might have already been assigned in a previous file.

To solve the problem, you can use the prefixIds plugin, which will add a prefix and increment it each time:

// astro.config.mjs

import { defineConfig } from 'astro/config';
import icon from 'astro-icon';

let prefixCounter = 0;

export default defineConfig({
  integrations: [
    icon({
      iconDir: 'src/assets/icons',
      svgoOptions: {
        multipass: true,
        plugins: [
          {
            name: 'cleanupIds', // optional
          },
          {
            name: 'prefixIds',
            params: {
              delim: '',
              prefix: () => prefixCounter++,
            },
          },
        ]
      }
    }),
  ],
});

@natemoo-re, it might be worth adding a note in the documentation or using the mentioned configuration as the default setting.

one thing thou why doesn't it happen in firefox than?