Skip to content

Conversation

Copy link

Copilot AI commented Dec 22, 2025

The CSS parser performs syntactic parsing but lacks semantic validation, silently accepting typos like colr: red and invalid combinations like color: 10px.

Changes

Core Validation (CSSValidator)

  • Property name validation with Levenshtein distance-based typo suggestions (distance ≤ 2)
  • Value type checking against property requirements (color, length, percentage, etc.)
  • Automatic allowlisting for custom properties (--*), vendor prefixes (-webkit-, -moz-, -ms-, -o-), and global keywords (inherit, initial, unset, revert, revert-layer)

Integration

  • Modified AbstractCSSParser.handleProperty() to invoke validator when enabled
  • Added setSemanticValidationEnabled(boolean) configuration API
  • Validation disabled by default (opt-in for backward compatibility)

Data

  • css-properties.txt resource file with 232 known CSS properties
  • ValidationWarning class with INFO/WARNING/ERROR severity levels

Usage

CSSOMParser parser = new CSSOMParser();
parser.setSemanticValidationEnabled(true);
parser.setErrorHandler(new MyErrorHandler());
parser.parseStyleSheet(inputSource, null);

Parsing .example { colr: red; } now reports:

ERROR: Unknown CSS property 'colr'. Did you mean 'color'?

Test Coverage

  • 14 unit tests for validator logic (property matching, Levenshtein distance, special cases)
  • 8 integration tests with actual CSS parsing scenarios

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • commons.apache.org
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.11/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.11/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.11 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.11/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/htmlunit-cssparser/htmlunit-cssparser org.codehaus.plexus.classworlds.launcher.Launcher clean verify -DskipTests=false (dns block)
  • junit.org
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --enable-native-access=ALL-UNNAMED -classpath /usr/share/apache-maven-3.9.11/boot/plexus-classworlds-2.9.0.jar -Dclassworlds.conf=/usr/share/apache-maven-3.9.11/bin/m2.conf -Dmaven.home=/usr/share/apache-maven-3.9.11 -Dlibrary.jansi.path=/usr/share/apache-maven-3.9.11/lib/jansi-native -Dmaven.multiModuleProjectDirectory=/home/REDACTED/work/htmlunit-cssparser/htmlunit-cssparser org.codehaus.plexus.classworlds.launcher.Launcher clean verify -DskipTests=false (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

Add Semantic Validation to CSS Parser

Problem

The current CSS parser performs syntactic parsing but lacks semantic validation. This means:

  • Unknown CSS properties are accepted without warnings (e.g., colr: red instead of color: red)
  • Invalid property-value combinations pass validation (e.g., color: 10px)
  • Type mismatches are not detected (e.g., width: red)
  • No helpful suggestions when users make typos
  • Browser compatibility issues are not flagged

Current behavior:

.example {
    colr: red;           /* Typo - silently accepted */
    color: 10px;         /* Wrong value type - accepted */
    background: inherit inherit;  /* Duplicate values - accepted */
    widht: 100%;         /* Typo - accepted */
}

All of the above parse successfully without any warnings, leading to CSS that won't work as expected.

Solution

Implement a comprehensive semantic validation layer that validates:

  1. Property names against known CSS properties
  2. Value types match property requirements
  3. Property-value compatibility
  4. Common typos with suggestions
  5. Deprecated properties/values (optional)

Implementation Plan

1. Create CSSValidator Class

package org.htmlunit.cssparser.parser.validator;

import java.util.*;
import org.htmlunit.cssparser.parser.*;

/**
 * Validates CSS properties and values for semantic correctness.
 * Provides suggestions for common mistakes and typos.
 */
public class CSSValidator {
    
    private final Set<String> knownProperties;
    private final Map<String, Set<ValueType>> propertyValueTypes;
    private final boolean strict;
    
    public enum ValueType {
        COLOR,
        LENGTH,
        PERCENTAGE,
        NUMBER,
        INTEGER,
        URL,
        STRING,
        IDENTIFIER,
        TIME,
        ANGLE,
        FREQUENCY,
        RESOLUTION,
        FUNCTION,
        KEYWORD
    }
    
    public CSSValidator() {
        this(false);
    }
    
    public CSSValidator(boolean strict) {
        this.strict = strict;
        this.knownProperties = loadKnownProperties();
        this.propertyValueTypes = loadPropertyValueTypes();
    }
    
    /**
     * Validates a CSS property declaration.
     * 
     * @param property The property name
     * @param value The lexical unit value
     * @param locator The locator for error reporting
     * @throws CSSParseException if validation fails in strict mode
     * @return List of validation warnings (empty if valid)
     */
    public List<ValidationWarning> validateProperty(String property, LexicalUnit value, Locator locator) {
        List<ValidationWarning> warnings = new ArrayList<>();
        
        // Validate property name
        if (!isKnownProperty(property)) {
            String suggestion = findClosestPropertyMatch(property);
            String message = "Unknown CSS property '" + property + "'.";
            if (suggestion != null) {
                message += " Did you mean '" + suggestion + "'?";
            }
            
            ValidationWarning warning = new ValidationWarning(
                message, 
                locator, 
                ValidationWarning.Level.ERROR
            );
            warnings.add(warning);
            
            if (strict) {
                throw new CSSParseException(message, locator);
            }
            return warnings; // Don't validate value if property is unknown
        }
        
        // Validate value type
        if (value != null && !isValidValueForProperty(property, value)) {
            Set<ValueType> expectedTypes = propertyValueTypes.get(property.toLowerCase(Locale.ROOT));
            String message = "Invalid value type for property '" + property + "'. " +
                           "Expected: " + formatExpectedTypes(expectedTypes) +
                           ", got: " + getValueType(value);
            
            ValidationWarning warning = new ValidationWarning(
                message,
                locator,
                ValidationWarning.Level.WARNING
            );
            warnings.add(warning);
        }
        
        // Validate specific property rules
        warnings.addAll(validatePropertySpecificRules(property, value, locator));
        
        return warnings;
    }
    
    /**
     * Checks if a property name is a known CSS property.
     */
    public boolean isKnownProperty(String property) {
        if (property == null) {
            return false;
        }
        
        // Custom properties (CSS variables) are always valid
        if (property.startsWith("--")) {
            return true;
        }
        
        // Vendor prefixes are allowed
        if (property.startsWith("-webkit-") || 
            property.startsWith("-moz-") || 
            property.startsWith("-ms-") || 
            property.startsWith("-o-")) {
            return true;
        }
        
        return knownProperties.contains(property.toLowerCase(Locale.ROOT));...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.

Copilot AI and others added 3 commits December 22, 2025 13:24
…ng classes

Co-authored-by: rbri <2544132+rbri@users.noreply.github.com>
Co-authored-by: rbri <2544132+rbri@users.noreply.github.com>
Co-authored-by: rbri <2544132+rbri@users.noreply.github.com>
Copilot AI changed the title [WIP] Add semantic validation to CSS parser Add semantic validation for CSS property names and value types Dec 22, 2025
Copilot AI requested a review from rbri December 22, 2025 13:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants