build: Provide SVGO for crunching SVG files

Stolen from Codex's version.

Change-Id: Iee6408c42ae2ef13eeadbbf74ec3132c77974279
This commit is contained in:
James D. Forrester 2024-10-10 18:16:33 -04:00
parent cb8cfaa28e
commit 0bfecf9118
4 changed files with 275 additions and 50 deletions

45
.svgo.config.mjs Normal file
View file

@ -0,0 +1,45 @@
/**
* SVGO Configuration
* Compatible to v3.0.0+
* Recommended options from:
* https://www.mediawiki.org/wiki/Manual:Coding_conventions/SVG#Exemplified_safe_configuration
*
* @type {import('svgo').Config}
*/
export default {
plugins: [
{
// Set of built-in plugins enabled by default.
name: 'preset-default',
params: {
overrides: {
cleanupIds: false,
removeDesc: false,
removeTitle: false,
removeViewBox: false,
// If the SVG doesn't start with an XML declaration, then its MIME type will
// be detected as "text/plain" rather than "image/svg+xml" by libmagic and,
// consequently, MediaWiki's CSSMin CSS minifier. libmagic's default database
// currently requires that SVGs contain an XML declaration:
// https://github.com/threatstack/libmagic/blob/master/magic/Magdir/sgml#L5
removeXMLProcInst: false,
convertPathData: {
// Set desired precision for float numbers.
floatPrecision: 2
}
}
}
},
'removeRasterImages'
],
// Set whitespace according to Wikimedia Coding Conventions.
// @see https://github.com/svg/svgo/blob/main/lib/svgo/coa.js#L194 for more config options
js2svg: {
eol: 'lf',
finalNewline: true,
// Configure the indent to tabs (default 4 spaces) used by `--pretty` here.
indent: '\t',
pretty: true
},
multipass: true
};

View file

@ -1,7 +1,7 @@
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="200" height="200" fill="white"/>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" fill="none" viewBox="0 0 200 200">
<path fill="#fff" d="M0 0h200v200H0z"/>
<g filter="url(#filter0_d)">
<mask id="mask0" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="25" y="25" width="150" height="150">
<mask id="mask0" width="150" height="150" x="25" y="25" maskUnits="userSpaceOnUse" style="mask-type:alpha">
<circle cx="100" cy="100" r="75" fill="#EAF3FF"/>
</mask>
<g mask="url(#mask0)">
@ -9,42 +9,42 @@
<circle cx="100" cy="100" r="75" fill="#EAF3FF"/>
</g>
<g filter="url(#filter2_d)">
<rect x="23" y="65" width="114" height="126" rx="2" fill="white"/>
<rect width="114" height="126" x="23" y="65" fill="#fff" rx="2"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M110.35 86.1H60.65C56.7288 86.1 53.55 88.8758 53.55 92.3V135.7C53.55 139.124 56.7288 141.9 60.65 141.9H110.35C114.271 141.9 117.45 139.124 117.45 135.7V92.3C117.45 88.8758 114.271 86.1 110.35 86.1ZM110.35 123.3H96.15L92.6 129.5H78.4L74.85 123.3H60.65V92.3H110.35V123.3Z" fill="#3366CC"/>
<path d="M113.776 46C115.503 46 116.904 47.4003 116.904 49.1277V67.894C116.904 69.6214 115.503 71.0217 113.776 71.0217C112.048 71.0217 110.648 69.6214 110.648 67.894V49.1277C110.648 47.4003 112.048 46 113.776 46ZM141.437 57.4357C142.237 57.4357 143.025 57.7536 143.636 58.3642C144.857 59.5858 144.857 61.5901 143.636 62.8115L132.591 73.8562C131.37 75.0777 129.365 75.0774 128.144 73.8562C126.922 72.6347 126.923 70.6303 128.144 69.409L139.189 58.3642C139.799 57.7535 140.636 57.4357 141.437 57.4357ZM86.1151 57.4357C86.9155 57.4357 87.7523 57.7535 88.3632 58.3642L99.4079 69.409C100.629 70.6303 100.629 72.6347 99.4079 73.8562C98.1864 75.0774 96.1821 75.0777 94.9608 73.8562L83.9159 62.8115C82.6946 61.5901 82.6948 59.5858 83.9159 58.3642C84.5268 57.7536 85.3147 57.4357 86.1151 57.4357ZM152.872 85.0964C154.6 85.0964 156 86.4967 156 88.2241C156 89.9516 154.6 91.3518 152.872 91.3518H134.106C132.379 91.3518 130.978 89.9516 130.978 88.2241C130.978 86.4967 132.379 85.0964 134.106 85.0964H152.872ZM130.343 101.663C131.143 101.664 131.98 101.981 132.591 102.592L143.636 113.637C144.857 114.858 144.857 116.862 143.636 118.084C142.414 119.305 140.41 119.305 139.189 118.084L128.144 107.039C126.923 105.818 126.922 103.814 128.144 102.592C128.755 101.981 129.542 101.663 130.343 101.663Z" fill="#FFCC33"/>
<path fill="#36C" fill-rule="evenodd" d="M110.35 86.1h-49.7c-3.92 0-7.1 2.78-7.1 6.2v43.4c0 3.42 3.18 6.2 7.1 6.2h49.7c3.92 0 7.1-2.78 7.1-6.2V92.3c0-3.42-3.18-6.2-7.1-6.2m0 37.2h-14.2l-3.55 6.2H78.4l-3.55-6.2h-14.2v-31h49.7z" clip-rule="evenodd"/>
<path fill="#FC3" d="M113.78 46c1.72 0 3.12 1.4 3.12 3.13v18.76a3.13 3.13 0 0 1-6.25 0V49.13c0-1.73 1.4-3.13 3.13-3.13m27.66 11.44a3.16 3.16 0 0 1 2.2 5.38l-11.05 11.04a3.16 3.16 0 0 1-4.45 0 3.16 3.16 0 0 1 0-4.45l11.05-11.05a3.2 3.2 0 0 1 2.25-.92m-55.32 0c.8 0 1.63.31 2.24.92l11.05 11.05a3.16 3.16 0 0 1 0 4.45 3.16 3.16 0 0 1-4.45 0L83.92 62.8a3.16 3.16 0 0 1 2.2-5.37m66.75 27.66a3.13 3.13 0 1 1 0 6.25h-18.76a3.13 3.13 0 0 1 0-6.25zm-22.53 16.56c.8 0 1.64.32 2.25.93l11.05 11.05a3.16 3.16 0 0 1 0 4.44 3.16 3.16 0 0 1-4.45 0l-11.05-11.04a3.16 3.16 0 0 1 2.2-5.38"/>
</g>
</g>
<defs>
<filter id="filter0_d" x="21" y="21" width="158" height="158" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter0_d" width="158" height="158" x="21" y="21" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter1_d" x="21" y="25" width="158" height="158" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter1_d" width="158" height="158" x="21" y="25" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
<filter id="filter2_d" x="18" y="60" width="124" height="136" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<filter id="filter2_d" width="124" height="136" x="18" y="60" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset/>
<feGaussianBlur stdDeviation="2.5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
</filter>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

180
package-lock.json generated
View file

