exercism / website

The codebase for Exercism's website.
https://exercism.org
GNU Affero General Public License v3.0
413 stars 122 forks source link

Add a script to run all images through svgo #462

Open iHiD opened 3 years ago

iHiD commented 3 years ago

https://github.com/svg/svgo

We can choose our options at https://jakearchibald.github.io/svgomg/

habere-et-dispertire commented 2 years ago

A caveat: by default svgo does not preserve viewBox which can be problematic, but you can override it:

module.exports = {
  plugins: [
    {
      name: 'preset-default',
      params: {
        overrides: {
          // or disable plugins
          removeViewBox: false,
        },
      },
    },
  ],
};

I did a test run preserving the viewBox on the 71 SVG files in website/app/images/graphics finding a saving of 27% (from 3,315,469 to 2,411,182 bytes) with SVGO's otherwise default settings. A cursory glance at the generated files shows no ill effects.

habere-et-dispertire commented 2 years ago

Running through the entire site gives just shy of 20% savings. One file is problematic.

habere-et-dispertire commented 2 years ago

I took the liberty of checking the...

SVG Files

Disclosure: the vnu validator is two years old and has dubious support for SVG 2. Some of the following issues may well be due to that.

Validation performed with:

$ vnu --skip-non-svg DIRECTORY_PATH

285 | Files

167 | Pass 59% 118 | Fail 41%

Element "stop" is missing required attribute "offset"

114 files:

