Skip to content

Bug: no-invalid-properties displays wrong error msg for invalid color val #40

@adamlui

Description

@adamlui

Environment

ESLint version: v9.17.0
@eslint/css version: v0.2.0
Node version: v22.9.0
npm version: v10.9.1
Operating System: Win10

Which language are you using?

stylesheet

What did you do?

Configuration
import js from '@eslint/js'
import globals from 'globals'
import css from '@eslint/css'
import importPlugin from 'eslint-plugin-import'
import json from '@eslint/json'
import markdown from '@eslint/markdown'
import regexp from 'eslint-plugin-regexp'
import stylisticJS from '@stylistic/eslint-plugin-js'
import yml from 'eslint-plugin-yml'

export default [
    { ignores: ['**/package-lock.json'] },
    {
        files: ['**/*.js', '**/*.mjs'],
        languageOptions: {
            ecmaVersion: 'latest', sourceType: 'script',
            globals: {
                ...globals.browser, ...globals.greasemonkey, ...globals.node, buttons: 'writable', chatgpt: 'readonly',
                chrome: 'readonly', config: 'writable', CryptoJS: 'readonly', dom: 'readonly', GM_cookie: 'readonly',
                hljs: 'readonly', icons: 'writable', ipv4: 'readonly', marked: 'readonly', modals: 'writable',
                renderMathInElement: 'readonly', settings: 'writable', toggles: 'writable'
            }
        },
        plugins: { 'import': importPlugin, 'js-styles': stylisticJS, regexp },
        rules: {
            ...js.configs.recommended.rules,
            ...importPlugin.flatConfigs.recommended.rules,
            ...regexp.configs['flat/recommended'].rules,
            'indent': 'off', 'no-unexpected-multiline': 'off', 'key-spacing': 'off', // allow whitespace anywhere
            'js-styles/no-trailing-spaces': 'error', // ...except at ends of lines
            'js-styles/max-len': ['error', { 'code': 120, // limit lines to 120 chars except if containing...
                'ignoreComments': true, 'ignoreStrings': true, // ...trailing/own-line comments, quoted strings...
                'ignoreTemplateLiterals': true, 'ignoreRegExpLiterals': true }], // ...or template/regex literals
            'js-styles/no-extra-semi': 'error', // disallow unnecessary semicolons
            'quotes': ['error', 'single', { 'allowTemplateLiterals': true }], // enforce single quotes except backticks to avoid escaping quotes
            'comma-dangle': ['error', 'never'], // enforce no trailing commas in arrays or objects
            'no-async-promise-executor': 'off', // allow promise executor functions to be async (to accomodate await lines)
            'no-constant-condition': 'off', // allow constant conditions
            'no-empty': 'off', // allow empty blocks
            'no-inner-declarations': 'off', // allow function declarations anywhere
            'no-useless-escape': 'off', // allow all escape chars cause ESLint sucks at detecting truly useless ones
            'no-unused-vars': ['error', { 'caughtErrors': 'none' }] // allow unused named args in catch blocks
        }
    },
    { files: ['**/chatgpt.js'], languageOptions: { globals: { chatgpt: 'off' }}},
    { files: ['**/*.css'], language: 'css/css', ...css.configs.recommended },
    { files: ['**/*.json'], language: 'json/json', ...json.configs.recommended },
    {
        files: ['**/*.md'], language: 'markdown/commonmark', plugins: { markdown },
        rules: {
            ...markdown.configs.recommended[0].rules,
            'markdown/heading-increment': 'off', // allow headings to skip levels
            'markdown/fenced-code-language': 'off', // allow code blocks w/ no language specified
            'markdown/no-missing-label-refs': 'off' // allow missing label references
        }
    },
    { files: ['**/*.mjs'], languageOptions: { sourceType: 'module' }},
    { files: ['**/*.yaml, **/*.yml'], ...yml.configs['flat/standard'][1] }
]
/* General size */
html { height: fit-content ; min-height: 50px }
body { width: max-content ; margin: 0 ; overflow: clip }

