mrsum / webpack-svgstore-plugin

Simple svg-sprite creating with webpack
https://www.npmjs.com/package/webpack-svgstore-plugin
200 stars 92 forks source link

Can't get prefixClassNames to work #179

Open jonascarlbaum opened 4 years ago

jonascarlbaum commented 4 years ago

Hi,

I'm having issues where many (all) svg icons have the same class names, but different styles on them. I'm using { prefixIds: true } to enable that plugin. By default it looks like that also would mean that it should have prefixClassNames: true.

I can't figure out how to make the prefixing of class names to work — do you have any suggestion on how to configure this?

Might it be onlyMatchedOnce in plugin that is making this not work?

How do I configure the prefixIds-plugin? Reading your documentation it seems like adding plugins is more or less adding { pluginName: true } in svgoOptions.plugins-array!? Or should I replace true with a plugin-option-object?

jonascarlbaum commented 4 years ago

Or is it your _fixIds in utils that is doing this and you need to add _fixClasses or something to make this work?

When testing it seems that I prefixIds-plugin does pretty much no difference, it's seems like it's your _fixIds that is doing the id-magic...

Is it possible to make a _fixClassNames or something that's inlining them?

I tried different plugins, but almost none seems to do as I wish.

            new SvgStore({
                prefix: 'icon--',
                svgoOptions: {
                    plugins: [
                        { cleanupIDs: false },
                        { collapseGroups: false },
                        { removeTitle: true },
                        //{ prefixIds: true },
                        //{ inlineStyles: true },
                        //{ convertStyleToAttrs: true },
                        //{ removeStyleElement: true },
                    ],
                },
            }),

However, the removeStyleElement does what it says.


I'm starting to like this webpack plugin, so it would be nice if we could put in any svg and just configure this correctly, not having to send the svg:s back to the customer and asking them to export inline styled versions — my guess is that it's possible, that I do something wrong!?

jonascarlbaum commented 4 years ago

I tried a hacky (not perfect at all) version, added a _fixClassNames directly in my node_modules/webpack-svgstore-plugin/src/helpers/utils.js, as a proof-of-concept.

/**
 * Fix classes
 * @param  {object} obj
 * @param  {string} id
 * @return {void}
 */
const _fixClassNames = function(obj, id) {
  if (obj.attribs && obj.attribs.class) {
    obj.attribs.class = [id, obj.attribs.class].join('-');
  }

  if (obj.type === 'text' && obj.parent.type === 'style' && obj.parent.name === 'style') {
    var result = [];
    var parts = obj.data.split('.');
    for (var i = 0; i < parts.length; i++) {
      var part = '.' + parts[i];
      var match = /(\.[^\{\}]*\{[^\{\}]*\})*/g.exec(part);

      if (match.length > 1 && match[1])
        result.push('.' + id + '-' + parts[i]);
    }

    obj.data = result.join('');
  }
};

And in _parseSVG calling that directly after _fixIds-call:

      // add ids
      _fixIds(obj, id);
      // prefix classNames
      _fixClassNames(obj, id);

It did solve my issues, maybe not a perfect solution. But I rather like it to be solved by svgoOptions if possible...