Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Commit

Permalink
Merge pull request #1509 from jbalsas/css-escapes-fix
Browse files Browse the repository at this point in the history
- Fix for Issue #391
  • Loading branch information
redmunds committed Sep 4, 2012
2 parents 6168ae9 + fd2c0fb commit 6c81f5f
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 3 deletions.
23 changes: 21 additions & 2 deletions src/language/CSSUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ define(function (require, exports, module) {
var selectorStartChar = -1, selectorStartLine = -1;
var selectorGroupStartLine = -1, selectorGroupStartChar = -1;
var declListStartLine = -1, declListStartChar = -1;

var escapePattern = new RegExp("\\\\[^\\\\]+", "g");
var validationPattern = new RegExp("\\\\([a-f0-9]{6}|[a-f0-9]{4}(\\s|\\\\|$)|[a-f0-9]{2}(\\s|\\\\|$)|.)", "i");

// implement _firstToken()/_nextToken() methods to
// provide a single stream of tokens

Expand Down Expand Up @@ -183,7 +185,24 @@ define(function (require, exports, module) {
break;
}
}


// Unicode character replacement as defined in http://www.w3.org/TR/CSS21/syndata.html#characters
if (/\\/.test(currentSelector)) {
// Double replace in case of pattern overlapping (regex improvement?)
currentSelector = currentSelector.replace(escapePattern, function (escapedToken) {
return escapedToken.replace(validationPattern, function (unicodeChar) {
unicodeChar = unicodeChar.substr(1);
if (unicodeChar.length === 1) {
return unicodeChar;
} else {
if (parseInt(unicodeChar, 16) < 0x10FFFF) {
return String.fromCharCode(parseInt(unicodeChar, 16));
} else { return String.fromCharCode(0xFFFD); }
}
});
});
}

currentSelector = currentSelector.trim();
if (currentSelector !== "") {
selectors.push({selector: currentSelector,
Expand Down
61 changes: 61 additions & 0 deletions test/spec/CSSUtils-test-files/escaped-identifiers.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* Test ".si\mple" (simple) */
.si\mple {}

/* Test ".not\\so\|simple\?" (not\so|simple?) */
.not\\so\|simple\? {}

/* Test ".\74 wodigi\74 s" (.twodigits)*/
.\74 wodigi\74 s {}

/* Test ".fourdigi\0074 s" (.fourdigits)*/
.fourdigi\0074 s {}

/* Test ".sixdigi\000074s" (.sixdigits) */
.sixdigi\000074s {}

/* Test ".two-digit-endspac\65 " (.two-digit-endspace) */
.two-digit-endspac\65 {}

/* Test ".four-digit-endspac\0065 " (.four-digit-endspace) */
.four-digit-endspac\0065 {}

/* Test ".six-digit-endspace\000065" (.six-digit-endspace) */
.six-digit-endspac\000065 {}

/* Test ".mi\78 in\002D it\2D a\00006C\006C" (.mixin-it-all) */
.mi\78 in\002D it\2D a\00006C\006C{}

/* Test ".\74 wo-wi\74out-space" (.two-wi74out-space) */
.\74 wo-wi\74out-space {}

/* Test ".four-n\0085-space" (.four-n0085-space) */
.four-n\0085-space {}

/* Test "" Out of range unicode char, uses replace instead */
.\110000\0075\74\cc6699frange {}

.escape\|random\|char {
color: red;
}

.mixin\!tUp {
font-weight: bold;
}

.\34 04 {
background: red;
}

.\34 04 strong {
color: #ff00ff;
font-weight: bold;
}

.trailingTest\+ {
color: red;
}

/* This hideous test of hideousness checks for the selector "blockquote" with various permutations of hex escapes */
\62\6c\6f \63 \6B \0071 \000075o\74 e {
color: silver;
}
77 changes: 76 additions & 1 deletion test/spec/CSSUtils-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ define(function (require, exports, module) {
universalCssFileEntry = new NativeFileSystem.FileEntry(testPath + "/universal.css"),
groupsFileEntry = new NativeFileSystem.FileEntry(testPath + "/groups.css"),
offsetsCssFileEntry = new NativeFileSystem.FileEntry(testPath + "/offsets.css"),
bootstrapCssFileEntry = new NativeFileSystem.FileEntry(testPath + "/bootstrap.css");
bootstrapCssFileEntry = new NativeFileSystem.FileEntry(testPath + "/bootstrap.css"),
escapesCssFileEntry = new NativeFileSystem.FileEntry(testPath + "/escaped-identifiers.css");


/**
Expand Down Expand Up @@ -251,6 +252,80 @@ define(function (require, exports, module) {
});
});


describe("escapes", function() {

beforeEach(function () {
init(this, escapesCssFileEntry);
});

it("should remove simple backslashes for simple characters", function() {
var selectors = CSSUtils.extractAllSelectors(this.fileCssContent);
expect(selectors[0].selector).toEqual(".simple");
});

it("should remove simple backslashes with escaped characters", function() {
var selectors = CSSUtils.extractAllSelectors(this.fileCssContent);
expect(selectors[1].selector).toEqual(".not\\so|simple?");
});

it("should parse '\\XX ' as a single character", function() {
var selectors = CSSUtils.extractAllSelectors(this.fileCssContent);
expect(selectors[2].selector).toEqual(".twodigits");
});

it("should parse '\\XXXX ' as a single character", function() {
var selectors = CSSUtils.extractAllSelectors(this.fileCssContent);
expect(selectors[3].selector).toEqual(".fourdigits");
});

it("should parse '\\XXXXXX' as a single character", function() {
var selectors = CSSUtils.extractAllSelectors(this.fileCssContent);
expect(selectors[4].selector).toEqual(".sixdigits");
});

it("should not trim end spaces", function() {
var selectors = CSSUtils.extractAllSelectors(this.fileCssContent);
expect(selectors[5].selector).toEqual(".two-digit-endspace");

selectors = CSSUtils.extractAllSelectors(this.fileCssContent);
expect(selectors[6].selector).toEqual(".four-digit-endspace");

selectors = CSSUtils.extractAllSelectors(this.fileCssContent);
expect(selectors[7].selector).toEqual(".six-digit-endspace");
});

it("should detect all combinations", function() {
var selectors = CSSUtils.extractAllSelectors(this.fileCssContent);
expect(selectors[8].selector).toEqual(".mixin-it-all");
});

it("should parse '\\AX' as AX", function() {
var selectors = CSSUtils.extractAllSelectors(this.fileCssContent);
expect(selectors[9].selector).toEqual(".two-wi74out-space");
});

it("should parse '\\AXXX' as AXXX", function() {
var selectors = CSSUtils.extractAllSelectors(this.fileCssContent);
expect(selectors[10].selector).toEqual(".four-n0085-space");
});

it("should replace out of range characters with �", function() {
var selectors = CSSUtils.extractAllSelectors(this.fileCssContent);
expect(selectors[11].selector).toEqual(".�ut�frange");
});

it("should parse everything less does", function() {
var selectors = CSSUtils.extractAllSelectors(this.fileCssContent);
expect(selectors[12].selector).toEqual(".escape|random|char");
expect(selectors[13].selector).toEqual(".mixin!tUp");
expect(selectors[14].selector).toEqual(".404");
expect(selectors[15].selector).toEqual(".404 strong");
expect(selectors[16].selector).toEqual(".trailingTest+");
expect(selectors[17].selector).toEqual("blockquote");
});
});

}); // describe("CSSUtils")


Expand Down

0 comments on commit 6c81f5f

Please sign in to comment.