diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..29b636a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +*.iml \ No newline at end of file diff --git a/src/main/java/com/vaadin/sass/internal/handler/SCSSDocumentHandlerImpl.java b/src/main/java/com/vaadin/sass/internal/handler/SCSSDocumentHandlerImpl.java index 3837a9a7..7ee75f7e 100644 --- a/src/main/java/com/vaadin/sass/internal/handler/SCSSDocumentHandlerImpl.java +++ b/src/main/java/com/vaadin/sass/internal/handler/SCSSDocumentHandlerImpl.java @@ -22,6 +22,7 @@ import java.util.logging.Level; import java.util.logging.Logger; +import com.vaadin.sass.internal.parser.MediaListImpl; import org.w3c.css.sac.CSSException; import org.w3c.css.sac.InputSource; import org.w3c.css.sac.LexicalUnit; @@ -168,7 +169,7 @@ public void importStyle(String uri, SACMediaList media, @Override public void startMedia(SACMediaList media) throws CSSException { - MediaNode node = new MediaNode(media); + MediaNode node = new MediaNode((MediaListImpl)media); nodeStack.peek().appendChild(node); nodeStack.push(node); } diff --git a/src/main/java/com/vaadin/sass/internal/parser/Interpolation.java b/src/main/java/com/vaadin/sass/internal/parser/Interpolation.java index 12061eff..68e9f7ae 100644 --- a/src/main/java/com/vaadin/sass/internal/parser/Interpolation.java +++ b/src/main/java/com/vaadin/sass/internal/parser/Interpolation.java @@ -130,7 +130,16 @@ public LexicalUnitImpl getContainedValue() { * @return The value of the evaluated expression, a SassListItem. */ public SassListItem replaceInterpolation() { - if (expression instanceof LexicalUnitImpl) { + if (expression instanceof SassList) { + StringBuilder buffer = new StringBuilder(); + if (appendLexicalItems((SassList)expression, buffer)) { + return new LexicalUnitImpl(getLineNumber(), getLineNumber(), + LexicalUnitImpl.SAC_IDENT, buffer.toString()); + + } else { + return expression; + } + } else if (expression instanceof LexicalUnitImpl) { String unquotedString = expression.unquotedString(); return new LexicalUnitImpl(getLineNumber(), getLineNumber(), LexicalUnitImpl.SAC_IDENT, unquotedString); @@ -139,6 +148,27 @@ public SassListItem replaceInterpolation() { } } + private boolean appendLexicalItems(SassList list, StringBuilder buffer) { + boolean first = true; + for (SassListItem sassListItem : list) { + if (first) { + first = false; + } else { + buffer.append(list.getSeparator()); + } + if ((sassListItem instanceof LexicalUnitImpl)) { + buffer.append(((LexicalUnitImpl)sassListItem).unquotedString()); + } else if (sassListItem instanceof SassList) { + if (!appendLexicalItems((SassList)sassListItem, buffer)) { + return false; + } + } else { + return false; + } + } + return true; + } + @Override public boolean containsVariable() { return expression.containsVariable(); diff --git a/src/main/java/com/vaadin/sass/internal/parser/MediaListImpl.java b/src/main/java/com/vaadin/sass/internal/parser/MediaListImpl.java index 579f58e9..0549812b 100644 --- a/src/main/java/com/vaadin/sass/internal/parser/MediaListImpl.java +++ b/src/main/java/com/vaadin/sass/internal/parser/MediaListImpl.java @@ -24,6 +24,8 @@ package com.vaadin.sass.internal.parser; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; import org.w3c.css.sac.SACMediaList; @@ -37,39 +39,49 @@ public class MediaListImpl implements SACMediaList, Serializable { * */ private static final long serialVersionUID = 1L; - String[] array = new String[10]; - int current; + private List items = new ArrayList(); + + public List getSassListItems() { + return items; + } + + public SassListItem getSassListItem(int index) { + if ((index < 0) || (index >= getLength())) { + return null; + } + return items.get(index); + } @Override public int getLength() { - return current; + return items.size(); } @Override public String item(int index) { - if ((index < 0) || (index >= current)) { + if ((index < 0) || (index >= getLength())) { return null; } - return array[index]; + return items.get(index).toString(); } - void addItem(String medium) { + public void addItem(String medium) { if (medium.equals("all")) { - array[0] = "all"; - current = 1; - return; + items.clear(); } - for (int i = 0; i < current; i++) { - if (medium.equals(array[i])) { - return; - } + addItem(new StringItem(medium)); + } + + public void addAllItems(Iterable items) { + for (SassListItem item : items) { + addItem(item); } - if (current == array.length) { - String[] old = array; - array = new String[current + current]; - System.arraycopy(old, 0, array, 0, current); + } + + public void addItem(SassListItem item) { + if (!items.contains(item)) { + items.add(item); } - array[current++] = medium; } /** @@ -77,24 +89,23 @@ void addItem(String medium) { */ @Override public String toString() { - switch (current) { + switch (items.size()) { case 0: return ""; case 1: - return array[0]; + return items.get(0).toString(); default: - boolean not_done = true; - int i = 0; - StringBuffer buf = new StringBuffer(50); - do { - buf.append(array[i++]); - if (i == current) { - not_done = false; + boolean first = true; + StringBuilder buffer = new StringBuilder(50); + for (SassListItem item : items) { + if (first) { + first = false; } else { - buf.append(", "); + buffer.append(", "); } - } while (not_done); - return buf.toString(); + buffer.append(item.toString()); + } + return buffer.toString(); } } } diff --git a/src/main/java/com/vaadin/sass/internal/tree/MediaNode.java b/src/main/java/com/vaadin/sass/internal/tree/MediaNode.java index 5f84e8f9..ed43a6ed 100644 --- a/src/main/java/com/vaadin/sass/internal/tree/MediaNode.java +++ b/src/main/java/com/vaadin/sass/internal/tree/MediaNode.java @@ -16,19 +16,18 @@ package com.vaadin.sass.internal.tree; -import java.util.Collection; -import java.util.Collections; - +import com.vaadin.sass.internal.ScssContext; +import com.vaadin.sass.internal.parser.*; import org.w3c.css.sac.SACMediaList; -import com.vaadin.sass.internal.ScssContext; +import java.util.*; -public class MediaNode extends Node { +public class MediaNode extends Node implements IVariableNode { private static final long serialVersionUID = 2502097081457509523L; - SACMediaList media; + MediaListImpl media; - public MediaNode(SACMediaList media) { + public MediaNode(MediaListImpl media) { super(); this.media = media; } @@ -42,7 +41,7 @@ public SACMediaList getMedia() { return media; } - public void setMedia(SACMediaList media) { + public void setMedia(MediaListImpl media) { this.media = media; } @@ -58,6 +57,7 @@ public String toString() { @Override public Collection traverse(ScssContext context) { + replaceVariables(context); traverseChildren(context); return Collections.singleton((Node) this); } @@ -69,7 +69,7 @@ private String buildString(BuildStringStrategy strategy, boolean indent) { if (i > 0) { builder.append(", "); } - builder.append(media.item(i)); + builder.append(media.getSassListItem(i).buildString(strategy)); } } builder.append(" {\n"); @@ -91,6 +91,25 @@ private String buildString(BuildStringStrategy strategy, boolean indent) { return builder.toString(); } + public void wrapInBlockNode(BlockNode blockNode) { + for (Node child : new ArrayList(getChildren())) { + blockNode.appendChild(child); + } + appendChild(blockNode); + } + + @Override + public void replaceVariables(ScssContext context) { + + MediaListImpl newMedia = new MediaListImpl(); + for (SassListItem sassListItem : media.getSassListItems()) { + StringInterpolationSequence interpolationSequence = new StringInterpolationSequence(Collections.singletonList(sassListItem)); + StringInterpolationSequence replacedSequence = interpolationSequence.replaceVariables(context); + newMedia.addAllItems(replacedSequence.getItems()); + } + media = newMedia; + } + @Override public MediaNode copy() { return new MediaNode(this); diff --git a/src/main/java/com/vaadin/sass/internal/visitor/BlockNodeHandler.java b/src/main/java/com/vaadin/sass/internal/visitor/BlockNodeHandler.java index c18f3989..643a509b 100644 --- a/src/main/java/com/vaadin/sass/internal/visitor/BlockNodeHandler.java +++ b/src/main/java/com/vaadin/sass/internal/visitor/BlockNodeHandler.java @@ -24,6 +24,7 @@ import com.vaadin.sass.internal.ScssStylesheet; import com.vaadin.sass.internal.selector.Selector; import com.vaadin.sass.internal.tree.BlockNode; +import com.vaadin.sass.internal.tree.MediaNode; import com.vaadin.sass.internal.tree.Node; /** @@ -65,6 +66,10 @@ public static Collection traverse(ScssContext context, BlockNode node) { ((BlockNode) child).setParentSelectors(node .getSelectorList()); result.addAll(child.traverse(context)); + } else if (child instanceof MediaNode) { + BlockNode mediaParentNode = new BlockNode(node.getSelectorList()); + ((MediaNode)child).wrapInBlockNode(mediaParentNode); + result.addAll(child.traverse(context)); } else { Collection childTraversed = child .traverse(context); diff --git a/src/main/javacc/com/vaadin/sass/internal/Parser.jj b/src/main/javacc/com/vaadin/sass/internal/Parser.jj index 415ad4a6..d81afd5c 100644 --- a/src/main/javacc/com/vaadin/sass/internal/Parser.jj +++ b/src/main/javacc/com/vaadin/sass/internal/Parser.jj @@ -962,10 +962,36 @@ void media() : void mediaDirective() : {} { - debuggingDirective() | LOOKAHEAD(2) styleRule() | skipUnknownRule() | contentDirective() + styleRuleOrDeclarationOrNestedProperties() | includeDirective() | contentDirective() } void mediaStatement(MediaListImpl ml) : +{ + List seq; + List list = new ArrayList(); +} +{ + (seq = mediaSeq() { list.addAll(seq); } (< COMMA > ( )* seq = mediaSeq() { list.addAll(seq); })* ( )*) + { + ml.addAllItems(list); + } | plainMediaStatement(ml) +} + +List mediaSeq() : +{ + List items = new ArrayList(); + Interpolation s; +} +{ + + (s = interpolation() {items.add(s);}) + { + return items; + } + +} + +void plainMediaStatement(MediaListImpl ml) : { Token t; } @@ -975,7 +1001,10 @@ void mediaStatement(MediaListImpl ml) : // loop over comma separated parts, add each to ml while ((t.kind != LBRACE) && (t.kind != EOF) && (t.kind != SEMICOLON)) { StringBuffer s = new StringBuffer(); - s.append(getToken(0).image); + String image = getToken(0).image; + if (!image.equals("@media")) { + s.append(image); + } while ((t.kind != COMMA) && (t.kind != LBRACE) && (t.kind != EOF) && (t.kind != SEMICOLON)) { s.append(t.image); getNextToken(); @@ -1879,7 +1908,7 @@ Interpolation interpolation() : SassListItem expression; } { - n = < START_INTERPOLATION> { line = n.beginLine; column = n.beginColumn; } expression = expr() + n = < START_INTERPOLATION> { line = n.beginLine; column = n.beginColumn; } expression = expressionList() { return new Interpolation(expression, line, column); }