website-main/app/images/icons/target.svg:10.1-10.28
website-main/app/images/icons/target.svg:13.111-14.28
website-main/app/images/icons/target.svg:18.1-18.28
website-main/app/images/icons/target.svg:22.1-22.28
website-main/app/images/icons/target.svg:26.1-26.28
website-main/app/images/icons/target.svg:30.1-30.28
website-main/app/images/icons/building-with-gradient.svg:12.1-12.28
website-main/app/images/icons/building-with-gradient.svg:16.1-16.28
website-main/app/images/icons/building-with-gradient.svg:20.1-20.28
website-main/app/images/icons/building-with-gradient.svg:24.1-24.28
website-main/app/images/icons/building-with-gradient.svg:28.1-28.28
website-main/app/images/icons/building-with-gradient.svg:32.1-32.28
website-main/app/images/icons/building-with-gradient.svg:36.1-36.28
website-main/app/images/icons/building-with-gradient.svg:40.1-40.28
website-main/app/images/icons/features-feedback.svg:6.1-6.28
website-main/app/images/icons/features-feedback.svg:10.1-10.28
website-main/app/images/icons/sample-track.svg:64.7-64.35
website-main/app/images/icons/sample-track.svg:76.7-76.35
website-main/app/images/icons/principles.svg:9.1-9.28
website-main/app/images/icons/principles.svg:13.1-13.28
website-main/app/images/icons/principles.svg:17.1-17.28
website-main/app/images/icons/principles.svg:21.1-21.28
website-main/app/images/icons/principles.svg:25.1-25.28
website-main/app/images/icons/ukraine.svg:5.1-5.28
website-main/app/images/icons/features-local.svg:8.1-8.28
website-main/app/images/icons/features-local.svg:12.1-12.28
website-main/app/images/icons/features-local.svg:16.1-16.28
website-main/app/images/icons/features-local.svg:20.1-20.28
website-main/app/images/icons/features-do-not-know.svg:7.1-7.28
website-main/app/images/icons/features-do-not-know.svg:11.1-11.28
website-main/app/images/icons/features-do-not-know.svg:15.1-15.28
website-main/app/images/icons/partnership.svg:15.1-15.28
website-main/app/images/icons/partnership.svg:19.1-19.28
website-main/app/images/icons/partnership.svg:23.1-23.28
website-main/app/images/icons/partnership.svg:27.1-27.28
website-main/app/images/icons/partnership.svg:31.1-31.28
website-main/app/images/icons/partnership.svg:35.1-35.28
website-main/app/images/icons/partnership.svg:39.1-39.28
website-main/app/images/icons/partnership.svg:43.1-43.28
website-main/app/images/icons/partnership.svg:47.1-47.28
website-main/app/images/icons/partnership.svg:51.1-51.28
website-main/app/images/icons/partnership.svg:55.1-55.28
website-main/app/images/icons/exercism-face-gradient.svg:12.1-12.28
website-main/app/images/icons/exercism-face-gradient.svg:16.1-16.28
website-main/app/images/icons/exercism-face-gradient.svg:20.1-20.28
website-main/app/images/icons/exercism-face-gradient.svg:24.1-24.28
website-main/app/images/icons/exercism-face-gradient.svg:28.1-28.28
website-main/app/images/icons/contributing-header.svg:13.1-13.28
website-main/app/images/icons/contributing-header.svg:17.1-17.28
website-main/app/images/icons/contributing-header.svg:20.109-21.28
website-main/app/images/icons/contributing-header.svg:25.1-25.28
website-main/app/images/icons/contributing-header.svg:29.1-29.28
website-main/app/images/icons/contributing-header.svg:33.1-33.28
website-main/app/images/icons/contributing-header.svg:37.1-37.28
website-main/app/images/icons/contributing-header.svg:41.1-41.28
website-main/app/images/icons/contributing-header.svg:45.1-45.28
website-main/app/images/icons/share-with-gradient.svg:7.1-7.28
website-main/app/images/icons/share-with-gradient.svg:11.1-11.28
website-main/app/images/icons/share-with-gradient.svg:15.1-15.28
website-main/app/images/icons/features-editor.svg:9.1-9.28
website-main/app/images/icons/features-editor.svg:13.1-13.28
website-main/app/images/icons/features-editor.svg:17.1-17.28
website-main/app/images/icons/features-editor.svg:21.1-21.28
website-main/app/images/icons/features-editor.svg:25.1-25.28
website-main/app/images/icons/mentoring-gradient.svg:11.1-11.28
website-main/app/images/icons/mentoring-gradient.svg:15.1-15.28
website-main/app/images/icons/mentoring-gradient.svg:19.1-19.28
website-main/app/images/icons/mentoring-gradient.svg:23.1-23.28
website-main/app/images/icons/mentoring-gradient.svg:27.1-27.28
website-main/app/images/icons/mentoring-gradient.svg:31.1-31.28
website-main/app/images/icons/mentoring-gradient.svg:35.1-35.28
website-main/app/images/icons/purpose.svg:9.103-10.28
website-main/app/images/icons/purpose.svg:14.1-14.28
website-main/app/images/icons/purpose.svg:18.1-18.28
website-main/app/images/icons/purpose.svg:22.1-22.28
website-main/app/images/icons/purpose.svg:26.1-26.28
website-main/app/images/icons/purpose.svg:30.1-30.28
website-main/app/images/icons/bubbly-background.svg:22.1-22.28
website-main/app/images/icons/bubbly-background.svg:26.1-26.28
website-main/app/images/icons/bubbly-background.svg:30.1-30.28
website-main/app/images/icons/bubbly-background.svg:34.1-34.28
website-main/app/images/icons/bubbly-background.svg:38.1-38.28
website-main/app/images/icons/bubbly-background.svg:42.1-42.28
website-main/app/images/icons/bubbly-background.svg:46.1-46.28
website-main/app/images/icons/features-fluency.svg:7.1-7.28
website-main/app/images/icons/features-fluency.svg:11.1-11.28
website-main/app/images/icons/features-fluency.svg:15.1-15.28
website-main/app/images/graphics/landing-page-top.svg:177.1-177.45
website-main/app/images/graphics/landing-page-top.svg:181.1-181.28
website-main/app/images/graphics/landing-page-top.svg:185.1-185.28
website-main/app/images/graphics/landing-page-top.svg:189.1-189.28
website-main/app/images/graphics/landing-page-top.svg:195.1-195.28
website-main/app/images/graphics/landing-page-top.svg:200.1-200.28
website-main/app/images/graphics/landing-page-top.svg:205.1-205.26
website-main/app/images/graphics/landing-page-top.svg:212.1-212.26
website-main/app/images/graphics/landing-page-top.svg:219.1-219.26
website-main/app/images/graphics/landing-page-top.svg:226.1-226.26
website-main/app/images/graphics/landing-page-top.svg:232.1-232.26
website-main/app/images/graphics/landing-page-top.svg:238.1-238.28
website-main/app/images/graphics/landing-page-top.svg:249.1-249.28
website-main/app/images/graphics/landing-page-top.svg:255.1-255.28
website-main/app/images/graphics/landing-page-top.svg:260.1-260.28
website-main/app/images/graphics/landing-page-top.svg:265.1-265.28
website-main/app/images/graphics/landing-page-top.svg:270.1-270.28
website-main/app/images/graphics/landing-page-top.svg:275.1-275.28
website-main/app/images/graphics/landing-page-top.svg:281.1-281.28
website-main/app/images/graphics/landing-page-top.svg:287.1-287.28
website-main/app/images/graphics/landing-page-top.svg:291.1-291.52
website-main/app/images/graphics/landing-page-top.svg:295.1-295.52
website-main/app/images/graphics/landing-page-top.svg:299.1-299.51
website-main/app/images/graphics/landing-page-top.svg:303.1-303.52
website-main/app/images/graphics/landing-page-top.svg:307.1-307.52
website-main/app/images/graphics/landing-page-top.svg:311.1-311.52
website-main/app/images/graphics/blog-placeholder-article.svg:18.1-18.28

