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

[Bug] Do not strip custom local icons of their classes #210

Open
stefanobartoletti opened this issue Jul 22, 2024 · 6 comments
Open

[Bug] Do not strip custom local icons of their classes #210

stefanobartoletti opened this issue Jul 22, 2024 · 6 comments
Labels

Comments

@stefanobartoletti
Copy link

stefanobartoletti commented Jul 22, 2024

I noticed a behavior that I consider a bug, but I'm not sure if this is wanted.

Anyway, I noticed that when using custom local icons, i.e. loaded from the assets folder, classes applied to their root svg element are stripped when the icon is actually loaded in the template.

This is not really a good behavior, because some classes could be used to apply animations to the said icon, and removing them will cause them to not be animated.

I prepared a simple reproduction here https://github.com/stefanobartoletti/icon-test, everything should be pretty much self-explanatory, but right now, the SVG icon directly pasted into the template can be animated via the custom icon-animation class, while the same SVG loaded with the Icon component cannot, because it is stripped of the said class.

A possible workaround right now could be to give this class to the Icon component, instead of the source SVG icon, but this is not optimal, since the same exact icon could be needed in many places in a project and it would make sense to give this class only once to the source, instead of needing to apply it to every and each instance of the Icon component using it.

Also, I noticed that the classes are stripped only from the root svg element, if you have classes in nested g or path elements, they remain in place.

Hopefully it is all clear, anyway, feel free to ask for more info if needed.


Edit:

I forgot to add that I'm talking about a configuration using the svg mode to load icons, where the source icon is inlined in the template.

@stefanobartoletti stefanobartoletti changed the title Do not strip custom local icons of their classes [Bug] Do not strip custom local icons of their classes Jul 22, 2024
@antfu
Copy link
Member

antfu commented Jul 22, 2024

At this line:

const data = convertParsedSVG(parseSVGContent(svg)!)

While parseSVGContent correctly parsed svg data with the root attributes, convertParsedSVG discarded them. At the interface of IconifyIcon, it doesn't have a field to represent custom attributes. This downs to Iconify does not support root attributes for icons in the JSON data format.

/cc @cyberalien is that something Iconify would consider in scope? If so I'd happy to send PR upstream to get this supported

@userquin
Copy link
Member

userquin commented Aug 8, 2024

@antfu parseSVGContent will return the attributes, nuxt icon ignoring them in your link: https://github.com/iconify/iconify/blob/main/packages/utils/src/svg/parse.ts#L42-L45

EDIT: convertParsedSVG ignoring custom attributes : that's weird, attributes should be applied in the build function

@cyberalien
Copy link

This is a tricky issue.

Current implementation is by design. IconifyIcon type is not designed to handle additional attributes, attributes are intended to be removed from SVG element.

Why is it so?

Editors like Adobe Illustrator (the worst of them, closely followed by Inkscape) add massive amounts of garbage to SVG it generates, all of it is always unused. The most common example of such garbage on SVG tag exported by various editors is id attribute. It is never used, value is a layer name.

Not having additional attributes makes it easy to deal with icon when rendering it. All that is added to SVG tag is viewBox attribute. Attributes like stroke-width (which was first similar issue I've encountered with valid use case a while ago) that some icons include are always moved to child elements when icon is optimised, but for CSS stuff applied to icon this solution won't work.

Should it be changed?

For this use case it makes sense to keep attributes.

Custom loaders should not modify user's icon. In this case it is absolutely safe. In cases when user provides a really bad icon with lots of Illustrator stuff without optimising it, it should still be kept as is and should be up to user to make sure icon is correct.

This was not considered many years ago when type was created, but I think it is about time to change it.

@cyberalien
Copy link

Need to think of a temporary solution for this issue.

Proper solution would require changing type, but simply adding extra attributes to type is not a good idea because I'd rather completely rebuild all types.

What I want to do with IconifyIcon type:

  • Get rid of dimension attributes, make it a viewBox.
  • Remove flip/rotation attributes.

Additionally, for IconifyJSON type I want to simplify icons, getting rid of flip/rotation (it uses IconifyIcon type) and simplifying aliases (value as string, not object, so everything is simple to use).

However, this is a huge task because first need to finalise types to make sure everything is included, then change tools to handle both new and old types, then change all components to handle new type, only then actually use new type.

So it won't work for this issue because it will take a lot of time.

@stefanobartoletti
Copy link
Author

@cyberalien I'm not sure if this is a valid suggestion, but the only needed attribute here is the class one.

Would this pipeline work?

  • Check if a class attribute is present in the root svg element
  • If true, save the content of class to a temporary variable, i.e. tempClasses or something
  • Optimize the icon, by stripping all the unwanted attributes (basically what it does right now)
  • If tempClasses is not empty, add back a class attribute to the optimized icon, and give it the content of tempClasses.

@cyberalien
Copy link

Unfortunately I don't think it would. Can't figure out how to make it work. Icons are converted to icon set in IconifyJSON format, which does not support extra attributes. Even if extra attributes are added, it would require changing unrelated @iconify/vue package to handle it.

I think best option for now is to change your icons. You know names of icons, which have those custom class names. When using those icons in code, you can add necessary class names to icon component.

Proper support can be added later with types redesign.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants