com.squarespace.less.parse.DirectiveParselet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of less-core Show documentation
Show all versions of less-core Show documentation
Less compiler in Java, based on less.js
/**
* 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.parse;
import static com.squarespace.less.parse.Parselets.BLOCK;
import static com.squarespace.less.parse.Parselets.DIRECTIVE_IMPORT;
import static com.squarespace.less.parse.Parselets.ENTITY;
import static com.squarespace.less.parse.Parselets.EXPRESSION;
import static com.squarespace.less.parse.Parselets.FEATURES;
import org.apache.commons.lang3.StringUtils;
import com.squarespace.less.LessException;
import com.squarespace.less.core.Chars;
import com.squarespace.less.model.Block;
import com.squarespace.less.model.BlockDirective;
import com.squarespace.less.model.Features;
import com.squarespace.less.model.Import;
import com.squarespace.less.model.Media;
import com.squarespace.less.model.Node;
/**
* Main parser for all directives of the form '@' NAME.
*/
public class DirectiveParselet implements Parselet {
@Override
public Node parse(LessStream stm) throws LessException {
Mark mark = stm.mark();
stm.skipWs();
int position = stm.position();
if (stm.peek() != Chars.AT_SIGN || !stm.matchDirective()) {
return null;
}
String name = stm.token();
String nvName = name;
if (name.charAt(1) == Chars.MINUS_SIGN) {
int index = name.indexOf(Chars.MINUS_SIGN, 2);
if (index > 0) {
nvName = "@" + name.substring(index + 1);
}
}
boolean hasBlock = false;
boolean hasExpression = false;
boolean hasIdentifier = false;
switch (nvName) {
case "@import":
case "@import-once":
{
Node result = parseImport(stm, nvName, position);
if (result == null) {
stm.restore(mark);
}
return result;
}
case "@media":
{
Node result = parseMedia(stm);
if (result == null) {
stm.restore(mark);
}
return result;
}
case "@font-face":
case "@viewport":
case "@top-left":
case "@top-left-corner":
case "@top-center":
case "@top-right":
case "@top-right-corner":
case "@bottom-left":
case "@bottom-left-corner":
case "@bottom-center":
case "@bottom-right":
case "@bottom-right-corner":
case "@left-top":
case "@left-middle":
case "@left-bottom":
case "@right-top":
case "@right-middle":
case "@right-bottom":
hasBlock = true;
break;
case "@page":
case "@document":
case "@supports":
case "@keyframes":
hasBlock = true;
hasIdentifier = true;
break;
case "@namespace":
hasExpression = true;
break;
default:
break;
}
if (hasIdentifier) {
name += parseIdentifier(stm);
}
if (hasBlock) {
Node block = stm.parse(BLOCK);
if (block != null) {
BlockDirective directive = stm.context().nodeBuilder().buildBlockDirective(name, (Block)block);
directive.fileName(stm.fileName());
return directive;
}
} else {
Node value = parseRest(stm, hasExpression);
if (value != null) {
return stm.context().nodeBuilder().buildDirective(name, value);
}
}
stm.restore(mark);
return null;
}
private Node parseMedia(LessStream stm) throws LessException {
Features features = (Features) stm.parse(FEATURES);
Node block = stm.parse(BLOCK);
if (block == null) {
return null;
}
Media media = stm.context().nodeBuilder().buildMedia(features, (Block)block);
media.fileName(stm.fileName());
return media;
}
private Node parseImport(LessStream stm, String name, int position) throws LessException {
boolean once = false;
if (name.endsWith("-once")) {
once = true;
}
// TODO: import keywords
Node path = stm.parse(DIRECTIVE_IMPORT);
if (path == null) {
return null;
}
Features features = (Features) stm.parse(FEATURES);
stm.skipWs();
if (stm.seekIf(Chars.SEMICOLON)) {
Import importNode = new Import(path, features, once);
importNode.parseOffset(position);
importNode.rootPath(stm.rootPath());
importNode.fileName(stm.fileName());
return importNode;
}
return null;
}
private String parseIdentifier(LessStream stm) throws LessException {
StringBuilder buf = new StringBuilder();
stm.skipWs();
char ch = stm.peek();
while (ch != Chars.NULL && ch != Chars.LEFT_CURLY_BRACKET && ch != Chars.LEFT_SQUARE_BRACKET) {
buf.append(ch);
stm.seek1();
ch = stm.peek();
}
return " " + StringUtils.strip(buf.toString());
}
private Node parseRest(LessStream stm, boolean hasExpression) throws LessException {
Node value = (hasExpression) ? stm.parse(EXPRESSION) : stm.parse(ENTITY);
stm.skipWs();
if (stm.seekIf(Chars.SEMICOLON)) {
return value;
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy