Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ export default [
| :--------------------------------------------------------------- | :-------------------------------- | :-------------: |
| [`no-duplicate-imports`](./docs/rules/no-duplicate-imports.md) | Disallow duplicate @import rules. | yes |
| [`no-empty-blocks`](./docs/rules/no-empty-blocks.md) | Disallow empty blocks. | yes |
| [`no-invalid-properties`](./docs/rules/no-invalid-properties.md) | Disallow invalid properties. | yes |
| [`no-unknown-at-rules`](./docs/rules/no-unknown-at-rules.md) | Disallow unknown at-rules. | yes |
| [`no-unknown-properties`](./docs/rules/no-unknown-properties.md) | Disallow unknown properties. | yes |

<!-- Rule Table End -->

Expand Down
53 changes: 53 additions & 0 deletions docs/rules/no-invalid-properties.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# no-invalid-properties

Disallow invalid properties.

## Background

CSS has a defined set of known properties that are expected to have specific values. While CSS may parse correctly, that doesn't mean that the properties are correctly matched with their values. For example, the following is syntactically valid CSS code:

```css
a {
display: black;
}
```

The property `display` doesn't accept a color for its value, so while this code will parse without error, it's still invalid CSS.

Similarly, as long as a property name is syntactically valid, it will parse without error even if it's not a known property. For example:

```css
a {
ccolor: black;
}
```

Here, `ccolor` is a syntactically valid identifier even though it will be ignored by browsers. Such errors are often caused by typos.

## Rule Details

This rule warns when it finds a CSS property that doesn't exist or a value that doesn't match with the property name in the CSS specification (custom properties such as `--my-color` are ignored). The property data is provided via the [CSSTree](https://github.com/csstree/csstree) project.

Examples of incorrect code:

```css
a {
display: black;
ccolor: black;
}

body {
overflow: 100%;
bg: red;
}
```

## When Not to Use It

If you aren't concerned with invalid properties, then you can safely disable this rule.

## Prior Art

- [`declaration-property-value-no-unknown`](https://stylelint.io/user-guide/rules/declaration-property-value-no-unknown/)

- [`property-no-unknown`](https://stylelint.io/user-guide/rules/property-no-unknown)
40 changes: 0 additions & 40 deletions docs/rules/no-unknown-properties.md

This file was deleted.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@
"devDependencies": {
"@eslint/core": "^0.6.0",
"@eslint/json": "^0.5.0",
"@types/css-tree": "^2.3.8",
"@types/eslint": "^8.56.10",
"c8": "^9.1.0",
"dedent": "^1.5.3",
Expand Down
6 changes: 3 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { CSSLanguage } from "./languages/css-language.js";
import { CSSSourceCode } from "./languages/css-source-code.js";
import noEmptyBlocks from "./rules/no-empty-blocks.js";
import noDuplicateImports from "./rules/no-duplicate-imports.js";
import noUnknownProperties from "./rules/no-unknown-properties.js";
import noUnknownAtRules from "./rules/no-unknown-at-rules.js";
import noInvalidProperties from "./rules/no-invalid-properties.js";

//-----------------------------------------------------------------------------
// Plugin
Expand All @@ -30,7 +30,7 @@ const plugin = {
"no-empty-blocks": noEmptyBlocks,
"no-duplicate-imports": noDuplicateImports,
"no-unknown-at-rules": noUnknownAtRules,
"no-unknown-properties": noUnknownProperties,
"no-invalid-properties": noInvalidProperties,
},
configs: {},
};
Expand All @@ -42,7 +42,7 @@ Object.assign(plugin.configs, {
"css/no-empty-blocks": "error",
"css/no-duplicate-imports": "error",
"css/no-unknown-at-rules": "error",
"css/no-unknown-properties": "error",
"css/no-invalid-properties": "error",
},
},
});
Expand Down
96 changes: 96 additions & 0 deletions src/rules/no-invalid-properties.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
* @fileoverview Rule to prevent invalid properties in CSS.
* @author Nicholas C. Zakas
*/

//-----------------------------------------------------------------------------
// Imports
//-----------------------------------------------------------------------------

import { lexer } from "css-tree";

//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------

/** @typedef {import("css-tree").SyntaxMatchError} SyntaxMatchError */

//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------

/**
* Determines if an error is a syntax match error.
* @param {Object} error The error object from the CSS parser.
* @returns {error is SyntaxMatchError} True if the error is a syntax match error, false if not.
*/
function isSyntaxMatchError(error) {
return typeof error.css === "string";
}

//-----------------------------------------------------------------------------
// Rule Definition
//-----------------------------------------------------------------------------

export default {
meta: {
type: "problem",

docs: {
description: "Disallow invalid properties.",
recommended: true,
},

messages: {
invalidPropertyValue:
"Invalid value '{{value}}' for property '{{property}}'. Expected {{expected}}.",
unknownProperty: "Unknown property '{{property}}' found.",
},
},

create(context) {
return {
"Rule > Block > Declaration"(node) {
// don't validate custom properties
if (node.property.startsWith("--")) {
return;
}

const { error } = lexer.matchDeclaration(node);

if (error) {
// validation failure
if (isSyntaxMatchError(error)) {
context.report({
loc: error.loc,
messageId: "invalidPropertyValue",
data: {
property: node.property,
value: error.css,
expected: error.syntax,
},
});
return;
}

// unknown property
context.report({
loc: {
start: node.loc.start,
end: {
line: node.loc.start.line,
column:
node.loc.start.column +
node.property.length,
},
},
messageId: "unknownProperty",
data: {
property: node.property,
},
});
}
},
};
},
};
62 changes: 0 additions & 62 deletions src/rules/no-unknown-properties.js

This file was deleted.

Loading