From 9a452212d65d1f0588458bb2945c189f2e5874d5 Mon Sep 17 00:00:00 2001 From: Felix Gnass Date: Sat, 18 May 2013 23:24:54 +0200 Subject: [PATCH 1/3] add option to include location data --- index.js | 35 ++++++++++++++++++++++++++++++++--- test/cases/comment.json | 6 +++++- test/cases/comment.url.json | 6 +++++- test/cases/media.json | 24 ++++++++++++++++++++---- test/cases/media.messed.json | 24 ++++++++++++++++++++---- test/cases/messed-up.json | 18 +++++++++++++++--- test/cases/no-semi.json | 6 +++++- test/cases/props.json | 6 +++++- test/cases/quoted.json | 6 +++++- test/cases/rule.json | 6 +++++- test/cases/rules.json | 12 ++++++++++-- test/cases/supports.json | 6 +++++- test/css-parse.js | 2 +- 13 files changed, 133 insertions(+), 24 deletions(-) diff --git a/index.js b/index.js index 13eae28..d1a8a6c 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,9 @@ -module.exports = function(css){ +module.exports = function(css, opts){ + + var line = 1 + , column = 1 + , location = opts && opts.loc; /** * Parse stylesheet. @@ -48,10 +52,30 @@ module.exports = function(css){ function match(re) { var m = re.exec(css); if (!m) return; + css = css.slice(m[0].length); + updateLocation(m[0]); return m; } + /** + * Update line and column number based on the passed `str`. + */ + + function updateLocation(str) { + if (!location) return; + var re = /\n/g + , i = 0 + , newline; + + while((newline = re.exec(str))) { + line++; + column = 0; + i = newline.index; + } + column += str.length-i; + } + /** * Parse whitespace. */ @@ -81,6 +105,7 @@ module.exports = function(css){ while ('*' != css[i] || '/' != css[i + 1]) ++i; i += 2; var comment = css.slice(2, i - 2); + updateLocation(comment); css = css.slice(i); whitespace(); return { comment: comment }; @@ -334,10 +359,14 @@ module.exports = function(css){ */ function rule() { - var sel = selector(); + var loc = location && { line: line, column: column } + , sel = selector(); + if (!sel) return; comments(); - return { selectors: sel, declarations: declarations() }; + var ret = { selectors: sel, declarations: declarations() }; + if (loc) ret.loc = loc; + return ret; } return stylesheet(); diff --git a/test/cases/comment.json b/test/cases/comment.json index 26bd743..122877d 100644 --- a/test/cases/comment.json +++ b/test/cases/comment.json @@ -19,7 +19,11 @@ "property": "bar", "value": "baz" } - ] + ], + "loc": { + "line": 12, + "column": 1 + } } ] } diff --git a/test/cases/comment.url.json b/test/cases/comment.url.json index 2efc0a8..197494b 100644 --- a/test/cases/comment.url.json +++ b/test/cases/comment.url.json @@ -13,7 +13,11 @@ "property": "bar", "value": "baz" } - ] + ], + "loc": { + "line": 3, + "column": 1 + } } ] } diff --git a/test/cases/media.json b/test/cases/media.json index e7c5a37..c212084 100644 --- a/test/cases/media.json +++ b/test/cases/media.json @@ -17,7 +17,11 @@ "property": "color", "value": "#300" } - ] + ], + "loc": { + "line": 2, + "column": 3 + } }, { "selectors": [ @@ -32,7 +36,11 @@ "property": "margin", "value": "0 auto" } - ] + ], + "loc": { + "line": 6, + "column": 3 + } } ] }, @@ -52,7 +60,11 @@ "property": "color", "value": "#000" } - ] + ], + "loc": { + "line": 13, + "column": 3 + } }, { "selectors": [ @@ -67,7 +79,11 @@ "property": "border", "value": "0.5pt solid #666" } - ] + ], + "loc": { + "line": 17, + "column": 3 + } } ] } diff --git a/test/cases/media.messed.json b/test/cases/media.messed.json index e7c5a37..9184e1a 100644 --- a/test/cases/media.messed.json +++ b/test/cases/media.messed.json @@ -17,7 +17,11 @@ "property": "color", "value": "#300" } - ] + ], + "loc": { + "line": 1, + "column": 28 + } }, { "selectors": [ @@ -32,7 +36,11 @@ "property": "margin", "value": "0 auto" } - ] + ], + "loc": { + "line": 7, + "column": 3 + } } ] }, @@ -52,7 +60,11 @@ "property": "color", "value": "#000" } - ] + ], + "loc": { + "line": 19, + "column": 15 + } }, { "selectors": [ @@ -67,7 +79,11 @@ "property": "border", "value": "0.5pt solid #666" } - ] + ], + "loc": { + "line": 23, + "column": 15 + } } ] } diff --git a/test/cases/messed-up.json b/test/cases/messed-up.json index cd5a121..1e1b06a 100644 --- a/test/cases/messed-up.json +++ b/test/cases/messed-up.json @@ -10,7 +10,11 @@ "property": "foo\n ", "value": "'bar'" } - ] + ], + "loc": { + "line": 1, + "column": 1 + } }, { "selectors": [ @@ -25,7 +29,11 @@ "property": "bar", "value": "baz" } - ] + ], + "loc": { + "line": 5, + "column": 4 + } }, { "selectors": [ @@ -40,7 +48,11 @@ "property": "bar\n ", "value": "baz" } - ] + ], + "loc": { + "line": 6, + "column": 4 + } } ] } diff --git a/test/cases/no-semi.json b/test/cases/no-semi.json index 70165dc..8ae2734 100644 --- a/test/cases/no-semi.json +++ b/test/cases/no-semi.json @@ -14,7 +14,11 @@ "property": "the-species", "value": "called \"ferrets\"" } - ] + ], + "loc": { + "line": 2, + "column": 1 + } } ] } diff --git a/test/cases/props.json b/test/cases/props.json index 8deb41b..ad4cbf2 100644 --- a/test/cases/props.json +++ b/test/cases/props.json @@ -18,7 +18,11 @@ "property": "*even", "value": "'ie crap'" } - ] + ], + "loc": { + "line": 2, + "column": 1 + } } ] } diff --git a/test/cases/quoted.json b/test/cases/quoted.json index fe312a1..c4a787f 100644 --- a/test/cases/quoted.json +++ b/test/cases/quoted.json @@ -10,7 +10,11 @@ "property": "background", "value": "url('some;stuff;here') 50% 50% no-repeat" } - ] + ], + "loc": { + "line": 1, + "column": 1 + } } ] } diff --git a/test/cases/rule.json b/test/cases/rule.json index 99f9445..9efd7f4 100644 --- a/test/cases/rule.json +++ b/test/cases/rule.json @@ -10,7 +10,11 @@ "property": "bar", "value": "'baz'" } - ] + ], + "loc": { + "line": 1, + "column": 1 + } } ] } diff --git a/test/cases/rules.json b/test/cases/rules.json index f941a12..e7b41b9 100644 --- a/test/cases/rules.json +++ b/test/cases/rules.json @@ -10,7 +10,11 @@ "property": "name", "value": "'tobi'" } - ] + ], + "loc": { + "line": 1, + "column": 1 + } }, { "selectors": [ @@ -21,7 +25,11 @@ "property": "name", "value": "'loki'" } - ] + ], + "loc": { + "line": 4, + "column": 1 + } } ] } diff --git a/test/cases/supports.json b/test/cases/supports.json index ecd0b99..18be528 100644 --- a/test/cases/supports.json +++ b/test/cases/supports.json @@ -17,7 +17,11 @@ "property": "display", "value": "flex" } - ] + ], + "loc": { + "line": 2, + "column": 3 + } } ] } diff --git a/test/css-parse.js b/test/css-parse.js index 1777e5b..d988121 100644 --- a/test/css-parse.js +++ b/test/css-parse.js @@ -16,7 +16,7 @@ describe('parse(str)', function(){ it('should parse ' + file, function(){ var css = read(path.join('test', 'cases', file + '.css'), 'utf8'); var json = read(path.join('test', 'cases', file + '.json'), 'utf8'); - var ret = parse(css); + var ret = parse(css, { loc: true }); ret = JSON.stringify(ret, null, 2); ret.should.equal(json); }) From fb2a4ea1be9ebb39c87f7238514f3312d18e7511 Mon Sep 17 00:00:00 2001 From: Felix Gnass Date: Tue, 21 May 2013 10:38:37 +0200 Subject: [PATCH 2/3] add npm test script so that Travis can run the tests --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index a97954e..b389ba1 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,9 @@ "description": "CSS parser", "keywords": ["css", "parser", "stylesheet"], "author": "TJ Holowaychuk ", + "scripts": { + "test": "./node_modules/.bin/mocha --require should" + }, "devDependencies": { "mocha": "*", "should": "*" From 5db9ac20cd0c54d31585ece2784452f942db7fbe Mon Sep 17 00:00:00 2001 From: Felix Gnass Date: Tue, 21 May 2013 10:40:52 +0200 Subject: [PATCH 3/3] add file option to include the name of the parsed file in every `loc` object --- index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index d1a8a6c..300dd02 100644 --- a/index.js +++ b/index.js @@ -365,7 +365,10 @@ module.exports = function(css, opts){ if (!sel) return; comments(); var ret = { selectors: sel, declarations: declarations() }; - if (loc) ret.loc = loc; + if (loc) { + if (opts.file) loc.file = opts.file; + ret.loc = loc; + } return ret; }