com.google.common.css.compiler.ast.CssFunctionNode Maven / Gradle / Ivy
Show all versions of closure-stylesheets Show documentation
/*
* Copyright 2008 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.ast;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.css.SourceCodeLocation;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
/**
* A node representing a function.
*
* @author [email protected] (Oana Florescu)
*/
public class CssFunctionNode extends CssValueNode implements ChunkAware {
/**
* Contains the list of recognized CSS functions.
*/
public abstract static class Function {
/**
* A map of function names to function objects.
*/
private static final Map NAME_TO_FUNCTION_MAP;
static {
List recognizedCssFunctions = ImmutableList.of(
// CSS 2.1
"attr",
"counter",
"rect",
"rgb",
"url",
// Per-site user stylesheet rules
// http://lists.w3.org/Archives/Public/www-style/2004Aug/0135
"domain",
"url-prefix",
// IE8 and earlier:
// .fiftyPercentOpacity { filter: alpha(opacity=50); }
"alpha",
// CSS 3
"cubic-bezier",
"format", // used with @font-face
"from",
"hsl",
"hsla",
"local", // used with @font-face
"matrix",
"matrix3d",
"perspective",
"rgba",
"rotate",
"rotateX",
"rotateY",
"rotateZ",
"rotate3d",
"scale",
"scaleX",
"scaleY",
"scaleZ",
"scale3d",
"skew",
"skewX",
"skewY",
"steps",
"to",
"translate",
"translateX",
"translateY",
"translateZ",
"translate3d",
// CSS 3+ mathematical expressions
// https://drafts.csswg.org/css-values/#calc-notation
"min",
"max",
// Filter
// w3.org/TR/filter-effects-1/#FilterProperty
// "url" already in list
"blur",
"brightness",
"contrast",
"drop-shadow",
"grayscale",
"hue-rotate",
"invert",
"opacity",
"saturate",
"sepia",
// Image-Set
"image-set",
"-moz-image-set",
"-ms-image-set",
"-o-image-set",
"-webkit-image-set",
// These take the type of gradient (linear or radial) as a parameter.
"-khtml-gradient",
"-webkit-gradient", // Prefer -webkit-(linear|radial)-gradient
// Linear gradients
"linear-gradient",
"-moz-linear-gradient",
"-ms-linear-gradient",
"-o-linear-gradient",
"-webkit-linear-gradient",
"repeating-linear-gradient",
"-moz-repeating-linear-gradient",
"-ms-repeating-linear-gradient",
"-o-repeating-linear-gradient",
"-webkit-repeating-linear-gradient",
// Radial gradients
"radial-gradient",
"-moz-radial-gradient",
"-ms-radial-gradient",
"-o-radial-gradient",
"-webkit-radial-gradient",
"repeating-radial-gradient",
"-moz-repeating-radial-gradient",
"-ms-repeating-radial-gradient",
"-o-repeating-radial-gradient",
"-webkit-repeating-radial-gradient",
// Calc
"calc",
"-webkit-calc",
"-moz-calc",
// CSS Shapes
"inset",
"circle",
"ellipse",
"polygon",
// Custom properties
"var"
);
ImmutableMap.Builder builder = ImmutableMap.builder();
for (String functionName : recognizedCssFunctions) {
builder.put(
functionName,
new Function(functionName) {
@Override
public boolean isRecognized() {
return true;
}
});
}
NAME_TO_FUNCTION_MAP = builder.build();
}
/**
* Serves as a placeholder for custom functions.
*/
public static final Function CUSTOM =
new Function(null /* functionName */) {
@Override
public boolean isRecognized() {
return false;
}
};
/**
* The name of the function, as it appears in a CSS stylesheet.
*/
private final String functionName;
private Function(String functionName) {
this.functionName = functionName;
}
/**
* Returns the CSS {@link Function} with the specified name, or {@code null}
* if the name is not in the list of recognized names. Multiple invocations
* of this method with the same parameter will return the same object. For a
* function that is not in the list of recognized names but should be
* considered valid, use {@link Function#CUSTOM}.
*
* @param name name
*/
public static Function byName(String name) {
return NAME_TO_FUNCTION_MAP.get(name);
}
/**
* Returns {@code true} when this function is in the list of
* recognized names.
*/
public abstract boolean isRecognized();
/**
* @return the name of the CSS function, such as "rgb" or "url"
*/
public String getFunctionName() {
return functionName;
}
/**
* For debugging only.
*/
@Override
public String toString() {
return getFunctionName();
}
}
private final Function function;
private CssFunctionArgumentsNode arguments;
private Object chunk;
/**
* Constructor of the class.
*
* TODO(oana): Deal with the situation that we have an unrecognized
* function.
*
* @param function function
* @param sourceCodeLocation sourceCodeLocation
*/
public CssFunctionNode(@Nullable Function function,
@Nullable SourceCodeLocation sourceCodeLocation) {
super(null, sourceCodeLocation);
this.function = function;
this.arguments = new CssFunctionArgumentsNode();
becomeParentForNode(this.arguments);
}
/**
* Copy constructor.
*
* @param function function
*/
public CssFunctionNode(CssFunctionNode function) {
super(function);
this.function = function.getFunction();
this.arguments = new CssFunctionArgumentsNode(function.getArguments());
becomeParentForNode(this.arguments);
this.chunk = function.getChunk();
}
/**
* Constructor used by the proxy mechanism, avoids unnecessary arguments node
* initialization.
*
*
NOTE(dgajda): The signature of this constructor only differs in argument
* order from the main constructor of this class.
*
* @param function implementation of the function which is "called" by this
* node
* @param sourceCodeLocation location of this node
*/
protected CssFunctionNode(@Nullable SourceCodeLocation sourceCodeLocation,
@Nullable Function function) {
super(null, sourceCodeLocation);
this.function = function;
}
@Override
public CssFunctionNode deepCopy() {
return new CssFunctionNode(this);
}
public Function getFunction() {
return function;
}
public String getFunctionName() {
return function.toString();
}
public CssFunctionArgumentsNode getArguments() {
return arguments;
}
public void setArguments(CssFunctionArgumentsNode arguments) {
removeAsParentOfNode(this.arguments);
this.arguments = arguments;
becomeParentForNode(this.arguments);
}
@Override
public String toString() {
StringBuilder output = new StringBuilder();
if (function.getFunctionName() != null) {
output.append(function.getFunctionName());
}
output.append("(");
for (CssNode node : getArguments().childIterable()) {
output.append(node.toString());
}
output.append(")");
return output.toString();
}
@Override
public Object getChunk() {
return chunk;
}
@Override
public void setChunk(Object chunk) {
this.chunk = chunk;
}
/**
* Print the node instead of null when this node is a parameter.
*/
@Override
public String getValue() {
return toString();
}
}