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

Option to resize SVGs to custom dimesnions #2005

Closed
xandemon opened this issue May 11, 2024 · 4 comments
Closed

Option to resize SVGs to custom dimesnions #2005

xandemon opened this issue May 11, 2024 · 4 comments

Comments

@xandemon
Copy link

SVGO is a great tool for optimizing SVGs. However, there are times when I need to resize or scale them to certain dimensions and I hate the fact that I have to manually use external tools to resize them and then pass resized SVGs to SVGO. It would be so much better to have this feature in SVGO.

My scenario was that I downloaded svgs online but they were too big at around 2000px width and height and I wouldn't want that because even while previewing those SVGs, they go beyond the viewport.

So could this feature be implemented as plugins in SVGO or something? I can work on this feature if approved.

@KTibow
Copy link
Contributor

KTibow commented May 12, 2024

SVGs have width/height and viewbox. You can easily resize a SVG by changing the width and height while leaving the viewbox the same. (However if the preexisting viewbox is incorrect, that's something different)

@xandemon
Copy link
Author

SVGs have width/height and viewbox. You can easily resize a SVG by changing the width and height while leaving the viewbox the same. (However if the preexisting viewbox is incorrect, that's something different)

Yeah exactly. Most of the SVGs downloaded online have incorrect viewport and thus are unscalable. When optimized with SVGO, the scaling works but by default, it takes the initial width and height and we need to manually resize the SVG with 3rd party tool. Would be great to have that resize feature built-in.

@SethFalco
Copy link
Member

SethFalco commented Jun 14, 2024

I have to manually use external tools to resize

By this, I'm assuming your gripe is using GUI tools rather than just using other tools in general? Or do you actually want SVGO to be the all-in-one tool for your needs?

Imo, functionality being split into many tools is a good thing imo, not a bad thing! (Or at least, for CLI applications.)

In UNIX/UNIX-like land, we generally favor small tools that perform one function and do it well. This reduces project scope, and ensures every tool can specialize in what it does. If we extend the scope of SVGO, we have to continue maintaining that, which doesn't seem worthwhile.

I wouldn't want that because even while previewing those SVGs, they go beyond the viewport

You may be able to fix this issue by using the removeDimensions plugin. Perhaps give this a try when you optimize with SVGO?

So could this feature be implemented as plugins in SVGO or something?

Now focusing more on the idea of resizing specifically, if removeDimensions doesn't do what you need.

I'm reluctant to add something like this to SVGO. There have been other requests that effectively try to bring editing capabilities into SVGO too, but that's not really in the scope of the project. We're an optimizer, not a CLI graphic manipulation tool like ImageMagick.

If you want to edit an SVG from the command-line or script, I'd recommend writing yourself a script using other commands, a custom SVGO plugin, or utilize the more general plugins available to achieve what you want.

Here are some off the shelf tools you could use already, including SVGO, all commands can be demoed with svgo_hackerman.svg, the commands will resize it to 512px wide. They are written in the order of recommendation:

rsvg-convert

rsvg-convert is part of librsvg, a project by GNOME. You can read an SVG and override the width or height very cleanly.

rsvg-convert -w 512 -o svgo_hackerman_resized.svg -f svg svgo_hackerman.svg

xmlstarlet

xmlstarlet is a command-line XML manipulation tool. You can use it to delete the width and height attributes and replace it with whatever you like. You can also use this for any other manipulation you may be interested in.

As SVGs are XML, you can use most XML manipulation tool as an SVG manipulation tool.

xmlstarlet ed -L -d '/_:svg/@width' -i '/_:svg' -t 'attr' -n 'width' -v '512' svgo_hackerman.svg

SVGO

In SVGO, you can combine the removeAttrs plugin and addAttributesToSVGElement to remove and add the width and height attribute with the desired values.

svgo.config.js

module.exports = {
  plugins: [
    {
      name: "removeAttrs",
      params: {
        attrs: [
          "svg:width"
        ],
        preserveCurrentColor: false
      }
    },
    {
      name: "addAttributesToSVGElement",
      params: {
        attributes: [
          { 
            width: 512 
          }
        ]
      }
    }
  ]
}

Then run the following command:

svgo svgo_hackerman.svg

This will now have a width of 512px, however it will probably break for SVGs with a nested <svg> element in it, though.

ImageMagick

You can use an actual command-line image graphic manipulation tool like ImageMagick. It's pretty great for raster images, but its SVG capabilities aren't perfect.

magick svgo_hackerman.svg -resize 512x svgo_hackerman_resized.svg

Normally, this will work, but it seems to break for more complex SVGs. It's also worth noting that the output appears to be the equivalent of both settings the width, but also removing view box, which may not be desirable. (This would render differently than only updating the width without changing the view box.)

sed

You could even try using sed for something like this, though it's a last resort and probably a bad idea, but noting it anyway in case the solutions don't work for whatever reason.

This deletes the original width, then appends a new width.

sed -i -E "s/(<svg [^>]+?) width\s*=\s*([\"'])([0-9]+)\2\s*(.*?>)/\1\4/" svgo_hackerman.svg
sed -i -E "s/(<svg\s+.+)(>)/\1 width=\"512\"\2/" svgo_hackerman.svg

This will break in cases where the <svg> node itself is distributed over multiple lines.

Obligatory: https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454

Custom SVGO Plugin

Finally, if none of the solutions above work, you can add a custom SVGO plugin to your pipeline. However, I can't provide advice on this without more information, as if every solution proposed above doesn't cut if for you, then the requirements must be more complex than just resizing.

You can read about how to write a custom plugin in our documentation.


I hope this helps, you're welcome to add more information or request guidance if you have trouble doing what you need with the advice given!

@SethFalco SethFalco closed this as not planned Won't fix, can't repro, duplicate, stale Jun 14, 2024
@xandemon
Copy link
Author

Thanks, @SethFalco ! That was very well-described response. I will try the above-mentioned approaches.

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

No branches or pull requests

4 participants
@KTibow @SethFalco @xandemon and others