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

com.google.common.css.compiler.passes.StrictCss3 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: 20160212
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.CssCombinatorNode;
import com.google.common.css.compiler.ast.CssCombinatorNode.Combinator;
import com.google.common.css.compiler.ast.CssPseudoClassNode;
import com.google.common.css.compiler.ast.CssPseudoElementNode;
import com.google.common.css.compiler.ast.CssRefinerNode;
import com.google.common.css.compiler.ast.ErrorManager;
import com.google.common.css.compiler.ast.GssError;
import com.google.common.css.compiler.ast.VisitController;

import java.util.Set;

/**
 * This compiler pass enforces that only correct CSS level 3 is used. Be aware
 * that there is no final specification yet and that the draft is distributed
 * over several documents.
 *
 * 

The official W3C drafts used here: * Selectors Level 3, * CSS3 Basic User Interface Module * *

Wikipedia gives a good overview: * * Comparison of layout engines (Cascading Style Sheets) * *

TODO(fbenz): The ProcessRefiners and ProcessKeyframes passes should * run before. * * @author [email protected] (Florian Benz) * */ public class StrictCss3 extends StrictCssBase { private static final ImmutableSet ALLOWED_COMBINATORS = ImmutableSet.of(Combinator.DESCENDANT, Combinator.CHILD, Combinator.ADJACENT_SIBLING, Combinator.GENERAL_SIBLING); private static final ImmutableSet PSEUDO_CLASSES = ImmutableSet.of( "root", "first-child", "last-child", "first-of-type", "last-of-type", "only-child", "only-of-type", "empty", "link", "visited", "active", "hover", "focus", "target", "enabled", "disabled", "checked", "indeterminate", "default", "valid", "invalid", "in-range", "out-of-range", "required", "optional", "read-only", "read-write"); private static final ImmutableSet PSEUDO_CLASSES_NTH = ImmutableSet.of("nth-child", "nth-last-child", "nth-of-type", "nth-last-of-type"); private static final ImmutableSet PSEUDO_ELEMENTS = ImmutableSet.of( "first-line", "first-letter", "before", "after", "value", "choices", "repeat-item", "repeat-index"); /** * Length units. * See Section 5 of * http://www.w3.org/TR/css3-values/#lengths */ private static final Set UNITS = Sets.newHashSet( "", // Relative measures "em", "ex", "%", "ch", "rem", "vw", "vh", "vm", // Absolute measures "in", "cm", "mm", "pt", "pc", "px", // angles "deg", "grad", "rad", "turn", // time "s", "ms", // frequency "hz", "khz"); @VisibleForTesting static final String UNSUPPORTED_COMBINATOR_ERROR_MESSAGE = "An unsupported combinator is used."; @VisibleForTesting static final String UNSUPPORTED_PESUDO_CLASS_ERROR_MESSAGE = "An unsupported pseudo-class is used."; @VisibleForTesting static final String UNSUPPORTED_PESUDO_CLASS_NTH_ERROR_MESSAGE = "An unsupported pseudo-class for the nth-pattern is used."; @VisibleForTesting static final String UNSUPPORTED_PESUDO_ELEMENT_ERROR_MESSAGE = "An unsupported pseudo-element is used."; @VisibleForTesting static final String MISSING_FUNCTION_PESUDO_CLASS_NTH_ERROR_MESSAGE = "A pseudo-class for the nth-pattern is used without an argument."; public StrictCss3(VisitController visitController, ErrorManager errorManager) { super(visitController, errorManager); } /** * Idenitifies valid units of 'width', 'height', etc. */ @Override Set getValidCssUnits() { return UNITS; } /** * Ensures that the combinator '/deep/' (not strict 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; } @Override public boolean enterPseudoClass(CssPseudoClassNode node) { switch (node.getFunctionType()) { case NONE: return checkNonFunctionPseudoClass(node); case NTH: return checkNthFunctionPseudoClass(node); } return true; } /** * Checks whether the pseudo-class is in the list of standard pseudo-classes * for CSS level 3. Note that this means that pseudo-elements, like * {@code after}, that are normally accepted using the pseudo-class style for * backwards compatibility are rejected. */ private boolean checkNonFunctionPseudoClass(CssRefinerNode refiner) { if (PSEUDO_CLASSES_NTH.contains(refiner.getRefinerName())) { errorManager.report(new GssError( MISSING_FUNCTION_PESUDO_CLASS_NTH_ERROR_MESSAGE, refiner.getSourceCodeLocation())); return false; } if (!PSEUDO_CLASSES.contains(refiner.getRefinerName())) { reportUnsupported(refiner, UNSUPPORTED_PESUDO_CLASS_ERROR_MESSAGE, PSEUDO_CLASSES); return false; } return true; } private boolean checkNthFunctionPseudoClass(CssRefinerNode refiner) { // If name is an nth function pseudo class, then it should be of the form: // "nth-child(". String name = refiner.getRefinerName(); if (!name.endsWith("(") || !PSEUDO_CLASSES_NTH.contains(name.substring(0, name.length() - 1))) { reportUnsupported(refiner, UNSUPPORTED_PESUDO_CLASS_NTH_ERROR_MESSAGE, PSEUDO_CLASSES_NTH); return false; } return true; } /** * Ensures that only pseudo-elements valid in CSS 3 are used. */ @Override public boolean enterPseudoElement(CssPseudoElementNode node) { if (!PSEUDO_ELEMENTS.contains(node.getRefinerName())) { reportUnsupported(node, UNSUPPORTED_PESUDO_ELEMENT_ERROR_MESSAGE, PSEUDO_ELEMENTS); return false; } return true; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy