All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.common.css.compiler.passes.StrictCss2 Maven / Gradle / Ivy

Go to download

Closure Stylesheets is an extension to CSS that adds variables, functions, conditionals, and mixins to standard CSS. The tool also supports minification, linting, RTL flipping, and CSS class renaming.

There is a newer version: 1.8.0
Show newest version
/*
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.css.compiler.passes;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.css.compiler.ast.*;
import com.google.common.css.compiler.ast.CssAttributeSelectorNode.MatchType;
import com.google.common.css.compiler.ast.CssCombinatorNode.Combinator;

import java.util.Set;

/**
 * This compiler pass enforces that only correct CSS 2.1 is used.
 * See "http://www.w3.org/TR/CSS21/" for the specification.
 *
 * @author [email protected] (Florian Benz)
 */
public class StrictCss2 extends StrictCssBase {
    private static final ImmutableSet PSEUDO_CLASSES_OR_ELEMENT =
            ImmutableSet.of("first-child", "link", "visited", "active", "hover",
                    "focus", "first-line", "first-letter", "before", "after");
    private static final ImmutableSet
            ALLOWED_COMBINATORS = ImmutableSet.of(Combinator.DESCENDANT,
            Combinator.CHILD, Combinator.ADJACENT_SIBLING);
    private static final ImmutableSet
            ALLOWED_ATTRIBUTE_SELECTORS = ImmutableSet.of(MatchType.ANY,
            MatchType.EXACT, MatchType.EXACT_OR_DASH, MatchType.ONE_WORD);

    /**
     * Units.
     * See Section 4.3.2 of
     * http://www.w3.org/TR/CSS2/syndata.html#value-def-length
     */
    private static final Set UNITS = Sets.newHashSet(
            "",

            // Relative measures
            "em",
            "ex",
            "%",

            // Absolute measures
            "in",
            "cm",
            "mm",
            "pt",
            "pc",
            "px");

    @VisibleForTesting
    static final String UNSUPPORTED_COMBINATOR_ERROR_MESSAGE =
            "An unsupported combinator is used.";
    @VisibleForTesting
    static final String UNSUPPORTED_PESUDO_CLASS_OR_ELEMENT_ERROR_MESSAGE =
            "An unsupported pseudo-class or pseudo-element is used.";
    @VisibleForTesting
    static final String NEW_PESUDO_ELEMENTS_NOT_ALLOWED_ERROR_MESSAGE =
            "Pseudo-elements starting with '::' are not allowed in CSS 2.1.";
    @VisibleForTesting
    static final String FORBIDDEN_ATTRIBUTE_COMPARER_ERROR_MESSAGE =
            "An operator for matching attributes not allowed in CSS 2.1 is used.";

    public StrictCss2(VisitController visitController,
                      ErrorManager errorManager) {
        super(visitController, errorManager);
    }

    /**
     * Idenitifies valid units of 'width', 'height', etc.
     */
    @Override
    Set getValidCssUnits() {
        return UNITS;
    }

    /**
     * Ensures that the combinator '~' (introduced in CSS 3) is not used.
     */
    @Override
    public boolean enterCombinator(CssCombinatorNode combinator) {
        if (!ALLOWED_COMBINATORS.contains(combinator.getCombinatorType())) {
            errorManager.report(new GssError(UNSUPPORTED_COMBINATOR_ERROR_MESSAGE,
                    combinator.getSourceCodeLocation()));
            return false;
        }
        return true;
    }

    /**
     * Ensures that only pseudo-classes valid in CSS 2.1 are used. Especially, the
     * new pseudo-classes introduced in CSS 3 are not valid.
     */
    @Override
    public boolean enterPseudoClass(CssPseudoClassNode node) {
        switch (node.getFunctionType()) {
            case NONE:
                return checkNonFunctionPseudoClass(node);
            case NTH:
            case NOT:
                reportUnsupported(node,
                        UNSUPPORTED_PESUDO_CLASS_OR_ELEMENT_ERROR_MESSAGE,
                        PSEUDO_CLASSES_OR_ELEMENT);
                return false;
        }
        return true;
    }

    /**
     * Ensures that only pseudo-classes and pseudo-elements listed in the
     * specification are used.
     */
    private boolean checkNonFunctionPseudoClass(CssRefinerNode refiner) {
        if (!PSEUDO_CLASSES_OR_ELEMENT.contains(refiner.getRefinerName())) {
            reportUnsupported(refiner,
                    UNSUPPORTED_PESUDO_CLASS_OR_ELEMENT_ERROR_MESSAGE,
                    PSEUDO_CLASSES_OR_ELEMENT);
            return false;
        }
        return true;
    }

    /**
     * Ensures that the new pseudo-element notation (::) is not used, because
     * the notation has been introduced in CSS 3.
     */
    @Override
    public boolean enterPseudoElement(CssPseudoElementNode node) {
        errorManager.report(new GssError(
                NEW_PESUDO_ELEMENTS_NOT_ALLOWED_ERROR_MESSAGE,
                node.getSourceCodeLocation()));
        return false;
    }

    /**
     * Ensures that attribute selectors are valid. If the equal sign is preceded
     * by a special character, only '~' and '|' are allowed.
     * Valid CSS 2.1 examples: {@code [att]}, {@code [att=val]},
     * {@code [att~=val]}, {@code [att|=val]}
     */
    @Override
    public boolean enterAttributeSelector(CssAttributeSelectorNode node) {
        if (!ALLOWED_ATTRIBUTE_SELECTORS.contains(node.getMatchType())) {
            errorManager.report(new GssError(
                    FORBIDDEN_ATTRIBUTE_COMPARER_ERROR_MESSAGE,
                    node.getSourceCodeLocation()));
            return false;
        }
        return true;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy