simple-icons/.svglintrc.js
David Beitey 5da34c7efd
Add linter to check svg path dimensions (#3107)
* Add linter to check svg path dimensions

Float precision is set at 3 which is the default for svgo in .svgo.yml;
precision can be raised over time.

This adds an ignore file with the current paths of non-conforming icons.

This also changes the name of the icon title linter as well so it reads
more nicely than "custom".

* Update CONTRIBUTING GUIDELINES

Add a note on visual imperfections and viewbox problems due to 
optimizing.

Co-authored-by: Eric Cornelisesn <ericornelissen@gmail.com>
Co-authored-by: Peter Noble <PeterShaggyNoble@users.noreply.github.com>
2020-06-10 12:59:42 +03:00

76 lines
2.8 KiB
JavaScript

const data = require("./_data/simple-icons.json");
const { htmlFriendlyToTitle } = require("./scripts/utils.js");
const getBounds = require("svg-path-bounding-box");
const titleRegexp = /(.+) icon$/;
const iconSize = 24;
const iconFloatPrecision = 3;
const iconIgnored = require("./.svglint-ignored.json");
module.exports = {
rules: {
elm: {
"svg": 1,
"svg > title": 1,
"svg > path": 1,
"*": false,
},
attr: [
{ // ensure that the SVG elm has the appropriate attrs
"role": "img",
"viewBox": `0 0 ${iconSize} ${iconSize}`,
"xmlns": "http://www.w3.org/2000/svg",
"rule::selector": "svg",
"rule::whitelist": true,
},
{ // ensure that the title elm has the appropriate attr
"rule::selector": "svg > title",
"rule::whitelist": true,
},
{ // ensure that the path element only has the 'd' attr (no style, opacity, etc.)
"d": /^[,a-zA-Z0-9\. -]+$/,
"rule::selector": "svg > path",
"rule::whitelist": true,
}
],
custom: [
function(reporter, $, ast) {
reporter.name = "icon-title";
const iconTitleText = $.find("title").text();
if (!titleRegexp.test(iconTitleText)) {
reporter.error("<title> should follow the format \"[ICON_NAME] icon\"");
} else {
const titleMatch = iconTitleText.match(titleRegexp);
// titleMatch = [ "[ICON_NAME] icon", "[ICON_NAME]" ]
const rawIconName = titleMatch[1];
const iconName = htmlFriendlyToTitle(rawIconName);
const icon = data.icons.find(icon => icon.title === iconName);
if (icon === undefined) {
reporter.error(`No icon with title "${iconName}" found in simple-icons.json`);
}
}
},
function(reporter, $, ast) {
reporter.name = "icon-size";
const iconPath = $.find("path").attr("d");
if (iconIgnored.hasOwnProperty(iconPath)) {
return;
}
const bounds = getBounds(iconPath);
const width = +bounds.width.toFixed(iconFloatPrecision);
const height = +bounds.height.toFixed(iconFloatPrecision);
if (width === 0 && height === 0) {
reporter.error("Path bounds were reported as 0 x 0; check if the path is valid");
} else if (width !== iconSize && height !== iconSize) {
reporter.error(`Size of <path> must be exactly ${iconSize} in one dimension; the size is currently ${width} x ${height}`);
}
},
]
}
};