@@ -0,0 +1,39 @@ | |||
package com.vaadin.sass; | |||
import java.io.File; | |||
import java.io.FileWriter; | |||
import java.io.IOException; | |||
public class SassCompiler { | |||
public static void main(String[] args) throws Exception { | |||
String input = null; | |||
String output = null; | |||
if (args.length == 0) { | |||
System.out | |||
.println("usage: SassCompile <scss file to compile> <css file to write>"); | |||
return; | |||
} else if (args.length == 1) { | |||
input = args[0]; | |||
} else { | |||
input = args[0]; | |||
output = args[1]; | |||
} | |||
File inputFile = new File(input); | |||
ScssStylesheet scss = ScssStylesheet.get(inputFile); | |||
scss.compile(); | |||
if (output == null) { | |||
System.out.println(scss.toString()); | |||
} else { | |||
writeFile(output, scss.toString()); | |||
} | |||
} | |||
public static void writeFile(String filename, String output) | |||
throws IOException { | |||
File file = new File(filename); | |||
FileWriter writer = new FileWriter(file); | |||
writer.write(output); | |||
writer.close(); | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
package com.vaadin.sass; | |||
import java.io.BufferedOutputStream; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.io.OutputStreamWriter; | |||
import javax.servlet.ServletException; | |||
import javax.servlet.http.HttpServlet; | |||
import javax.servlet.http.HttpServletRequest; | |||
import javax.servlet.http.HttpServletResponse; | |||
public class ScssServlet extends HttpServlet { | |||
@Override | |||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) | |||
throws ServletException, IOException { | |||
String cssPath = req.getRequestURI(); | |||
if (cssPath.endsWith(".css")) { | |||
File cssFile = new File(cssPath); | |||
if (cssFile.exists()) { | |||
} else { | |||
String scssPath = cssPath.replace(".css", ".scss"); | |||
File scssFile = new File(scssPath); | |||
if (scssFile.exists()) { | |||
ScssStylesheet scss = ScssStylesheet.get(new File(cssPath)); | |||
try { | |||
scss.compile(); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
resp.setContentType("text/css"); | |||
OutputStream fout = resp.getOutputStream(); | |||
OutputStream bos = new BufferedOutputStream(fout); | |||
OutputStreamWriter outputwriter = new OutputStreamWriter( | |||
bos); | |||
outputwriter.write(scss.toString()); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,102 @@ | |||
package com.vaadin.sass; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.w3c.css.sac.CSSException; | |||
import com.vaadin.sass.handler.SCSSDocumentHandler; | |||
import com.vaadin.sass.handler.SCSSDocumentHandlerImpl; | |||
import com.vaadin.sass.parser.Parser; | |||
import com.vaadin.sass.tree.Node; | |||
import com.vaadin.sass.visitor.BlockVisitor; | |||
import com.vaadin.sass.visitor.ExtendVisitor; | |||
import com.vaadin.sass.visitor.ImportVisitor; | |||
import com.vaadin.sass.visitor.MixinVisitor; | |||
import com.vaadin.sass.visitor.NestPropertiesVisitor; | |||
import com.vaadin.sass.visitor.ParentSelectorVisitor; | |||
import com.vaadin.sass.visitor.VariableVisitor; | |||
import com.vaadin.sass.visitor.Visitor; | |||
public class ScssStylesheet extends Node { | |||
private static final long serialVersionUID = 3849790204404961608L; | |||
/** | |||
* Read in a file SCSS and parse it into a ScssStylesheet | |||
* | |||
* @param file | |||
* @throws IOException | |||
*/ | |||
public ScssStylesheet() { | |||
super(); | |||
} | |||
/** | |||
* Main entry point for the SASS compiler. Takes in a file and builds upp a | |||
* ScssStylesheet tree out of it. Calling compile() on it will transform | |||
* SASS into CSS. Calling toString() will print out the SCSS/CSS. | |||
* | |||
* @param file | |||
* @return | |||
* @throws CSSException | |||
* @throws IOException | |||
*/ | |||
public static ScssStylesheet get(File file) throws CSSException, | |||
IOException { | |||
Parser parser = new Parser(); | |||
SCSSDocumentHandler handler = new SCSSDocumentHandlerImpl(); | |||
file = file.getCanonicalFile(); | |||
handler.getStyleSheet().setFileName(file.getAbsoluteFile().getParent()); | |||
parser.setDocumentHandler(handler); | |||
parser.parseStyleSheet(file.getAbsolutePath()); | |||
return handler.getStyleSheet(); | |||
} | |||
/** | |||
* Applies all the visitors and compiles SCSS into Css. | |||
* | |||
* @throws Exception | |||
*/ | |||
public void compile() throws Exception { | |||
List<Visitor> visitors = new ArrayList<Visitor>(); | |||
visitors.add(new ImportVisitor()); | |||
visitors.add(new MixinVisitor()); | |||
visitors.add(new VariableVisitor()); | |||
visitors.add(new ParentSelectorVisitor()); | |||
visitors.add(new BlockVisitor()); | |||
visitors.add(new NestPropertiesVisitor()); | |||
visitors.add(new ExtendVisitor()); | |||
for (Visitor visitor : visitors) { | |||
visitor.traverse(this); | |||
} | |||
} | |||
/** | |||
* Prints out the current state of the node tree. Will return SCSS before | |||
* compile and CSS after. | |||
* | |||
* For now this is an own method with it's own implementation that most node | |||
* types will implement themselves. | |||
*/ | |||
@Override | |||
public String toString() { | |||
StringBuilder string = new StringBuilder(""); | |||
if (children.size() > 0) { | |||
string.append(children.get(0).toString()); | |||
} | |||
String delimeter = "\n\n"; | |||
if (children.size() > 1) { | |||
for (int i = 1; i < children.size(); i++) { | |||
String childString = children.get(i).toString(); | |||
if (childString != null) { | |||
string.append(delimeter).append(childString); | |||
} | |||
} | |||
} | |||
String output = string.toString(); | |||
return output; | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
package com.vaadin.sass.handler; | |||
import java.util.Collection; | |||
import org.w3c.css.sac.DocumentHandler; | |||
import org.w3c.css.sac.LexicalUnit; | |||
import org.w3c.css.sac.SACMediaList; | |||
import org.w3c.css.sac.SelectorList; | |||
import com.vaadin.sass.ScssStylesheet; | |||
import com.vaadin.sass.tree.EachNode; | |||
import com.vaadin.sass.tree.ForNode; | |||
import com.vaadin.sass.tree.IfNode; | |||
import com.vaadin.sass.tree.MixinDefNode; | |||
import com.vaadin.sass.tree.VariableNode; | |||
import com.vaadin.sass.tree.WhileNode; | |||
public interface SCSSDocumentHandler extends DocumentHandler { | |||
ScssStylesheet getStyleSheet(); | |||
void variable(String name, LexicalUnit value, boolean guarded); | |||
void startMixinDirective(String name, Collection<VariableNode> args); | |||
void endMixinDirective(String name, Collection<VariableNode> args); | |||
MixinDefNode mixinDirective(String name, String args, String body); | |||
void debugDirective(); | |||
ForNode forDirective(String var, String from, String to, boolean exclusive, | |||
String body); | |||
EachNode eachDirective(String var, String list, String body); | |||
WhileNode whileDirective(String condition, String body); | |||
IfNode ifDirective(); | |||
void extendDirective(SelectorList list); | |||
void startNestedProperties(String name); | |||
void endNestedProperties(String name); | |||
void includeDirective(String name, Collection<LexicalUnit> args); | |||
void importStyle(String uri, SACMediaList media, boolean isURL); | |||
void property(String name, LexicalUnit value, boolean important, | |||
String comment); | |||
} |
@@ -0,0 +1,251 @@ | |||
package com.vaadin.sass.handler; | |||
import java.util.Collection; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import java.util.Stack; | |||
import org.w3c.css.sac.CSSException; | |||
import org.w3c.css.sac.InputSource; | |||
import org.w3c.css.sac.LexicalUnit; | |||
import org.w3c.css.sac.SACMediaList; | |||
import org.w3c.css.sac.SelectorList; | |||
import com.vaadin.sass.ScssStylesheet; | |||
import com.vaadin.sass.tree.BlockNode; | |||
import com.vaadin.sass.tree.EachNode; | |||
import com.vaadin.sass.tree.ExtendNode; | |||
import com.vaadin.sass.tree.ForNode; | |||
import com.vaadin.sass.tree.IfNode; | |||
import com.vaadin.sass.tree.ImportNode; | |||
import com.vaadin.sass.tree.MediaNode; | |||
import com.vaadin.sass.tree.MixinDefNode; | |||
import com.vaadin.sass.tree.MixinNode; | |||
import com.vaadin.sass.tree.NestPropertiesNode; | |||
import com.vaadin.sass.tree.Node; | |||
import com.vaadin.sass.tree.RuleNode; | |||
import com.vaadin.sass.tree.VariableNode; | |||
import com.vaadin.sass.tree.WhileNode; | |||
public class SCSSDocumentHandlerImpl implements SCSSDocumentHandler { | |||
private final ScssStylesheet styleSheet; | |||
Stack<Node> nodeStack = new Stack<Node>(); | |||
private Map<String, Stack<LexicalUnit>> variableMap; | |||
public SCSSDocumentHandlerImpl() { | |||
this(new ScssStylesheet()); | |||
variableMap = new HashMap<String, Stack<LexicalUnit>>(); | |||
} | |||
public SCSSDocumentHandlerImpl(ScssStylesheet styleSheet) { | |||
this.styleSheet = styleSheet; | |||
nodeStack.push(styleSheet); | |||
} | |||
public void addVariable(String varName, LexicalUnit value) { | |||
if (variableMap.get(varName) == null) { | |||
variableMap.put(varName, new Stack<LexicalUnit>()); | |||
} | |||
Stack<LexicalUnit> valueStack = variableMap.get(varName); | |||
valueStack.push(value); | |||
} | |||
public void removeVaraible(String varName) { | |||
Stack<LexicalUnit> valueStack = variableMap.get(varName); | |||
if (valueStack != null && !valueStack.isEmpty()) { | |||
valueStack.pop(); | |||
} | |||
} | |||
public LexicalUnit getVariable(String varName) { | |||
Stack<LexicalUnit> valueStack = variableMap.get(varName); | |||
if (valueStack != null && !valueStack.isEmpty()) { | |||
return valueStack.peek(); | |||
} | |||
return null; | |||
} | |||
@Override | |||
public ScssStylesheet getStyleSheet() { | |||
return styleSheet; | |||
} | |||
@Override | |||
public void startDocument(InputSource source) throws CSSException { | |||
nodeStack.push(styleSheet); | |||
// System.out.println("startDocument(InputSource source): " | |||
// + source.getURI()); | |||
} | |||
@Override | |||
public void endDocument(InputSource source) throws CSSException { | |||
// System.out.println("endDocument(InputSource source): " | |||
// + source.getURI()); | |||
} | |||
@Override | |||
public void variable(String name, LexicalUnit value, boolean guarded) { | |||
VariableNode node = new VariableNode(name, value, guarded); | |||
nodeStack.peek().appendChild(node); | |||
} | |||
@Override | |||
public void debugDirective() { | |||
} | |||
@Override | |||
public ForNode forDirective(String var, String from, String to, | |||
boolean exclusive, String body) { | |||
ForNode node = new ForNode(var, from, to, exclusive, body); | |||
System.out.println(node); | |||
return node; | |||
} | |||
@Override | |||
public EachNode eachDirective(String var, String list, String body) { | |||
EachNode node = new EachNode(var, list, body); | |||
System.out.println(node); | |||
return node; | |||
} | |||
@Override | |||
public WhileNode whileDirective(String condition, String body) { | |||
WhileNode node = new WhileNode(condition, body); | |||
System.out.println(node); | |||
return node; | |||
} | |||
@Override | |||
public IfNode ifDirective() { | |||
return new IfNode(); | |||
} | |||
@Override | |||
public void comment(String text) throws CSSException { | |||
System.out.println("comment(String text): " + text); | |||
} | |||
@Override | |||
public void ignorableAtRule(String atRule) throws CSSException { | |||
System.out.println("ignorableAtRule(String atRule): " + atRule); | |||
} | |||
@Override | |||
public void namespaceDeclaration(String prefix, String uri) | |||
throws CSSException { | |||
System.out.println("namespaceDeclaration(String prefix, String uri): " | |||
+ prefix + ", " + uri); | |||
} | |||
@Override | |||
public void importStyle(String uri, SACMediaList media, | |||
String defaultNamespaceURI) throws CSSException { | |||
} | |||
@Override | |||
public void startMedia(SACMediaList media) throws CSSException { | |||
MediaNode node = new MediaNode(media); | |||
nodeStack.peek().appendChild(node); | |||
nodeStack.push(node); | |||
} | |||
@Override | |||
public void endMedia(SACMediaList media) throws CSSException { | |||
nodeStack.pop(); | |||
} | |||
@Override | |||
public void startPage(String name, String pseudo_page) throws CSSException { | |||
System.out.println("startPage(String name, String pseudo_page): " | |||
+ name + ", " + pseudo_page); | |||
} | |||
@Override | |||
public void endPage(String name, String pseudo_page) throws CSSException { | |||
System.out.println("endPage(String name, String pseudo_page): " + name | |||
+ ", " + pseudo_page); | |||
} | |||
@Override | |||
public void startFontFace() throws CSSException { | |||
System.out.println("startFontFace()"); | |||
} | |||
@Override | |||
public void endFontFace() throws CSSException { | |||
System.out.println("endFontFace()"); | |||
} | |||
@Override | |||
public void startSelector(SelectorList selectors) throws CSSException { | |||
BlockNode node = new BlockNode(selectors); | |||
nodeStack.peek().appendChild(node); | |||
nodeStack.push(node); | |||
} | |||
@Override | |||
public void endSelector(SelectorList selectors) throws CSSException { | |||
nodeStack.pop(); | |||
} | |||
@Override | |||
public void property(String name, LexicalUnit value, boolean important) | |||
throws CSSException { | |||
property(name, value, important, null); | |||
} | |||
public void property(String name, LexicalUnit value, boolean important, | |||
String comment) { | |||
RuleNode node = new RuleNode(name, value, important, comment); | |||
nodeStack.peek().appendChild(node); | |||
} | |||
@Override | |||
public void extendDirective(SelectorList list) { | |||
ExtendNode node = new ExtendNode(list); | |||
nodeStack.peek().appendChild(node); | |||
} | |||
@Override | |||
public MixinDefNode mixinDirective(String name, String args, String body) { | |||
MixinDefNode node = new MixinDefNode(name, args, body); | |||
return node; | |||
} | |||
@Override | |||
public void startNestedProperties(String name) { | |||
NestPropertiesNode node = new NestPropertiesNode(name); | |||
nodeStack.peek().appendChild(node); | |||
nodeStack.push(node); | |||
} | |||
@Override | |||
public void endNestedProperties(String name) { | |||
nodeStack.pop(); | |||
} | |||
@Override | |||
public void startMixinDirective(String name, Collection<VariableNode> args) { | |||
MixinDefNode node = new MixinDefNode(name, args); | |||
nodeStack.peek().appendChild(node); | |||
nodeStack.push(node); | |||
} | |||
@Override | |||
public void endMixinDirective(String name, Collection<VariableNode> args) { | |||
nodeStack.pop(); | |||
} | |||
@Override | |||
public void includeDirective(String name, Collection<LexicalUnit> args) { | |||
MixinNode node = new MixinNode(name, args); | |||
nodeStack.peek().appendChild(node); | |||
} | |||
@Override | |||
public void importStyle(String uri, SACMediaList media, boolean isURL) { | |||
ImportNode node = new ImportNode(uri, media, isURL); | |||
nodeStack.peek().appendChild(node); | |||
} | |||
} |
@@ -0,0 +1,115 @@ | |||
/* Generated By:JavaCC: Do not edit this line. CharStream.java Version 5.0 */ | |||
/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ | |||
package com.vaadin.sass.parser; | |||
/** | |||
* This interface describes a character stream that maintains line and | |||
* column number positions of the characters. It also has the capability | |||
* to backup the stream to some extent. An implementation of this | |||
* interface is used in the TokenManager implementation generated by | |||
* JavaCCParser. | |||
* | |||
* All the methods except backup can be implemented in any fashion. backup | |||
* needs to be implemented correctly for the correct operation of the lexer. | |||
* Rest of the methods are all used to get information like line number, | |||
* column number and the String that constitutes a token and are not used | |||
* by the lexer. Hence their implementation won't affect the generated lexer's | |||
* operation. | |||
*/ | |||
public | |||
interface CharStream { | |||
/** | |||
* Returns the next character from the selected input. The method | |||
* of selecting the input is the responsibility of the class | |||
* implementing this interface. Can throw any java.io.IOException. | |||
*/ | |||
char readChar() throws java.io.IOException; | |||
@Deprecated | |||
/** | |||
* Returns the column position of the character last read. | |||
* @deprecated | |||
* @see #getEndColumn | |||
*/ | |||
int getColumn(); | |||
@Deprecated | |||
/** | |||
* Returns the line number of the character last read. | |||
* @deprecated | |||
* @see #getEndLine | |||
*/ | |||
int getLine(); | |||
/** | |||
* Returns the column number of the last character for current token (being | |||
* matched after the last call to BeginTOken). | |||
*/ | |||
int getEndColumn(); | |||
/** | |||
* Returns the line number of the last character for current token (being | |||
* matched after the last call to BeginTOken). | |||
*/ | |||
int getEndLine(); | |||
/** | |||
* Returns the column number of the first character for current token (being | |||
* matched after the last call to BeginTOken). | |||
*/ | |||
int getBeginColumn(); | |||
/** | |||
* Returns the line number of the first character for current token (being | |||
* matched after the last call to BeginTOken). | |||
*/ | |||
int getBeginLine(); | |||
/** | |||
* Backs up the input stream by amount steps. Lexer calls this method if it | |||
* had already read some characters, but could not use them to match a | |||
* (longer) token. So, they will be used again as the prefix of the next | |||
* token and it is the implemetation's responsibility to do this right. | |||
*/ | |||
void backup(int amount); | |||
/** | |||
* Returns the next character that marks the beginning of the next token. | |||
* All characters must remain in the buffer between two successive calls | |||
* to this method to implement backup correctly. | |||
*/ | |||
char BeginToken() throws java.io.IOException; | |||
/** | |||
* Returns a string made up of characters from the marked token beginning | |||
* to the current buffer position. Implementations have the choice of returning | |||
* anything that they want to. For example, for efficiency, one might decide | |||
* to just return null, which is a valid implementation. | |||
*/ | |||
String GetImage(); | |||
/** | |||
* Returns an array of characters that make up the suffix of length 'len' for | |||
* the currently matched token. This is used to build up the matched string | |||
* for use in actions in the case of MORE. A simple and inefficient | |||
* implementation of this is as follows : | |||
* | |||
* { | |||
* String t = GetImage(); | |||
* return t.substring(t.length() - len, t.length()).toCharArray(); | |||
* } | |||
*/ | |||
char[] GetSuffix(int len); | |||
/** | |||
* The lexer calls this function to indicate that it is done with the stream | |||
* and hence implementations can free any resources held by this class. | |||
* Again, the body of this function can be just empty and it will not | |||
* affect the lexer's operation. | |||
*/ | |||
void Done(); | |||
} | |||
/* JavaCC - OriginalChecksum=28e31651bf0ffe57018eaaa3310c55ac (do not edit this line) */ |
@@ -0,0 +1,355 @@ | |||
/* Generated By:JavaCC: Do not edit this line. Generic_CharStream.java Version 0.7pre6 */ | |||
package com.vaadin.sass.parser; | |||
/** | |||
* An implementation of interface CharStream, where the stream is assumed to | |||
* contain only ASCII characters (without unicode processing). | |||
*/ | |||
public final class Generic_CharStream implements CharStream | |||
{ | |||
public static final boolean staticFlag = false; | |||
int bufsize; | |||
int available; | |||
int tokenBegin; | |||
public int bufpos = -1; | |||
private int bufline[]; | |||
private int bufcolumn[]; | |||
private int column = 0; | |||
private int line = 1; | |||
private boolean prevCharIsCR = false; | |||
private boolean prevCharIsLF = false; | |||
private java.io.Reader reader; | |||
private char[] buffer; | |||
private int maxNextCharInd = 0; | |||
private int inBuf = 0; | |||
private final void ExpandBuff(boolean wrapAround) | |||
{ | |||
char[] newbuffer = new char[bufsize + 2048]; | |||
int newbufline[] = new int[bufsize + 2048]; | |||
int newbufcolumn[] = new int[bufsize + 2048]; | |||
try | |||
{ | |||
if (wrapAround) | |||
{ | |||
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); | |||
System.arraycopy(buffer, 0, newbuffer, | |||
bufsize - tokenBegin, bufpos); | |||
buffer = newbuffer; | |||
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); | |||
System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); | |||
bufline = newbufline; | |||
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); | |||
System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); | |||
bufcolumn = newbufcolumn; | |||
maxNextCharInd = (bufpos += (bufsize - tokenBegin)); | |||
} | |||
else | |||
{ | |||
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); | |||
buffer = newbuffer; | |||
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); | |||
bufline = newbufline; | |||
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); | |||
bufcolumn = newbufcolumn; | |||
maxNextCharInd = (bufpos -= tokenBegin); | |||
} | |||
} | |||
catch (Throwable t) | |||
{ | |||
throw new Error(t.getMessage()); | |||
} | |||
bufsize += 2048; | |||
available = bufsize; | |||
tokenBegin = 0; | |||
} | |||
private final void FillBuff() throws java.io.IOException | |||
{ | |||
if (maxNextCharInd == available) | |||
{ | |||
if (available == bufsize) | |||
{ | |||
if (tokenBegin > 2048) | |||
{ | |||
bufpos = maxNextCharInd = 0; | |||
available = tokenBegin; | |||
} | |||
else if (tokenBegin < 0) | |||
bufpos = maxNextCharInd = 0; | |||
else | |||
ExpandBuff(false); | |||
} | |||
else if (available > tokenBegin) | |||
available = bufsize; | |||
else if ((tokenBegin - available) < 2048) | |||
ExpandBuff(true); | |||
else | |||
available = tokenBegin; | |||
} | |||
int i; | |||
try { | |||
if ((i = reader.read(buffer, maxNextCharInd, | |||
available - maxNextCharInd)) == -1) | |||
{ | |||
reader.close(); | |||
throw new java.io.IOException(); | |||
} | |||
else | |||
maxNextCharInd += i; | |||
return; | |||
} | |||
catch(java.io.IOException e) { | |||
--bufpos; | |||
backup(0); | |||
if (tokenBegin == -1) | |||
tokenBegin = bufpos; | |||
throw e; | |||
} | |||
} | |||
public final char BeginToken() throws java.io.IOException | |||
{ | |||
tokenBegin = -1; | |||
char c = readChar(); | |||
tokenBegin = bufpos; | |||
return c; | |||
} | |||
private final void UpdateLineColumn(char c) | |||
{ | |||
column++; | |||
if (prevCharIsLF) | |||
{ | |||
prevCharIsLF = false; | |||
line += (column = 1); | |||
} | |||
else if (prevCharIsCR) | |||
{ | |||
prevCharIsCR = false; | |||
if (c == '\n') | |||
{ | |||
prevCharIsLF = true; | |||
} | |||
else | |||
line += (column = 1); | |||
} | |||
switch (c) | |||
{ | |||
case '\r' : | |||
prevCharIsCR = true; | |||
break; | |||
case '\n' : | |||
prevCharIsLF = true; | |||
break; | |||
case '\t' : | |||
column--; | |||
column += (8 - (column & 07)); | |||
break; | |||
default : | |||
break; | |||
} | |||
bufline[bufpos] = line; | |||
bufcolumn[bufpos] = column; | |||
} | |||
public final char readChar() throws java.io.IOException | |||
{ | |||
if (inBuf > 0) | |||
{ | |||
--inBuf; | |||
return (char)((char)0xff & buffer[(bufpos == bufsize - 1) ? (bufpos = 0) : ++bufpos]); | |||
} | |||
if (++bufpos >= maxNextCharInd) | |||
FillBuff(); | |||
char c = (char)((char)0xff & buffer[bufpos]); | |||
UpdateLineColumn(c); | |||
return (c); | |||
} | |||
/** | |||
* @deprecated | |||
* @see #getEndColumn | |||
*/ | |||
public final int getColumn() { | |||
return bufcolumn[bufpos]; | |||
} | |||
/** | |||
* @deprecated | |||
* @see #getEndLine | |||
*/ | |||
public final int getLine() { | |||
return bufline[bufpos]; | |||
} | |||
public final int getEndColumn() { | |||
return bufcolumn[bufpos]; | |||
} | |||
public final int getEndLine() { | |||
return bufline[bufpos]; | |||
} | |||
public final int getBeginColumn() { | |||
return bufcolumn[tokenBegin]; | |||
} | |||
public final int getBeginLine() { | |||
return bufline[tokenBegin]; | |||
} | |||
public final void backup(int amount) { | |||
inBuf += amount; | |||
if ((bufpos -= amount) < 0) | |||
bufpos += bufsize; | |||
} | |||
public Generic_CharStream(java.io.Reader dstream, int startline, | |||
int startcolumn, int buffersize) | |||
{ | |||
reader = dstream; | |||
line = startline; | |||
column = startcolumn - 1; | |||
available = bufsize = buffersize; | |||
buffer = new char[buffersize]; | |||
bufline = new int[buffersize]; | |||
bufcolumn = new int[buffersize]; | |||
} | |||
public Generic_CharStream(java.io.Reader dstream, int startline, | |||
int startcolumn) | |||
{ | |||
this(dstream, startline, startcolumn, 4096); | |||
} | |||
public void ReInit(java.io.Reader dstream, int startline, | |||
int startcolumn, int buffersize) | |||
{ | |||
reader = dstream; | |||
line = startline; | |||
column = startcolumn - 1; | |||
if (buffer == null || buffersize != buffer.length) | |||
{ | |||
available = bufsize = buffersize; | |||
buffer = new char[buffersize]; | |||
bufline = new int[buffersize]; | |||
bufcolumn = new int[buffersize]; | |||
} | |||
prevCharIsLF = prevCharIsCR = false; | |||
tokenBegin = inBuf = maxNextCharInd = 0; | |||
bufpos = -1; | |||
} | |||
public void ReInit(java.io.Reader dstream, int startline, | |||
int startcolumn) | |||
{ | |||
ReInit(dstream, startline, startcolumn, 4096); | |||
} | |||
public final String GetImage() | |||
{ | |||
if (bufpos >= tokenBegin) | |||
return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); | |||
else | |||
return new String(buffer, tokenBegin, bufsize - tokenBegin) + | |||
new String(buffer, 0, bufpos + 1); | |||
} | |||
public final char[] GetSuffix(int len) | |||
{ | |||
char[] ret = new char[len]; | |||
if ((bufpos + 1) >= len) | |||
System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); | |||
else | |||
{ | |||
System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, | |||
len - bufpos - 1); | |||
System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); | |||
} | |||
return ret; | |||
} | |||
public void Done() | |||
{ | |||
buffer = null; | |||
bufline = null; | |||
bufcolumn = null; | |||
} | |||
/** | |||
* Method to adjust line and column numbers for the start of a token.<BR> | |||
*/ | |||
public void adjustBeginLineColumn(int newLine, int newCol) | |||
{ | |||
int start = tokenBegin; | |||
int len; | |||
if (bufpos >= tokenBegin) | |||
{ | |||
len = bufpos - tokenBegin + inBuf + 1; | |||
} | |||
else | |||
{ | |||
len = bufsize - tokenBegin + bufpos + 1 + inBuf; | |||
} | |||
int i = 0, j = 0, k = 0; | |||
int nextColDiff = 0, columnDiff = 0; | |||
while (i < len && | |||
bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) | |||
{ | |||
bufline[j] = newLine; | |||
nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; | |||
bufcolumn[j] = newCol + columnDiff; | |||
columnDiff = nextColDiff; | |||
i++; | |||
} | |||
if (i < len) | |||
{ | |||
bufline[j] = newLine++; | |||
bufcolumn[j] = newCol + columnDiff; | |||
while (i++ < len) | |||
{ | |||
if (bufline[j = start % bufsize] != bufline[++start % bufsize]) | |||
bufline[j] = newLine++; | |||
else | |||
bufline[j] = newLine; | |||
} | |||
} | |||
line = bufline[j]; | |||
column = bufcolumn[j]; | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
/* | |||
* (c) COPYRIGHT 1999 World Wide Web Consortium | |||
* (Massachusetts Institute of Technology, Institut National de Recherche | |||
* en Informatique et en Automatique, Keio University). | |||
* All Rights Reserved. http://www.w3.org/Consortium/Legal/ | |||
* | |||
* $Id: JumpException.java,v 1.1 1999/06/09 15:21:33 plehegar Exp $ | |||
*/ | |||
package com.vaadin.sass.parser; | |||
/** | |||
* @version $Revision: 1.1 $ | |||
* @author Philippe Le Hegaret | |||
*/ | |||
public class JumpException extends RuntimeException { | |||
private static final long serialVersionUID = -2010286909393046205L; | |||
/** | |||
* Creates a new JumpException | |||
*/ | |||
public JumpException() { | |||
} | |||
} |
@@ -0,0 +1,575 @@ | |||
/* | |||
* Copyright (c) 1999 World Wide Web Consortium | |||
* (Massachusetts Institute of Technology, Institut National de Recherche | |||
* en Informatique et en Automatique, Keio University). | |||
* All Rights Reserved. http://www.w3.org/Consortium/Legal/ | |||
* | |||
* $Id: LexicalUnitImpl.java,v 1.3 2000/02/15 02:08:19 plehegar Exp $ | |||
*/ | |||
package com.vaadin.sass.parser; | |||
import java.io.Serializable; | |||
import org.w3c.css.sac.LexicalUnit; | |||
import com.vaadin.sass.util.ColorUtil; | |||
/** | |||
* @version $Revision: 1.3 $ | |||
* @author Philippe Le Hegaret | |||
*/ | |||
public class LexicalUnitImpl implements LexicalUnit, SCSSLexicalUnit, | |||
Serializable { | |||
private static final long serialVersionUID = -6649833716809789399L; | |||
LexicalUnit prev; | |||
LexicalUnit next; | |||
short type; | |||
int line; | |||
int column; | |||
int i; | |||
float f; | |||
short dimension; | |||
String sdimension; | |||
String s; | |||
String fname; | |||
LexicalUnitImpl params; | |||
LexicalUnitImpl(short type, int line, int column, LexicalUnitImpl p) { | |||
if (p != null) { | |||
prev = p; | |||
p.next = this; | |||
} | |||
this.line = line; | |||
this.column = column - 1; | |||
this.type = type; | |||
} | |||
LexicalUnitImpl(int line, int column, LexicalUnitImpl previous, int i) { | |||
this(SAC_INTEGER, line, column, previous); | |||
this.i = i; | |||
} | |||
LexicalUnitImpl(int line, int column, LexicalUnitImpl previous, | |||
short dimension, String sdimension, float f) { | |||
this(dimension, line, column, previous); | |||
this.f = f; | |||
this.dimension = dimension; | |||
this.sdimension = sdimension; | |||
} | |||
LexicalUnitImpl(int line, int column, LexicalUnitImpl previous, short type, | |||
String s) { | |||
this(type, line, column, previous); | |||
this.s = s; | |||
} | |||
LexicalUnitImpl(short type, int line, int column, LexicalUnitImpl previous, | |||
String fname, LexicalUnitImpl params) { | |||
this(type, line, column, previous); | |||
this.fname = fname; | |||
this.params = params; | |||
} | |||
public int getLineNumber() { | |||
return line; | |||
} | |||
public int getColumnNumber() { | |||
return column; | |||
} | |||
@Override | |||
public short getLexicalUnitType() { | |||
return type; | |||
} | |||
@Override | |||
public LexicalUnit getNextLexicalUnit() { | |||
return next; | |||
} | |||
public void setNextLexicalUnit(LexicalUnit n) { | |||
next = n; | |||
} | |||
@Override | |||
public LexicalUnit getPreviousLexicalUnit() { | |||
return prev; | |||
} | |||
@Override | |||
public int getIntegerValue() { | |||
return i; | |||
} | |||
void setIntegerValue(int i) { | |||
this.i = i; | |||
} | |||
@Override | |||
public float getFloatValue() { | |||
return f; | |||
} | |||
public void setFloatValue(float f) { | |||
this.f = f; | |||
} | |||
@Override | |||
public String getDimensionUnitText() { | |||
switch (type) { | |||
case SAC_PERCENTAGE: | |||
return "%"; | |||
case SAC_EM: | |||
return "em"; | |||
case SAC_EX: | |||
return "ex"; | |||
case SAC_PIXEL: | |||
return "px"; | |||
case SAC_CENTIMETER: | |||
return "cm"; | |||
case SAC_MILLIMETER: | |||
return "mm"; | |||
case SAC_INCH: | |||
return "in"; | |||
case SAC_POINT: | |||
return "pt"; | |||
case SAC_PICA: | |||
return "pc"; | |||
case SAC_DEGREE: | |||
return "deg"; | |||
case SAC_RADIAN: | |||
return "rad"; | |||
case SAC_GRADIAN: | |||
return "grad"; | |||
case SAC_MILLISECOND: | |||
return "ms"; | |||
case SAC_SECOND: | |||
return "s"; | |||
case SAC_HERTZ: | |||
return "Hz"; | |||
case SAC_KILOHERTZ: | |||
return "kHz"; | |||
case SAC_DIMENSION: | |||
return sdimension; | |||
default: | |||
throw new IllegalStateException("invalid dimension " + type); | |||
} | |||
} | |||
@Override | |||
public String getStringValue() { | |||
return s; | |||
} | |||
public void setStringValue(String str) { | |||
s = str; | |||
} | |||
@Override | |||
public String getFunctionName() { | |||
return fname; | |||
} | |||
@Override | |||
public LexicalUnitImpl getParameters() { | |||
return params; | |||
} | |||
@Override | |||
public LexicalUnitImpl getSubValues() { | |||
return params; | |||
} | |||
@Override | |||
public String toString() { | |||
short type = getLexicalUnitType(); | |||
String text = null; | |||
switch (type) { | |||
case SCSS_VARIABLE: | |||
text = "$" + s; | |||
break; | |||
case LexicalUnit.SAC_OPERATOR_COMMA: | |||
text = ","; | |||
break; | |||
case LexicalUnit.SAC_OPERATOR_PLUS: | |||
text = "+"; | |||
break; | |||
case LexicalUnit.SAC_OPERATOR_MINUS: | |||
text = "-"; | |||
break; | |||
case LexicalUnit.SAC_OPERATOR_MULTIPLY: | |||
text = "*"; | |||
break; | |||
case LexicalUnit.SAC_OPERATOR_SLASH: | |||
text = "/"; | |||
break; | |||
case LexicalUnit.SAC_OPERATOR_MOD: | |||
text = "%"; | |||
break; | |||
case LexicalUnit.SAC_OPERATOR_EXP: | |||
text = "^"; | |||
break; | |||
case LexicalUnit.SAC_OPERATOR_LT: | |||
text = "<"; | |||
break; | |||
case LexicalUnit.SAC_OPERATOR_GT: | |||
text = ">"; | |||
break; | |||
case LexicalUnit.SAC_OPERATOR_LE: | |||
text = "<="; | |||
break; | |||
case LexicalUnit.SAC_OPERATOR_GE: | |||
text = "=>"; | |||
break; | |||
case LexicalUnit.SAC_OPERATOR_TILDE: | |||
text = "~"; | |||
break; | |||
case LexicalUnit.SAC_INHERIT: | |||
text = "inherit"; | |||
break; | |||
case LexicalUnit.SAC_INTEGER: | |||
text = Integer.toString(getIntegerValue(), 10); | |||
break; | |||
case LexicalUnit.SAC_REAL: | |||
text = getFloatValue() + ""; | |||
break; | |||
case LexicalUnit.SAC_EM: | |||
case LexicalUnit.SAC_EX: | |||
case LexicalUnit.SAC_PIXEL: | |||
case LexicalUnit.SAC_INCH: | |||
case LexicalUnit.SAC_CENTIMETER: | |||
case LexicalUnit.SAC_MILLIMETER: | |||
case LexicalUnit.SAC_POINT: | |||
case LexicalUnit.SAC_PICA: | |||
case LexicalUnit.SAC_PERCENTAGE: | |||
case LexicalUnit.SAC_DEGREE: | |||
case LexicalUnit.SAC_GRADIAN: | |||
case LexicalUnit.SAC_RADIAN: | |||
case LexicalUnit.SAC_MILLISECOND: | |||
case LexicalUnit.SAC_SECOND: | |||
case LexicalUnit.SAC_HERTZ: | |||
case LexicalUnit.SAC_KILOHERTZ: | |||
case LexicalUnit.SAC_DIMENSION: | |||
float f = getFloatValue(); | |||
int i = (int) f; | |||
if ((i) == f) { | |||
text = i + getDimensionUnitText(); | |||
} else { | |||
text = f + getDimensionUnitText(); | |||
} | |||
break; | |||
case LexicalUnit.SAC_URI: | |||
text = "url(" + getStringValue() + ")"; | |||
break; | |||
case LexicalUnit.SAC_RGBCOLOR: | |||
case LexicalUnit.SAC_COUNTER_FUNCTION: | |||
case LexicalUnit.SAC_COUNTERS_FUNCTION: | |||
case LexicalUnit.SAC_RECT_FUNCTION: | |||
case LexicalUnit.SAC_FUNCTION: | |||
String funcName = getFunctionName(); | |||
LexicalUnitImpl firstParam = getParameters(); | |||
if ("round".equals(funcName)) { | |||
firstParam | |||
.setFloatValue(Math.round(firstParam.getFloatValue())); | |||
text = firstParam.toString(); | |||
} else if ("ceil".equals(funcName)) { | |||
firstParam.setFloatValue((float) Math.ceil(firstParam | |||
.getFloatValue())); | |||
text = firstParam.toString(); | |||
} else if ("floor".equals(funcName)) { | |||
firstParam.setFloatValue((float) Math.floor(firstParam | |||
.getFloatValue())); | |||
text = firstParam.toString(); | |||
} else if ("abs".equals(funcName)) { | |||
firstParam.setFloatValue(Math.abs(firstParam.getFloatValue())); | |||
text = firstParam.toString(); | |||
} else if ("darken".equals(funcName)) { | |||
LexicalUnitImpl dark = ColorUtil.darken(this); | |||
text = dark.toString(); | |||
} else if ("lighten".equals(funcName)) { | |||
text = ColorUtil.lighten(this).toString(); | |||
} else { | |||
text = getFunctionName() + "(" + getParameters() + ")"; | |||
} | |||
break; | |||
case LexicalUnit.SAC_IDENT: | |||
text = getStringValue(); | |||
break; | |||
case LexicalUnit.SAC_STRING_VALUE: | |||
// @@SEEME. not exact | |||
text = "\"" + getStringValue() + "\""; | |||
break; | |||
case LexicalUnit.SAC_ATTR: | |||
text = "attr(" + getStringValue() + ")"; | |||
break; | |||
case LexicalUnit.SAC_UNICODERANGE: | |||
text = "@@TODO"; | |||
break; | |||
case LexicalUnit.SAC_SUB_EXPRESSION: | |||
text = getSubValues().toString(); | |||
break; | |||
default: | |||
text = "@unknown"; | |||
break; | |||
} | |||
if (getNextLexicalUnit() != null) { | |||
if (getNextLexicalUnit().getLexicalUnitType() == SAC_OPERATOR_COMMA) { | |||
return text + getNextLexicalUnit(); | |||
} | |||
return text + ' ' + getNextLexicalUnit(); | |||
} else { | |||
return text; | |||
} | |||
} | |||
@Override | |||
public LexicalUnitImpl divide(LexicalUnitImpl denominator) { | |||
setFloatValue(getFloatValue() / denominator.getIntegerValue()); | |||
return this; | |||
} | |||
@Override | |||
public LexicalUnitImpl add(LexicalUnitImpl another) { | |||
setFloatValue(getFloatValue() + another.getFloatValue()); | |||
return this; | |||
} | |||
@Override | |||
public LexicalUnitImpl minus(LexicalUnitImpl another) { | |||
setFloatValue(getFloatValue() - another.getFloatValue()); | |||
return this; | |||
} | |||
@Override | |||
public LexicalUnitImpl multiply(LexicalUnitImpl another) { | |||
setFloatValue(getFloatValue() * another.getIntegerValue()); | |||
return this; | |||
} | |||
public void replaceValue(LexicalUnitImpl another) { | |||
type = another.getLexicalUnitType(); | |||
i = another.getIntegerValue(); | |||
f = another.getFloatValue(); | |||
dimension = another.getDimension(); | |||
sdimension = another.getSdimension(); | |||
s = another.getStringValue(); | |||
fname = getFunctionName(); | |||
params = another.getParameters(); | |||
prev = another.getPreviousLexicalUnit(); | |||
LexicalUnit finalNextInAnother = another; | |||
while (finalNextInAnother.getNextLexicalUnit() != null) { | |||
finalNextInAnother = finalNextInAnother.getNextLexicalUnit(); | |||
} | |||
((LexicalUnitImpl) finalNextInAnother).setNextLexicalUnit(next); | |||
next = another.next; | |||
} | |||
public short getDimension() { | |||
return dimension; | |||
} | |||
public String getSdimension() { | |||
return sdimension; | |||
} | |||
// here some useful function for creation | |||
public static LexicalUnitImpl createVariable(int line, int column, | |||
LexicalUnitImpl previous, String name) { | |||
return new LexicalUnitImpl(line, column, previous, SCSS_VARIABLE, name); | |||
} | |||
public static LexicalUnitImpl createNumber(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
int i = (int) v; | |||
if (v == i) { | |||
return new LexicalUnitImpl(line, column, previous, i); | |||
} else { | |||
return new LexicalUnitImpl(line, column, previous, SAC_REAL, "", v); | |||
} | |||
} | |||
public static LexicalUnitImpl createInteger(int line, int column, | |||
LexicalUnitImpl previous, int i) { | |||
return new LexicalUnitImpl(line, column, previous, i); | |||
} | |||
public static LexicalUnitImpl createPercentage(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_PERCENTAGE, | |||
null, v); | |||
} | |||
static LexicalUnitImpl createEMS(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_EM, null, v); | |||
} | |||
static LexicalUnitImpl createEXS(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_EX, null, v); | |||
} | |||
static LexicalUnitImpl createPX(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_PIXEL, null, v); | |||
} | |||
static LexicalUnitImpl createCM(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_CENTIMETER, | |||
null, v); | |||
} | |||
static LexicalUnitImpl createMM(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_MILLIMETER, | |||
null, v); | |||
} | |||
static LexicalUnitImpl createIN(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_INCH, null, v); | |||
} | |||
static LexicalUnitImpl createPT(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_POINT, null, v); | |||
} | |||
static LexicalUnitImpl createPC(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_PICA, null, v); | |||
} | |||
static LexicalUnitImpl createDEG(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_DEGREE, null, v); | |||
} | |||
static LexicalUnitImpl createRAD(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_RADIAN, null, v); | |||
} | |||
static LexicalUnitImpl createGRAD(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_GRADIAN, null, v); | |||
} | |||
static LexicalUnitImpl createMS(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
if (v < 0) { | |||
throw new ParseException("Time values may not be negative"); | |||
} | |||
return new LexicalUnitImpl(line, column, previous, SAC_MILLISECOND, | |||
null, v); | |||
} | |||
static LexicalUnitImpl createS(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
if (v < 0) { | |||
throw new ParseException("Time values may not be negative"); | |||
} | |||
return new LexicalUnitImpl(line, column, previous, SAC_SECOND, null, v); | |||
} | |||
static LexicalUnitImpl createHZ(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
if (v < 0) { | |||
throw new ParseException("Frequency values may not be negative"); | |||
} | |||
return new LexicalUnitImpl(line, column, previous, SAC_HERTZ, null, v); | |||
} | |||
static LexicalUnitImpl createKHZ(int line, int column, | |||
LexicalUnitImpl previous, float v) { | |||
if (v < 0) { | |||
throw new ParseException("Frequency values may not be negative"); | |||
} | |||
return new LexicalUnitImpl(line, column, previous, SAC_KILOHERTZ, null, | |||
v); | |||
} | |||
static LexicalUnitImpl createDimen(int line, int column, | |||
LexicalUnitImpl previous, float v, String s) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_DIMENSION, s, v); | |||
} | |||
static LexicalUnitImpl createInherit(int line, int column, | |||
LexicalUnitImpl previous) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_INHERIT, | |||
"inherit"); | |||
} | |||
public static LexicalUnitImpl createIdent(int line, int column, | |||
LexicalUnitImpl previous, String s) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_IDENT, s); | |||
} | |||
static LexicalUnitImpl createString(int line, int column, | |||
LexicalUnitImpl previous, String s) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_STRING_VALUE, s); | |||
} | |||
static LexicalUnitImpl createURL(int line, int column, | |||
LexicalUnitImpl previous, String s) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_URI, s); | |||
} | |||
static LexicalUnitImpl createAttr(int line, int column, | |||
LexicalUnitImpl previous, String s) { | |||
return new LexicalUnitImpl(line, column, previous, SAC_ATTR, s); | |||
} | |||
static LexicalUnitImpl createCounter(int line, int column, | |||
LexicalUnitImpl previous, LexicalUnit params) { | |||
return new LexicalUnitImpl(SAC_COUNTER_FUNCTION, line, column, | |||
previous, "counter", (LexicalUnitImpl) params); | |||
} | |||
public static LexicalUnitImpl createCounters(int line, int column, | |||
LexicalUnitImpl previous, LexicalUnit params) { | |||
return new LexicalUnitImpl(SAC_COUNTERS_FUNCTION, line, column, | |||
previous, "counters", (LexicalUnitImpl) params); | |||
} | |||
public static LexicalUnitImpl createRGBColor(int line, int column, | |||
LexicalUnitImpl previous, LexicalUnit params) { | |||
return new LexicalUnitImpl(SAC_RGBCOLOR, line, column, previous, "rgb", | |||
(LexicalUnitImpl) params); | |||
} | |||
public static LexicalUnitImpl createRect(int line, int column, | |||
LexicalUnitImpl previous, LexicalUnit params) { | |||
return new LexicalUnitImpl(SAC_RECT_FUNCTION, line, column, previous, | |||
"rect", (LexicalUnitImpl) params); | |||
} | |||
public static LexicalUnitImpl createFunction(int line, int column, | |||
LexicalUnitImpl previous, String fname, LexicalUnit params) { | |||
return new LexicalUnitImpl(SAC_FUNCTION, line, column, previous, fname, | |||
(LexicalUnitImpl) params); | |||
} | |||
public static LexicalUnitImpl createUnicodeRange(int line, int column, | |||
LexicalUnit previous, LexicalUnit params) { | |||
// @@ return new LexicalUnitImpl(line, column, previous, null, | |||
// SAC_UNICODERANGE, params); | |||
return null; | |||
} | |||
public static LexicalUnitImpl createComma(int line, int column, | |||
LexicalUnitImpl previous) { | |||
return new LexicalUnitImpl(SAC_OPERATOR_COMMA, line, column, previous); | |||
} | |||
public static LexicalUnitImpl createSlash(int line, int column, | |||
LexicalUnitImpl previous) { | |||
return new LexicalUnitImpl(SAC_OPERATOR_SLASH, line, column, previous); | |||
} | |||
} |
@@ -0,0 +1,130 @@ | |||
/* | |||
* Copyright (c) 1999 World Wide Web Consortium | |||
* (Massachusetts Institute of Technology, Institut National de Recherche | |||
* en Informatique et en Automatique, Keio University). | |||
* All Rights Reserved. http://www.w3.org/Consortium/Legal/ | |||
* | |||
* $Id: LocatorImpl.java,v 1.2 2000/02/14 16:59:06 plehegar Exp $ | |||
*/ | |||
package com.vaadin.sass.parser; | |||
import org.w3c.css.sac.Locator; | |||
/** | |||
* @version $Revision: 1.2 $ | |||
* @author Philippe Le Hegaret | |||
*/ | |||
public class LocatorImpl implements Locator { | |||
// W3C DEBUG mode | |||
private static boolean W3CDebug; | |||
static { | |||
try { | |||
W3CDebug = (Boolean.getBoolean("debug") | |||
|| Boolean.getBoolean("org.w3c.flute.parser.LocatorImpl.debug") | |||
|| Boolean.getBoolean("org.w3c.flute.parser.debug") | |||
|| Boolean.getBoolean("org.w3c.flute.debug") | |||
|| Boolean.getBoolean("org.w3c.debug") | |||
|| Boolean.getBoolean("org.debug")); | |||
} catch (Exception e) { | |||
// nothing | |||
} | |||
} | |||
String uri; | |||
int line; | |||
int column; | |||
public String getURI() { | |||
return uri; | |||
} | |||
public int getLineNumber() { | |||
return line; | |||
} | |||
public int getColumnNumber() { | |||
return column; | |||
} | |||
/** | |||
* Creates a new LocatorImpl | |||
*/ | |||
public LocatorImpl(Parser p) { | |||
if (W3CDebug) { | |||
System.err.println( "LocatorImpl::newLocator(" + p + ");"); | |||
} | |||
uri = p.source.getURI(); | |||
line = p.token.beginLine; | |||
column = p.token.beginColumn; | |||
} | |||
/** | |||
* Reinitializes a LocatorImpl | |||
*/ | |||
public LocatorImpl(Parser p, Token tok) { | |||
if (W3CDebug) { | |||
System.err.println( "LocatorImpl::newLocator(" + p | |||
+ ", " + tok + ");"); | |||
} | |||
uri = p.source.getURI(); | |||
line = tok.beginLine; | |||
column = tok.beginColumn; | |||
} | |||
/** | |||
* Reinitializes a LocatorImpl | |||
*/ | |||
public LocatorImpl(Parser p, int line, int column) { | |||
if (W3CDebug) { | |||
System.err.println( "LocatorImpl::newLocator(" + p | |||
+ ", " + line | |||
+ ", " + column + ");"); | |||
} | |||
uri = p.source.getURI(); | |||
this.line = line; | |||
this.column = column; | |||
} | |||
/** | |||
* Reinitializes a LocatorImpl | |||
*/ | |||
public LocatorImpl reInit(Parser p) { | |||
if (W3CDebug) { | |||
System.err.println( "LocatorImpl::reInit(" + p + ");" ); | |||
} | |||
uri = p.source.getURI(); | |||
line = p.token.beginLine; | |||
column = p.token.beginColumn; | |||
return this; | |||
} | |||
/** | |||
* Reinitializes a LocatorImpl | |||
*/ | |||
public LocatorImpl reInit(Parser p, Token tok) { | |||
if (W3CDebug) { | |||
System.err.println( "LocatorImpl::reInit(" + p | |||
+ ", " + tok + ");"); | |||
} | |||
uri = p.source.getURI(); | |||
line = tok.beginLine; | |||
column = tok.beginColumn; | |||
return this; | |||
} | |||
/** | |||
* Reinitializes a LocatorImpl | |||
*/ | |||
public LocatorImpl reInit(Parser p, int line, int column) { | |||
if (W3CDebug) { | |||
System.err.println("LocatorImpl::reInit(" + p | |||
+ ", " + line | |||
+ ", " + column + ");"); | |||
} | |||
uri = p.source.getURI(); | |||
this.line = line; | |||
this.column = column; | |||
return this; | |||
} | |||
} |
@@ -0,0 +1,79 @@ | |||
/* | |||
* (c) COPYRIGHT 1999 World Wide Web Consortium | |||
* (Massachusetts Institute of Technology, Institut National de Recherche | |||
* en Informatique et en Automatique, Keio University). | |||
* All Rights Reserved. http://www.w3.org/Consortium/Legal/ | |||
* | |||
* $Id: MediaListImpl.java,v 1.4 2000/04/26 13:40:19 plehegar Exp $ | |||
*/ | |||
package com.vaadin.sass.parser; | |||
import org.w3c.css.sac.SACMediaList; | |||
/** | |||
* @version $Revision: 1.4 $ | |||
* @author Philippe Le Hegaret | |||
*/ | |||
public class MediaListImpl implements SACMediaList { | |||
String[] array = new String[10]; | |||
int current; | |||
@Override | |||
public int getLength() { | |||
return current; | |||
} | |||
@Override | |||
public String item(int index) { | |||
if ((index < 0) || (index >= current)) { | |||
return null; | |||
} | |||
return array[index]; | |||
} | |||
void addItem(String medium) { | |||
if (medium.equals("all")) { | |||
array[0] = "all"; | |||
current = 1; | |||
return; | |||
} | |||
for (int i = 0; i < current; i++) { | |||
if (medium.equals(array[i])) { | |||
return; | |||
} | |||
} | |||
if (current == array.length) { | |||
String[] old = array; | |||
array = new String[current + current]; | |||
System.arraycopy(old, 0, array, 0, current); | |||
} | |||
array[current++] = medium; | |||
} | |||
/** | |||
* Returns a string representation of this object. | |||
*/ | |||
@Override | |||
public String toString() { | |||
switch (current) { | |||
case 0: | |||
return ""; | |||
case 1: | |||
return array[0]; | |||
default: | |||
boolean not_done = true; | |||
int i = 0; | |||
StringBuffer buf = new StringBuffer(50); | |||
do { | |||
buf.append(array[i++]); | |||
if (i == current) { | |||
not_done = false; | |||
} else { | |||
buf.append(", "); | |||
} | |||
} while (not_done); | |||
return buf.toString(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,188 @@ | |||
/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 0.7pre6 */ | |||
package com.vaadin.sass.parser; | |||
import org.w3c.css.sac.CSSException; | |||
/** | |||
* This exception is thrown when parse errors are encountered. You can | |||
* explicitly create objects of this exception type by calling the method | |||
* generateParseException in the generated parser. | |||
* | |||
* You can modify this class to customize your error reporting mechanisms so | |||
* long as you retain the public fields. | |||
*/ | |||
public class ParseException extends CSSException { | |||
private static final long serialVersionUID = -8556588037264585977L; | |||
/** | |||
* This constructor is used by the method "generateParseException" in the | |||
* generated parser. Calling this constructor generates a new object of this | |||
* type with the fields "currentToken", "expectedTokenSequences", and | |||
* "tokenImage" set. The boolean flag "specialConstructor" is also set to | |||
* true to indicate that this constructor was used to create this object. | |||
* This constructor calls its super class with the empty string to force the | |||
* "toString" method of parent class "Throwable" to print the error message | |||
* in the form: ParseException: <result of getMessage> | |||
*/ | |||
public ParseException(Token currentTokenVal, | |||
int[][] expectedTokenSequencesVal, String[] tokenImageVal) { | |||
super(""); | |||
specialConstructor = true; | |||
currentToken = currentTokenVal; | |||
expectedTokenSequences = expectedTokenSequencesVal; | |||
tokenImage = tokenImageVal; | |||
} | |||
/** | |||
* The following constructors are for use by you for whatever purpose you | |||
* can think of. Constructing the exception in this manner makes the | |||
* exception behave in the normal way - i.e., as documented in the class | |||
* "Throwable". The fields "errorToken", "expectedTokenSequences", and | |||
* "tokenImage" do not contain relevant information. The JavaCC generated | |||
* code does not use these constructors. | |||
*/ | |||
public ParseException() { | |||
super(); | |||
specialConstructor = false; | |||
} | |||
public ParseException(String message) { | |||
super(message); | |||
specialConstructor = false; | |||
} | |||
/** | |||
* This variable determines which constructor was used to create this object | |||
* and thereby affects the semantics of the "getMessage" method (see below). | |||
*/ | |||
protected boolean specialConstructor; | |||
/** | |||
* This is the last token that has been consumed successfully. If this | |||
* object has been created due to a parse error, the token followng this | |||
* token will (therefore) be the first error token. | |||
*/ | |||
public Token currentToken; | |||
/** | |||
* Each entry in this array is an array of integers. Each array of integers | |||
* represents a sequence of tokens (by their ordinal values) that is | |||
* expected at this point of the parse. | |||
*/ | |||
public int[][] expectedTokenSequences; | |||
/** | |||
* This is a reference to the "tokenImage" array of the generated parser | |||
* within which the parse error occurred. This array is defined in the | |||
* generated ...Constants interface. | |||
*/ | |||
public String[] tokenImage; | |||
/** | |||
* This method has the standard behavior when this object has been created | |||
* using the standard constructors. Otherwise, it uses "currentToken" and | |||
* "expectedTokenSequences" to generate a parse error message and returns | |||
* it. If this object has been created due to a parse error, and you do not | |||
* catch it (it gets thrown from the parser), then this method is called | |||
* during the printing of the final stack trace, and hence the correct error | |||
* message gets displayed. | |||
*/ | |||
@Override | |||
public String getMessage() { | |||
if (!specialConstructor) { | |||
return super.getMessage(); | |||
} | |||
String expected = ""; | |||
int maxSize = 0; | |||
for (int i = 0; i < expectedTokenSequences.length; i++) { | |||
if (maxSize < expectedTokenSequences[i].length) { | |||
maxSize = expectedTokenSequences[i].length; | |||
} | |||
for (int j = 0; j < expectedTokenSequences[i].length; j++) { | |||
expected += tokenImage[expectedTokenSequences[i][j]] + " "; | |||
} | |||
if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { | |||
expected += "..."; | |||
} | |||
expected += eol + " "; | |||
} | |||
String retval = "Encountered \""; | |||
Token tok = currentToken.next; | |||
for (int i = 0; i < maxSize; i++) { | |||
if (i != 0) { | |||
retval += " "; | |||
} | |||
if (tok.kind == 0) { | |||
retval += tokenImage[0]; | |||
break; | |||
} | |||
retval += add_escapes(tok.image); | |||
tok = tok.next; | |||
} | |||
retval += "\" at line " + currentToken.next.beginLine + ", column " | |||
+ currentToken.next.beginColumn + "." + eol; | |||
if (expectedTokenSequences.length == 1) { | |||
retval += "Was expecting:" + eol + " "; | |||
} else { | |||
retval += "Was expecting one of:" + eol + " "; | |||
} | |||
retval += expected; | |||
return retval; | |||
} | |||
/** | |||
* The end of line string for this machine. | |||
*/ | |||
protected String eol = System.getProperty("line.separator", "\n"); | |||
/** | |||
* Used to convert raw characters to their escaped version when these raw | |||
* version cannot be used as part of an ASCII string literal. | |||
*/ | |||
protected String add_escapes(String str) { | |||
StringBuffer retval = new StringBuffer(); | |||
char ch; | |||
for (int i = 0; i < str.length(); i++) { | |||
switch (str.charAt(i)) { | |||
case 0: | |||
continue; | |||
case '\b': | |||
retval.append("\\b"); | |||
continue; | |||
case '\t': | |||
retval.append("\\t"); | |||
continue; | |||
case '\n': | |||
retval.append("\\n"); | |||
continue; | |||
case '\f': | |||
retval.append("\\f"); | |||
continue; | |||
case '\r': | |||
retval.append("\\r"); | |||
continue; | |||
case '\"': | |||
retval.append("\\\""); | |||
continue; | |||
case '\'': | |||
retval.append("\\\'"); | |||
continue; | |||
case '\\': | |||
retval.append("\\\\"); | |||
continue; | |||
default: | |||
if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { | |||
String s = "0000" + Integer.toString(ch, 16); | |||
retval.append("\\u" | |||
+ s.substring(s.length() - 4, s.length())); | |||
} else { | |||
retval.append(ch); | |||
} | |||
continue; | |||
} | |||
} | |||
return retval.toString(); | |||
} | |||
} |
@@ -0,0 +1,323 @@ | |||
/* Generated By:JavaCC: Do not edit this line. ParserConstants.java */ | |||
package com.vaadin.sass.parser; | |||
/** | |||
* Token literal values and constants. | |||
* Generated by org.javacc.parser.OtherFilesGen#start() | |||
*/ | |||
public interface ParserConstants { | |||
/** End of File. */ | |||
int EOF = 0; | |||
/** RegularExpression Id. */ | |||
int S = 1; | |||
/** RegularExpression Id. */ | |||
int INTERPOLATION = 4; | |||
/** RegularExpression Id. */ | |||
int FORMAL_COMMENT = 10; | |||
/** RegularExpression Id. */ | |||
int MULTI_LINE_COMMENT = 11; | |||
/** RegularExpression Id. */ | |||
int CDO = 13; | |||
/** RegularExpression Id. */ | |||
int CDC = 14; | |||
/** RegularExpression Id. */ | |||
int LBRACE = 15; | |||
/** RegularExpression Id. */ | |||
int RBRACE = 16; | |||
/** RegularExpression Id. */ | |||
int DASHMATCH = 17; | |||
/** RegularExpression Id. */ | |||
int INCLUDES = 18; | |||
/** RegularExpression Id. */ | |||
int EQ = 19; | |||
/** RegularExpression Id. */ | |||
int PLUS = 20; | |||
/** RegularExpression Id. */ | |||
int MINUS = 21; | |||
/** RegularExpression Id. */ | |||
int COMMA = 22; | |||
/** RegularExpression Id. */ | |||
int SEMICOLON = 23; | |||
/** RegularExpression Id. */ | |||
int PRECEDES = 24; | |||
/** RegularExpression Id. */ | |||
int DIV = 25; | |||
/** RegularExpression Id. */ | |||
int LBRACKET = 26; | |||
/** RegularExpression Id. */ | |||
int RBRACKET = 27; | |||
/** RegularExpression Id. */ | |||
int ANY = 28; | |||
/** RegularExpression Id. */ | |||
int PARENT = 29; | |||
/** RegularExpression Id. */ | |||
int DOT = 30; | |||
/** RegularExpression Id. */ | |||
int LPARAN = 31; | |||
/** RegularExpression Id. */ | |||
int RPARAN = 32; | |||
/** RegularExpression Id. */ | |||
int COLON = 33; | |||
/** RegularExpression Id. */ | |||
int NONASCII = 34; | |||
/** RegularExpression Id. */ | |||
int H = 35; | |||
/** RegularExpression Id. */ | |||
int UNICODE = 36; | |||
/** RegularExpression Id. */ | |||
int ESCAPE = 37; | |||
/** RegularExpression Id. */ | |||
int NMSTART = 38; | |||
/** RegularExpression Id. */ | |||
int NMCHAR = 39; | |||
/** RegularExpression Id. */ | |||
int STRINGCHAR = 40; | |||
/** RegularExpression Id. */ | |||
int D = 41; | |||
/** RegularExpression Id. */ | |||
int NAME = 42; | |||
/** RegularExpression Id. */ | |||
int TO = 43; | |||
/** RegularExpression Id. */ | |||
int THROUGH = 44; | |||
/** RegularExpression Id. */ | |||
int EACH_IN = 45; | |||
/** RegularExpression Id. */ | |||
int MIXIN_SYM = 46; | |||
/** RegularExpression Id. */ | |||
int INCLUDE_SYM = 47; | |||
/** RegularExpression Id. */ | |||
int FUNCTION_SYM = 48; | |||
/** RegularExpression Id. */ | |||
int RETURN_SYM = 49; | |||
/** RegularExpression Id. */ | |||
int DEBUG_SYM = 50; | |||
/** RegularExpression Id. */ | |||
int WARN_SYM = 51; | |||
/** RegularExpression Id. */ | |||
int FOR_SYM = 52; | |||
/** RegularExpression Id. */ | |||
int EACH_SYM = 53; | |||
/** RegularExpression Id. */ | |||
int WHILE_SYM = 54; | |||
/** RegularExpression Id. */ | |||
int IF_SYM = 55; | |||
/** RegularExpression Id. */ | |||
int ELSE_SYM = 56; | |||
/** RegularExpression Id. */ | |||
int EXTEND_SYM = 57; | |||
/** RegularExpression Id. */ | |||
int MOZ_DOCUMENT_SYM = 58; | |||
/** RegularExpression Id. */ | |||
int SUPPORTS_SYM = 59; | |||
/** RegularExpression Id. */ | |||
int GUARDED_SYM = 60; | |||
/** RegularExpression Id. */ | |||
int STRING = 61; | |||
/** RegularExpression Id. */ | |||
int IDENT = 62; | |||
/** RegularExpression Id. */ | |||
int NUMBER = 63; | |||
/** RegularExpression Id. */ | |||
int _URL = 64; | |||
/** RegularExpression Id. */ | |||
int URL = 65; | |||
/** RegularExpression Id. */ | |||
int VARIABLE = 66; | |||
/** RegularExpression Id. */ | |||
int PERCENTAGE = 67; | |||
/** RegularExpression Id. */ | |||
int PT = 68; | |||
/** RegularExpression Id. */ | |||
int MM = 69; | |||
/** RegularExpression Id. */ | |||
int CM = 70; | |||
/** RegularExpression Id. */ | |||
int PC = 71; | |||
/** RegularExpression Id. */ | |||
int IN = 72; | |||
/** RegularExpression Id. */ | |||
int PX = 73; | |||
/** RegularExpression Id. */ | |||
int EMS = 74; | |||
/** RegularExpression Id. */ | |||
int EXS = 75; | |||
/** RegularExpression Id. */ | |||
int DEG = 76; | |||
/** RegularExpression Id. */ | |||
int RAD = 77; | |||
/** RegularExpression Id. */ | |||
int GRAD = 78; | |||
/** RegularExpression Id. */ | |||
int MS = 79; | |||
/** RegularExpression Id. */ | |||
int SECOND = 80; | |||
/** RegularExpression Id. */ | |||
int HZ = 81; | |||
/** RegularExpression Id. */ | |||
int KHZ = 82; | |||
/** RegularExpression Id. */ | |||
int DIMEN = 83; | |||
/** RegularExpression Id. */ | |||
int HASH = 84; | |||
/** RegularExpression Id. */ | |||
int IMPORT_SYM = 85; | |||
/** RegularExpression Id. */ | |||
int MEDIA_SYM = 86; | |||
/** RegularExpression Id. */ | |||
int CHARSET_SYM = 87; | |||
/** RegularExpression Id. */ | |||
int PAGE_SYM = 88; | |||
/** RegularExpression Id. */ | |||
int FONT_FACE_SYM = 89; | |||
/** RegularExpression Id. */ | |||
int ATKEYWORD = 90; | |||
/** RegularExpression Id. */ | |||
int IMPORTANT_SYM = 91; | |||
/** RegularExpression Id. */ | |||
int RANGE0 = 92; | |||
/** RegularExpression Id. */ | |||
int RANGE1 = 93; | |||
/** RegularExpression Id. */ | |||
int RANGE2 = 94; | |||
/** RegularExpression Id. */ | |||
int RANGE3 = 95; | |||
/** RegularExpression Id. */ | |||
int RANGE4 = 96; | |||
/** RegularExpression Id. */ | |||
int RANGE5 = 97; | |||
/** RegularExpression Id. */ | |||
int RANGE6 = 98; | |||
/** RegularExpression Id. */ | |||
int RANGE = 99; | |||
/** RegularExpression Id. */ | |||
int UNI = 100; | |||
/** RegularExpression Id. */ | |||
int UNICODERANGE = 101; | |||
/** RegularExpression Id. */ | |||
int FUNCTION = 102; | |||
/** RegularExpression Id. */ | |||
int UNKNOWN = 103; | |||
/** Lexical state. */ | |||
int DEFAULT = 0; | |||
/** Lexical state. */ | |||
int IN_INTERPOLATION = 1; | |||
/** Lexical state. */ | |||
int IN_SINGLE_LINE_COMMENT = 2; | |||
/** Lexical state. */ | |||
int IN_FORMAL_COMMENT = 3; | |||
/** Lexical state. */ | |||
int IN_MULTI_LINE_COMMENT = 4; | |||
/** Literal token values. */ | |||
String[] tokenImage = { | |||
"<EOF>", | |||
"<S>", | |||
"\"#{\"", | |||
"<token of kind 3>", | |||
"\"}\"", | |||
"\"//\"", | |||
"<token of kind 6>", | |||
"<token of kind 7>", | |||
"<token of kind 8>", | |||
"\"/*\"", | |||
"\"*/\"", | |||
"\"*/\"", | |||
"<token of kind 12>", | |||
"\"<!--\"", | |||
"\"-->\"", | |||
"\"{\"", | |||
"\"}\"", | |||
"\"|=\"", | |||
"\"~=\"", | |||
"\"=\"", | |||
"\"+\"", | |||
"\"-\"", | |||
"\",\"", | |||
"\";\"", | |||
"\">\"", | |||
"\"/\"", | |||
"\"[\"", | |||
"\"]\"", | |||
"\"*\"", | |||
"\"&\"", | |||
"\".\"", | |||
"\"(\"", | |||
"\")\"", | |||
"\":\"", | |||
"<NONASCII>", | |||
"<H>", | |||
"<UNICODE>", | |||
"<ESCAPE>", | |||
"<NMSTART>", | |||
"<NMCHAR>", | |||
"<STRINGCHAR>", | |||
"<D>", | |||
"<NAME>", | |||
"\"to\"", | |||
"\"through\"", | |||
"\"in\"", | |||
"\"@mixin\"", | |||
"\"@include\"", | |||
"\"@function\"", | |||
"\"@return\"", | |||
"\"@debug\"", | |||
"\"@warn\"", | |||
"\"@for\"", | |||
"\"@each\"", | |||
"\"@while\"", | |||
"\"@if\"", | |||
"\"@else\"", | |||
"\"@extend\"", | |||
"\"@-moz-document\"", | |||
"\"@supports\"", | |||
"<GUARDED_SYM>", | |||
"<STRING>", | |||
"<IDENT>", | |||
"<NUMBER>", | |||
"<_URL>", | |||
"<URL>", | |||
"<VARIABLE>", | |||
"<PERCENTAGE>", | |||
"<PT>", | |||
"<MM>", | |||
"<CM>", | |||
"<PC>", | |||
"<IN>", | |||
"<PX>", | |||
"<EMS>", | |||
"<EXS>", | |||
"<DEG>", | |||
"<RAD>", | |||
"<GRAD>", | |||
"<MS>", | |||
"<SECOND>", | |||
"<HZ>", | |||
"<KHZ>", | |||
"<DIMEN>", | |||
"<HASH>", | |||
"\"@import\"", | |||
"\"@media\"", | |||
"\"@charset\"", | |||
"\"@page\"", | |||
"\"@font-face\"", | |||
"<ATKEYWORD>", | |||
"<IMPORTANT_SYM>", | |||
"<RANGE0>", | |||
"<RANGE1>", | |||
"<RANGE2>", | |||
"<RANGE3>", | |||
"<RANGE4>", | |||
"<RANGE5>", | |||
"<RANGE6>", | |||
"<RANGE>", | |||
"<UNI>", | |||
"<UNICODERANGE>", | |||
"<FUNCTION>", | |||
"<UNKNOWN>", | |||
}; | |||
} |
@@ -0,0 +1,16 @@ | |||
package com.vaadin.sass.parser; | |||
import org.w3c.css.sac.LexicalUnit; | |||
public interface SCSSLexicalUnit extends LexicalUnit { | |||
static final short SCSS_VARIABLE = 100; | |||
LexicalUnitImpl divide(LexicalUnitImpl denominator); | |||
LexicalUnitImpl add(LexicalUnitImpl another); | |||
LexicalUnitImpl minus(LexicalUnitImpl another); | |||
LexicalUnitImpl multiply(LexicalUnitImpl another); | |||
} |
@@ -0,0 +1,62 @@ | |||
/* | |||
* Copyright (c) 1999 World Wide Web Consortium, | |||
* (Massachusetts Institute of Technology, Institut National de | |||
* Recherche en Informatique et en Automatique, Keio University). All | |||
* Rights Reserved. This program is distributed under the W3C's Software | |||
* Intellectual Property License. This program is distributed in the | |||
* hope that it will be useful, but WITHOUT ANY WARRANTY; without even | |||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
* PURPOSE. | |||
* See W3C License http://www.w3.org/Consortium/Legal/ for more details. | |||
* | |||
* $Id: SelectorListImpl.java,v 1.1 2000/08/07 01:16:21 plehegar Exp $ | |||
*/ | |||
package com.vaadin.sass.parser; | |||
import org.w3c.css.sac.Selector; | |||
import org.w3c.css.sac.SelectorList; | |||
/** | |||
* @version $Revision: 1.1 $ | |||
* @author Philippe Le Hegaret | |||
*/ | |||
public class SelectorListImpl implements SelectorList { | |||
Selector[] selectors = new Selector[5]; | |||
int current; | |||
@Override | |||
public Selector item(int index) { | |||
if ((index < 0) || (index >= current)) { | |||
return null; | |||
} | |||
return selectors[index]; | |||
} | |||
public Selector itemSelector(int index) { | |||
if ((index < 0) || (index >= current)) { | |||
return null; | |||
} | |||
return selectors[index]; | |||
} | |||
@Override | |||
public int getLength() { | |||
return current; | |||
} | |||
public void addSelector(Selector selector) { | |||
if (current == selectors.length) { | |||
Selector[] old = selectors; | |||
selectors = new Selector[old.length + old.length]; | |||
System.arraycopy(old, 0, selectors, 0, old.length); | |||
} | |||
selectors[current++] = selector; | |||
} | |||
public void replaceSelector(int index, Selector selector) { | |||
if ((index >= 0) && (index < current)) { | |||
selectors[index] = selector; | |||
} | |||
} | |||
} |
@@ -0,0 +1,54 @@ | |||
/* | |||
* Copyright (c) 1999 World Wide Web Consortium, | |||
* (Massachusetts Institute of Technology, Institut National de | |||
* Recherche en Informatique et en Automatique, Keio University). All | |||
* Rights Reserved. This program is distributed under the W3C's Software | |||
* Intellectual Property License. This program is distributed in the | |||
* hope that it will be useful, but WITHOUT ANY WARRANTY; without even | |||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |||
* PURPOSE. | |||
* See W3C License http://www.w3.org/Consortium/Legal/ for more details. | |||
* | |||
* $Id: Selectors.java,v 1.1 2000/02/14 16:58:31 plehegar Exp $ | |||
*/ | |||
package com.vaadin.sass.parser; | |||
import org.w3c.css.sac.SelectorList; | |||
import org.w3c.css.sac.Selector; | |||
/** | |||
* @version $Revision: 1.1 $ | |||
* @author Philippe Le Hegaret | |||
*/ | |||
class Selectors implements SelectorList { | |||
Selector[] selectors = new Selector[5]; | |||
int current; | |||
public Selector item(int index) { | |||
if ((index < 0) || (index >= current)) { | |||
return null; | |||
} | |||
return selectors[index]; | |||
} | |||
public Selector itemSelector(int index) { | |||
if ((index < 0) || (index >= current)) { | |||
return null; | |||
} | |||
return selectors[index]; | |||
} | |||
public int getLength() { | |||
return current; | |||
} | |||
void addSelector(Selector selector) { | |||
if (current == selectors.length) { | |||
Selector[] old = selectors; | |||
selectors = new Selector[old.length + old.length]; | |||
System.arraycopy(old, 0, selectors, 0, old.length); | |||
} | |||
selectors[current++] = selector; | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
/* | |||
* (c) COPYRIGHT 1999 World Wide Web Consortium | |||
* (Massachusetts Institute of Technology, Institut National de Recherche | |||
* en Informatique et en Automatique, Keio University). | |||
* All Rights Reserved. http://www.w3.org/Consortium/Legal/ | |||
* | |||
* $Id: ThrowedParseException.java,v 1.1 1999/06/09 15:21:33 plehegar Exp $ | |||
*/ | |||
package com.vaadin.sass.parser; | |||
/** | |||
* @version $Revision: 1.1 $ | |||
* @author Philippe Le Hegaret | |||
*/ | |||
class ThrowedParseException extends RuntimeException { | |||
private static final long serialVersionUID = -7926371344505913546L; | |||
ParseException e; | |||
/** | |||
* Creates a new ThrowedParseException | |||
*/ | |||
ThrowedParseException(ParseException e) { | |||
this.e = e; | |||
} | |||
} |
@@ -0,0 +1,131 @@ | |||
/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */ | |||
/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ | |||
package com.vaadin.sass.parser; | |||
/** | |||
* Describes the input token stream. | |||
*/ | |||
public class Token implements java.io.Serializable { | |||
/** | |||
* The version identifier for this Serializable class. | |||
* Increment only if the <i>serialized</i> form of the | |||
* class changes. | |||
*/ | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* An integer that describes the kind of this token. This numbering | |||
* system is determined by JavaCCParser, and a table of these numbers is | |||
* stored in the file ...Constants.java. | |||
*/ | |||
public int kind; | |||
/** The line number of the first character of this Token. */ | |||
public int beginLine; | |||
/** The column number of the first character of this Token. */ | |||
public int beginColumn; | |||
/** The line number of the last character of this Token. */ | |||
public int endLine; | |||
/** The column number of the last character of this Token. */ | |||
public int endColumn; | |||
/** | |||
* The string image of the token. | |||
*/ | |||
public String image; | |||
/** | |||
* A reference to the next regular (non-special) token from the input | |||
* stream. If this is the last token from the input stream, or if the | |||
* token manager has not read tokens beyond this one, this field is | |||
* set to null. This is true only if this token is also a regular | |||
* token. Otherwise, see below for a description of the contents of | |||
* this field. | |||
*/ | |||
public Token next; | |||
/** | |||
* This field is used to access special tokens that occur prior to this | |||
* token, but after the immediately preceding regular (non-special) token. | |||
* If there are no such special tokens, this field is set to null. | |||
* When there are more than one such special token, this field refers | |||
* to the last of these special tokens, which in turn refers to the next | |||
* previous special token through its specialToken field, and so on | |||
* until the first special token (whose specialToken field is null). | |||
* The next fields of special tokens refer to other special tokens that | |||
* immediately follow it (without an intervening regular token). If there | |||
* is no such token, this field is null. | |||
*/ | |||
public Token specialToken; | |||
/** | |||
* An optional attribute value of the Token. | |||
* Tokens which are not used as syntactic sugar will often contain | |||
* meaningful values that will be used later on by the compiler or | |||
* interpreter. This attribute value is often different from the image. | |||
* Any subclass of Token that actually wants to return a non-null value can | |||
* override this method as appropriate. | |||
*/ | |||
public Object getValue() { | |||
return null; | |||
} | |||
/** | |||
* No-argument constructor | |||
*/ | |||
public Token() {} | |||
/** | |||
* Constructs a new token for the specified Image. | |||
*/ | |||
public Token(int kind) | |||
{ | |||
this(kind, null); | |||
} | |||
/** | |||
* Constructs a new token for the specified Image and Kind. | |||
*/ | |||
public Token(int kind, String image) | |||
{ | |||
this.kind = kind; | |||
this.image = image; | |||
} | |||
/** | |||
* Returns the image. | |||
*/ | |||
public String toString() | |||
{ | |||
return image; | |||
} | |||
/** | |||
* Returns a new Token object, by default. However, if you want, you | |||
* can create and return subclass objects based on the value of ofKind. | |||
* Simply add the cases to the switch for all those special cases. | |||
* For example, if you have a subclass of Token called IDToken that | |||
* you want to create if ofKind is ID, simply add something like : | |||
* | |||
* case MyParserConstants.ID : return new IDToken(ofKind, image); | |||
* | |||
* to the following switch statement. Then you can cast matchedToken | |||
* variable to the appropriate type and use sit in your lexical actions. | |||
*/ | |||
public static Token newToken(int ofKind, String image) | |||
{ | |||
switch(ofKind) | |||
{ | |||
default : return new Token(ofKind, image); | |||
} | |||
} | |||
public static Token newToken(int ofKind) | |||
{ | |||
return newToken(ofKind, null); | |||
} | |||
} | |||
/* JavaCC - OriginalChecksum=fd921a11cd37e391729b9460c71d3ad6 (do not edit this line) */ |
@@ -0,0 +1,147 @@ | |||
/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */ | |||
/* JavaCCOptions: */ | |||
package com.vaadin.sass.parser; | |||
/** Token Manager Error. */ | |||
public class TokenMgrError extends Error | |||
{ | |||
/** | |||
* The version identifier for this Serializable class. | |||
* Increment only if the <i>serialized</i> form of the | |||
* class changes. | |||
*/ | |||
private static final long serialVersionUID = 1L; | |||
/* | |||
* Ordinals for various reasons why an Error of this type can be thrown. | |||
*/ | |||
/** | |||
* Lexical error occurred. | |||
*/ | |||
static final int LEXICAL_ERROR = 0; | |||
/** | |||
* An attempt was made to create a second instance of a static token manager. | |||
*/ | |||
static final int STATIC_LEXER_ERROR = 1; | |||
/** | |||
* Tried to change to an invalid lexical state. | |||
*/ | |||
static final int INVALID_LEXICAL_STATE = 2; | |||
/** | |||
* Detected (and bailed out of) an infinite loop in the token manager. | |||
*/ | |||
static final int LOOP_DETECTED = 3; | |||
/** | |||
* Indicates the reason why the exception is thrown. It will have | |||
* one of the above 4 values. | |||
*/ | |||
int errorCode; | |||
/** | |||
* Replaces unprintable characters by their escaped (or unicode escaped) | |||
* equivalents in the given string | |||
*/ | |||
protected static final String addEscapes(String str) { | |||
StringBuffer retval = new StringBuffer(); | |||
char ch; | |||
for (int i = 0; i < str.length(); i++) { | |||
switch (str.charAt(i)) | |||
{ | |||
case 0 : | |||
continue; | |||
case '\b': | |||
retval.append("\\b"); | |||
continue; | |||
case '\t': | |||
retval.append("\\t"); | |||
continue; | |||
case '\n': | |||
retval.append("\\n"); | |||
continue; | |||
case '\f': | |||
retval.append("\\f"); | |||
continue; | |||
case '\r': | |||
retval.append("\\r"); | |||
continue; | |||
case '\"': | |||
retval.append("\\\""); | |||
continue; | |||
case '\'': | |||
retval.append("\\\'"); | |||
continue; | |||
case '\\': | |||
retval.append("\\\\"); | |||
continue; | |||
default: | |||
if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { | |||
String s = "0000" + Integer.toString(ch, 16); | |||
retval.append("\\u" + s.substring(s.length() - 4, s.length())); | |||
} else { | |||
retval.append(ch); | |||
} | |||
continue; | |||
} | |||
} | |||
return retval.toString(); | |||
} | |||
/** | |||
* Returns a detailed message for the Error when it is thrown by the | |||
* token manager to indicate a lexical error. | |||
* Parameters : | |||
* EOFSeen : indicates if EOF caused the lexical error | |||
* curLexState : lexical state in which this error occurred | |||
* errorLine : line number when the error occurred | |||
* errorColumn : column number when the error occurred | |||
* errorAfter : prefix that was seen before this error occurred | |||
* curchar : the offending character | |||
* Note: You can customize the lexical error message by modifying this method. | |||
*/ | |||
protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { | |||
return("Lexical error at line " + | |||
errorLine + ", column " + | |||
errorColumn + ". Encountered: " + | |||
(EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") + | |||
"after : \"" + addEscapes(errorAfter) + "\""); | |||
} | |||
/** | |||
* You can also modify the body of this method to customize your error messages. | |||
* For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not | |||
* of end-users concern, so you can return something like : | |||
* | |||
* "Internal Error : Please file a bug report .... " | |||
* | |||
* from this method for such cases in the release version of your parser. | |||
*/ | |||
public String getMessage() { | |||
return super.getMessage(); | |||
} | |||
/* | |||
* Constructors of various flavors follow. | |||
*/ | |||
/** No arg constructor. */ | |||
public TokenMgrError() { | |||
} | |||
/** Constructor with message and reason. */ | |||
public TokenMgrError(String message, int reason) { | |||
super(message); | |||
errorCode = reason; | |||
} | |||
/** Full Constructor. */ | |||
public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { | |||
this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); | |||
} | |||
} | |||
/* JavaCC - OriginalChecksum=7d5524d89510a94f7c2ac022e99c24c3 (do not edit this line) */ |
@@ -0,0 +1,27 @@ | |||
package com.vaadin.sass.selector; | |||
import org.w3c.css.sac.Selector; | |||
public class CompositeSelector implements Selector { | |||
public static final short SCSS_COMPOSITE_SELECTOR = 100; | |||
private Selector first; | |||
private Selector second; | |||
public CompositeSelector(Selector first, Selector second) { | |||
this.first = first; | |||
this.second = second; | |||
} | |||
public Selector getFirst() { | |||
return first; | |||
} | |||
public Selector getSecond() { | |||
return second; | |||
} | |||
@Override | |||
public short getSelectorType() { | |||
return SCSS_COMPOSITE_SELECTOR; | |||
} | |||
} |
@@ -0,0 +1,292 @@ | |||
package com.vaadin.sass.selector; | |||
import org.w3c.css.sac.CombinatorCondition; | |||
import org.w3c.css.sac.Condition; | |||
import org.w3c.css.sac.ConditionFactory; | |||
import org.w3c.css.sac.ConditionalSelector; | |||
import org.w3c.css.sac.DescendantSelector; | |||
import org.w3c.css.sac.ElementSelector; | |||
import org.w3c.css.sac.Selector; | |||
import org.w3c.css.sac.SelectorFactory; | |||
import org.w3c.css.sac.SelectorList; | |||
import org.w3c.css.sac.SiblingSelector; | |||
import org.w3c.css.sac.SimpleSelector; | |||
import org.w3c.flute.parser.selectors.AndConditionImpl; | |||
import org.w3c.flute.parser.selectors.AttributeConditionImpl; | |||
import org.w3c.flute.parser.selectors.ClassConditionImpl; | |||
import org.w3c.flute.parser.selectors.ConditionFactoryImpl; | |||
import org.w3c.flute.parser.selectors.DirectAdjacentSelectorImpl; | |||
import org.w3c.flute.parser.selectors.ElementSelectorImpl; | |||
import org.w3c.flute.parser.selectors.IdConditionImpl; | |||
import org.w3c.flute.parser.selectors.PseudoClassConditionImpl; | |||
import org.w3c.flute.parser.selectors.PseudoElementSelectorImpl; | |||
import org.w3c.flute.parser.selectors.SelectorFactoryImpl; | |||
import com.vaadin.sass.parser.SelectorListImpl; | |||
public class SelectorUtil { | |||
public static String toString(CompositeSelector compositeSelector) { | |||
StringBuilder builder = new StringBuilder(); | |||
if (compositeSelector != null) { | |||
if (compositeSelector.getFirst() != null) { | |||
builder.append(toString(compositeSelector.getFirst())).append( | |||
" "); | |||
} | |||
if (compositeSelector.getSecond() != null) { | |||
builder.append(toString(compositeSelector.getSecond())); | |||
} | |||
} | |||
return builder.toString(); | |||
} | |||
public static String toString(SelectorList selectorList) { | |||
StringBuilder stringBuilder = new StringBuilder(); | |||
for (int i = 0; i < selectorList.getLength(); i++) { | |||
String selectorString = toString(selectorList.item(i)); | |||
stringBuilder.append(selectorString); | |||
if (selectorList.getLength() > i + 1) { | |||
stringBuilder.append(", "); | |||
} | |||
} | |||
return stringBuilder.toString(); | |||
} | |||
public static String toString(Selector selector) { | |||
if (selector == null) { | |||
return ""; | |||
} | |||
if (selector.getSelectorType() == Selector.SAC_CONDITIONAL_SELECTOR) { | |||
StringBuilder stringBuilder = new StringBuilder(); | |||
ConditionalSelector conditionalSelector = (ConditionalSelector) selector; | |||
String simpleSelectorString = toString(conditionalSelector | |||
.getSimpleSelector()); | |||
if (simpleSelectorString != null) { | |||
stringBuilder.append(simpleSelectorString); | |||
} | |||
String conditionString = getConditionString(conditionalSelector | |||
.getCondition()); | |||
stringBuilder.append(conditionString); | |||
return stringBuilder.toString(); | |||
} else if (selector.getSelectorType() == Selector.SAC_DESCENDANT_SELECTOR) { | |||
return getDecendantSelectorString((DescendantSelector) selector, | |||
" "); | |||
} else if (selector.getSelectorType() == Selector.SAC_CHILD_SELECTOR) { | |||
DescendantSelector childSelector = (DescendantSelector) selector; | |||
String seperator = " > "; | |||
if (childSelector.getSimpleSelector() instanceof PseudoElementSelectorImpl) { | |||
seperator = "::"; | |||
} | |||
return getDecendantSelectorString((DescendantSelector) selector, | |||
seperator); | |||
} else if (selector.getSelectorType() == Selector.SAC_ELEMENT_NODE_SELECTOR) { | |||
ElementSelectorImpl elementSelector = (ElementSelectorImpl) selector; | |||
return elementSelector.getLocalName() == null ? "" | |||
: elementSelector.getLocalName(); | |||
} else if (selector.getSelectorType() == Selector.SAC_DIRECT_ADJACENT_SELECTOR) { | |||
DirectAdjacentSelectorImpl directAdjacentSelector = (DirectAdjacentSelectorImpl) selector; | |||
StringBuilder stringBuilder = new StringBuilder(); | |||
stringBuilder | |||
.append(toString(directAdjacentSelector.getSelector())); | |||
stringBuilder.append(" + "); | |||
stringBuilder.append(toString(directAdjacentSelector | |||
.getSiblingSelector())); | |||
return stringBuilder.toString(); | |||
} else if (selector.getSelectorType() == Selector.SAC_PSEUDO_ELEMENT_SELECTOR) { | |||
PseudoElementSelectorImpl pseudoElementSelectorImpl = (PseudoElementSelectorImpl) selector; | |||
return pseudoElementSelectorImpl.getLocalName(); | |||
} else if (selector.getSelectorType() == CompositeSelector.SCSS_COMPOSITE_SELECTOR) { | |||
return toString((CompositeSelector) selector); | |||
} else { | |||
System.out.println("SU !Unknown selector type, type: " | |||
+ selector.getSelectorType() + ", " + selector.toString()); | |||
} | |||
return ""; | |||
} | |||
private static String getDecendantSelectorString( | |||
DescendantSelector selector, String separator) { | |||
StringBuilder stringBuilder = new StringBuilder(); | |||
String ancestor = toString(selector.getAncestorSelector()); | |||
String simpleSelector = toString(selector.getSimpleSelector()); | |||
stringBuilder.append(ancestor); | |||
stringBuilder.append(separator); | |||
stringBuilder.append(simpleSelector); | |||
return stringBuilder.toString(); | |||
} | |||
private static String getConditionString(Condition condition) { | |||
short conditionType = condition.getConditionType(); | |||
if (conditionType == Condition.SAC_CLASS_CONDITION) { | |||
ClassConditionImpl classCondition = (ClassConditionImpl) condition; | |||
return "." + classCondition.getValue(); | |||
} else if (conditionType == Condition.SAC_ID_CONDITION) { | |||
IdConditionImpl idCondition = (IdConditionImpl) condition; | |||
return "#" + idCondition.getValue(); | |||
} else if (conditionType == Condition.SAC_AND_CONDITION) { | |||
AndConditionImpl andCondition = (AndConditionImpl) condition; | |||
return getConditionString(andCondition.getFirstCondition()) | |||
+ getConditionString(andCondition.getSecondCondition()); | |||
} else if (conditionType == Condition.SAC_ATTRIBUTE_CONDITION) { | |||
AttributeConditionImpl attributeCondition = (AttributeConditionImpl) condition; | |||
StringBuilder string = new StringBuilder(); | |||
string.append('['); | |||
string.append(attributeCondition.getLocalName()); | |||
String value = attributeCondition.getValue(); | |||
if ("true".equals(value) || "false".equals(value)) { | |||
string.append("=").append(value).append(']'); | |||
} else { | |||
string.append("=\""); | |||
string.append(attributeCondition.getValue()); | |||
string.append("\"]"); | |||
} | |||
return string.toString(); | |||
} else if (conditionType == Condition.SAC_PSEUDO_CLASS_CONDITION) { | |||
PseudoClassConditionImpl pseudoClassCondition = (PseudoClassConditionImpl) condition; | |||
return ":" + pseudoClassCondition.getValue(); | |||
} else { | |||
System.out.println("CU !condition type not identified, type: " | |||
+ conditionType + ", " + condition.toString()); | |||
return ""; | |||
} | |||
} | |||
public static boolean hasParentSelector(SelectorList selectorList) { | |||
String selectorString = toString(selectorList); | |||
return selectorString.contains("&"); | |||
} | |||
public static SelectorList createNewSelectorListFromAnOldOneWithSomPartReplaced( | |||
SelectorList oldList, String toBeReplacedSelectorName, | |||
SelectorList candidateSelectorList) throws Exception { | |||
if (candidateSelectorList.getLength() != 1) { | |||
throw new Exception("Candidate selector should not be a list"); | |||
} | |||
if (!(candidateSelectorList.item(0) instanceof SimpleSelector)) { | |||
throw new Exception( | |||
"Candidate selector should only be a SimpleSelector"); | |||
} | |||
SelectorListImpl newSelectorList = new SelectorListImpl(); | |||
SimpleSelector candidateSelector = (SimpleSelector) candidateSelectorList | |||
.item(0); | |||
for (int i = 0; i < oldList.getLength(); i++) { | |||
Selector selector = oldList.item(i); | |||
newSelectorList.addSelector(createSelectorWithSomePartReplaced( | |||
selector, toBeReplacedSelectorName, candidateSelector)); | |||
} | |||
return newSelectorList; | |||
} | |||
private static Selector createSelectorWithSomePartReplaced( | |||
Selector selector, String toBeReplacedSelectorName, | |||
SimpleSelector candidateSelector) { | |||
if (!toString(selector).contains(toBeReplacedSelectorName)) { | |||
return selector; | |||
} | |||
SelectorFactory factory = new SelectorFactoryImpl(); | |||
if (selector instanceof SimpleSelector) { | |||
return createSimpleSelectorWithSomePartReplaced( | |||
(SimpleSelector) selector, toBeReplacedSelectorName, | |||
candidateSelector); | |||
} else if (selector instanceof DescendantSelector) { | |||
DescendantSelector descendantSelector = (DescendantSelector) selector; | |||
Selector ancestor = descendantSelector.getAncestorSelector(); | |||
SimpleSelector simpleSelector = descendantSelector | |||
.getSimpleSelector(); | |||
return factory.createDescendantSelector( | |||
createSelectorWithSomePartReplaced(ancestor, | |||
toBeReplacedSelectorName, candidateSelector), | |||
createSimpleSelectorWithSomePartReplaced(simpleSelector, | |||
toBeReplacedSelectorName, candidateSelector)); | |||
} else if (selector instanceof DirectAdjacentSelectorImpl) { | |||
SiblingSelector siblingSelector = (SiblingSelector) selector; | |||
Selector ancestor = siblingSelector.getSelector(); | |||
SimpleSelector simpleSelector = siblingSelector | |||
.getSiblingSelector(); | |||
return factory.createDirectAdjacentSelector( | |||
Selector.SAC_DIRECT_ADJACENT_SELECTOR, ancestor, | |||
simpleSelector); | |||
} else if (selector instanceof CompositeSelector) { | |||
CompositeSelector compositeSelector = (CompositeSelector) selector; | |||
Selector first = compositeSelector.getFirst(); | |||
Selector second = compositeSelector.getSecond(); | |||
return new CompositeSelector(createSelectorWithSomePartReplaced( | |||
first, toBeReplacedSelectorName, candidateSelector), | |||
createSelectorWithSomePartReplaced(second, | |||
toBeReplacedSelectorName, candidateSelector)); | |||
} | |||
return null; | |||
} | |||
private static SimpleSelector createSimpleSelectorWithSomePartReplaced( | |||
SimpleSelector simpleSelector, String toBeReplacedSelectorName, | |||
SimpleSelector candidateSelector) { | |||
if (simpleSelector == null | |||
|| !toString(simpleSelector).contains(toBeReplacedSelectorName)) { | |||
return simpleSelector; | |||
} | |||
if (simpleSelector instanceof ElementSelector | |||
&& candidateSelector instanceof ElementSelector) { | |||
return candidateSelector; | |||
} | |||
if (simpleSelector instanceof ConditionalSelector) { | |||
return createConditionSelectorWithSomePartReplaced( | |||
(ConditionalSelector) simpleSelector, | |||
toBeReplacedSelectorName, candidateSelector); | |||
} | |||
return simpleSelector; | |||
} | |||
private static ConditionalSelector createConditionSelectorWithSomePartReplaced( | |||
ConditionalSelector oldConditionSelector, | |||
String toBeReplacedSelectorName, SimpleSelector candidateSelector) { | |||
if (oldConditionSelector == null | |||
|| !toString(oldConditionSelector).contains( | |||
toBeReplacedSelectorName)) { | |||
return oldConditionSelector; | |||
} | |||
SelectorFactory selectorFactory = new SelectorFactoryImpl(); | |||
if (candidateSelector instanceof ElementSelector) { | |||
return selectorFactory.createConditionalSelector(candidateSelector, | |||
oldConditionSelector.getCondition()); | |||
} | |||
if (candidateSelector instanceof ConditionalSelector) { | |||
// TODO some cases not covered. | |||
ConditionalSelector candidateConditionSelector = (ConditionalSelector) candidateSelector; | |||
Condition newCondition = createConditionWithSomePartReplaced( | |||
oldConditionSelector.getCondition(), | |||
toBeReplacedSelectorName, | |||
candidateConditionSelector.getCondition()); | |||
return selectorFactory.createConditionalSelector( | |||
oldConditionSelector.getSimpleSelector(), newCondition); | |||
} | |||
return oldConditionSelector; | |||
} | |||
private static Condition createConditionWithSomePartReplaced( | |||
Condition oldCondition, String toBeReplaced, Condition candidate) { | |||
if (oldCondition == null | |||
|| !getConditionString(oldCondition).contains(toBeReplaced)) { | |||
return oldCondition; | |||
} | |||
if (oldCondition.getConditionType() == Condition.SAC_AND_CONDITION) { | |||
ConditionFactory conditionFactory = new ConditionFactoryImpl(); | |||
CombinatorCondition oldCombinatorCondition = (CombinatorCondition) oldCondition; | |||
Condition newFirstCondition = createConditionWithSomePartReplaced( | |||
oldCombinatorCondition.getFirstCondition(), toBeReplaced, | |||
candidate); | |||
Condition newSecondCondition = createConditionWithSomePartReplaced( | |||
oldCombinatorCondition.getSecondCondition(), toBeReplaced, | |||
candidate); | |||
return conditionFactory.createAndCondition(newFirstCondition, | |||
newSecondCondition); | |||
} else { | |||
return candidate; | |||
} | |||
} | |||
public static boolean equals(Selector one, Selector another) { | |||
return one == null ? another == null : toString(one).equals( | |||
toString(another)); | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
package com.vaadin.sass.tree; | |||
import org.w3c.css.sac.SelectorList; | |||
import com.vaadin.sass.parser.SelectorListImpl; | |||
import com.vaadin.sass.selector.SelectorUtil; | |||
public class BlockNode extends Node { | |||
private static final long serialVersionUID = 5742962631468325048L; | |||
SelectorList selectorList; | |||
public BlockNode(SelectorList selectorList) { | |||
this.selectorList = selectorList; | |||
} | |||
public SelectorList getSelectorList() { | |||
return selectorList; | |||
} | |||
public void setSelectorList(SelectorList selectorList) { | |||
this.selectorList = selectorList; | |||
} | |||
public String toString(boolean indent) { | |||
StringBuilder string = new StringBuilder(); | |||
string.append(SelectorUtil.toString(selectorList)); | |||
string.append(" {\n"); | |||
for (Node child : children) { | |||
if (indent) { | |||
string.append("\t"); | |||
} | |||
string.append("\t" + child.toString() + "\n"); | |||
} | |||
if (indent) { | |||
string.append("\t"); | |||
} | |||
string.append("}"); | |||
return string.toString(); | |||
} | |||
@Override | |||
public String toString() { | |||
return toString(false); | |||
} | |||
@Override | |||
protected Object clone() throws CloneNotSupportedException { | |||
SelectorListImpl clonedSelectorList = new SelectorListImpl(); | |||
for (int i = 0; i < selectorList.getLength(); i++) { | |||
clonedSelectorList.addSelector(selectorList.item(i)); | |||
} | |||
return null; | |||
// BlockNode clone = new BlockNode() | |||
} | |||
} |
@@ -0,0 +1,22 @@ | |||
package com.vaadin.sass.tree; | |||
public class EachNode extends Node { | |||
private static final long serialVersionUID = 7943948981204906221L; | |||
private String var; | |||
private String list; | |||
private String body; | |||
public EachNode(String var, String list, String body) { | |||
super(); | |||
this.var = var; | |||
this.list = list; | |||
this.body = body; | |||
} | |||
@Override | |||
public String toString() { | |||
return "Each Node: {variable: " + var + ", list: " + list + ", body: " | |||
+ body + "}"; | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
package com.vaadin.sass.tree; | |||
import org.w3c.css.sac.SelectorList; | |||
public class ExtendNode extends Node { | |||
private static final long serialVersionUID = 3301805078983796878L; | |||
SelectorList list; | |||
public ExtendNode(SelectorList list) { | |||
super(); | |||
this.list = list; | |||
} | |||
public SelectorList getList() { | |||
return list; | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
package com.vaadin.sass.tree; | |||
public class ForNode extends Node { | |||
private static final long serialVersionUID = -1159180539216623335L; | |||
String var; | |||
String from; | |||
String to; | |||
boolean exclusive; | |||
String body; | |||
public ForNode(String var, String from, String to, boolean exclusive, | |||
String body) { | |||
super(); | |||
this.var = var; | |||
this.from = from; | |||
this.to = to; | |||
this.exclusive = exclusive; | |||
this.body = body; | |||
} | |||
@Override | |||
public String toString() { | |||
return "For Node: " + "{variable: " + var + ", from:" + from + ", to: " | |||
+ to + ", exclusive: " + exclusive + ", body" + body; | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
package com.vaadin.sass.tree; | |||
public class FunctionNode extends Node { | |||
private static final long serialVersionUID = -5383104165955523923L; | |||
private String name; | |||
private String args; | |||
private String body; | |||
public FunctionNode(String name) { | |||
super(); | |||
this.name = name; | |||
} | |||
public FunctionNode(String name, String args, String body) { | |||
this.name = name; | |||
this.args = args; | |||
this.body = body; | |||
} | |||
@Override | |||
public String toString() { | |||
return "Function Node: {name: " + name + ", args: " + args + ", body: " | |||
+ body + "}"; | |||
} | |||
} |
@@ -0,0 +1,6 @@ | |||
package com.vaadin.sass.tree; | |||
public class IfNode extends Node { | |||
private static final long serialVersionUID = 1561250630856748066L; | |||
} |
@@ -0,0 +1,55 @@ | |||
package com.vaadin.sass.tree; | |||
import org.w3c.css.sac.SACMediaList; | |||
public class ImportNode extends Node { | |||
private static final long serialVersionUID = 5671255892282668438L; | |||
private String uri; | |||
private SACMediaList ml; | |||
private boolean isURL; | |||
public ImportNode(String uri, SACMediaList ml, boolean isURL) { | |||
super(); | |||
this.uri = uri; | |||
this.ml = ml; | |||
this.isURL = isURL; | |||
} | |||
public boolean isPureCssImport() { | |||
return (isURL || uri.endsWith(".css") || uri.startsWith("http://") || hasMediaQueries()); | |||
} | |||
private boolean hasMediaQueries() { | |||
return (ml != null && ml.getLength() >= 1 && !"all".equals(ml.item(0))); | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuilder builder = new StringBuilder("@import "); | |||
if (isURL) { | |||
builder.append("url(").append(uri).append(")"); | |||
} else { | |||
builder.append("\"").append(uri).append("\""); | |||
} | |||
if (hasMediaQueries()) { | |||
for (int i = 0; i < ml.getLength(); i++) { | |||
builder.append(" ").append(ml.item(i)); | |||
} | |||
} | |||
builder.append(";"); | |||
return builder.toString(); | |||
} | |||
public String getUri() { | |||
return uri; | |||
} | |||
public void setUri(String uri) { | |||
this.uri = uri; | |||
} | |||
public SACMediaList getMl() { | |||
return ml; | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
package com.vaadin.sass.tree; | |||
import org.w3c.css.sac.SACMediaList; | |||
public class MediaNode extends Node { | |||
private static final long serialVersionUID = 2502097081457509523L; | |||
SACMediaList media; | |||
public MediaNode(SACMediaList media) { | |||
super(); | |||
this.media = media; | |||
} | |||
public SACMediaList getMedia() { | |||
return media; | |||
} | |||
public void setMedia(SACMediaList media) { | |||
this.media = media; | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuilder builder = new StringBuilder("@media "); | |||
if (media != null) { | |||
for (int i = 0; i < media.getLength(); i++) { | |||
builder.append(media.item(i)); | |||
} | |||
} | |||
builder.append(" {\n"); | |||
for (Node child : children) { | |||
if (child instanceof BlockNode) { | |||
builder.append("\t" + ((BlockNode) child).toString(true) + "\n"); | |||
} else { | |||
builder.append("\t" + child.toString() + "\n"); | |||
} | |||
} | |||
builder.append("}"); | |||
return builder.toString(); | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
package com.vaadin.sass.tree; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
public class MixinDefNode extends Node { | |||
private static final long serialVersionUID = 5469294053247343948L; | |||
private String name; | |||
private ArrayList<VariableNode> arglist; | |||
private String args; | |||
private String body; | |||
public MixinDefNode(String name, Collection<VariableNode> args) { | |||
super(); | |||
this.name = name; | |||
arglist = new ArrayList<VariableNode>(); | |||
if (args != null && !args.isEmpty()) { | |||
arglist.addAll(args); | |||
} | |||
} | |||
public MixinDefNode(String name, String args, String body) { | |||
this.name = name; | |||
this.args = args; | |||
this.body = body; | |||
} | |||
@Override | |||
public String toString() { | |||
return "Mixin Definition Node: {name: " + name + ", args: " + args | |||
+ ", body: " + body + "}"; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public void setName(String name) { | |||
this.name = name; | |||
} | |||
public ArrayList<VariableNode> getArglist() { | |||
return arglist; | |||
} | |||
public void setArglist(ArrayList<VariableNode> arglist) { | |||
this.arglist = arglist; | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
package com.vaadin.sass.tree; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import org.w3c.css.sac.LexicalUnit; | |||
public class MixinNode extends Node { | |||
private static final long serialVersionUID = 4725008226813110658L; | |||
private String name; | |||
private ArrayList<LexicalUnit> arglist; | |||
public MixinNode(String name, Collection<LexicalUnit> args) { | |||
super(); | |||
this.name = name; | |||
arglist = new ArrayList<LexicalUnit>(); | |||
if (args != null && !args.isEmpty()) { | |||
arglist.addAll(args); | |||
} | |||
} | |||
@Override | |||
public String toString() { | |||
return "name: " + name + " args: " + arglist; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public void setName(String name) { | |||
this.name = name; | |||
} | |||
public ArrayList<LexicalUnit> getArglist() { | |||
return arglist; | |||
} | |||
public void setArglist(ArrayList<LexicalUnit> arglist) { | |||
this.arglist = arglist; | |||
} | |||
} |
@@ -0,0 +1,40 @@ | |||
package com.vaadin.sass.tree; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.List; | |||
public class NestPropertiesNode extends Node { | |||
private static final long serialVersionUID = 3671253315690598308L; | |||
public NestPropertiesNode(String name) { | |||
super(); | |||
this.name = name; | |||
} | |||
private String name; | |||
public String getName() { | |||
return name; | |||
} | |||
public void setName(String name) { | |||
this.name = name; | |||
} | |||
public Collection<RuleNode> unNesting() { | |||
List<RuleNode> result = new ArrayList<RuleNode>(); | |||
for (Node child : children) { | |||
result.add(createNewRuleNodeFromChild((RuleNode) child)); | |||
} | |||
return result; | |||
} | |||
public RuleNode createNewRuleNodeFromChild(RuleNode child) { | |||
StringBuilder builder = new StringBuilder(name); | |||
builder.append("-").append(child.getVariable()); | |||
RuleNode newRuleNode = new RuleNode(builder.toString(), | |||
child.getValue(), child.isImportant(), null); | |||
return newRuleNode; | |||
} | |||
} |
@@ -0,0 +1,92 @@ | |||
package com.vaadin.sass.tree; | |||
import java.io.Serializable; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.List; | |||
public abstract class Node implements Serializable { | |||
private static final long serialVersionUID = 5914711715839294816L; | |||
protected ArrayList<Node> children; | |||
private String fileName; | |||
protected String rawString; | |||
protected List<String> variables; | |||
public Node() { | |||
children = new ArrayList<Node>(); | |||
variables = new ArrayList<String>(); | |||
} | |||
public Node(String raw) { | |||
this(); | |||
rawString = raw; | |||
} | |||
public void appendAll(Collection<Node> nodes) { | |||
if (nodes != null && !nodes.isEmpty()) { | |||
children.addAll(nodes); | |||
} | |||
} | |||
public void appendChild(Node node) { | |||
if (node != null) { | |||
children.add(node); | |||
} | |||
} | |||
public void appendChild(Node node, Node after) { | |||
if (node != null) { | |||
int index = children.indexOf(after); | |||
if (index != -1) { | |||
children.add(index + 1, node); | |||
} else { | |||
throw new NullPointerException("after-node was not found"); | |||
} | |||
} | |||
} | |||
public void removeChild(Node node) { | |||
if (node != null) { | |||
children.remove(node); | |||
} | |||
} | |||
public ArrayList<Node> getChildren() { | |||
return children; | |||
} | |||
public void setChildren(ArrayList<Node> children) { | |||
this.children = children; | |||
} | |||
public boolean hasChildren() { | |||
return !children.isEmpty(); | |||
} | |||
public void setFileName(String fileName) { | |||
this.fileName = fileName; | |||
} | |||
public String getFileName() { | |||
return fileName; | |||
} | |||
@Override | |||
public String toString() { | |||
return ""; | |||
} | |||
public String getRawString() { | |||
return rawString; | |||
} | |||
public void addVariable(String var) { | |||
variables.add(var); | |||
} | |||
public void removeVariable(String var) { | |||
variables.remove(var); | |||
} | |||
} |
@@ -0,0 +1,64 @@ | |||
package com.vaadin.sass.tree; | |||
import org.w3c.css.sac.LexicalUnit; | |||
public class RuleNode extends Node { | |||
private static final long serialVersionUID = 6653493127869037022L; | |||
String variable; | |||
LexicalUnit value; | |||
String comment; | |||
private boolean important; | |||
public RuleNode(String variable, LexicalUnit value, boolean important, | |||
String comment) { | |||
this.variable = variable; | |||
this.value = value; | |||
this.important = important; | |||
this.comment = comment; | |||
} | |||
public String getVariable() { | |||
return variable; | |||
} | |||
public void setVariable(String variable) { | |||
this.variable = variable; | |||
} | |||
public LexicalUnit getValue() { | |||
return value; | |||
} | |||
public void setValue(LexicalUnit value) { | |||
this.value = value; | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuilder builder = new StringBuilder(); | |||
builder.append(variable).append(": ").append(value.toString()); | |||
builder.append(important ? " !important;" : ";"); | |||
if (comment != null) { | |||
builder.append(comment); | |||
} | |||
return builder.toString(); | |||
} | |||
public boolean isImportant() { | |||
return important; | |||
} | |||
public void setImportant(boolean important) { | |||
this.important = important; | |||
} | |||
public String getComment() { | |||
return comment; | |||
} | |||
public void setComment(String comment) { | |||
this.comment = comment; | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
package com.vaadin.sass.tree; | |||
import org.w3c.css.sac.LexicalUnit; | |||
public class VariableNode extends Node { | |||
private static final long serialVersionUID = 7003372557547748734L; | |||
private String name; | |||
private LexicalUnit expr; | |||
private boolean guarded; | |||
public VariableNode(String name, LexicalUnit expr, boolean guarded) { | |||
super(); | |||
this.name = name; | |||
this.expr = expr; | |||
this.guarded = guarded; | |||
} | |||
public VariableNode(String name, String raw) { | |||
super(raw); | |||
this.name = name; | |||
} | |||
public LexicalUnit getExpr() { | |||
return expr; | |||
} | |||
public void setExpr(LexicalUnit expr) { | |||
this.expr = expr; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public boolean isGuarded() { | |||
return guarded; | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuilder builder = new StringBuilder("$"); | |||
builder.append(name).append(": ").append(expr); | |||
return builder.toString(); | |||
} | |||
public void setGuarded(boolean guarded) { | |||
this.guarded = guarded; | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
package com.vaadin.sass.tree; | |||
public class WhileNode extends Node { | |||
private static final long serialVersionUID = 7593896018196027279L; | |||
private String condition; | |||
private String body; | |||
public WhileNode(String condition, String body) { | |||
this.condition = condition; | |||
this.body = body; | |||
} | |||
@Override | |||
public String toString() { | |||
return "While Node: { condition: " + condition + ", body:" + body + "}"; | |||
} | |||
} |
@@ -0,0 +1,290 @@ | |||
package com.vaadin.sass.util; | |||
import org.w3c.css.sac.LexicalUnit; | |||
import com.vaadin.sass.parser.LexicalUnitImpl; | |||
public class ColorUtil { | |||
public static LexicalUnitImpl hexColorToHsl(LexicalUnitImpl hexColor) { | |||
String s = hexColor.getStringValue().substring(1); | |||
int r = 0, g = 0, b = 0; | |||
if (s.length() == 3) { | |||
String sh = s.substring(0, 1); | |||
r = Integer.parseInt(sh + sh, 16); | |||
sh = s.substring(1, 2); | |||
g = Integer.parseInt(sh + sh, 16); | |||
sh = s.substring(2, 3); | |||
b = Integer.parseInt(sh + sh, 16); | |||
} else if (s.length() == 6) { | |||
r = Integer.parseInt(s.substring(0, 2), 16); | |||
g = Integer.parseInt(s.substring(2, 4), 16); | |||
b = Integer.parseInt(s.substring(4, 6), 16); | |||
} | |||
int hsl[] = calculateHsl(r, g, b); | |||
LexicalUnitImpl hslParams = createHslParameters(hsl[0], hsl[1], hsl[2], | |||
hexColor.getLineNumber(), hexColor.getColumnNumber(), | |||
(LexicalUnitImpl) hexColor.getPreviousLexicalUnit()); | |||
return LexicalUnitImpl.createFunction(hexColor.getLineNumber(), | |||
hexColor.getColumnNumber(), | |||
(LexicalUnitImpl) hexColor.getPreviousLexicalUnit(), "hsl", | |||
hslParams); | |||
} | |||
public static LexicalUnitImpl hslToHexColor(LexicalUnitImpl hsl, int lengh) { | |||
int[] rgb = calculateRgb(hsl); | |||
StringBuilder builder = new StringBuilder("#"); | |||
for (int i = 0; i < 3; i++) { | |||
String color = Integer.toHexString(rgb[i]); | |||
if (lengh == 3) { | |||
if (color.length() == 1) { | |||
color = "0" + color; | |||
} | |||
} | |||
if (lengh == 6) { | |||
color = color.substring(0, 1); | |||
} | |||
builder.append(color); | |||
} | |||
return LexicalUnitImpl.createIdent(hsl.getLineNumber(), | |||
hsl.getColumnNumber(), | |||
(LexicalUnitImpl) hsl.getPreviousLexicalUnit(), | |||
builder.toString()); | |||
} | |||
private static int[] calculateRgb(LexicalUnitImpl hsl) { | |||
LexicalUnitImpl hslParam = hsl.getParameters(); | |||
LexicalUnitImpl hue = null; | |||
LexicalUnitImpl saturation = null; | |||
LexicalUnitImpl lightness = null; | |||
int i = 0; | |||
while (i < 5) { | |||
switch (i) { | |||
case 0: | |||
hue = hslParam; | |||
break; | |||
case 2: | |||
saturation = hslParam; | |||
break; | |||
case 4: | |||
lightness = hslParam; | |||
break; | |||
case 1: | |||
case 3: | |||
break; | |||
} | |||
hslParam = (LexicalUnitImpl) hslParam.getNextLexicalUnit(); | |||
i++; | |||
} | |||
float h = ((hue.getFloatValue() % 360) + 360) % 360 / 360; | |||
float s = saturation.getFloatValue() / 100; | |||
float l = lightness.getFloatValue() / 100; | |||
float m2, m1; | |||
int[] rgb = new int[3]; | |||
m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; | |||
m1 = l * 2 - m2; | |||
rgb[0] = Math.round(hueToRgb(m1, m2, h + 1f / 3) * 255); | |||
rgb[1] = Math.round(hueToRgb(m1, m2, h) * 255); | |||
rgb[2] = Math.round(hueToRgb(m1, m2, h - 1f / 3) * 255); | |||
return rgb; | |||
} | |||
public static LexicalUnitImpl rgbToHsl(LexicalUnitImpl rgb) { | |||
LexicalUnitImpl rgbParam = rgb.getParameters(); | |||
LexicalUnitImpl red = null; | |||
LexicalUnitImpl green = null; | |||
LexicalUnitImpl blue = null; | |||
int i = 0; | |||
while (i < 5) { | |||
switch (i) { | |||
case 0: | |||
red = rgbParam; | |||
break; | |||
case 2: | |||
green = rgbParam; | |||
break; | |||
case 4: | |||
blue = rgbParam; | |||
break; | |||
case 1: | |||
case 3: | |||
break; | |||
} | |||
rgbParam = (LexicalUnitImpl) rgbParam.getNextLexicalUnit(); | |||
i++; | |||
} | |||
int hsl[] = calculateHsl(red.getIntegerValue(), | |||
green.getIntegerValue(), blue.getIntegerValue()); | |||
rgbParam = rgb.getParameters(); | |||
LexicalUnitImpl hslParams = createHslParameters(hsl[0], hsl[1], hsl[2], | |||
rgbParam.getLineNumber(), rgbParam.getColumnNumber(), | |||
(LexicalUnitImpl) rgbParam.getPreviousLexicalUnit()); | |||
return LexicalUnitImpl.createFunction(rgb.getLineNumber(), | |||
rgb.getColumnNumber(), | |||
(LexicalUnitImpl) rgb.getPreviousLexicalUnit(), "hsl", | |||
hslParams); | |||
} | |||
private static int[] calculateHsl(int red, int green, int blue) { | |||
int[] hsl = new int[3]; | |||
float r = red / 255f; | |||
float g = green / 255f; | |||
float b = blue / 255f; | |||
float max = Math.max(Math.max(r, g), b); | |||
float min = Math.min(Math.min(r, g), b); | |||
float d = max - min; | |||
float h = 0f, s = 0f, l = 0f; | |||
if (max == min) { | |||
h = 0; | |||
} | |||
if (max == r) { | |||
h = 60 * (g - b) / d; | |||
} else if (max == g) { | |||
h = 60 * (b - r) / d + 120; | |||
} else if (max == b) { | |||
h = 60 * (r - g) / d + 240; | |||
} | |||
l = (max + min) / 2f; | |||
if (max == min) { | |||
s = 0; | |||
} else if (l < 0.5) { | |||
s = d / (2 * l); | |||
} else { | |||
s = d / (2 - 2 * l); | |||
} | |||
hsl[0] = Math.round(h % 360); | |||
hsl[1] = Math.round(s * 100); | |||
hsl[2] = Math.round(l * 100); | |||
return hsl; | |||
} | |||
public static LexicalUnitImpl hslToRgb(LexicalUnitImpl hsl) { | |||
int[] rgb = calculateRgb(hsl); | |||
LexicalUnitImpl hslParam = hsl.getParameters(); | |||
LexicalUnitImpl rgbParams = createRgbParameters(rgb[0], rgb[1], rgb[2], | |||
hslParam.getLineNumber(), hslParam.getColumnNumber(), | |||
(LexicalUnitImpl) hslParam.getPreviousLexicalUnit()); | |||
return LexicalUnitImpl.createFunction(hsl.getLineNumber(), | |||
hsl.getColumnNumber(), | |||
(LexicalUnitImpl) hsl.getPreviousLexicalUnit(), "rgb", | |||
rgbParams); | |||
} | |||
private static float hueToRgb(float m1, float m2, float h) { | |||
if (h < 0) { | |||
h = h + 1; | |||
} | |||
if (h > 1) { | |||
h = h - 1; | |||
} | |||
if (h * 6 < 1) { | |||
return m1 + (m2 - m1) * h * 6; | |||
} | |||
if (h * 2 < 1) { | |||
return m2; | |||
} | |||
if (h * 3 < 2) { | |||
return m1 + (m2 - m1) * (2f / 3 - h) * 6; | |||
} | |||
return m1; | |||
} | |||
private static LexicalUnitImpl createRgbParameters(int r, int g, int b, | |||
int ln, int cn, LexicalUnitImpl prev) { | |||
LexicalUnitImpl red = LexicalUnitImpl.createInteger(ln, cn, prev, r); | |||
LexicalUnitImpl firstComma = LexicalUnitImpl.createComma(ln, cn, red); | |||
LexicalUnitImpl green = LexicalUnitImpl.createInteger(ln, cn, | |||
firstComma, g); | |||
LexicalUnitImpl secondComma = LexicalUnitImpl | |||
.createComma(ln, cn, green); | |||
LexicalUnitImpl.createInteger(ln, cn, secondComma, b); | |||
return red; | |||
} | |||
private static LexicalUnitImpl createHslParameters(int h, int s, int l, | |||
int ln, int cn, LexicalUnitImpl prev) { | |||
LexicalUnitImpl hue = LexicalUnitImpl.createInteger(ln, cn, prev, h); | |||
LexicalUnitImpl firstComma = LexicalUnitImpl.createComma(ln, cn, hue); | |||
LexicalUnitImpl saturation = LexicalUnitImpl.createPercentage(ln, cn, | |||
firstComma, s); | |||
LexicalUnitImpl secondComma = LexicalUnitImpl.createComma(ln, cn, | |||
saturation); | |||
LexicalUnitImpl.createPercentage(ln, cn, secondComma, l); | |||
return hue; | |||
} | |||
public static LexicalUnitImpl darken(LexicalUnitImpl darkenFunc) { | |||
LexicalUnitImpl color = darkenFunc.getParameters(); | |||
LexicalUnit amount = color.getNextLexicalUnit().getNextLexicalUnit(); | |||
LexicalUnitImpl pre = (LexicalUnitImpl) darkenFunc | |||
.getPreviousLexicalUnit(); | |||
return adjust(color, amount, ColorOperation.Darken, pre); | |||
} | |||
private static LexicalUnitImpl adjust(LexicalUnitImpl color, | |||
LexicalUnit amount, ColorOperation op, LexicalUnitImpl pre) { | |||
if (color.getLexicalUnitType() == LexicalUnit.SAC_FUNCTION) { | |||
LexicalUnit funcParam = color.getParameters(); | |||
if ("hsl".equals(color.getFunctionName())) { | |||
LexicalUnit lightness = funcParam; | |||
for (int index = 0; index < 4; index++) { | |||
lightness = lightness.getNextLexicalUnit(); | |||
} | |||
float newValue = 0f; | |||
if (op == ColorOperation.Darken) { | |||
newValue = lightness.getFloatValue() | |||
- amount.getFloatValue(); | |||
newValue = newValue < 0 ? 0 : newValue; | |||
} else if (op == ColorOperation.Lighten) { | |||
newValue = lightness.getFloatValue() | |||
+ amount.getFloatValue(); | |||
newValue = newValue > 100 ? 100 : newValue; | |||
} | |||
((LexicalUnitImpl) lightness).setFloatValue(newValue); | |||
return LexicalUnitImpl.createFunction(color.getLineNumber(), | |||
color.getColumnNumber(), pre, color.getFunctionName(), | |||
funcParam); | |||
} | |||
} else if (color.getLexicalUnitType() == LexicalUnit.SAC_IDENT) { | |||
if (color.getStringValue().startsWith("#")) { | |||
return hslToHexColor( | |||
adjust(hexColorToHsl(color), amount, op, pre), color | |||
.getStringValue().substring(1).length()); | |||
} | |||
} else if (color.getLexicalUnitType() == LexicalUnit.SAC_RGBCOLOR) { | |||
LexicalUnitImpl hsl = rgbToHsl(color); | |||
LexicalUnitImpl hslAfterDarken = adjust(hsl, amount, op, pre); | |||
return hslToRgb(hslAfterDarken); | |||
} | |||
return color; | |||
} | |||
public static LexicalUnitImpl lighten(LexicalUnitImpl lightenFunc) { | |||
LexicalUnitImpl color = lightenFunc.getParameters(); | |||
LexicalUnit amount = color.getNextLexicalUnit().getNextLexicalUnit(); | |||
LexicalUnitImpl pre = (LexicalUnitImpl) lightenFunc | |||
.getPreviousLexicalUnit(); | |||
return adjust(color, amount, ColorOperation.Lighten, pre); | |||
} | |||
enum ColorOperation { | |||
Darken, Lighten | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
package com.vaadin.sass.util; | |||
import java.io.IOException; | |||
import java.io.ObjectInputStream; | |||
import java.io.ObjectOutputStream; | |||
/** | |||
* Utility for making deep copies (vs. clone()'s shallow copies) of objects. | |||
* Objects are first serialized and then deserialized. Error checking is fairly | |||
* minimal in this implementation. If an object is encountered that cannot be | |||
* serialized (or that references an object that cannot be serialized) an error | |||
* is printed to System.err and null is returned. Depending on your specific | |||
* application, it might make more sense to have copy(...) re-throw the | |||
* exception. | |||
*/ | |||
public class DeepCopy { | |||
/** | |||
* Returns a copy of the object, or null if the object cannot be serialized. | |||
*/ | |||
public static Object copy(Object orig) { | |||
Object obj = null; | |||
try { | |||
// Write the object out to a byte array | |||
FastByteArrayOutputStream fbos = new FastByteArrayOutputStream(); | |||
ObjectOutputStream out = new ObjectOutputStream(fbos); | |||
out.writeObject(orig); | |||
out.flush(); | |||
out.close(); | |||
// Retrieve an input stream from the byte array and read | |||
// a copy of the object back in. | |||
ObjectInputStream in = new ObjectInputStream(fbos.getInputStream()); | |||
obj = in.readObject(); | |||
in.close(); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} catch (ClassNotFoundException cnfe) { | |||
cnfe.printStackTrace(); | |||
} | |||
return obj; | |||
} | |||
} |
@@ -0,0 +1,66 @@ | |||
package com.vaadin.sass.util; | |||
import java.io.InputStream; | |||
/** | |||
* ByteArrayInputStream implementation that does not synchronize methods. | |||
*/ | |||
public class FastByteArrayInputStream extends InputStream { | |||
/** | |||
* Our byte buffer | |||
*/ | |||
protected byte[] buf = null; | |||
/** | |||
* Number of bytes that we can read from the buffer | |||
*/ | |||
protected int count = 0; | |||
/** | |||
* Number of bytes that have been read from the buffer | |||
*/ | |||
protected int pos = 0; | |||
public FastByteArrayInputStream(byte[] buf, int count) { | |||
this.buf = buf; | |||
this.count = count; | |||
} | |||
@Override | |||
public final int available() { | |||
return count - pos; | |||
} | |||
@Override | |||
public final int read() { | |||
return (pos < count) ? (buf[pos++] & 0xff) : -1; | |||
} | |||
@Override | |||
public final int read(byte[] b, int off, int len) { | |||
if (pos >= count) { | |||
return -1; | |||
} | |||
if ((pos + len) > count) { | |||
len = (count - pos); | |||
} | |||
System.arraycopy(buf, pos, b, off, len); | |||
pos += len; | |||
return len; | |||
} | |||
@Override | |||
public final long skip(long n) { | |||
if ((pos + n) > count) { | |||
n = count - pos; | |||
} | |||
if (n < 0) { | |||
return 0; | |||
} | |||
pos += n; | |||
return n; | |||
} | |||
} |
@@ -0,0 +1,87 @@ | |||
package com.vaadin.sass.util; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
/** | |||
* ByteArrayOutputStream implementation that doesn't synchronize methods and | |||
* doesn't copy the data on toByteArray(). | |||
*/ | |||
public class FastByteArrayOutputStream extends OutputStream { | |||
/** | |||
* Buffer and size | |||
*/ | |||
protected byte[] buf = null; | |||
protected int size = 0; | |||
/** | |||
* Constructs a stream with buffer capacity size 5K | |||
*/ | |||
public FastByteArrayOutputStream() { | |||
this(5 * 1024); | |||
} | |||
/** | |||
* Constructs a stream with the given initial size | |||
*/ | |||
public FastByteArrayOutputStream(int initSize) { | |||
size = 0; | |||
buf = new byte[initSize]; | |||
} | |||
/** | |||
* Ensures that we have a large enough buffer for the given size. | |||
*/ | |||
private void verifyBufferSize(int sz) { | |||
if (sz > buf.length) { | |||
byte[] old = buf; | |||
buf = new byte[Math.max(sz, 2 * buf.length)]; | |||
System.arraycopy(old, 0, buf, 0, old.length); | |||
old = null; | |||
} | |||
} | |||
public int getSize() { | |||
return size; | |||
} | |||
/** | |||
* Returns the byte array containing the written data. Note that this array | |||
* will almost always be larger than the amount of data actually written. | |||
*/ | |||
public byte[] getByteArray() { | |||
return buf; | |||
} | |||
@Override | |||
public final void write(byte b[]) { | |||
verifyBufferSize(size + b.length); | |||
System.arraycopy(b, 0, buf, size, b.length); | |||
size += b.length; | |||
} | |||
@Override | |||
public final void write(byte b[], int off, int len) { | |||
verifyBufferSize(size + len); | |||
System.arraycopy(b, off, buf, size, len); | |||
size += len; | |||
} | |||
@Override | |||
public final void write(int b) { | |||
verifyBufferSize(size + 1); | |||
buf[size++] = (byte) b; | |||
} | |||
public void reset() { | |||
size = 0; | |||
} | |||
/** | |||
* Returns a ByteArrayInputStream for reading back the written data | |||
*/ | |||
public InputStream getInputStream() { | |||
return new FastByteArrayInputStream(buf, size); | |||
} | |||
} |
@@ -0,0 +1,120 @@ | |||
package com.vaadin.sass.util; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Iterator; | |||
import java.util.LinkedList; | |||
import java.util.List; | |||
public class StringUtil { | |||
private static final String FOLDER_SEPARATOR = "/"; // folder separator | |||
private static final String WINDOWS_FOLDER_SEPARATOR = "\\"; // Windows | |||
// folder | |||
// separator | |||
private static final String TOP_PATH = ".."; // top folder | |||
private static final String CURRENT_PATH = "."; // current folder | |||
public static String cleanPath(String path) { | |||
String pathToUse = replace(path, WINDOWS_FOLDER_SEPARATOR, | |||
FOLDER_SEPARATOR); | |||
String[] pathArray = delimitedListToStringArray(pathToUse, | |||
FOLDER_SEPARATOR); | |||
List pathElements = new LinkedList(); | |||
int tops = 0; | |||
for (int i = pathArray.length - 1; i >= 0; i--) { | |||
if (CURRENT_PATH.equals(pathArray[i])) { | |||
// do nothing | |||
} else if (TOP_PATH.equals(pathArray[i])) { | |||
tops++; | |||
} else { | |||
if (tops > 0) { | |||
tops--; | |||
} else { | |||
pathElements.add(0, pathArray[i]); | |||
} | |||
} | |||
} | |||
for (int i = 0; i < tops; i++) { | |||
pathElements.add(0, TOP_PATH); | |||
} | |||
return collectionToDelimitedString(pathElements, FOLDER_SEPARATOR); | |||
} | |||
public static String replace(String inString, String oldPattern, | |||
String newPattern) { | |||
if (inString == null) { | |||
return null; | |||
} | |||
if (oldPattern == null || newPattern == null) { | |||
return inString; | |||
} | |||
StringBuffer sbuf = new StringBuffer(); | |||
// output StringBuffer we'll build up | |||
int pos = 0; // our position in the old string | |||
int index = inString.indexOf(oldPattern); | |||
// the index of an occurrence we've found, or -1 | |||
int patLen = oldPattern.length(); | |||
while (index >= 0) { | |||
sbuf.append(inString.substring(pos, index)); | |||
sbuf.append(newPattern); | |||
pos = index + patLen; | |||
index = inString.indexOf(oldPattern, pos); | |||
} | |||
sbuf.append(inString.substring(pos)); | |||
// remember to append any characters to the right of a match | |||
return sbuf.toString(); | |||
} | |||
public static String[] delimitedListToStringArray(String str, | |||
String delimiter) { | |||
if (str == null) { | |||
return new String[0]; | |||
} | |||
if (delimiter == null) { | |||
return new String[] { str }; | |||
} | |||
List result = new ArrayList(); | |||
int pos = 0; | |||
int delPos = 0; | |||
while ((delPos = str.indexOf(delimiter, pos)) != -1) { | |||
result.add(str.substring(pos, delPos)); | |||
pos = delPos + delimiter.length(); | |||
} | |||
if (str.length() > 0 && pos <= str.length()) { | |||
// Add rest of String, but not in case of empty input. | |||
result.add(str.substring(pos)); | |||
} | |||
return (String[]) result.toArray(new String[result.size()]); | |||
} | |||
public static String collectionToDelimitedString(Collection coll, | |||
String delim, String prefix, String suffix) { | |||
if (coll == null) { | |||
return ""; | |||
} | |||
StringBuffer sb = new StringBuffer(); | |||
Iterator it = coll.iterator(); | |||
int i = 0; | |||
while (it.hasNext()) { | |||
if (i > 0) { | |||
sb.append(delim); | |||
} | |||
sb.append(prefix).append(it.next()).append(suffix); | |||
i++; | |||
} | |||
return sb.toString(); | |||
} | |||
public static String collectionToDelimitedString(Collection coll, | |||
String delim) { | |||
return collectionToDelimitedString(coll, delim, "", ""); | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
package com.vaadin.sass.visitor; | |||
import java.util.HashSet; | |||
import java.util.Set; | |||
import org.w3c.css.sac.Selector; | |||
import org.w3c.css.sac.SelectorList; | |||
import com.vaadin.sass.parser.SelectorListImpl; | |||
import com.vaadin.sass.selector.CompositeSelector; | |||
import com.vaadin.sass.tree.BlockNode; | |||
import com.vaadin.sass.tree.Node; | |||
public class BlockVisitor implements Visitor { | |||
@Override | |||
public void traverse(Node node) { | |||
traverse(null, node); | |||
} | |||
private void traverse(Node parent, Node node) { | |||
Node after = node; | |||
Set<Node> toBeDeleted = new HashSet<Node>(); | |||
for (int pos = 0; pos < node.getChildren().size(); pos++) { | |||
Node child = node.getChildren().get(pos); | |||
traverse(node, child); | |||
if (child instanceof BlockNode && node instanceof BlockNode | |||
&& parent != null) { | |||
combineParentSelectorListToChild(node, child); | |||
toBeDeleted.add(child); | |||
parent.appendChild(child, after); | |||
after = child; | |||
} | |||
} | |||
for (Node child : toBeDeleted) { | |||
node.removeChild(child); | |||
} | |||
} | |||
private void combineParentSelectorListToChild(Node parent, Node child) { | |||
if (parent instanceof BlockNode && child instanceof BlockNode) { | |||
SelectorListImpl newList = new SelectorListImpl(); | |||
SelectorList parentSelectors = ((BlockNode) parent) | |||
.getSelectorList(); | |||
SelectorList childSelectors = ((BlockNode) child).getSelectorList(); | |||
for (int i = 0; i < parentSelectors.getLength(); i++) { | |||
Selector parentSelector = parentSelectors.item(i); | |||
for (int j = 0; j < childSelectors.getLength(); j++) { | |||
Selector childSelector = childSelectors.item(j); | |||
newList.addSelector(new CompositeSelector(parentSelector, | |||
childSelector)); | |||
} | |||
} | |||
((BlockNode) child).setSelectorList(newList); | |||
} | |||
} | |||
} |
@@ -0,0 +1,98 @@ | |||
package com.vaadin.sass.visitor; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Map.Entry; | |||
import org.w3c.css.sac.SelectorList; | |||
import com.vaadin.sass.parser.SelectorListImpl; | |||
import com.vaadin.sass.selector.SelectorUtil; | |||
import com.vaadin.sass.tree.BlockNode; | |||
import com.vaadin.sass.tree.ExtendNode; | |||
import com.vaadin.sass.tree.Node; | |||
public class ExtendVisitor implements Visitor { | |||
private Map<String, List<SelectorList>> extendsMap = new HashMap<String, List<SelectorList>>(); | |||
@Override | |||
public void traverse(Node node) throws Exception { | |||
buildExtendsMap(node); | |||
modifyTree(node); | |||
} | |||
private void modifyTree(Node node) throws Exception { | |||
for (Node child : node.getChildren()) { | |||
if (child instanceof BlockNode) { | |||
BlockNode blockNode = (BlockNode) child; | |||
String selectorString = SelectorUtil.toString(blockNode | |||
.getSelectorList()); | |||
if (extendsMap.get(selectorString) != null) { | |||
for (SelectorList sList : extendsMap.get(selectorString)) { | |||
SelectorList newList = SelectorUtil | |||
.createNewSelectorListFromAnOldOneWithSomPartReplaced( | |||
blockNode.getSelectorList(), | |||
selectorString, sList); | |||
addAdditionalSelectorListToBlockNode(blockNode, newList); | |||
} | |||
} else { | |||
for (Entry<String, List<SelectorList>> entry : extendsMap | |||
.entrySet()) { | |||
if (selectorString.contains(entry.getKey())) { | |||
for (SelectorList sList : entry.getValue()) { | |||
SelectorList newList = SelectorUtil | |||
.createNewSelectorListFromAnOldOneWithSomPartReplaced( | |||
blockNode.getSelectorList(), | |||
entry.getKey(), sList); | |||
addAdditionalSelectorListToBlockNode(blockNode, | |||
newList); | |||
} | |||
} | |||
} | |||
} | |||
} else { | |||
buildExtendsMap(child); | |||
} | |||
} | |||
} | |||
private void buildExtendsMap(Node node) { | |||
if (node instanceof BlockNode) { | |||
BlockNode blockNode = (BlockNode) node; | |||
for (Node child : new ArrayList<Node>(node.getChildren())) { | |||
if (child instanceof ExtendNode) { | |||
ExtendNode extendNode = (ExtendNode) child; | |||
String extendedString = SelectorUtil.toString(extendNode | |||
.getList()); | |||
if (extendsMap.get(extendedString) == null) { | |||
extendsMap.put(extendedString, | |||
new ArrayList<SelectorList>()); | |||
} | |||
extendsMap.get(extendedString).add( | |||
blockNode.getSelectorList()); | |||
node.removeChild(child); | |||
} else { | |||
buildExtendsMap(child); | |||
} | |||
} | |||
} else { | |||
for (Node child : node.getChildren()) { | |||
buildExtendsMap(child); | |||
} | |||
} | |||
} | |||
private void addAdditionalSelectorListToBlockNode(BlockNode blockNode, | |||
SelectorList list) { | |||
if (list != null) { | |||
for (int i = 0; i < list.getLength(); i++) { | |||
((SelectorListImpl) blockNode.getSelectorList()) | |||
.addSelector(list.item(i)); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,87 @@ | |||
package com.vaadin.sass.visitor; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import org.w3c.css.sac.CSSException; | |||
import org.w3c.css.sac.LexicalUnit; | |||
import com.vaadin.sass.ScssStylesheet; | |||
import com.vaadin.sass.parser.LexicalUnitImpl; | |||
import com.vaadin.sass.tree.ImportNode; | |||
import com.vaadin.sass.tree.Node; | |||
import com.vaadin.sass.tree.RuleNode; | |||
import com.vaadin.sass.util.StringUtil; | |||
public class ImportVisitor implements Visitor { | |||
@Override | |||
public void traverse(Node node) { | |||
for (Node child : new ArrayList<Node>(node.getChildren())) { | |||
if (child instanceof ImportNode) { | |||
ImportNode importNode = (ImportNode) child; | |||
if (!importNode.isPureCssImport()) { | |||
StringBuilder filePathBuilder = new StringBuilder( | |||
node.getFileName()); | |||
filePathBuilder.append(File.separatorChar).append( | |||
importNode.getUri()); | |||
if (!filePathBuilder.toString().endsWith(".scss")) { | |||
filePathBuilder.append(".scss"); | |||
} | |||
try { | |||
ScssStylesheet imported = ScssStylesheet.get(new File( | |||
filePathBuilder.toString())); | |||
traverse(imported); | |||
String prefix = getUrlPrefix(importNode.getUri()); | |||
if (prefix != null) { | |||
updateUrlInImportedSheet(imported, prefix); | |||
} | |||
Node pre = importNode; | |||
for (Node importedChild : imported.getChildren()) { | |||
node.appendChild(importedChild, pre); | |||
pre = importedChild; | |||
} | |||
node.removeChild(importNode); | |||
} catch (CSSException e) { | |||
e.printStackTrace(); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
private String getUrlPrefix(String url) { | |||
if (url == null) { | |||
return null; | |||
} | |||
int pos = url.lastIndexOf(File.separatorChar); | |||
if (pos == -1) { | |||
return null; | |||
} | |||
return url.substring(0, pos + 1); | |||
} | |||
private void updateUrlInImportedSheet(Node node, String prefix) { | |||
for (Node child : node.getChildren()) { | |||
if (child instanceof RuleNode) { | |||
LexicalUnit value = ((RuleNode) child).getValue(); | |||
while (value != null) { | |||
if (value.getLexicalUnitType() == LexicalUnit.SAC_URI) { | |||
String path = value.getStringValue(); | |||
if (!path.startsWith("/") && !path.contains(":")) { | |||
path = prefix + path; | |||
path = StringUtil.cleanPath(path); | |||
((LexicalUnitImpl) value).setStringValue(path); | |||
} | |||
} | |||
value = value.getNextLexicalUnit(); | |||
} | |||
} | |||
updateUrlInImportedSheet(child, prefix); | |||
} | |||
} | |||
} |
@@ -0,0 +1,77 @@ | |||
package com.vaadin.sass.visitor; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import com.vaadin.sass.tree.MixinDefNode; | |||
import com.vaadin.sass.tree.MixinNode; | |||
import com.vaadin.sass.tree.Node; | |||
import com.vaadin.sass.tree.VariableNode; | |||
import com.vaadin.sass.util.DeepCopy; | |||
public class MixinVisitor implements Visitor { | |||
Map<String, MixinDefNode> mixinDefs = new HashMap<String, MixinDefNode>(); | |||
@Override | |||
public void traverse(Node node) throws Exception { | |||
// create mixin map. | |||
for (Node child : node.getChildren()) { | |||
if (child instanceof MixinDefNode) { | |||
mixinDefs.put(((MixinDefNode) child).getName(), | |||
(MixinDefNode) child); | |||
} | |||
} | |||
replaceMixins(node); | |||
// delete MixinDefNode | |||
for (Node child : new ArrayList<Node>(node.getChildren())) { | |||
if (child instanceof MixinDefNode) { | |||
node.removeChild(child); | |||
} | |||
} | |||
} | |||
private void replaceMixins(Node node) throws Exception { | |||
for (Node child : new ArrayList<Node>(node.getChildren())) { | |||
replaceMixins(child); | |||
if (child instanceof MixinNode) { | |||
MixinNode mixinNode = (MixinNode) child; | |||
MixinDefNode mixinDef = mixinDefs.get(mixinNode.getName()); | |||
if (mixinDef == null) { | |||
throw new Exception("Mixin Definition: " | |||
+ mixinNode.getName() + " not found"); | |||
} | |||
replaceMixinNode(node, mixinNode, mixinDef); | |||
} | |||
} | |||
} | |||
private void replaceMixinNode(Node current, MixinNode mixinNode, | |||
MixinDefNode mixinDef) { | |||
Node pre = mixinNode; | |||
if (mixinDef.getArglist().isEmpty()) { | |||
for (Node child : mixinDef.getChildren()) { | |||
current.appendChild(child, pre); | |||
pre = child; | |||
} | |||
} else { | |||
for (int i = 0; i < mixinDef.getArglist().size(); i++) { | |||
VariableNode arg = (VariableNode) DeepCopy.copy(mixinDef | |||
.getArglist().get(i)); | |||
if (i < mixinNode.getArglist().size()) { | |||
arg.setExpr(mixinNode.getArglist().get(i)); | |||
} | |||
current.appendChild(arg, pre); | |||
pre = arg; | |||
} | |||
for (Node child : mixinDef.getChildren()) { | |||
Node clonedChild = (Node) DeepCopy.copy(child); | |||
current.appendChild(clonedChild, pre); | |||
pre = clonedChild; | |||
} | |||
} | |||
current.removeChild(mixinNode); | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
package com.vaadin.sass.visitor; | |||
import java.util.ArrayList; | |||
import com.vaadin.sass.tree.NestPropertiesNode; | |||
import com.vaadin.sass.tree.Node; | |||
import com.vaadin.sass.tree.RuleNode; | |||
public class NestPropertiesVisitor implements Visitor { | |||
@Override | |||
public void traverse(Node node) { | |||
for (Node child : new ArrayList<Node>(node.getChildren())) { | |||
if (child instanceof NestPropertiesNode) { | |||
Node previous = child; | |||
for (RuleNode unNested : ((NestPropertiesNode) child) | |||
.unNesting()) { | |||
node.appendChild(unNested, previous); | |||
previous = unNested; | |||
node.removeChild(child); | |||
} | |||
} else { | |||
traverse(child); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
package com.vaadin.sass.visitor; | |||
import java.util.ArrayList; | |||
import org.w3c.css.sac.SelectorList; | |||
import com.vaadin.sass.selector.SelectorUtil; | |||
import com.vaadin.sass.tree.BlockNode; | |||
import com.vaadin.sass.tree.Node; | |||
public class ParentSelectorVisitor implements Visitor { | |||
@Override | |||
public void traverse(Node node) throws Exception { | |||
for (Node child : new ArrayList<Node>(node.getChildren())) { | |||
if (child instanceof BlockNode) { | |||
traverse(node, (BlockNode) child); | |||
} | |||
} | |||
} | |||
private void traverse(Node parent, BlockNode block) throws Exception { | |||
Node pre = block; | |||
for (Node child : new ArrayList<Node>(block.getChildren())) { | |||
if (child instanceof BlockNode) { | |||
BlockNode blockChild = (BlockNode) child; | |||
traverse(block, blockChild); | |||
if (SelectorUtil | |||
.hasParentSelector(blockChild.getSelectorList())) { | |||
parent.appendChild(child, pre); | |||
pre = child; | |||
block.removeChild(child); | |||
SelectorList newSelectorList = SelectorUtil | |||
.createNewSelectorListFromAnOldOneWithSomPartReplaced( | |||
blockChild.getSelectorList(), "&", | |||
block.getSelectorList()); | |||
blockChild.setSelectorList(newSelectorList); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
package com.vaadin.sass.visitor; | |||
import java.util.HashMap; | |||
import java.util.HashSet; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import org.w3c.css.sac.LexicalUnit; | |||
import com.vaadin.sass.parser.LexicalUnitImpl; | |||
import com.vaadin.sass.parser.SCSSLexicalUnit; | |||
import com.vaadin.sass.tree.Node; | |||
import com.vaadin.sass.tree.RuleNode; | |||
import com.vaadin.sass.tree.VariableNode; | |||
public class VariableVisitor implements Visitor { | |||
@Override | |||
public void traverse(Node node) { | |||
Map<String, LexicalUnitImpl> variables = new HashMap<String, LexicalUnitImpl>(); | |||
traverse(node, variables); | |||
} | |||
private void traverse(Node node, Map<String, LexicalUnitImpl> variables) { | |||
if (node instanceof RuleNode) { | |||
LexicalUnit value = ((RuleNode) node).getValue(); | |||
for (String variable : variables.keySet()) { | |||
if (value.getLexicalUnitType() == SCSSLexicalUnit.SCSS_VARIABLE) { | |||
if (value.getStringValue().contains(variable)) { | |||
LexicalUnitImpl lexVal = (LexicalUnitImpl) value; | |||
lexVal.replaceValue(variables.get(variable)); | |||
} | |||
} | |||
} | |||
} else { | |||
Set<Node> toBeDeleted = new HashSet<Node>(); | |||
for (Node child : node.getChildren()) { | |||
if (child instanceof VariableNode) { | |||
variables.put(((VariableNode) child).getName(), | |||
(LexicalUnitImpl) ((VariableNode) child).getExpr()); | |||
toBeDeleted.add(child); | |||
} else { | |||
traverse(child, new HashMap<String, LexicalUnitImpl>( | |||
variables)); | |||
} | |||
} | |||
for (Node child : toBeDeleted) { | |||
node.removeChild(child); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
package com.vaadin.sass.visitor; | |||
import com.vaadin.sass.tree.Node; | |||
public interface Visitor { | |||
public void traverse(Node node) throws Exception; | |||
} |
@@ -0,0 +1,9 @@ | |||
.v-button:focus { | |||
background-image: url(img/left-focus.png);/** sprite-ref: buttons */ | |||
outline: none; | |||
} | |||
.v-button:focus .v-button-wrap { | |||
background-image: url(img/right-focus.png);/** sprite-ref: buttons; sprite-alignment: right */ | |||
outline: none; | |||
} |
@@ -0,0 +1,2 @@ | |||
.v-panel-deco { | |||
} |
@@ -0,0 +1,27 @@ | |||
.v-view { | |||
height: 100%; | |||
width: 100%; | |||
overflow: auto; | |||
outline: none; | |||
margin-top: -1px; | |||
border-top: 1px solid transparent; | |||
position: relative; | |||
} | |||
@media print { | |||
.v-generated-body { | |||
height: auto; | |||
min-height: 20cm; | |||
overflow: visible; | |||
} | |||
.v-app { | |||
height: auto; | |||
min-height: 20cm; | |||
} | |||
.v-view { | |||
overflow: visible; | |||
} | |||
.v-gridlayout { | |||
overflow: visible !important; | |||
} | |||
} |
@@ -0,0 +1,72 @@ | |||
.all-the-properties { | |||
font-family: Arial, Helvetica, "Lucida Grande", "Lucida Sans Unicode", Tahoma, Verdana, sans-serif; ; | |||
position: absolute;; | |||
overflow: hidden; | |||
outline: none; | |||
text-align: left; | |||
zoom: 1; | |||
white-space: nowrap; | |||
background: #123456; | |||
border-bottom: 1px solid #ffffff; | |||
filter: alpha(opacity = 30); | |||
cursor: pointer; | |||
overflow: auto; | |||
width: 100%; | |||
display: inline-block; | |||
} | |||
.missing-semicolon-on-last-row { | |||
color: red; | |||
background-color: blue | |||
} | |||
.lexical-value-test { | |||
margin: none; | |||
margin: 0px; | |||
margin: 0; | |||
margin: 0.5px; | |||
margin: 2px; | |||
margin: -0.5px; | |||
margin: -2px; | |||
margin: 10px 20px; | |||
margin: -10px 20px; | |||
margin: 20px -10px -20px 40px; | |||
margin-right: -0.5px; | |||
} | |||
.background-positioning { | |||
background-position: 0 0; | |||
background-position: left top; | |||
background-position: left 40px; | |||
background-position: 50px left; | |||
background-position: right -286px; | |||
} | |||
.user-select-rules { | |||
user-select: none; | |||
-ie-user-select: none; | |||
} | |||
.box-sizing-rules { | |||
box-sizing: border-box; | |||
-moz-box-sizing: border-box; | |||
} | |||
.user-select-and-box-sizing-combined { | |||
-khtml-user-select: none; | |||
-moz-user-select: none; | |||
-ie-user-select: none; | |||
user-select: none; | |||
-webkit-box-sizing: border-box; | |||
-moz-box-sizing: border-box; | |||
-ms-box-sizing: border-box; | |||
box-sizing: border-box; | |||
} | |||
@media print { | |||
.v-generated-body { | |||
height: auto; | |||
min-height: 20cm; | |||
overflow: visible; | |||
} | |||
} |
@@ -0,0 +1,103 @@ | |||
.foo { | |||
color: red; | |||
} | |||
.foo-bar { | |||
color: red; | |||
} | |||
.foo_bar { | |||
color: red; | |||
} | |||
.foo .bar { | |||
color: red; | |||
} | |||
.foo .bar .baz .fee .roo { | |||
color: red; | |||
} | |||
.foo.bar.baz.fee.roo { | |||
color: red; | |||
} | |||
.foo.bar .baz.fee.roo .dar { | |||
color: red; | |||
} | |||
.foo > .bar { | |||
color: red; | |||
} | |||
#foo { | |||
color: red; | |||
} | |||
#foo .bar { | |||
color: red; | |||
} | |||
.foo #bar { | |||
color: red; | |||
} | |||
#foo.bar { | |||
color: red; | |||
} | |||
#foo, #bar, .baz, .roo .dar { | |||
color: red; | |||
} | |||
#foo a, .foo pre img { | |||
color: red; | |||
} | |||
#foo a.bar { | |||
color: red; | |||
} | |||
a:link { | |||
color: red; | |||
} | |||
a.foo:visited, .bar { | |||
color: red; | |||
} | |||
.v-app input[type="text"] { | |||
color: red; | |||
} | |||
.foo + .bar { | |||
color: red; | |||
} | |||
h1 + .foo { | |||
color: red; | |||
} | |||
.foo * { | |||
color: red; | |||
} | |||
.foo * h1 { | |||
color: red; | |||
} | |||
h1 * .foo { | |||
color: red; | |||
} | |||
* .foo { | |||
color: red; | |||
} | |||
p::abc { | |||
color: red; | |||
} | |||
p:first { | |||
color: red; | |||
} |
@@ -0,0 +1 @@ | |||
Implement a sane test case. |
@@ -0,0 +1,13 @@ | |||
.error, .badError { | |||
border: 1px #f00; | |||
background: #fdd; | |||
} | |||
.error.intrusion, .badError.intrusion { | |||
font-size: 1.3em; | |||
font-weight: bold; | |||
} | |||
.badError { | |||
border-width: 3px; | |||
} |
@@ -0,0 +1,14 @@ | |||
.main { | |||
margin: 2px; | |||
border: 11px; | |||
border: 10px; | |||
border: 10px; | |||
color: hsl(0, 0%, 30%); | |||
color: hsl(25, 100%, 50%); | |||
color: rgb(36, 0, 0); | |||
color: rgb(240, 0, 0); | |||
color: #200; | |||
color: #240000; | |||
color: #f00; | |||
color: #f00000; | |||
} |
@@ -0,0 +1,11 @@ | |||
.caption { | |||
border: 1px solid black; | |||
background: #ff0000; | |||
padding: 10px; | |||
margin: 10px; | |||
} | |||
.text { | |||
font-weight: bold; | |||
color: red; | |||
} |
@@ -0,0 +1,41 @@ | |||
.main { | |||
border: 1px solid black; | |||
-webkit-border-radius: 3px; | |||
-moz-border-radius: 3px; | |||
border-radius: 3px; | |||
font-family: arial; | |||
font-size: 16px; | |||
font-weight: bold; | |||
} | |||
.footer { | |||
border: 2px solid black; | |||
-webkit-border-radius: 10px; | |||
-moz-border-radius: 10px; | |||
border-radius: 10px; | |||
} | |||
.header { | |||
width: 100%; | |||
} | |||
.main { | |||
width: 100%; | |||
height: 100%; | |||
} | |||
.footer { | |||
width: 100%; | |||
} | |||
@media print { | |||
.v-view { | |||
overflow: visible; | |||
} | |||
} | |||
font-family: arial; | |||
font-size: 16px; | |||
font-weight: bold; |
@@ -0,0 +1,5 @@ | |||
li { | |||
font-family: serif; | |||
font-weight: bold; | |||
font-size: 1.2em; | |||
} |
@@ -0,0 +1,47 @@ | |||
.top-bar { | |||
color: red; | |||
} | |||
.top-bar .alt { | |||
color: blue; | |||
} | |||
.menu { | |||
background-color: red; | |||
} | |||
.menu a { | |||
color: blue; | |||
} | |||
.caption { | |||
padding: 10px; | |||
} | |||
.caption .text, .caption .header { | |||
color: green; | |||
} | |||
.footer { | |||
padding: 10px; | |||
} | |||
.footer .left, .footer .right { | |||
color: purple; | |||
} | |||
.footer .left a, .footer .right a { | |||
color: orange; | |||
} | |||
.main { | |||
color: red; | |||
} | |||
.main .second.third { | |||
color: blue; | |||
} | |||
.main .second.third .fourth { | |||
color: black; | |||
} |
@@ -0,0 +1,25 @@ | |||
.content-navigation { | |||
border-color: #3bbfce; | |||
color: #0000ff; | |||
} | |||
.border { | |||
padding: 8px; | |||
margin: 8px; | |||
border-color: #3bbfce; | |||
} | |||
.body { | |||
background-image: url(../folder-test2/bg.png); | |||
background: transparent url(../folder-test2/img/loading-indicator.gif); | |||
background-image: url(http://abc/bg.png); | |||
background-image: url(/abc/bg.png); | |||
} | |||
.base { | |||
color: red; | |||
} | |||
.text { | |||
font-weight: bold; | |||
} |
@@ -0,0 +1,24 @@ | |||
a { | |||
font-weight: bold; | |||
text-decoration: none; | |||
} | |||
a:hover { | |||
text-decoration: underline; | |||
} | |||
body.firefox a { | |||
font-weight: normal; | |||
} | |||
#main { | |||
color: black; | |||
} | |||
#main a { | |||
font-weight: bold; | |||
} | |||
#main a:hover { | |||
color: red; | |||
} |
@@ -0,0 +1,11 @@ | |||
.content-navigation { | |||
border-color: #3bbfce; | |||
color: #0000ff; | |||
font-family: Arial, Helvetica, "Lucida Grande", "Lucida Sans Unicode", Tahoma, Verdana, sans-serif; | |||
} | |||
.border { | |||
padding: 8px; | |||
margin: 8px; | |||
border-color: #3bbfce; | |||
} |
@@ -0,0 +1,9 @@ | |||
$foo : red; | |||
.caption { | |||
$side: right; | |||
border: 1px solid black; | |||
background: #ff0000; | |||
padding: 10px; | |||
margin: 10px; | |||
} |
@@ -0,0 +1,14 @@ | |||
@for $i from 1 through 3 { | |||
.item-#{$i} { width: 2em * $i; } | |||
} | |||
@while $i > 0 { | |||
.item-#{$i} { width: 2em * $i; } | |||
$i: $i - 2; | |||
} | |||
@each $animal in puma, sea-slug, egret, salamander { | |||
.#{$animal}-icon { | |||
background-image: url('/images/#{$animal}.png'); | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
.error { | |||
border: 1px #f00; | |||
background: #fdd; | |||
} | |||
.error.intrusion { | |||
font-size: 1.3em; | |||
font-weight: bold; | |||
} | |||
.badError { | |||
@extend .error; | |||
border-width: 3px; | |||
} |
@@ -0,0 +1,6 @@ | |||
@import "../folder-test2/variables.scss"; | |||
@import "../folder-test2/url"; | |||
@import "../folder-test2/base-imported.scss"; | |||
.text { | |||
font-weight: bold; | |||
} |
@@ -0,0 +1 @@ | |||
@import "base.scss"; |
@@ -0,0 +1,3 @@ | |||
.base{ | |||
color: red; | |||
} |
@@ -0,0 +1,6 @@ | |||
.body{ | |||
background-image: url(bg.png); | |||
background: transparent url(img/loading-indicator.gif); | |||
background-image: url(http://abc/bg.png); | |||
background-image: url(/abc/bg.png); | |||
} |
@@ -0,0 +1,14 @@ | |||
$blue: #3bbfce; | |||
$margin: 8px; | |||
.content-navigation { | |||
border-color: $blue; | |||
$blue: #0000ff; | |||
color: $blue; | |||
} | |||
.border { | |||
padding: $margin; | |||
margin: $margin; | |||
border-color: $blue; | |||
} |
@@ -0,0 +1,16 @@ | |||
.main { | |||
margin: abs(-2px); | |||
border: ceil(10.4px); | |||
border: floor(10.4px); | |||
border: round(10.4px); | |||
color: lighten(hsl(0, 0%, 0%), 30%); | |||
color: darken(hsl(25, 100%, 80%), 30%); | |||
color: darken(rgb(136, 0, 0), 20%); | |||
color: lighten(rgb(136, 0, 0), 20%); | |||
color: darken(#880000, 20%); | |||
color: darken(#800, 20%); | |||
color: lighten(#880000, 20%); | |||
color: lighten(#800, 20%); | |||
} | |||
@@ -0,0 +1,6 @@ | |||
@import "_partial-for-import"; | |||
.text { | |||
font-weight: bold; | |||
color: $foo; | |||
} |
@@ -0,0 +1,3 @@ | |||
$name: foo; | |||
$attr: border; | |||
p.#{$name}abc { abc#{$attr}-color: blue } |
@@ -0,0 +1,44 @@ | |||
//asfdasdf | |||
@mixin font-settings { | |||
font-family: arial; | |||
font-size: 16px; | |||
font-weight: bold; | |||
} | |||
@mixin rounded-borders($thickness, $radius : 3px) { | |||
border: $thickness solid black; | |||
-webkit-border-radius: $radius; | |||
-moz-border-radius: $radius; | |||
border-radius: $radius; | |||
} | |||
.main { | |||
@include rounded-borders(1px); | |||
@include font-settings; | |||
} | |||
.footer { | |||
@include rounded-borders(2px, 10px); | |||
} | |||
@mixin layout { | |||
.header { | |||
width: 100%; | |||
} | |||
.main { | |||
width: 100%; | |||
height: 100%; | |||
} | |||
.footer { | |||
width: 100%; | |||
} | |||
@media print { | |||
.v-view { | |||
overflow: visible; | |||
} | |||
} | |||
@include font-settings; | |||
} | |||
@include layout; |
@@ -0,0 +1,7 @@ | |||
li { | |||
font: { | |||
family: serif;; | |||
weight: bold; | |||
size: 1.2em | |||
} | |||
} |
@@ -0,0 +1,40 @@ | |||
.top-bar { | |||
color: red; | |||
.alt { | |||
color: blue; | |||
} | |||
} | |||
.menu { | |||
background-color: red; | |||
a { | |||
color: blue; | |||
} | |||
} | |||
.caption { | |||
padding: 10px; | |||
.text, .header { | |||
color: green; | |||
} | |||
} | |||
.footer { | |||
padding: 10px; | |||
.left, .right { | |||
color: purple; | |||
a { | |||
color: orange; | |||
} | |||
} | |||
} | |||
.main { | |||
color: red; | |||
.second.third { | |||
color: blue; | |||
.fourth { | |||
color: black; | |||
} | |||
} | |||
} |
@@ -0,0 +1,14 @@ | |||
a { | |||
font-weight: bold; | |||
text-decoration: none; | |||
&:hover { text-decoration: underline; } | |||
body.firefox & { font-weight: normal; } | |||
} | |||
#main { | |||
color: black; | |||
a { | |||
font-weight: bold; | |||
&:hover { color: red; } | |||
} | |||
} |
@@ -0,0 +1,6 @@ | |||
a { | |||
color: #660000; | |||
&:hover {color: #000000;} | |||
&:visited {color:#660066;} | |||
&:active {color: #ffffff;} | |||
} |
@@ -0,0 +1,16 @@ | |||
$blue: #3bbfce; | |||
$margin: 8px; | |||
$chameleon-font-family: Arial, Helvetica, "Lucida Grande", "Lucida Sans Unicode", Tahoma, Verdana, sans-serif; | |||
.content-navigation { | |||
border-color: $blue; | |||
$blue: #0000ff; | |||
color: $blue; | |||
font-family: $chameleon-font-family; | |||
} | |||
.border { | |||
padding: $margin; | |||
margin: $margin; | |||
border-color: $blue; | |||
} |
@@ -0,0 +1,11 @@ | |||
package com.vaadin.sass; | |||
import org.junit.runner.RunWith; | |||
import org.junit.runners.Suite; | |||
import org.junit.runners.Suite.SuiteClasses; | |||
@RunWith(Suite.class) | |||
@SuiteClasses({ CssTestSuite.class, ScssTestSuite.class, VisitorTestSuite.class }) | |||
public class AllTests { | |||
} |
@@ -0,0 +1,17 @@ | |||
package com.vaadin.sass; | |||
import org.junit.runner.RunWith; | |||
import org.junit.runners.Suite; | |||
import org.junit.runners.Suite.SuiteClasses; | |||
import com.vaadin.sass.testcases.css.Comments; | |||
import com.vaadin.sass.testcases.css.Media; | |||
import com.vaadin.sass.testcases.css.Properties; | |||
import com.vaadin.sass.testcases.css.Reindeer; | |||
import com.vaadin.sass.testcases.css.Selectors; | |||
@RunWith(Suite.class) | |||
@SuiteClasses({ Selectors.class, Properties.class, Reindeer.class, Media.class, | |||
Comments.class }) | |||
public class CssTestSuite { | |||
} |
@@ -0,0 +1,26 @@ | |||
package com.vaadin.sass; | |||
import org.junit.runner.RunWith; | |||
import org.junit.runners.Suite; | |||
import org.junit.runners.Suite.SuiteClasses; | |||
import com.vaadin.sass.testcases.scss.ControlDirectives; | |||
import com.vaadin.sass.testcases.scss.Extends; | |||
import com.vaadin.sass.testcases.scss.Functions; | |||
import com.vaadin.sass.testcases.scss.Imports; | |||
import com.vaadin.sass.testcases.scss.Mixins; | |||
import com.vaadin.sass.testcases.scss.NestedProperties; | |||
import com.vaadin.sass.testcases.scss.Nesting; | |||
import com.vaadin.sass.testcases.scss.ParentImports; | |||
import com.vaadin.sass.testcases.scss.ParentSelector; | |||
import com.vaadin.sass.testcases.scss.Variables; | |||
import com.vaadin.sass.tree.ImportNodeTest; | |||
@RunWith(Suite.class) | |||
@SuiteClasses({ ControlDirectives.class, Extends.class, Functions.class, | |||
ImportNodeTest.class, Imports.class, Mixins.class, | |||
NestedProperties.class, Nesting.class, ParentImports.class, | |||
Variables.class, ParentSelector.class }) | |||
public class ScssTestSuite { | |||
} |
@@ -0,0 +1,84 @@ | |||
package com.vaadin.sass; | |||
import java.io.BufferedReader; | |||
import java.io.File; | |||
import java.io.FileReader; | |||
import java.io.IOException; | |||
import java.net.URISyntaxException; | |||
import org.w3c.css.sac.CSSException; | |||
public class TestBase { | |||
protected ScssStylesheet stylesheet; | |||
protected String originalScss; | |||
protected String parsedScss; | |||
protected String comparisonCss; | |||
public ScssStylesheet getStyleSheet(String filename) | |||
throws URISyntaxException, CSSException, IOException { | |||
File file = getFile(filename); | |||
stylesheet = ScssStylesheet.get(file); | |||
return stylesheet; | |||
} | |||
public File getFile(String filename) throws URISyntaxException, | |||
CSSException, IOException { | |||
return new File(getClass().getResource(filename).toURI()); | |||
} | |||
public String getFileContent(String filename) throws IOException, | |||
CSSException, URISyntaxException { | |||
File file = getFile(filename); | |||
return getFileContent(file); | |||
} | |||
/** | |||
* Read in the full content of a file into a string. | |||
* | |||
* @param file | |||
* the file to be read | |||
* @return a String with the content of the | |||
* @throws IOException | |||
* when file reading fails | |||
*/ | |||
public String getFileContent(File file) throws IOException { | |||
StringBuilder content = new StringBuilder(); | |||
FileReader fileReader = new FileReader(file); | |||
BufferedReader bufferedReader = new BufferedReader(fileReader); | |||
String line = null; | |||
// Handle the first line separately to get the right amount of line | |||
// separators in the loop | |||
if ((line = bufferedReader.readLine()) != null) { | |||
content.append(line); | |||
} | |||
// Handle the rest of the lines | |||
while ((line = bufferedReader.readLine()) != null) { | |||
content.append(System.getProperty("line.separator")); | |||
content.append(line); | |||
} | |||
bufferedReader.close(); | |||
return content.toString(); | |||
} | |||
public boolean testParser(String file) throws CSSException, IOException, | |||
URISyntaxException { | |||
originalScss = getFileContent(file); | |||
ScssStylesheet sheet = getStyleSheet(file); | |||
parsedScss = sheet.toString(); | |||
return parsedScss.equals(originalScss); | |||
} | |||
public boolean testCompiler(String scss, String css) { | |||
try { | |||
comparisonCss = getFileContent(css); | |||
ScssStylesheet sheet = getStyleSheet(scss); | |||
sheet.compile(); | |||
parsedScss = sheet.toString(); | |||
} catch (Exception e) { | |||
return false; | |||
} | |||
return parsedScss.equals(comparisonCss); | |||
} | |||
} |
@@ -0,0 +1,14 @@ | |||
package com.vaadin.sass; | |||
import org.junit.runner.RunWith; | |||
import org.junit.runners.Suite; | |||
import org.junit.runners.Suite.SuiteClasses; | |||
import com.vaadin.sass.testcases.visitor.MixinVisitorTest; | |||
import com.vaadin.sass.testcases.visitor.NestedPropertiesVisitorTest; | |||
@RunWith(Suite.class) | |||
@SuiteClasses({ NestedPropertiesVisitorTest.class, MixinVisitorTest.class }) | |||
public class VisitorTestSuite { | |||
} |
@@ -0,0 +1,49 @@ | |||
package com.vaadin.sass.parser; | |||
import java.io.IOException; | |||
import java.io.StringReader; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
import org.w3c.css.sac.CSSException; | |||
import org.w3c.css.sac.InputSource; | |||
import org.w3c.css.sac.LexicalUnit; | |||
import com.vaadin.sass.handler.SCSSDocumentHandler; | |||
import com.vaadin.sass.handler.SCSSDocumentHandlerImpl; | |||
public class ParserTest { | |||
@Test | |||
public void testParsePropertyValue() throws CSSException, IOException { | |||
Parser parser = new Parser(); | |||
LexicalUnit value = parser.parsePropertyValue(new InputSource( | |||
new StringReader("$margin/2;"))); | |||
Assert.assertEquals("margin", value.getStringValue()); | |||
Assert.assertEquals(SCSSLexicalUnit.SCSS_VARIABLE, | |||
value.getLexicalUnitType()); | |||
value = value.getNextLexicalUnit(); | |||
Assert.assertEquals(LexicalUnit.SAC_OPERATOR_SLASH, | |||
value.getLexicalUnitType()); | |||
value = value.getNextLexicalUnit(); | |||
Assert.assertEquals(LexicalUnit.SAC_INTEGER, value.getLexicalUnitType()); | |||
Assert.assertEquals(2, value.getIntegerValue()); | |||
} | |||
@Test | |||
public void testCanIngoreSingleLineComment() { | |||
Parser parser = new Parser(); | |||
SCSSDocumentHandler handler = new SCSSDocumentHandlerImpl(); | |||
parser.setDocumentHandler(handler); | |||
try { | |||
parser.parseStyleSheet(new InputSource(new StringReader( | |||
"//kjaljsföajsfalkj\n@12abcg;"))); | |||
Assert.assertTrue(true); | |||
} catch (Exception e) { | |||
Assert.fail(e.getMessage()); | |||
} | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
package com.vaadin.sass.testcases.css; | |||
import java.io.IOException; | |||
import java.net.URISyntaxException; | |||
import junit.framework.Assert; | |||
import org.junit.Test; | |||
import org.w3c.css.sac.CSSException; | |||
import com.vaadin.sass.TestBase; | |||
public class Comments extends TestBase { | |||
String css = "/basic/comments.css"; | |||
@Test | |||
public void testParser() throws CSSException, URISyntaxException, | |||
IOException { | |||
testParser(css); | |||
Assert.assertEquals("Original CSS and parsed CSS doesn't match", | |||
originalScss, parsedScss); | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
package com.vaadin.sass.testcases.css; | |||
import java.io.IOException; | |||
import java.net.URISyntaxException; | |||
import junit.framework.Assert; | |||
import org.junit.Test; | |||
import org.w3c.css.sac.CSSException; | |||
import com.vaadin.sass.TestBase; | |||
public class EmptyBlock extends TestBase { | |||
String css = "/basic/empty_block.css"; | |||
@Test | |||
public void testParser() throws CSSException, URISyntaxException, | |||
IOException { | |||
testParser(css); | |||
Assert.assertEquals("Original CSS and parsed CSS doesn't match", | |||
originalScss, parsedScss); | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
package com.vaadin.sass.testcases.css; | |||
import java.io.IOException; | |||
import java.net.URISyntaxException; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
import org.w3c.css.sac.CSSException; | |||
import com.vaadin.sass.ScssStylesheet; | |||
import com.vaadin.sass.TestBase; | |||
import com.vaadin.sass.handler.SCSSDocumentHandler; | |||
import com.vaadin.sass.handler.SCSSDocumentHandlerImpl; | |||
import com.vaadin.sass.parser.Parser; | |||
import com.vaadin.sass.tree.BlockNode; | |||
public class Interpolation extends TestBase { | |||
String scss = "/scss/interpolation.scss"; | |||
@Test | |||
public void testParser() throws CSSException, URISyntaxException, | |||
IOException { | |||
Parser parser = new Parser(); | |||
SCSSDocumentHandler handler = new SCSSDocumentHandlerImpl(); | |||
parser.setDocumentHandler(handler); | |||
parser.parseStyleSheet(getClass().getResource(scss).getPath()); | |||
ScssStylesheet root = handler.getStyleSheet(); | |||
Assert.assertEquals(3, root.getChildren().size()); | |||
BlockNode blockNodeWithInterpolation = (BlockNode) root.getChildren() | |||
.get(2); | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
package com.vaadin.sass.testcases.css; | |||
import java.io.IOException; | |||
import java.net.URISyntaxException; | |||
import junit.framework.Assert; | |||
import org.junit.Test; | |||
import org.w3c.css.sac.CSSException; | |||
import com.vaadin.sass.TestBase; | |||
public class Media extends TestBase { | |||
String css = "/basic/media.css"; | |||
@Test | |||
public void testParser() throws CSSException, URISyntaxException, | |||
IOException { | |||
testParser(css); | |||
Assert.assertEquals("Original CSS and parsed CSS doesn't match", | |||
originalScss, parsedScss); | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
package com.vaadin.sass.testcases.css; | |||
import java.io.IOException; | |||
import java.net.URISyntaxException; | |||
import junit.framework.Assert; | |||
import org.junit.Test; | |||
import org.w3c.css.sac.CSSException; | |||
import com.vaadin.sass.TestBase; | |||
public class Properties extends TestBase { | |||
String css = "/basic/properties.css"; | |||
@Test | |||
public void testParser() throws CSSException, URISyntaxException, | |||
IOException { | |||
testParser(css); | |||
Assert.assertEquals("Original CSS and parsed CSS doesn't match", | |||
originalScss, parsedScss); | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
package com.vaadin.sass.testcases.css; | |||
import java.io.IOException; | |||
import java.net.URISyntaxException; | |||
import junit.framework.Assert; | |||
import org.junit.Test; | |||
import org.w3c.css.sac.CSSException; | |||
import com.vaadin.sass.TestBase; | |||
public class Reindeer extends TestBase { | |||
String css = "/basic/reindeer.css"; | |||
@Test | |||
public void testParser() throws CSSException, URISyntaxException, | |||
IOException { | |||
testParser(css); | |||
Assert.assertEquals("Original CSS and parsed CSS doesn't match", | |||
originalScss, parsedScss); | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
package com.vaadin.sass.testcases.css; | |||
import java.io.IOException; | |||
import java.net.URISyntaxException; | |||
import junit.framework.Assert; | |||
import org.junit.Test; | |||
import org.w3c.css.sac.CSSException; | |||
import com.vaadin.sass.TestBase; | |||
public class Selectors extends TestBase { | |||
String css = "/basic/selectors.css"; | |||
@Test | |||
public void testParser() throws CSSException, URISyntaxException, | |||
IOException { | |||
testParser(css); | |||
Assert.assertEquals("Original CSS and parsed CSS doesn't match", | |||
originalScss, parsedScss); | |||
} | |||
} |
@@ -0,0 +1,40 @@ | |||
package com.vaadin.sass.testcases.scss; | |||
import java.io.IOException; | |||
import java.net.URISyntaxException; | |||
import junit.framework.Assert; | |||
import org.junit.Test; | |||
import org.w3c.css.sac.CSSException; | |||
import com.vaadin.sass.ScssStylesheet; | |||
import com.vaadin.sass.TestBase; | |||
import com.vaadin.sass.handler.SCSSDocumentHandler; | |||
import com.vaadin.sass.handler.SCSSDocumentHandlerImpl; | |||
import com.vaadin.sass.parser.Parser; | |||
public class ControlDirectives extends TestBase { | |||
String scss = "/scss/control-directives.scss"; | |||
String css = "/css/control-directives.css"; | |||
@Test | |||
public void testParser() throws CSSException, IOException { | |||
Parser parser = new Parser(); | |||
SCSSDocumentHandler handler = new SCSSDocumentHandlerImpl(); | |||
parser.setDocumentHandler(handler); | |||
parser.parseStyleSheet(getClass().getResource(scss).getPath()); | |||
ScssStylesheet root = handler.getStyleSheet(); | |||
Assert.assertNotNull(root); | |||
Assert.fail("Implement assert nodes"); | |||
} | |||
@Test | |||
public void testCompiler() throws CSSException, URISyntaxException, | |||
IOException { | |||
testCompiler(scss, css); | |||
Assert.assertEquals("Original CSS and parsed CSS doesn't match", | |||
comparisonCss, parsedScss); | |||
} | |||
} |