Skip to content

Add replaceUse plugin - #808

Open
tshedor wants to merge 6 commits into
svg:mainfrom
tshedor:master
Open

Add replaceUse plugin#808
tshedor wants to merge 6 commits into
svg:mainfrom
tshedor:master

Conversation

@tshedor

@tshedor tshedor commented Oct 12, 2017

Copy link
Copy Markdown

This plugin replaces all <use> elements with the nodes they clone and removes the top-level xlink attribute. While this doesn't "optimize" the SVG, it allows the contents to be used in SVG sprites within <symbol> elements. This plugin is best used in conjunction with removeUselessDefs.

@bbqaaq

bbqaaq commented Oct 15, 2017

Copy link
Copy Markdown
Contributor

This is a good plugins! I probably will use it in my project!

But Im suggesting to make this plugin being executed before the removeUselessDefs plugins, otherwise it will just duplicate the path after removing the <use> tag

@tshedor

tshedor commented Oct 15, 2017

Copy link
Copy Markdown
Author

@bbqaaq Great call. I almost always run with multipass enabled, so I didn't notice. I've moved it before removeUselessDefs.

@TiagoDinisFonseca

Copy link
Copy Markdown

Hi, I was testing this plugin and I found several bugs:

  • It is removing necessary IDs (remove line 22)
  • The tag use can have some attributes, unfortunately we cannot copy it inside the object being moved, perhaps it is best to use a new group and some transformations
  • It ignores all defined object outside defs (yes, it is possible to do so with a svg)

… outside <defs>

This commit also removes referenced nodes if they’re inside <defs> and ultimately removes <defs> if it is empty.
@tshedor

tshedor commented Oct 18, 2017

Copy link
Copy Markdown
Author

@TiagoDinisFonseca I've addressed those bugs. Thanks for reporting them.

Regarding the <use> attributes, I changed the <use> tag into a group as per your suggestion, and my tests show equivalent behavior between <use> and <g>. However, please verify that your tests work as expected.

These fixes mean the plugin is no longer complimented by removeUselessDefs as it achieves the desired effect on its own.

@TiagoDinisFonseca

TiagoDinisFonseca commented Oct 19, 2017

Copy link
Copy Markdown

Unfortunately, this is not true. The tag has some attributes: x, y, height and width that g has not.
(see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use)
x and y should be equivalent to a translate
height and width are still mysterious for me here
in all my experiences height and width do nothing

@bbqaaq

bbqaaq commented Oct 29, 2017

Copy link
Copy Markdown
Contributor

As a user I do support adding this plugin as a optional one as I am useful with this.
In my project I got some SVGs with <use> and <defs> which is annoying to me

I have gone through this plugin and it works quite fine with the SVGs.

@lifeiscontent

Copy link
Copy Markdown

@TiagoDinisFonseca @tshedor any updates here? I'd really like to use this plugin.

@lifeiscontent

Copy link
Copy Markdown

I'd guess you should move the attributes from use to the path and not the tag.

@lifeiscontent

Copy link
Copy Markdown

@GreLI can we prioritize this?

what would you need in order to get this merged?

@TiagoDinisFonseca

TiagoDinisFonseca commented Apr 11, 2018

Copy link
Copy Markdown

@lifeiscontent
At the time I was interested on this because it could be useful for me. It turns out, I was wrong.
Therefore, I did not care to solve its problems. Sorry for that, eventually I can do it when I have the time to run this on my personal PC.

But you can solve it:
1- Your solution is not good enough, you never know what is inside, it could be a second group.
2- I guess that attributes x and y can be transformed into some translation (x,y) => transform="translation(x, y)"
3- What about width and height??? I feel bad about erasing some fields just because I do not understand them.
3.1 - There is a solution for this: we erase those fields... if this is a problem, this will be a bug in the future (I don't like this attitude, but perhaps it is ok)

@tommoor

tommoor commented Jun 22, 2019

Copy link
Copy Markdown

Does this need to be absolutely perfect to be considered for addition? This would be very useful for me in it's current state

@akre54

akre54 commented Nov 28, 2022

Copy link
Copy Markdown

Rewritten to use the latest csstree api:

exports.fn = () => {
  const defs = new Map;
  const used = new Set;

  return {
    element: {
      enter(node, parentNode) {
        if (node.name === 'svg') {
          delete node.attributes['xmlns:xlink'];
          return
        }

        if (parentNode.name === 'defs') {
          defs.set('#' + node.attributes.id, node);
          return;
        }

        if (node.name === 'use') {
          const id = node.attributes.href || node.attributes['xlink:href'];
          const def = defs.get(id);

          if (!def) {
            console.warn(`Could not find definition for ${id}`);
            return;
          }

          delete node.attributes['xlink:href'];
          delete node.attributes['href'];

          node.name = 'g';
          node.children = [...def.children];

          used.add(def);
        }

      },
    },
    root: {
      exit(root) {
        const defs = querySelector(root, 'defs');
        if (defs) {
          defs.children = defs.children.filter(node => !used.has(node));
          if (!defs.children.length) {
            defs.parentNode.children = defs.parentNode.children.filter(node => node !== defs);
          }
        }
      }
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants