Fixes line tracking in blocks (@media, @font-face, etc).
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Thu, 6 Nov 2014 13:51:57 +0000 (13:51 +0000)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Mon, 8 Dec 2014 09:39:14 +0000 (09:39 +0000)
lib/selectors/tokenizer.js
lib/utils/extractors.js
lib/utils/source-maps.js
test/selectors/tokenizer-source-maps-test.js

index 48e48d3..d1c727c 100644 (file)
@@ -127,14 +127,15 @@ function tokenize(context) {
         context.cursor = nextEnd + 1;
       } else {
         nextEnd = chunk.indexOf('{', nextSpecial + 1);
-        value = chunk.substring(context.cursor, nextEnd).trim();
+        value = chunk.substring(context.cursor, nextEnd);
 
-        var isFlat = flatBlock.test(value);
+        var trimmedValue = value.trim();
+        var isFlat = flatBlock.test(trimmedValue);
         oldMode = context.mode;
         context.cursor = nextEnd + 1;
         context.mode = isFlat ? 'body' : 'block';
 
-        newToken = { kind: 'block', value: value, isFlatBlock: isFlat };
+        newToken = { kind: 'block', value: trimmedValue, isFlatBlock: isFlat };
 
         if (addSourceMap)
           newToken.metadata = SourceMaps.saveAndTrack(value, context, true);
index 40d1cc9..9575907 100644 (file)
@@ -1,26 +1,6 @@
 var Splitter = require('./splitter');
 var SourceMaps = require('../utils/source-maps');
 
-function tokenMetadata(value, context, addExtra) {
-  var withoutContent;
-  var total;
-  var split = value.split('\n');
-  var shift = 0;
-  for (withoutContent = 0, total = split.length; withoutContent < total; withoutContent++) {
-    var part = split[withoutContent];
-    if (/\S/.test(part))
-      break;
-
-    shift += part.length + 1;
-  }
-
-  context.line += withoutContent;
-  context.column = withoutContent > 0 ? 1 : context.column;
-  context.column += /^(\s)*/.exec(split[withoutContent])[0].length;
-
-  return SourceMaps.saveAndTrack(value.substring(shift).trimLeft(), context, addExtra);
-}
-
 var Extractors = {
   properties: function (string, context) {
     var tokenized = [];
@@ -58,7 +38,7 @@ var Extractors = {
           list.push(property);
 
           if (addSourceMap)
-            token.metadata = tokenMetadata(all.join(''), context, !isEscape);
+            token.metadata = SourceMaps.saveAndTrack(all.join(''), context, !isEscape);
         }
         buffer = [];
         all = [];
@@ -95,7 +75,7 @@ var Extractors = {
       list.push(property);
 
       if (addSourceMap)
-        token.metadata = tokenMetadata(all.join(''), context, false);
+        token.metadata = SourceMaps.saveAndTrack(all.join(''), context, false);
     } else if (all.indexOf('\n') > -1) {
       SourceMaps.track(all.join('\n'), context);
     }
@@ -121,7 +101,7 @@ var Extractors = {
       tokenized.push(token);
 
       if (addSourceMap)
-        token.metadata = tokenMetadata(selector, context, true);
+        token.metadata = SourceMaps.saveAndTrack(selector, context, true);
     }
 
     return {
index 70b4cd8..a36ccb2 100644 (file)
@@ -1,12 +1,34 @@
+function trimLeft(value, context) {
+  var withoutContent;
+  var total;
+  var split = value.split('\n');
+  var shift = 0;
+  for (withoutContent = 0, total = split.length; withoutContent < total; withoutContent++) {
+    var part = split[withoutContent];
+    if (/\S/.test(part))
+      break;
+
+    shift += part.length + 1;
+  }
+
+  context.line += withoutContent;
+  context.column = withoutContent > 0 ? 1 : context.column;
+  context.column += /^(\s)*/.exec(split[withoutContent])[0].length;
+
+  return value.substring(shift).trimLeft();
+}
+
 var SourceMaps = {
   saveAndTrack: function (data, context, hasSuffix) {
+    var trimmedValue = trimLeft(data, context);
+
     var metadata = {
       line: context.line,
       column: context.column,
       source: context.source
     };
 
-    this.track(data, context);
+    this.track(trimmedValue, context);
 
     if (hasSuffix)
       context.column++;
index 8486831..e72589d 100644 (file)
@@ -267,12 +267,12 @@ vows.describe('source-maps/analyzer')
             body: [
               {
                 kind: 'selector',
-                value: [{ value: '\na', metadata: { line: 3, column: 1, source: undefined } }],
-                body: [{ value: 'color:red', metadata: { line: 4, column: 1, source: undefined } }]
+                value: [{ value: '\na', metadata: { line: 4, column: 1, source: undefined } }],
+                body: [{ value: 'color:red', metadata: { line: 5, column: 1, source: undefined } }]
               },
               {
                 kind: 'selector',
-                value: [{ value: 'p', metadata: { line: 5, column: 5, source: undefined } }],
+                value: [{ value: 'p', metadata: { line: 6, column: 5, source: undefined } }],
                 body: []
               }
             ]
@@ -300,6 +300,20 @@ vows.describe('source-maps/analyzer')
             body: []
           }
         ]
+      ],
+      '@font-face with breaks': [
+        '\n@font-face\n{font-family: "Font"}',
+        [
+          {
+            kind: 'block',
+            value: '@font-face',
+            metadata: { line: 2, column: 1, source: undefined },
+            isFlatBlock: true,
+            body: [
+              { value: 'font-family:"Font"', metadata: { line: 3, column: 2, source: undefined } },
+            ]
+          }
+        ]
       ]
     })
   )