@@ -522,7 +522,7 @@ TOKEN : | |||
< DEFAULT > | |||
TOKEN : | |||
{ | |||
< EACH_VAR : "#{"< VARIABLE > "}"> | |||
< INTERPOLATION : "#{"< VARIABLE > "}"> | |||
} | |||
<DEFAULT> | |||
@@ -999,7 +999,7 @@ void microsoftExtension() : | |||
< COLON > | |||
((n = < IDENT > { value += n.image; }) | |||
| (n = < NUMBER > { value += n.image; }) | |||
| (n = < EACH_VAR > { value += n.image; }) | |||
| (n = < INTERPOLATION > { value += n.image; }) | |||
| (n = < COLON > { value += n.image; }) | |||
| (n = < FUNCTION > { value += n.image; }) | |||
| (n = < RPARAN > { value += n.image; }) | |||
@@ -1188,7 +1188,7 @@ String _class(String pred) : | |||
String s = "."; | |||
} | |||
{ | |||
"." (t = <IDENT>{s += t.image; }|t = < EACH_VAR >{ s += t.image; })+ | |||
"." (t = <IDENT>{s += t.image; }|t = < INTERPOLATION >{ s += t.image; })+ | |||
{ | |||
if (pred == null) { | |||
@@ -1205,7 +1205,7 @@ String s = "."; | |||
String element_name() : | |||
{Token t; String s = "";} | |||
{ | |||
(t = <IDENT>{s += t.image; }|t = < EACH_VAR >{ s += t.image; })+ | |||
(t = <IDENT>{s += t.image; }|t = < INTERPOLATION >{ s += t.image; })+ | |||
{ | |||
return s; | |||
} | |||
@@ -1483,7 +1483,6 @@ void mixinDirective() : | |||
args = arglist()) <RPARAN> (<S>)*) <LBRACE> (<S>)* | |||
{documentHandler.startMixinDirective(name, args);} | |||
( includeDirective() | media() | eachDirective() | extendDirective()| variable() | LOOKAHEAD(3) declarationOrNestedProperties() | styleRule())* | |||
//(includeDirective() | media() | LOOKAHEAD(declaration()) declaration()";"(<S>)* | styleRule())* | |||
<RBRACE>(<S>)* | |||
{documentHandler.endMixinDirective(name, args);} | |||
} |
@@ -69,7 +69,7 @@ public interface ParserConstants { | |||
/** RegularExpression Id. */ | |||
int COLON = 35; | |||
/** RegularExpression Id. */ | |||
int EACH_VAR = 36; | |||
int INTERPOLATION = 36; | |||
/** RegularExpression Id. */ | |||
int NONASCII = 37; | |||
/** RegularExpression Id. */ | |||
@@ -264,7 +264,7 @@ public interface ParserConstants { | |||
"\"&&\"", | |||
"\"!=\"", | |||
"\":\"", | |||
"<EACH_VAR>", | |||
"<INTERPOLATION>", | |||
"<NONASCII>", | |||
"<H>", | |||
"<UNICODE>", |
@@ -18,7 +18,7 @@ package com.vaadin.sass.tree; | |||
import java.util.ArrayList; | |||
public class BlockNode extends Node implements IVariableNode { | |||
public class BlockNode extends Node implements IVariableNode, InterpolationNode { | |||
private static final long serialVersionUID = 5742962631468325048L; | |||
@@ -66,6 +66,21 @@ public class BlockNode extends Node implements IVariableNode { | |||
@Override | |||
public void replaceVariables(ArrayList<VariableNode> variables) { | |||
if (selectorList == null || selectorList.isEmpty()) { | |||
return; | |||
} | |||
for (final VariableNode var : variables) { | |||
for (final String selector : new ArrayList<String>(selectorList)) { | |||
String interpolation = "#{$" + var.getName() + "}"; | |||
if (selector.contains(interpolation)) { | |||
String replace = selector.replace(interpolation, var | |||
.getExpr().toString()); | |||
selectorList.add(selectorList.indexOf(selector), replace); | |||
selectorList.remove(selector); | |||
} | |||
} | |||
} | |||
} | |||
public String getSelectors() { | |||
@@ -77,4 +92,25 @@ public class BlockNode extends Node implements IVariableNode { | |||
return b.toString(); | |||
} | |||
@Override | |||
public void replaceInterpolation(String variableName, String variable) { | |||
if (selectorList == null || selectorList.isEmpty()) { | |||
return; | |||
} | |||
for (final String selector : new ArrayList<String>(selectorList)) { | |||
String interpolation = "#{" + variableName + "}"; | |||
if (selector.contains(interpolation)) { | |||
String replace = selector.replace(interpolation, variable); | |||
selectorList.add(selectorList.indexOf(selector), replace); | |||
selectorList.remove(selector); | |||
} | |||
} | |||
} | |||
@Override | |||
public boolean containsInterpolationVariable(String variable) { | |||
return getSelectors().contains(variable); | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
package com.vaadin.sass.tree; | |||
public interface InterpolationNode { | |||
public void replaceInterpolation(String variableName, String variable); | |||
public boolean containsInterpolationVariable(String variable); | |||
} |
@@ -17,10 +17,11 @@ | |||
package com.vaadin.sass.tree; | |||
import java.util.ArrayList; | |||
import java.util.regex.Pattern; | |||
import com.vaadin.sass.parser.LexicalUnitImpl; | |||
public class RuleNode extends Node implements IVariableNode { | |||
public class RuleNode extends Node implements IVariableNode, InterpolationNode { | |||
private static final long serialVersionUID = 6653493127869037022L; | |||
String variable; | |||
@@ -83,10 +84,11 @@ public class RuleNode extends Node implements IVariableNode { | |||
public void replaceVariables(ArrayList<VariableNode> variables) { | |||
for (final VariableNode node : variables) { | |||
if (value.getLexicalUnitType() == LexicalUnitImpl.SAC_FUNCTION) { | |||
if (value.getParameters().toString().contains(node.getName())) { | |||
if (value.getParameters().toString() | |||
.contains("$" + node.getName())) { | |||
if (value.getParameters() != null) { | |||
if (value.getParameters().toString() | |||
.contains("$" + node.getName())) { | |||
.contains(node.getName())) { | |||
LexicalUnitImpl param = value.getParameters(); | |||
while (param != null) { | |||
@@ -125,4 +127,34 @@ public class RuleNode extends Node implements IVariableNode { | |||
} | |||
} | |||
} | |||
@Override | |||
public void replaceInterpolation(String variableName, String variable) { | |||
if (this.variable.contains(variableName)) { | |||
this.variable = this.variable.replaceAll(variableName, variable); | |||
} | |||
if (value.toString().contains(variableName)) { | |||
LexicalUnitImpl current = value; | |||
while (current != null) { | |||
if (current.getValue().toString().contains(variableName)) { | |||
current.setStringValue(current | |||
.getValue() | |||
.toString() | |||
.replaceAll( | |||
Pattern.quote("#{" + variableName + "}"), | |||
variable)); | |||
} | |||
current = value.getNextLexicalUnit(); | |||
} | |||
} | |||
} | |||
@Override | |||
public boolean containsInterpolationVariable(String variable) { | |||
return value.toString().contains(variable) | |||
|| this.variable.contains(variable); | |||
} | |||
} |
@@ -1,54 +1,70 @@ | |||
package com.vaadin.sass.visitor; | |||
import java.util.HashSet; | |||
import java.util.regex.Pattern; | |||
import java.util.HashMap; | |||
import java.util.Map.Entry; | |||
import com.vaadin.sass.tree.BlockNode; | |||
import com.vaadin.sass.tree.Node; | |||
import com.vaadin.sass.tree.SimpleNode; | |||
import com.vaadin.sass.tree.RuleNode; | |||
import com.vaadin.sass.tree.controldirective.EachDefNode; | |||
import com.vaadin.sass.util.DeepCopy; | |||
public class EachVisitor implements Visitor { | |||
HashSet<EachDefNode> controlDefs = new HashSet<EachDefNode>(); | |||
HashMap<EachDefNode, Node> controlDefs = new HashMap<EachDefNode, Node>(); | |||
private Node rootNode; | |||
@Override | |||
public void traverse(Node node) throws Exception { | |||
this.rootNode = node; | |||
for (Node child : node.getChildren()) { | |||
if (child instanceof EachDefNode) { | |||
controlDefs.add((EachDefNode) child); | |||
} | |||
} | |||
findDefNodes(null, node); | |||
replaceControlNodes(); | |||
} | |||
private void replaceControlNodes() { | |||
for (final EachDefNode defNode : controlDefs) { | |||
replaceEachDefNode(defNode); | |||
private void findDefNodes(Node parent, Node node) { | |||
for (Node child : node.getChildren()) { | |||
findDefNodes(node, child); | |||
} | |||
if (node instanceof EachDefNode) { | |||
controlDefs.put((EachDefNode) node, parent); | |||
} | |||
} | |||
private void replaceControlNodes() { | |||
for (final Entry<EachDefNode, Node> entry : controlDefs.entrySet()) { | |||
replaceEachDefNode(entry.getKey(), entry.getValue()); | |||
} | |||
} | |||
private void replaceEachDefNode(EachDefNode defNode) { | |||
private void replaceEachDefNode(EachDefNode defNode, Node parent) { | |||
Node last = defNode; | |||
for (final Node child : defNode.getChildren()) { | |||
if (child instanceof BlockNode) { | |||
Node lastNode = defNode; | |||
for (final String variable : defNode.getVariables()) { | |||
BlockNode iNode = (BlockNode) child; | |||
String interpolation = "#{" + defNode.getVariableName() + "}"; | |||
if (iNode.containsInterpolationVariable(interpolation)) { | |||
for (final String variable : defNode.getVariables()) { | |||
BlockNode copy = (BlockNode) DeepCopy.copy(child); | |||
copy.replaceInterpolation(defNode.getVariableName(), | |||
variable); | |||
String output = child.toString(); | |||
output = output.replaceAll( | |||
Pattern.quote("#{" + defNode.getVariableName() | |||
+ "}"), variable); | |||
SimpleNode simple = new SimpleNode(output); | |||
for (final Node blockChild : copy.getChildren()) { | |||
if (blockChild instanceof RuleNode) { | |||
((RuleNode) blockChild).replaceInterpolation( | |||
defNode.getVariableName(), variable); | |||
} | |||
} | |||
rootNode.appendChild(simple, lastNode); | |||
lastNode = simple; | |||
parent.appendChild(copy, last); | |||
last = copy; | |||
} | |||
} | |||
} | |||
last = child; | |||
} | |||
rootNode.removeChild(defNode); | |||
} |
@@ -24,6 +24,10 @@ | |||
border: 1px solid black; | |||
} | |||
.interpolation-test { | |||
font-size: 14px; | |||
} | |||
.header { | |||
width: 100%; | |||
} |
@@ -62,4 +62,12 @@ $mixinVar : 1px; | |||
border : $border; | |||
} | |||
@include interpolation(interpolation); | |||
@mixin interpolation($interpolation){ | |||
.#{$interpolation}-test { | |||
font-size: 14px; | |||
} | |||
} | |||
@include layout; |
@@ -19,8 +19,7 @@ package com.vaadin.sass.testcases.scss; | |||
import java.io.IOException; | |||
import java.net.URISyntaxException; | |||
import junit.framework.Assert; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
import org.w3c.css.sac.CSSException; | |||
import org.w3c.css.sac.LexicalUnit; | |||
@@ -64,7 +63,7 @@ public class Mixins extends AbstractTestBase { | |||
Assert.assertEquals(LexicalUnit.SAC_PIXEL, mixinDefNode1.getArglist() | |||
.get(1).getExpr().getLexicalUnitType()); | |||
Assert.assertEquals(3f, mixinDefNode1.getArglist().get(1).getExpr() | |||
.getFloatValue()); | |||
.getFloatValue(), 0f); | |||
Assert.assertEquals(4, mixinDefNode1.getChildren().size()); | |||