Using svgo as SVG linter
Is your feature request related to a problem? Please describe.
I would like to use svgo as a "linter", that would validate against some rules specific to a project. An example of such rule is one that would validate the artboard size of the SVG (viewBox attribute value) but there are many more such rules that I have in mind.
I know that svgo is an optimizer, so I would like to ask if you are open to extend
Describe the solution you'd like
Looking at the current architecture of svgo, I think the solution would be to extend plugins to return diagnostic/validation information as well. This would work in a way similar to what ESLint does: by default it just reports failed rules but the user can also provide --fix flag to automatically fix the errors, if the given rule provides code transformations to perform autofix (the "fix" option would probably stay as the default in case of svgo).
Taking the "artboard size validation" rule, it could for example just check the viewBox , width and height attributes (based on the plugin configuration) and return some validation information, possibly with an autofix.
Also, it would be possible to use different output formats (again, based on other tools like ESLint: https://eslint.org/docs/user-guide/formatters/ or Stylelint), for example to format the output in JSON.
Describe alternatives you've considered
An alternative is to write a separate library. However, I think that the idea I am presenting fits pretty nicely into what svgo already does and into its architecture.
Hi! This cannot be implemented with current architecture. Though once we have own parser and ready for exposing set of utilities we will create new project specifically for linting to not mess the code with svgo. You can write here possible lint rules so we could rely on something in the future.
once we have own parser and ready for exposing set of utilities we will create new project specifically for linting to not mess the code with svgo
Is this work already planned and has some timeline? Please let me know if I can help make this happen (I mean code refactoring, not only writing lint rules here).
No really planning. I just improve things in my free time. So the best you can do for now is give some ideas. I'll ping you when something will be ready.
Well, there is an old idea just to optimize SVG, but don't save. Just tell whether it can be optimized with some threshold value. E.g. fail if it can be reduced more than by N% (but not less than M bytes, so don't bother about couple of bytes). I don't know though what values it should be. Something like 5% and 20 bytes for example? It should be configurable for sure.
Well, there is an old idea just to optimize SVG, but don't save. Just tell whether it can be optimized with some threshold value. E.g. fail if it can be reduced more than by N% (but not less than M bytes, so don't bother about couple of bytes). I don't know though what values it should be. Something like 5% and 20 bytes for example? It should be configurable for sure.
But the point here is to be able to return linting/validation in something that could be later used by other tools (like JSON reporter in ESLint). Right now it could only be console-logged.
I just don't know what do you want to be reported.
Maybe a dry-run which can say what can different plugins save? There is plenty of combinations though, maybe with a set of presets.
For invalid syntax it should be separate tool.
Maybe an option to report for things like fill-rule which can be safely optimized now automatically? (Due to complexity)
These are mostly some project-specific rules, not any invalid syntax. Something that a graphic designer would create but wouldn't match some standards.
For example: the artboard doesn't have proper size. This could technically be fixed using SVGO plugin but is not always something the user would want because it would actually required the SVG graphics to be fixed as well. I was thinking about the dry run but still, there is currently no ways to get validation information except for parsing command line output.
Sounds like out of SVGO's scope. It's for an optimizing in terms of the file size in the first place, with a bit of image manipulating (for optimization purposes as well). I can understand optimization-related hints, but everything else should be done elsewhere.
@GreLI We are planning to expand the ecosystem of svgo a bit. This might fit.
Proposed linter rules:
titleelement must not be empty.descelement must not be empty.- Container elements (
g,svg,defs,metadata, etc) must not be empty. textelement must have text.useelement must have ahrefattribute.hrefattribute must point to a valid id reference.idattribute must be valid name according to the spec.
roleattribute must a valid role.aria-labelledbyandaria-describedbyattribute must point to valid reference.- Units must be valid units as defined in the standard.
- There can only be one
titleelement. - The
titleelement can only be at the top. - Any indention should be consistent.
titleshould not exceed XX chars.descshould not exceed XXX chars.urlfunction infilterattribute should point to a valid id that exists.- For encoding you probably want UTF-8.
- Without byte order mark (BOM)
- Class names in
classattributes you probably want kebab case, i.e. lowercase with words separated by a hyphen. - Class names you might want to use semantic naming rather than presentational naming, e.g.
text-dangernottext-red.
For what it's worth, there is already tooling available that retrofits linting functionality on top of SVGO.
- https://trunk.io/linters/nodejs/svgo
- https://github.com/trunk-io/plugins
Found out about this while reviewing some conversations in ESLint:
- https://github.com/eslint/eslint/pull/18643#issuecomment-2268888139