From 3b888fe28b22de289ac658e9d36073d751705c70 Mon Sep 17 00:00:00 2001 From: Henri Sara Date: Thu, 23 May 2013 12:42:14 +0300 Subject: [PATCH] Support nested SASS imports (#11909) Change-Id: I05f88e398e7e28f476d8c0d50b7f9ac54a7cba0b --- .../vaadin/sass/internal/parser/Parser.java | 16 ++++++---- .../com/vaadin/sass/internal/parser/Parser.jj | 6 ++-- .../vaadin/sass/internal/tree/ImportNode.java | 5 ++-- .../internal/visitor/ImportNodeHandler.java | 29 +++++++++++++++++-- .../resources/automatic/css/nested-import.css | 5 ++++ .../automatic/scss/nested-import.scss | 3 ++ 6 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 theme-compiler/tests/resources/automatic/css/nested-import.css create mode 100644 theme-compiler/tests/resources/automatic/scss/nested-import.scss diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java index d938dfefe8..382e8e6711 100755 --- a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java @@ -136,6 +136,7 @@ public class Parser implements org.w3c.css.sac.Parser, ParserConstants { * @exception IOException the source can't be parsed. * @exception CSSException the source is not CSS valid. */ + // TODO required by original parser but not used by Vaadin? public void parseRule(InputSource source) throws CSSException, IOException { this.source = source; @@ -1870,6 +1871,7 @@ char connector = ' '; case IDENT: case VARIABLE: case HASH: + case IMPORT_SYM: case MEDIA_SYM: case KEY_FRAME_SYM: ; @@ -1907,6 +1909,9 @@ char connector = ' '; case MICROSOFT_RULE: microsoftExtension(); break; + case IMPORT_SYM: + importDeclaration(); + break; default: jj_la1[69] = jj_gen; jj_consume_token(-1); @@ -6080,6 +6085,7 @@ LexicalUnitImpl result = null; * The following functions are useful for a DOM CSS implementation only and are * not part of the general CSS2 parser. */ +// TODO required by original parser but not used by Vaadin? final public void _parseRule() throws ParseException { String ret = null; label_168: @@ -7364,13 +7370,13 @@ LexicalUnitImpl result = null; return false; } - private boolean jj_3R_261() { - if (jj_scan_token(INTERPOLATION)) return true; + private boolean jj_3_9() { + if (jj_3R_184()) return true; return false; } - private boolean jj_3_9() { - if (jj_3R_184()) return true; + private boolean jj_3R_261() { + if (jj_scan_token(INTERPOLATION)) return true; return false; } @@ -7529,7 +7535,7 @@ LexicalUnitImpl result = null; jj_la1_2 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x401,0x4000,0x0,0x0,0x0,0x0,0x2200,0x0,0x0,0x0,0x400,0x400,0x0,0x0,0x8000,0x0,0x8000,0x0,0x0,0x4465,0x4465,0x0,0x0,0x0,0xae00,0xae00,0x0,0x0,0x0,0x400,0x0,0x0,0x400,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x400,0x0,0x0,0x400,0x0,0xaa00,0x0,0x0,0x0,0x0,0x0,0xe00,0xe00,0x0,0x400,0x400,0x0,0x0,0x0,0x0,0x4465,0x4465,0x0,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400,0x400,0x400,0x400,0x400,0x400,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x0,0x0,0x400,0x0,0x100,0x0,0x0,0x1,0x424,0x4000,0x4c00,0x0,0x4424,0x0,0x2,0x0,0x4c00,0x80,0x0,0x4424,0x0,0x4c00,0x0,0x0,0x0,0x4400,0x0,0x4424,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400,0x0,0x4425,0x4425,0x0,0x0,0x0,0x0,0x0,0x0,0x4000,0x4000,0xffffee00,0x0,0x0,0x0,0x0,0xffffee00,0x0,0x0,0x0,0x4400,0x0,0x0,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400,0x0,0x0,0x400,0x0,0x0,0x400,0x0,0x0,0x0,0x400,0x0,0x0,0x400,0x0,0xffffee00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffffee00,0x0,0xffff8800,0x0,0x400,0x2600,0xffffae00,0x0,0x0,0xffffee00,0x0,0x400,0x0,0x0,0x0,0x400,0x0,0x0,0x400,0x0,}; } private static void jj_la1_init_3() { - jj_la1_3 = new int[] {0x20,0x200,0x200,0x8,0x200,0x0,0x0,0x0,0x1d4,0x0,0x200,0x0,0x200,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x114,0x114,0x0,0x0,0x0,0x31006fc,0x31006fc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x31006f8,0x0,0x0,0x0,0x0,0x0,0x1000000,0x1000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x114,0x114,0x0,0x0,0x0,0x4,0x0,0x4,0x4,0x0,0x0,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000000,0x0,0x0,0x0,0x0,0x0,0x114,0x0,0x800000,0x0,0x114,0x0,0x0,0x0,0x800000,0x0,0x0,0x114,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x114,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000000,0x0,0x1d4,0x1d4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1100007,0x0,0x0,0x0,0x0,0x1100007,0x0,0x0,0x0,0x1000000,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0xe00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x1100007,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1100007,0x0,0x1000003,0x0,0x0,0x100004,0x1100007,0x0,0x0,0x1100007,0x0,0xdc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,}; + jj_la1_3 = new int[] {0x20,0x200,0x200,0x8,0x200,0x0,0x0,0x0,0x1d4,0x0,0x200,0x0,0x200,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x114,0x114,0x0,0x0,0x0,0x31006fc,0x31006fc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x31006f8,0x0,0x0,0x0,0x0,0x0,0x1000000,0x1000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x11c,0x11c,0x0,0x0,0x0,0x4,0x0,0x4,0x4,0x0,0x0,0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000000,0x0,0x0,0x0,0x0,0x0,0x114,0x0,0x800000,0x0,0x114,0x0,0x0,0x0,0x800000,0x0,0x0,0x114,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x114,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000000,0x0,0x1d4,0x1d4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1100007,0x0,0x0,0x0,0x0,0x1100007,0x0,0x0,0x0,0x1000000,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0xe00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x1100007,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1100007,0x0,0x1000003,0x0,0x0,0x100004,0x1100007,0x0,0x0,0x1100007,0x0,0xdc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,}; } final private JJCalls[] jj_2_rtns = new JJCalls[9]; private boolean jj_rescan = false; diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.jj b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.jj index 7f86527015..daf20423d6 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.jj +++ b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.jj @@ -169,6 +169,7 @@ public class Parser implements org.w3c.css.sac.Parser { * @exception IOException the source can't be parsed. * @exception CSSException the source is not CSS valid. */ + // TODO required by original parser but not used by Vaadin? public void parseRule(InputSource source) throws CSSException, IOException { this.source = source; @@ -1188,7 +1189,8 @@ void styleRule() : start = true; documentHandler.startSelector(l); } - ( ifContentStatement() | controlDirective() | microsoftExtension() )* + // a CSS import here will not work + ( ifContentStatement() | controlDirective() | microsoftExtension() | importDeclaration() )* ()* } catch (ThrowedParseException e) { if (errorHandler != null) { @@ -2947,7 +2949,7 @@ String skipAfterExpression() { * The following functions are useful for a DOM CSS implementation only and are * not part of the general CSS2 parser. */ - +// TODO required by original parser but not used by Vaadin? void _parseRule() : {String ret = null; } diff --git a/theme-compiler/src/com/vaadin/sass/internal/tree/ImportNode.java b/theme-compiler/src/com/vaadin/sass/internal/tree/ImportNode.java index f7d664d54d..6dc95db5c2 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/tree/ImportNode.java +++ b/theme-compiler/src/com/vaadin/sass/internal/tree/ImportNode.java @@ -18,7 +18,6 @@ package com.vaadin.sass.internal.tree; import org.w3c.css.sac.SACMediaList; -import com.vaadin.sass.internal.ScssStylesheet; import com.vaadin.sass.internal.visitor.ImportNodeHandler; public class ImportNode extends Node { @@ -74,7 +73,7 @@ public class ImportNode extends Node { @Override public void traverse() { - // TODO shouldn't be reached with current setup, try anyway? - ImportNodeHandler.traverse((ScssStylesheet) getParentNode()); + // nested imports + ImportNodeHandler.traverse(getParentNode()); } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java b/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java index e356ed3525..cb9896967a 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java +++ b/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java @@ -26,6 +26,7 @@ import org.w3c.css.sac.LexicalUnit; import com.vaadin.sass.internal.ScssStylesheet; import com.vaadin.sass.internal.parser.LexicalUnitImpl; +import com.vaadin.sass.internal.parser.ParseException; import com.vaadin.sass.internal.tree.ImportNode; import com.vaadin.sass.internal.tree.Node; import com.vaadin.sass.internal.tree.RuleNode; @@ -33,7 +34,23 @@ import com.vaadin.sass.internal.util.StringUtil; public class ImportNodeHandler { - public static void traverse(ScssStylesheet node) { + public static void traverse(Node node) { + ScssStylesheet styleSheet = null; + if (node instanceof ScssStylesheet) { + styleSheet = (ScssStylesheet) node; + } else { + // iterate to parents of node, find ScssStylesheet + Node parent = node.getParentNode(); + while (parent != null && !(parent instanceof ScssStylesheet)) { + parent = parent.getParentNode(); + } + if (parent instanceof ScssStylesheet) { + styleSheet = (ScssStylesheet) parent; + } + } + if (styleSheet == null) { + throw new ParseException("Nested import in an invalid context"); + } ArrayList c = new ArrayList(node.getChildren()); for (Node n : c) { if (n instanceof ImportNode) { @@ -41,7 +58,7 @@ public class ImportNodeHandler { if (!importNode.isPureCssImport()) { try { StringBuilder filePathBuilder = new StringBuilder( - node.getFileName()); + styleSheet.getFileName()); filePathBuilder.append(File.separatorChar).append( importNode.getUri()); if (!filePathBuilder.toString().endsWith(".scss")) { @@ -50,7 +67,8 @@ public class ImportNodeHandler { // set parent's charset to imported node. ScssStylesheet imported = ScssStylesheet.get( - filePathBuilder.toString(), node.getCharset()); + filePathBuilder.toString(), + styleSheet.getCharset()); if (imported == null) { imported = ScssStylesheet.get(importNode.getUri()); } @@ -76,6 +94,11 @@ public class ImportNodeHandler { } catch (IOException e) { e.printStackTrace(); } + } else { + if (styleSheet != node) { + throw new ParseException( + "CSS imports can only be used at the top level, not as nested imports. Within style rules, use SCSS imports."); + } } } } diff --git a/theme-compiler/tests/resources/automatic/css/nested-import.css b/theme-compiler/tests/resources/automatic/css/nested-import.css new file mode 100644 index 0000000000..7c6793f9ed --- /dev/null +++ b/theme-compiler/tests/resources/automatic/css/nested-import.css @@ -0,0 +1,5 @@ +.foo .bar { + background: url(foo/lorem.png); + background: url(foo/lorem.png); + background: url(foo/lorem.png); +} \ No newline at end of file diff --git a/theme-compiler/tests/resources/automatic/scss/nested-import.scss b/theme-compiler/tests/resources/automatic/scss/nested-import.scss new file mode 100644 index 0000000000..605d64a13a --- /dev/null +++ b/theme-compiler/tests/resources/automatic/scss/nested-import.scss @@ -0,0 +1,3 @@ +.foo { + @import "foo/bar.scss"; +} \ No newline at end of file -- 2.39.5