com.squarespace.less.plugins.StringFunctions Maven / Gradle / Ivy
The newest version!
/**
* Copyright (c) 2014 SQUARESPACE, 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.squarespace.less.plugins;
import static com.squarespace.less.core.CharClass.CLASSIFIER;
import static com.squarespace.less.core.ExecuteErrorMaker.formatFunctionArgs;
import java.util.List;
import com.squarespace.less.LessException;
import com.squarespace.less.core.Buffer;
import com.squarespace.less.core.EncodeUtils;
import com.squarespace.less.exec.ExecEnv;
import com.squarespace.less.exec.Function;
import com.squarespace.less.exec.Registry;
import com.squarespace.less.exec.SymbolTable;
import com.squarespace.less.model.Anonymous;
import com.squarespace.less.model.BaseColor;
import com.squarespace.less.model.Node;
import com.squarespace.less.model.Quoted;
import com.squarespace.less.model.RGBColor;
/**
* String function implementations.
*
* http://lesscss.org/functions/#string-functions
*/
public class StringFunctions implements Registry {
@Override
public void registerPlugins(SymbolTable table) {
table.add(E);
table.add(ESCAPE);
table.add(FORMAT);
}
public static final Function E = new Function("e", "s") {
@Override
public Node invoke(ExecEnv env, List args) throws LessException {
Quoted str = (Quoted)args.get(0);
str = new Quoted(str.delimiter(), true, str.parts());
return new Anonymous(env.context().render(str));
}
};
public static final Function ESCAPE = new Function("escape", "s") {
@Override
public Node invoke(ExecEnv env, List args) throws LessException {
String value = asString(env, args.get(0), true);
return new Anonymous(EncodeUtils.escape(value));
}
};
/**
* See http://lesscss.org/#reference "% format" section.
*/
public static final Function FORMAT = new Function("%", "s.") {
@Override
public Node invoke(ExecEnv env, List args) throws LessException {
Quoted orig = (Quoted)args.get(0);
String format = asString(env, orig, true);
Buffer buf = env.context().newBuffer();
int size = format.length();
int i = 0; // character index
int j = 1; // argument index
int formatters = 0;
boolean error = false;
while (i < size) {
char ch = format.charAt(i);
if (ch != '%') {
buf.append(ch);
i++;
continue;
}
i++;
if (i == size) {
buf.append('%');
break;
}
ch = format.charAt(i);
if (ch == '%') {
buf.append('%');
i++;
continue;
}
formatters++;
if (j >= args.size()) {
i++;
error = true;
continue;
}
Node arg = args.get(j);
if (arg instanceof BaseColor) {
// Force representation of this color to always be hex, not keyword.
RGBColor color = ((BaseColor)arg).toRGB().copy();
color.forceHex(true);
arg = color;
}
boolean escape = (ch == 's' || ch == 'S');
String value = asString(env, arg, escape);
if (CLASSIFIER.uppercase(ch)) {
value = EncodeUtils.encodeURIComponent(value);
}
buf.append(value);
i++;
j++;
}
if (error) {
throw new LessException(formatFunctionArgs(formatters, args.size() - 1));
}
Quoted result = new Quoted(orig.delimiter(), orig.escaped());
result.append(new Anonymous(buf.toString()));
return result;
}
};
private static String asString(ExecEnv env, Node node, boolean escape) throws LessException {
if (escape && (node instanceof Quoted)) {
Quoted str = (Quoted)node;
str = str.copy();
str.setEscape(true);
node = str;
}
return env.context().render(node);
}
}