Possible resolution

When a single stop offset is specified, then all stop offsets must be specified. Add an appropriate stop offset.

See https://stackoverflow.com/questions/32957626/element-stop-is-missing-required-attribute-offset-on-svg-linear-gradient-fill


Attribute "className" not allowed on element "svg" at this point.

1 file:

/website-main/app/images/icons/completed-check-circle.svg":1.1-6.1

Possible resolution

Use the attribute "class" not "className" as a hook since className is not the same in HTML and SVG.

See https://stackoverflow.com/questions/37943006/unable-to-change-class-name-of-svg-element


Expected '"' or "'" (found "“")

1 file:

website-main/app/images/icons/features-oop.svg:1.1-1.12

Possible resolution

Replace Unicode quotation marks with ASCII equivalents.

See https://github.com/exercism/website/pull/2781


Attribute "mask-type" not allowed on element "mask" at this point.

1 file:

website-main/app/images/icons/avatar-placeholder.svg":3.1-3.97

This appears to be a SVG 2 feature which although well supported by browsers is still not an official specification (it is at candidate recommendation stage). Ignore?


Attribute "aria-label" not allowed on element "g" at this point.

1 file:

website-main/app/images/graphics/go-gopher.svg":1.44183-1.44426

I have no clarity on this. It appears that between SVG 1.1 and 2, the validator has tightened certain restrictions.

Possible resolution

Use a title child element with descriptive text.

habere-et-dispertire commented 2 years ago

I am happy to make any changes you'd like. :)

As the SVG files appear somewhat compressed, perhaps this work would have to be redone unless the changes are made upstream. I don't yet know where in the large Exercism ecosystem they live, so please point if you'd like me to do anything. :)

iHiD commented 2 years ago

Thank you :)

Maybe you and Erik could agree a good workflow for svgo (either as part of deploy, or as part of the PR process) that compresses things. And then we can have a separate PR that tidies up the existing ones.

From a "what matters" perspective, size feels important/valuable, and then anything that actually changes how they look in the browser. e.g. for the offset one above, if it doesn't matter from a rendering perspective then I don't massively care whether it's added or not, but if it means they pass the validator and we can use that in a github-action moving forward, that's great.

What I don't want to have to do is do manual work on each PR to check things or keep them up to date.

As an FYI, Erik is quite busy atm (we have team away week next week then onboarding new front-end dev the week after) so we're both probably slower than usual in replying etc.

ErikSchierboom commented 2 years ago

The linting stuff could easily go into a workflow I feel. It's just a matter of finding the time to do so.

What I don't want to have to do is do manual work on each PR to check things or keep them up to date.

Are you saying you want us to automatically correct SVGs that are added/changed in a PR? Would a script to run through the files in bulk help? We could theoretically also use a git hook 🤷

iHiD commented 2 years ago

Are you saying you want us to automatically correct SVGs that are added/changed in a PR? Would a script to run through the files in bulk help? We could theoretically also use a git hook 🤷

That would be nice, yes!