@ -14,7 +14,8 @@
"grunt-eslint": "24.3.0",
"grunt-stylelint": "0.20.1",
"grunt-tyops": "0.1.1",
"stylelint-config-wikimedia": "0.17.2"
"stylelint-config-wikimedia": "0.17.2",
"svgo": "3.3.2"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@ -435,6 +436,15 @@
"node": ">=0.10.0"
}
},
"node_modules/@trysound/sax": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
"integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==",
"dev": true,
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/@types/eslint": {
"version": "8.56.10",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz",
@ -959,6 +969,15 @@
"node": ">=0.1.90"
}
},
"node_modules/commander": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
"dev": true,
"engines": {
"node": ">= 10"
}
},
"node_modules/comment-parser": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
@ -1042,6 +1061,22 @@
"node": ">=12 || >=16"
}
},
"node_modules/css-select": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
"dev": true,
"dependencies": {
"boolbase": "^1.0.0",
"css-what": "^6.1.0",
"domhandler": "^5.0.2",
"domutils": "^3.0.1",
"nth-check": "^2.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-tokenize": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/css-tokenize/-/css-tokenize-1.0.1.tgz",
@ -1065,6 +1100,18 @@
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
}
},
"node_modules/css-what": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
"dev": true,
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@ -1077,6 +1124,39 @@
"node": ">=4"
}
},
"node_modules/csso": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz",
"integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==",
"dev": true,
"dependencies": {
"css-tree": "~2.2.0"
},
"engines": {
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/csso/node_modules/css-tree": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz",
"integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==",
"dev": true,
"dependencies": {
"mdn-data": "2.0.28",
"source-map-js": "^1.0.1"
},
"engines": {
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
"npm": ">=7.0.0"
}
},
"node_modules/csso/node_modules/mdn-data": {
"version": "2.0.28",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
"dev": true
},
"node_modules/dateformat": {
"version": "4.6.3",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
@ -4640,6 +4720,31 @@
"integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=",
"dev": true
},
"node_modules/svgo": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz",
"integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==",
"dev": true,
"dependencies": {
"@trysound/sax": "0.2.0",
"commander": "^7.2.0",
"css-select": "^5.1.0",
"css-tree": "^2.3.1",
"css-what": "^6.1.0",
"csso": "^5.0.5",
"picocolors": "^1.0.0"
},
"bin": {
"svgo": "bin/svgo"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/svgo"
}
},
"node_modules/table": {
"version": "6.8.2",
"resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz",
@ -5334,6 +5439,12 @@
}
}
},
"@trysound/sax": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
"integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==",
"dev": true
},
"@types/eslint": {
"version": "8.56.10",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz",
@ -5695,6 +5806,12 @@
"integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
"dev": true
},
"commander": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
"dev": true
},
"comment-parser": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
@ -5751,6 +5868,19 @@
"integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==",
"dev": true
},
"css-select": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
"dev": true,
"requires": {
"boolbase": "^1.0.0",
"css-what": "^6.1.0",
"domhandler": "^5.0.2",
"domutils": "^3.0.1",
"nth-check": "^2.0.1"
}
},
"css-tokenize": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/css-tokenize/-/css-tokenize-1.0.1.tgz",
@ -5771,12 +5901,45 @@
"source-map-js": "^1.0.1"
}
},
"css-what": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
"dev": true
},
"cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true
},
"csso": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz",
"integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==",
"dev": true,
"requires": {
"css-tree": "~2.2.0"
},
"dependencies": {
"css-tree": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz",
"integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==",
"dev": true,
"requires": {
"mdn-data": "2.0.28",
"source-map-js": "^1.0.1"
}
},
"mdn-data": {
"version": "2.0.28",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
"dev": true
}
}
},
"dateformat": {
"version": "4.6.3",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
@ -8391,6 +8554,21 @@
"integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=",
"dev": true
},
"svgo": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz",
"integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==",
"dev": true,
"requires": {
"@trysound/sax": "0.2.0",
"commander": "^7.2.0",
"css-select": "^5.1.0",
"css-tree": "^2.3.1",
"css-what": "^6.1.0",
"csso": "^5.0.5",
"picocolors": "^1.0.0"
}
},
"table": {
"version": "6.8.2",
"resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz",

View file

@ -3,6 +3,7 @@
"name": "DiscussionTools",
"version": "0.0.0",
"scripts": {
"minify:svg": "svgo --config=.svgo.config.mjs --quiet --recursive --folder ./modules",
"test": "grunt test"
},
"devDependencies": {
@ -12,6 +13,7 @@
"grunt-eslint": "24.3.0",
"grunt-stylelint": "0.20.1",
"grunt-tyops": "0.1.1",
"svgo": "3.3.2",
"stylelint-config-wikimedia": "0.17.2"
}
}