Skip to content

Commit

Permalink
Document configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
mondeja committed May 13, 2024
1 parent d6f1444 commit ab137ad
Showing 1 changed file with 171 additions and 16 deletions.
187 changes: 171 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@

Lints SVG files. Can be run as a commandline utility, or as a NodeJS library.

<!-- markdownlint-disable MD033 MD024 -->

<p align="center">
<img src="https://raw.githubusercontent.com/birjolaxew/svglint/master/example.png" alt="Example of a commandline execution"/>
</p>

<!-- markdownlint-enable MD033 -->

## Usage

The tool can be used as a commandline tool by executing the CLI.
If installed as a dependency by NPM this will be found at `./node_modules/.bin/svglint`.
If installed globally by NPM it can be executed directly as `svglint`.

```
```shell
$ svglint --help

Linter for SVGs
Expand All @@ -36,8 +40,9 @@ The tool can also be used through the JS API.
import SVGLint from "svglint";

const linting = await SVGLint.lintSource("<svg>...</svg>", {
// ... config goes here
// ... config object goes here
});

linting.on("done", () => {
if (!linting.valid) {
console.log("You've been a naughty boy!");
Expand All @@ -47,34 +52,184 @@ linting.on("done", () => {

## Config

SVGLint can run without a configuration file. In that case, it uses an empty object as the default configuration, which means that no rules are enabled. This default configuration may be changed such that previously valid SVGs become invalid in minor releases and patches.

In order to specify what should be linted SVGLint must be given a configuration object.
If you are using the CLI, this configuration object is read from the file specified by `--config`. This defaults to `.svglintrc.js`, which will be searched for up through the directory tree, or in the user's home directory (e.g. `~/.svglintrc.js` on Unix-like systems) - this is similar to tools such as ESLint.

If you are using the CLI, this configuration object is read from the file specified by `--config`. This defaults to:

- *.svglintrc.js*
- If the *package.json* `type` field is set to `"module"`, then *.svglintrc.cjs* is also checked, else *.svglintrc.mjs* is checked.

These files will be searched for up through the directory tree, or in the user's home directory (e.g. `~/` on Unix-like systems).

This configuration file should export a single object, of the format:

```javascript
export default {
// additional configuration may go here in the future
// for now, "rules" is the only useful key
rules: {
elm: [{
// config 1 for the "elm" rule
// Built-in rules
elm: {
// config for the `elm` rule
},
attr: [{
// config 1 for the `attr` rule
}, {
// config 2 for the "elm" rule
// config 2 for the `attr` rule
}],
attr: {
// config 1 for the "attr" rule
},
valid: true,

// Custom rules
custom: [
(reporter, $, ast) => {
// config for a custom rule named `my-first-rule`
reporter.name = 'my-first-rule';
},
(reporter, $, ast) => {
// config for a custom rule named `my-second-rule`
reporter.name = 'my-second-rule';
}
],

// External rules
'simple-icons-svglint-rules/icon-precision': {
// config for the rule `icon-precision` of the external
// hypotetical npm package `simple-icons-svglint-rules`
}
}
}
```

Additional configuration may be added in the future. For now, `rules` is the only useful key.

### Rules

All rules are optional.

#### `elm`

The `elm` rule specifies what elements are allowed in the SVG. It should be an object or an array of objects where:

- The keys are the element CSS selectors. See [_Selecting elements_ on cheerio's documentation][selecting-elements-cheerio].
- The values are either:
- `true` if at least one of the element is present.
- `false` if the element must not be present.
- A number to specify the number of times the element must be present.
- An array of two numbers to specify the minimum and maximum number of times the element must be present.

##### Example

Only one `<svg>` element with one `<title>` element and one `<path>` element inside.

```javascript
export default {
rules: {
elm: {
'svg': 1,
'svg > title': 1,
'svg > path': 1,
'*': false
}
}
}
```

#### `attr`

The `attr` rule specifies what attributes are allowed on elements. It should be an object or an array of objects where the keys must be either:

- `"rule::selector"`: The value must be the CSS selector of the element to which the rule applies. See [_Selecting elements_ on cheerio's documentation][selecting-elements-cheerio].
- `"rule::whitelist"`: If enabled, extra attributes beyond of the ones defined in additional keys are not allowed on the element. The value must be a boolean.
- `"rule::order"`: The value must be either:
- `true`: the attributes must be defined in alphabetical order.
- An array of strings: the attributes must be defined in the order specified by the array.
- Other strings to refer to the attributes that are allowed for the element. The values can be either:
- `false`: the attribute must not be present.
- An string: the attribute must be present and have the value specified.
- An array of strings: the attribute must be present and have one of the values specified.
- A regular expression: the attribute must be present and match the regular expression.

##### Example

```javascript
export default {
rules: {
attr: [
{
// Ensure that the SVG element has the appropriate attributes
// and alphabetically ordered
role: 'img',
viewBox: `0 0 24 24`,
xmlns: 'http://www.w3.org/2000/svg',
'rule::selector': 'svg',
'rule::whitelist': true,
'rule::order': true,
},
{
// Ensure that the title element has not attributes
'rule::selector': 'svg > title',
'rule::whitelist': true,
},
{
// Ensure that the path element only has the 'd' attribute
d: /^m[-mzlhvcsqtae\d,. ]+$/i,
'rule::selector': 'svg > path',
'rule::whitelist': true,
},
],
}
}
```

#### `valid`

The `valid` rule specifies if the SVG is valid or not. It should be a boolean to enable or disable the rule.

#### Custom rules

Custom rules can be specified by an array of functions. Each function should have the signature `(reporter, $, ast, { filename }) => void`, where:

- `reporter` is the object that will be used to report the errors.
- `$` is the cheerio object of the SVG.
- `ast` is the abstract syntax tree of the SVG.
- `filepath` is the full path of the file being linted.

You can set `reporter.name` to define the name of the rule shown by the output when an error is found. You can call `repoter.error(message)` to report an error.

##### Example

```javascript
export default {
rules: {
custom: [
function() { // config 1 for the "custom" rule }
(reporter, $, ast, { filename }) => {
reporter.name = 'no-self-closing-path';

// Don't allow explicit '</path>' closing tag
if (!ast.source.includes('</path>')) {
return;
}

const index = ast.source.indexOf('</path>');
const reason =
`found a closing "path" tag at index ${index}.` +
` The path should be self-closing,` +
' use "/>" instead of "></path>".';
reporter.error(`Invalid SVG content format: ${reason}`);
},
]
}
}
```

For specifics on how the config for each rule should be formatted, see [their specific rule files](https://github.com/birjolaxew/svglint/tree/master/src/rules).
#### External rules

External rules can be specified by their package name and rule name, separated by a slash. The package must be installed as a dependency and will be imported by the import machinery using:

```javascript
import("package-of-the-rule/rule-name.js");
```

If you are using the JS API, this configuration object is passed as the second parameter.
So you need to export the rule function from the file `rule-name.js` in the package `package-of-the-rule` as default to expose it.

If no configuration is found or provided, a default configuration object is used.
This default configuration may be changed such that previously valid SVGs become invalid in minor releases and patches.
[selecting-elements-cheerio]: https://cheerio.js.org/docs/basics/selecting

0 comments on commit ab137ad

Please sign in to comment.