/* General font */
body, button, input, select, textarea {
    font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto,
        "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", sans-serif ;
    font-size: .905rem ; user-select: none
}
a { color: #999 ; text-decoration: none }
a:focus, a:hover { text-decoration: underline ; color: inherit }

/* Loader */
.loading-bg {
    background-color: white ; width: 100% ; height: 100% ; position: absolute ; z-index: 1111 ;
    display: inline-grid ; align-content: center ; justify-content: center /* center spinner */
}
.loading-spinner {
    width: 11px ; aspect-ratio: 1 ; border-radius: 50% ; border: 5px solid #000 ;
    animation: loader-move-head-tail 0.8s infinite linear alternate, loader-rotate 1.6s infinite linear
}
@keyframes loader-move-head-tail {
     0% { clip-path: polygon(50% 50%, 0 0, 50% 0, 50% 0, 50% 0, 50% 0, 50% 0) }
     12.5% { clip-path: polygon(50% 50%, 0 0, 50% 0, 100% 0, 100% 0, 100% 0, 100% 0) }
     25% { clip-path: polygon(50% 50%, 0 0, 50% 0, 100% 0, 100% 100%, 100% 100%, 100% 100%) }
     50% { clip-path: polygon(50% 50%, 0 0, 50% 0, 100% 0, 100% 100%, 50% 100%, 0 100%) }
     62.5% { clip-path: polygon(50% 50%, 100% 0, 100% 0%, 100% 0, 100% 100%, 50% 100%, 0 100%) }
     75% { clip-path: polygon(50% 50%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 50% 100%, 0 100%) }
     100% { clip-path: polygon(50% 50%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 0 100%) }
}
@keyframes loader-rotate { 
    0% { transform: scaleY(1) rotate(0deg) } 49.99% { transform: scaleY(1) rotate(135deg) }
    50% { transform: scaleY(-1) rotate(0deg) } 100% { transform: scaleY(-1) rotate(-135deg) }
}  

/* Header */
.menu-header {
    border-bottom: solid 1px lightgrey ; padding: 5px 5px 5px 0; margin: 0 ;
    display: flex; background: white ; align-items: center }
.logo { margin: 4px 8px 4px 12px ; position: relative ; top: 3px }
.menu-title { font-size: 0.85rem ; font-weight: 600 ; padding-right: 3px }
.menu-icons > .toggle-switch { transform: scale(1.1) } /* make master toggle bigger */
.main-toggle { margin-left: auto ; display: flex }

/* Menu item elements */
.menu-item {    
    position: relative ; align-items: center ; border-bottom: 1px solid lightgrey ;
    display: flex ; min-height: 2rem ; padding-right: 14px ; white-space: nowrap ; font-size: 91%
}
.menu-icon { padding: 8px }
.menu-area:focus, .menu-area:hover { /* add hover color/cursor */
    color: var(--bg) ; background: rgb(100, 149, 237) ; cursor: pointer }
.menu-item:hover span:not(.slider) { filter: invert(1) } /* invert setting labels on hover */
.menu-item > label > .slider { transform: scale(0.95) ; top: 1px } /* make child toggles smaller */
.menu-prompt { margin-left: 2px } /* align non-toggle items */

/* Toggle elements */
.toggle-switch input[type="checkbox"] { display: none } /* hide checkbox from toggles */
.toggle-switch .slider { /* style sliders */
    background-color: white;  display: block; border: 1px solid black; border-radius: 7px ; 
    position: relative ; top: 0.05rem ; height: 10px ; width: 18px ; cursor: pointer ;
}
.toggle-switch .slider::before { /* style slider knobs */
    position: absolute ; height: 0.625rem ; width: 0.625rem ; left: -0.04rem ; top: -0.05rem ;
    border: 1px solid black ; border-radius: 50% ; background-color: white ; content: ""
}
.toggle-switch input[type="checkbox"]:checked + .slider { background-color: black } /* color active slider */
.toggle-switch input[type="checkbox"]:checked + .slider::before { transform: translateX(9px) } /* toggle knob right */

/* Footer */
footer { font-size: 12px ; text-align: center ; color: #999 ; background: #f5f5f5 ; height: 40px ; line-height: 40px }
footer > .menu-icon { position: absolute ; bottom: -10px ; opacity: 0.7 }
.chatgpt-js { position: absolute ; bottom: -.25rem ; left: 0.7rem ; cursor: pointer }

/* Master toggle effects */
.disabled { opacity: 0.3 ; pointer-events: none }
.enabled { opacity: 1 }

Here:

.menu-area:focus, .menu-area:hover { /* add hover color/cursor */
    color: var(--bg) ; background: rgb(100, 149, 237) ; cursor: pointer }

ESLint warns Unknown property 'color' found css/no-invalid-properties @ https://github.com/adamlui/ai-web-extensions/actions/runs/12736621825/job/35496732116 for file https://github.com/adamlui/ai-web-extensions/blob/d2e6e6e0a00ceca3ade63b0c8a6de36c9314f489/chatgpt-auto-continue/chromium/extension/popup/style.css

...but it is a valid prop and val:
https://developer.mozilla.org/en-US/docs/Web/CSS/color
https://developer.mozilla.org/en-US/docs/Web/CSS/var

What did you expect to happen?

No error

What actually happened?

Error

Link to Minimal Reproducible Example

https://github.com/adamlui/ai-web-extensions/actions/runs/12736621825/job/35496732116

Participation

  • I am willing to submit a pull request for this issue.

Additional comments

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    Complete

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions