compiler Support for expression of non-breaking-space and zero-width-space in CSS
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/royale/JSCSSCompilationSession.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/royale/JSCSSCompilationSession.java
index 88a5d49..2b9d067 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/royale/JSCSSCompilationSession.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/royale/JSCSSCompilationSession.java
@@ -347,10 +347,22 @@
private String escapeDoubleQuotes(String s)
{
+ s = replaceUnicodeEncoded(s);
if (s.contains("\""))
s = s.replace("\"", "\\\"");
return s;
}
+
+ private String replaceUnicodeEncoded(String s)
+ {
+ //almost all escape sequences are converted to actual character sequences, except for some that don't have
+ //a good result for Character.toChars (e.g. zero width space or non-breaking-space)
+ //convert hex char values to unicode
+ if (s.matches("\\\\[0-9a-fA-F]{1,4}")) {
+ s = s.replaceAll("\\\\([0-9a-fA-F]{1,4})\\s?","\\\\u$1");
+ }
+ return s;
+ }
private String encodeRule(ICSSRule rule)
{
@@ -378,7 +390,6 @@
ImmutableList<ICSSSelector> slist = rule.getSelectorGroup();
result.append(slist.size());
-
for (ICSSSelector sel : slist)
{
result.append(",\n");
@@ -525,7 +536,7 @@
}
else if (value instanceof CSSStringPropertyValue)
{
- line.append("\"" + ((CSSStringPropertyValue)value).getValue() + "\"");
+ line.append("\"" + replaceUnicodeEncoded(((CSSStringPropertyValue)value).getValue()) + "\"");
}
else if (value instanceof CSSColorPropertyValue)
{
diff --git a/compiler/src/main/antlr3/org/apache/royale/compiler/internal/css/CSS.g b/compiler/src/main/antlr3/org/apache/royale/compiler/internal/css/CSS.g
index e14dc99..37b631a 100644
--- a/compiler/src/main/antlr3/org/apache/royale/compiler/internal/css/CSS.g
+++ b/compiler/src/main/antlr3/org/apache/royale/compiler/internal/css/CSS.g
@@ -140,28 +140,32 @@
// Check if there's white space between the previous token and the next token.
final CommonToken lastToken = (CommonToken) getTokenStream().LT(-1);
- final int lastType = lastToken.getType();
- if (lastType == CHILD)
- {
- return 1;
- }
- if (lastType == PRECEDED)
+ if (lastToken != null)
{
- return 2;
- }
- if (lastType == TILDE)
- {
- return 3;
- }
- if (lastToken != null && nextToken != null)
- {
- final int lastStop = lastToken.getStopIndex();
- final int nextStart = nextToken.getStartIndex();
- if (lastStop + 1 < nextStart)
+ final int lastType = lastToken.getType();
+ if (lastType == CHILD)
{
- return 0;
+ return 1;
+ }
+ if (lastType == PRECEDED)
+ {
+ return 2;
+ }
+ if (lastType == TILDE)
+ {
+ return 3;
+ }
+ if (nextToken != null)
+ {
+ final int lastStop = lastToken.getStopIndex();
+ final int nextStart = nextToken.getStartIndex();
+ if (lastStop + 1 < nextStart)
+ {
+ return 0;
+ }
}
}
+
// If the next token is "{" or ",", it's also end of a selector.
if (nextType == BLOCK_OPEN || nextType == COMMA)
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSStringPropertyValue.java b/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSStringPropertyValue.java
index 22dd35b..c5c5a57 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSStringPropertyValue.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSStringPropertyValue.java
@@ -81,7 +81,8 @@
{
int idx = 0;
int c = value.indexOf('\\');
- while (c != -1)
+
+ while (c != -1 && c + 1 < value.length())
{
char cnext = value.charAt(c + 1);
if (cnext != '\\' && cnext != 'n' && cnext != 't' && cnext != 'r')
@@ -94,15 +95,28 @@
for (; i < n; i++)
{
char cc = value.charAt(c + i + 1);
- if (cc != ' ')
+ if (cc != ' ') {
sub.append(cc);
+ idx++; //this represents each 'digit' char
+ }
else
break;
}
+ idx++; //this represents the first escape char
int ccode = Integer.parseInt(sub.toString(), 16);
- sub = new StringBuilder();
- sub.append(Character.toChars(ccode));
- value = value.substring(0, c) + sub.toString() + value.substring(c + i + 1);
+ String insert;
+
+ if (ccode == /* nbsp */ 0xA0) {
+ insert = "\\a0"; //restore nbsp as the encoded form
+ } else if (ccode == /* ZERO WIDTH SPACE */ 0x200B) {
+ insert = "\\200b"; //restore zero-width space as the encoded form
+ } else {
+ sub = new StringBuilder();
+ sub.append(Character.toChars(ccode));
+ insert = sub.toString();
+ }
+
+ value = value.substring(0, c) + insert + value.substring(c + i + 1);
}
else
idx += 2;