Skip to content

Commit

Permalink
better support for \0 and \9 hack (fixes #2)
Browse files Browse the repository at this point in the history
  • Loading branch information
lahmatiy committed Mar 9, 2017
1 parent cd31a15 commit 84728a8
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 3 deletions.
22 changes: 21 additions & 1 deletion lib/lexer/Lexer.js
Expand Up @@ -38,6 +38,26 @@ function valueHasVar(value) {
return hasVar;
}

// check node is \0 or \9 hack
function isHack(node) {
return node.type === 'Identifier' && /^\\[09]/.test(node.name);
}

// white spaces, comments and some hacks can to be ignored at the end of value
function isNextMayToBeIgnored(cursor) {
while (cursor !== null) {
if (cursor.data.type !== 'WhiteSpace' &&
cursor.data.type !== 'Comment' &&
!isHack(cursor.data)) {
return false;
}

cursor = cursor.next;
}

return true;
}

function matchSyntax(lexer, syntax, value) {
var result;

Expand Down Expand Up @@ -65,7 +85,7 @@ function matchSyntax(lexer, syntax, value) {
}
}

if (result.next) {
if (result.next && !isNextMayToBeIgnored(result.next)) {
lexer.lastMatchError = new MatchError('Uncomplete match', lexer, syntax.syntax, value, result.badNode || unwrapNode(result.next));
return null;
}
Expand Down
8 changes: 7 additions & 1 deletion lib/lexer/match.js
Expand Up @@ -312,9 +312,15 @@ module.exports = function match(syntax, syntaxNode, node) {

if (node.data.type === 'Identifier') {
var keyword = names.keyword(node.data.name);
var keywordName = keyword.name;
var name = syntaxNode.name.toLowerCase();

if (name !== keyword.vendor + keyword.name) {
// drop \0 and \9 hack from keyword name
if (keywordName.indexOf('\\') !== -1) {
keywordName = keywordName.replace(/\\[09].*$/, '');
}

if (name !== keyword.vendor + keywordName) {
break mismatch;
}
} else {
Expand Down
8 changes: 7 additions & 1 deletion lib/syntax/scope/default.js
Expand Up @@ -13,6 +13,7 @@ var COMMA = TYPE.Comma;
var SOLIDUS = TYPE.Solidus;
var ASTERISK = TYPE.Asterisk;
var PERCENTSIGN = TYPE.PercentSign;
var BACKSLASH = TYPE.Backslash;
var U = 117; // 'u'.charCodeAt(0)

module.exports = function defaultRecognizer(context) {
Expand Down Expand Up @@ -46,7 +47,12 @@ module.exports = function defaultRecognizer(context) {
return this.Percentage();

case IDENTIFIER:
return this.Dimension();
// edge case: number with folowing \0 and \9 hack shouldn't to be a Dimension
if (cmpChar(this.scanner.source, this.scanner.tokenEnd, BACKSLASH)) {
return this.Number();
} else {
return this.Dimension();
}

default:
return this.Number();
Expand Down
34 changes: 34 additions & 0 deletions test/fixture/parse/value/Value.json
Expand Up @@ -144,6 +144,40 @@
]
}
},
"should parse number with following \\0 or \\9 hack as Number": [
{
"source": "1\\0",
"ast": {
"type": "Value",
"children": [
{
"type": "Number",
"value": "1"
},
{
"type": "Identifier",
"name": "\\0"
}
]
}
},
{
"source": "1\\9",
"ast": {
"type": "Value",
"children": [
{
"type": "Number",
"value": "1"
},
{
"type": "Identifier",
"name": "\\9"
}
]
}
}
],
"should parse a custom property value when parseCustomProperty is true": {
"options": {
"property": "--var",
Expand Down
32 changes: 32 additions & 0 deletions test/fixture/syntax/edgecases.json
Expand Up @@ -12,5 +12,37 @@
"invalid:Mismatch": [
"300"
]
},
"\\9 hack": {
"syntax": {
"generic": true,
"properties": {
"test": "foo | <number> | <length>"
}
},
"valid": [
"foo\\9",
"foo \\9",
"0\\9",
"0 \\9",
"1px\\9",
"1px \\9"
]
},
"\\0 hack": {
"syntax": {
"generic": true,
"properties": {
"test": "foo | <number> | <length>"
}
},
"valid": [
"foo\\0",
"foo \\0",
"0\\0",
"0 \\0",
"1px\\0",
"1px \\0"
]
}
}

0 comments on commit 84728a8

Please sign in to comment.