toy / image_optim

Optimize images using multiple utilities
https://github.com/toy/image_optim
MIT License
1.52k stars 109 forks source link

Add support for SVGo 2.x #191

Open mtancoigne opened 3 years ago

mtancoigne commented 3 years ago

Version 2 has CLI changes, which makes it incompatible with image_optim. I have not dug into the code to see how the different versions can be handled, but for now, I can say that a call like

optimizer = ImageOptim.new(svgo: { enable_plugins: %w[removeScriptElement removeStyleElement removeOffCanvasPaths removeRasterImages] })
optimizer.optimize_image! path

leaves the picture unchanged.

From the release notes:

Painful coa was replaced with well maintained commander.

--enable and --disable flags are removed. In later versions we will explore plugins setup via CLI.

Inlined json config is no longer suppored. CLI flags should be used instead.

--config="{multipass:true}"

By default SVGO CLI will search for svgo.config.js. --config flag allows to specify js config with any name.

YAML and JSON configuration is no longer supported for the sake of simplicity and less dependencies.

mtancoigne commented 3 years ago

From the 2.x CLI: svgo --help

Usage: svgo [options] [INPUT...]

Nodejs-based tool for optimizing SVG vector graphics files

Arguments:
  INPUT                      Alias to --input

Options:
  [...]
  --config <CONFIG>          Config file or JSON string to extend or replace default
  [...]

So it seems that the plugins should be enabled/disabled in a JSON string passed to the --config argument, as for version 1.3.x. I'm looking at the format to see if it's compatible.

mtancoigne commented 3 years ago

As per the README, about JSON configuration, "If plugins field is specified default list is fully overrided". The other possibility would be to use a javascript configuration file to keep the default plugins, and create a json from scratch if file does not exist... which is, IMO, not optimal.

toy commented 3 years ago

Thanks for opening the issue. Checking release 2.0.0 there is a note about using extendDefaultPlugins([…]) and active: false to disable default plugin, so it should be possible to make it work without creating config file.

mtancoigne commented 3 years ago

extendDefaultPlugins([…]) is available in JS configuration files, as the methods returns the default list. I'm not sure SVGo handles raw javascript from the --config option. I'll check this

mtancoigne commented 3 years ago

Well... passing raw JSON in the CLI does nothing. SVGo ignores it:

node_modules/.bin/svgo -i in.svg -o defaults.svg --pretty
node_modules/.bin/svgo -i in.svg -o out.svg --pretty --config="{floatPrecision:1}"
diff defaults.svg out.svg
# no difference

# With svgo.config.js and the same options
node_modules/.bin/svgo -i in.svg -o out.svg --pretty
diff defaults.svg out.svg
# lots of differences

Passing raw javascript is silently ignored, as I thought:

node_modules/.bin/svgo -i in.svg -o out.svg --pretty --config="module.exports={floatPrecision:1};"
diff defaults.svg out.svg
# no difference

While not evaluating JS from --config seems a good thing, the fact that SVGo silently ignores the content of --config while its manual states "Config file or JSON string" is clearly an issue. I'll open one on the project.

mtancoigne commented 3 years ago

They dropped support for inline JSON in '--config', it now only takes a JS file as argument. I guess we're stuck with v 1.3 for now, or specify a configuration file or have a svgo.config.js file in our projects.

toy commented 3 years ago

You already saw that in 2.1.0 properly documents that config can be only a js file path. The solution would be to detect svgo >= 2 and create a temp config file if enabled/disabled were used (but one for the worker, not for every optimised svg file). I'm trying to think about the problems of such solution.