Adds source file tracking to source maps.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Sun, 2 Nov 2014 15:57:17 +0000 (15:57 +0000)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Mon, 8 Dec 2014 09:39:14 +0000 (09:39 +0000)
lib/clean.js
lib/imports/inliner.js
lib/selectors/tokenizer.js
lib/utils/source-maps.js
test/selectors/tokenizer-source-maps-test.js

index a7693c0..f3f4b93 100644 (file)
@@ -86,7 +86,7 @@ function runMinifier(callback, self) {
 
 function minifyWithDebug(self, data) {
   var startedAt = process.hrtime();
-  self.stats.originalSize = data.length;
+  self.stats.originalSize = data.replace(/__ESCAPED_SOURCE_CLEAN_CSS\(.+\)__/g, '').length;
 
   data = minify.call(self, data);
 
index ec2b67a..0a64165 100644 (file)
@@ -249,6 +249,7 @@ module.exports = function Inliner(context, options) {
       res.on('end', function() {
         var importedData = chunks.join('');
         importedData = UrlRewriter.process(importedData, { toBase: importedUrl });
+        importedData = '__ESCAPED_SOURCE_CLEAN_CSS(' + url + ')__' + importedData;
 
         if (mediaQuery.length > 0)
           importedData = '@media ' + mediaQuery + '{' + importedData + '}';
@@ -300,6 +301,7 @@ module.exports = function Inliner(context, options) {
       fromBase: importRelativeTo,
       toBase: options._baseRelativeTo
     });
+    importedData = '__ESCAPED_SOURCE_CLEAN_CSS(' + path.relative(options.root, fullPath) + ')__' + importedData;
 
     if (mediaQuery.length > 0)
       importedData = '@media ' + mediaQuery + '{' + importedData + '}';
index 568fbb8..48e48d3 100644 (file)
@@ -26,7 +26,8 @@ Tokenizer.prototype.toTokens = function (data) {
     addMetadata: this.addMetadata,
     addSourceMap: this.addSourceMap,
     line: 1,
-    column: 1
+    column: 1,
+    source: undefined
   };
 
   return tokenize(context);
@@ -152,7 +153,13 @@ function tokenize(context) {
     } else if (what == 'escape') {
       nextEnd = chunk.indexOf('__', nextSpecial + 1);
       var escaped = chunk.substring(context.cursor, nextEnd + 2);
-      tokenized.push({ kind: 'text', value: escaped });
+      var isSourceMarker = escaped.indexOf('__ESCAPED_SOURCE_CLEAN_CSS') > -1;
+
+      if (isSourceMarker) {
+        context.source = escaped.substring(escaped.indexOf('(') + 1, escaped.indexOf(')'));
+      } else {
+        tokenized.push({ kind: 'text', value: escaped });
+      }
 
       if (addSourceMap)
         SourceMaps.track(escaped, context);
index 1413c7a..70b4cd8 100644 (file)
@@ -2,7 +2,8 @@ var SourceMaps = {
   saveAndTrack: function (data, context, hasSuffix) {
     var metadata = {
       line: context.line,
-      column: context.column
+      column: context.column,
+      source: context.source
     };
 
     this.track(data, context);
index 6a36d36..8486831 100644 (file)
@@ -32,7 +32,7 @@ vows.describe('source-maps/analyzer')
         'a{}',
         [{
           kind: 'selector',
-          value: [{ value: 'a', metadata: { line: 1, column: 1 } }],
+          value: [{ value: 'a', metadata: { line: 1, column: 1, source: undefined } }],
           body: []
         }]
       ],
@@ -41,8 +41,8 @@ vows.describe('source-maps/analyzer')
         [{
           kind: 'selector',
           value: [
-            { value: 'a', metadata: { line: 1, column: 1 } },
-            { value: 'div', metadata: { line: 1, column: 3 } }
+            { value: 'a', metadata: { line: 1, column: 1, source: undefined } },
+            { value: 'div', metadata: { line: 1, column: 3, source: undefined } }
           ],
           body: []
         }]
@@ -52,8 +52,8 @@ vows.describe('source-maps/analyzer')
         [{
           kind: 'selector',
           value: [
-            { value: ' a', metadata: { line: 1, column: 2 } },
-            { value: '\n\ndiv', metadata: { line: 3, column: 1 } }
+            { value: ' a', metadata: { line: 1, column: 2, source: undefined } },
+            { value: '\n\ndiv', metadata: { line: 3, column: 1, source: undefined } }
           ],
           body: []
         }]
@@ -63,9 +63,9 @@ vows.describe('source-maps/analyzer')
         [{
           kind: 'selector',
           value: [
-            { value: 'a', metadata: { line: 1, column: 1 } },
-            { value: 'div', metadata: { line: 1, column: 3 } },
-            { value: 'p', metadata: { line: 1, column: 7 } }
+            { value: 'a', metadata: { line: 1, column: 1, source: undefined } },
+            { value: 'div', metadata: { line: 1, column: 3, source: undefined } },
+            { value: 'p', metadata: { line: 1, column: 7, source: undefined } }
           ],
           body: []
         }]
@@ -75,9 +75,9 @@ vows.describe('source-maps/analyzer')
         [{
           kind: 'selector',
           value: [
-            { value: ' a', metadata: { line: 1, column: 2 } },
-            { value: '\n\ndiv\na', metadata: { line: 3, column: 1 } },
-            { value: '\n p', metadata: { line: 5, column: 2 } }
+            { value: ' a', metadata: { line: 1, column: 2, source: undefined } },
+            { value: '\n\ndiv\na', metadata: { line: 3, column: 1, source: undefined } },
+            { value: '\n p', metadata: { line: 5, column: 2, source: undefined } }
           ],
           body: []
         }]
@@ -87,12 +87,12 @@ vows.describe('source-maps/analyzer')
         [
           {
             kind: 'selector',
-            value: [{ value: 'a', metadata: { line: 1, column: 1 } }],
+            value: [{ value: 'a', metadata: { line: 1, column: 1, source: undefined } }],
             body: []
           },
           {
             kind: 'selector',
-            value: [{ value: 'div', metadata: { line: 1, column: 4 } }],
+            value: [{ value: 'div', metadata: { line: 1, column: 4, source: undefined } }],
             body: []
           }
         ]
@@ -102,17 +102,17 @@ vows.describe('source-maps/analyzer')
         [
           {
             kind: 'selector',
-            value: [{ value: 'a ', metadata: { line: 1, column: 1 } }],
+            value: [{ value: 'a ', metadata: { line: 1, column: 1, source: undefined } }],
             body: []
           },
           {
             kind: 'selector',
-            value: [{ value: '\n\ndiv', metadata: { line: 3, column: 1 } }],
+            value: [{ value: '\n\ndiv', metadata: { line: 3, column: 1, source: undefined } }],
             body: []
           },
           {
             kind: 'selector',
-            value: [{ value: '\n \n  p', metadata: { line: 5, column: 3 } }],
+            value: [{ value: '\n \n  p', metadata: { line: 5, column: 3, source: undefined } }],
             body: []
           }
         ]
@@ -125,18 +125,18 @@ vows.describe('source-maps/analyzer')
         'a{color:red}',
         [{
           kind: 'selector',
-          value: [{ value: 'a', metadata: { line: 1, column: 1 } }],
-          body: [{ value: 'color:red', metadata: { line: 1, column: 3 } }]
+          value: [{ value: 'a', metadata: { line: 1, column: 1, source: undefined } }],
+          body: [{ value: 'color:red', metadata: { line: 1, column: 3, source: undefined } }]
         }]
       ],
       'double': [
         'a{color:red;border:none}',
         [{
           kind: 'selector',
-          value: [{ value: 'a', metadata: { line: 1, column: 1 } }],
+          value: [{ value: 'a', metadata: { line: 1, column: 1, source: undefined } }],
           body: [
-            { value: 'color:red', metadata: { line: 1, column: 3 } },
-            { value: 'border:none', metadata: { line: 1, column: 13 } }
+            { value: 'color:red', metadata: { line: 1, column: 3, source: undefined } },
+            { value: 'border:none', metadata: { line: 1, column: 13, source: undefined } }
           ]
         }]
       ],
@@ -144,11 +144,11 @@ vows.describe('source-maps/analyzer')
         'a{color:red;\nborder:\nnone;\n\n  display:block}',
         [{
           kind: 'selector',
-          value: [{ value: 'a', metadata: { line: 1, column: 1 } }],
+          value: [{ value: 'a', metadata: { line: 1, column: 1, source: undefined } }],
           body: [
-            { value: 'color:red', metadata: { line: 1, column: 3 } },
-            { value: 'border:none', metadata: { line: 2, column: 1 } },
-            { value: 'display:block', metadata: { line: 5, column: 3 } }
+            { value: 'color:red', metadata: { line: 1, column: 3, source: undefined } },
+            { value: 'border:none', metadata: { line: 2, column: 1, source: undefined } },
+            { value: 'display:block', metadata: { line: 5, column: 3, source: undefined } }
           ]
         }]
       ],
@@ -157,13 +157,13 @@ vows.describe('source-maps/analyzer')
         [
           {
             kind: 'selector',
-            value: [{ value: 'a', metadata: { line: 1, column: 1 } }],
-            body: [{ value: 'color:red', metadata: { line: 1, column: 3 } }]
+            value: [{ value: 'a', metadata: { line: 1, column: 1, source: undefined } }],
+            body: [{ value: 'color:red', metadata: { line: 1, column: 3, source: undefined } }]
           },
           {
             kind: 'selector',
-            value: [{ value: 'div', metadata: { line: 1, column: 13 } }],
-            body: [{ value: 'color:blue', metadata: { line: 1, column: 17 } }]
+            value: [{ value: 'div', metadata: { line: 1, column: 13, source: undefined } }],
+            body: [{ value: 'color:blue', metadata: { line: 1, column: 17, source: undefined } }]
           }
         ]
       ],
@@ -172,13 +172,13 @@ vows.describe('source-maps/analyzer')
         [
           {
             kind: 'selector',
-            value: [{ value: 'a', metadata: { line: 1, column: 1 } }],
-            body: [{ value: 'color:red', metadata: { line: 1, column: 3 } }]
+            value: [{ value: 'a', metadata: { line: 1, column: 1, source: undefined } }],
+            body: [{ value: 'color:red', metadata: { line: 1, column: 3, source: undefined } }]
           },
           {
             kind: 'selector',
-            value: [{ value: '\n div', metadata: { line: 2, column: 2 } }],
-            body: [{ value: 'color:blue', metadata: { line: 2, column: 6 } }]
+            value: [{ value: '\n div', metadata: { line: 2, column: 2, source: undefined } }],
+            body: [{ value: 'color:blue', metadata: { line: 2, column: 6, source: undefined } }]
           }
         ]
       ],
@@ -187,13 +187,13 @@ vows.describe('source-maps/analyzer')
         [
           {
             kind: 'selector',
-            value: [{ value: 'a', metadata: { line: 1, column: 1 } }],
-            body: [{ value: 'color:red', metadata: { line: 1, column: 3 } }]
+            value: [{ value: 'a', metadata: { line: 1, column: 1, source: undefined } }],
+            body: [{ value: 'color:red', metadata: { line: 1, column: 3, source: undefined } }]
           },
           {
             kind: 'selector',
-            value: [{ value: '\n div', metadata: { line: 3, column: 2 } }],
-            body: [{ value: 'color:blue', metadata: { line: 3, column: 6 } }]
+            value: [{ value: '\n div', metadata: { line: 3, column: 2, source: undefined } }],
+            body: [{ value: 'color:blue', metadata: { line: 3, column: 6, source: undefined } }]
           }
         ]
       ]
@@ -206,18 +206,18 @@ vows.describe('source-maps/analyzer')
         [
           {
             kind: 'selector',
-            value: [{ value: 'a', metadata: { line: 1, column: 1 } }],
+            value: [{ value: 'a', metadata: { line: 1, column: 1, source: undefined } }],
             body: []
           },
           {
             kind: 'at-rule',
             value: '@import \n"test.css";',
-            metadata: { line: 1, column: 4 }
+            metadata: { line: 1, column: 4, source: undefined }
           },
           {
             kind: 'selector',
-            value: [{ value: '\n\na', metadata: { line: 4, column: 1 } }],
-            body: [{ value: 'color:red', metadata: { line: 4, column: 3 } }]
+            value: [{ value: '\n\na', metadata: { line: 4, column: 1, source: undefined } }],
+            body: [{ value: 'color:red', metadata: { line: 4, column: 3, source: undefined } }]
           }
         ]
       ],
@@ -227,12 +227,12 @@ vows.describe('source-maps/analyzer')
           {
             kind: 'at-rule',
             value: '@charset "utf-8";',
-            metadata: { line: 1, column: 1 }
+            metadata: { line: 1, column: 1, source: undefined }
           },
           {
             kind: 'selector',
-            value: [{ value: 'a', metadata: { line: 1, column: 19 } }],
-            body: [{ value: 'color:red', metadata: { line: 1, column: 21 } }]
+            value: [{ value: 'a', metadata: { line: 1, column: 19, source: undefined } }],
+            body: [{ value: 'color:red', metadata: { line: 1, column: 21, source: undefined } }]
           }
         ]
       ]
@@ -246,12 +246,12 @@ vows.describe('source-maps/analyzer')
           {
             kind: 'block',
             value: '@media (min-width:980px)',
-            metadata: { line: 1, column: 1 },
+            metadata: { line: 1, column: 1, source: undefined },
             isFlatBlock: false,
             body: [{
               kind: 'selector',
-              value: [{ value: 'a', metadata: { line: 1, column: 26 } }],
-              body: [{ value: 'color:red', metadata: { line: 1, column: 28 } }]
+              value: [{ value: 'a', metadata: { line: 1, column: 26, source: undefined } }],
+              body: [{ value: 'color:red', metadata: { line: 1, column: 28, source: undefined } }]
             }]
           }
         ]
@@ -262,17 +262,17 @@ vows.describe('source-maps/analyzer')
           {
             kind: 'block',
             value: '@media (\nmin-width:980px)',
-            metadata: { line: 1, column: 1 },
+            metadata: { line: 1, column: 1, source: undefined },
             isFlatBlock: false,
             body: [
               {
                 kind: 'selector',
-                value: [{ value: '\na', metadata: { line: 3, column: 1 } }],
-                body: [{ value: 'color:red', metadata: { line: 4, column: 1 } }]
+                value: [{ value: '\na', metadata: { line: 3, column: 1, source: undefined } }],
+                body: [{ value: 'color:red', metadata: { line: 4, column: 1, source: undefined } }]
               },
               {
                 kind: 'selector',
-                value: [{ value: 'p', metadata: { line: 5, column: 5 } }],
+                value: [{ value: 'p', metadata: { line: 5, column: 5, source: undefined } }],
                 body: []
               }
             ]
@@ -285,18 +285,18 @@ vows.describe('source-maps/analyzer')
           {
             kind: 'block',
             value: '@font-face',
-            metadata: { line: 1, column: 1 },
+            metadata: { line: 1, column: 1, source: undefined },
             isFlatBlock: true,
             body: [
-              { value: 'font-family:"Font"', metadata: { line: 1, column: 12 } },
-              { value: 'src:url("font.ttf")', metadata: { line: 2, column: 1 } },
-              { value: 'font-weight:normal', metadata: { line: 3, column: 1 } },
-              { value: 'font-style:normal', metadata: { line: 3, column: 21 } }
+              { value: 'font-family:"Font"', metadata: { line: 1, column: 12, source: undefined } },
+              { value: 'src:url("font.ttf")', metadata: { line: 2, column: 1, source: undefined } },
+              { value: 'font-weight:normal', metadata: { line: 3, column: 1, source: undefined } },
+              { value: 'font-style:normal', metadata: { line: 3, column: 21, source: undefined } }
             ]
           },
           {
             kind: 'selector',
-            value: [{ value: 'a', metadata: { line: 3, column: 40 } }],
+            value: [{ value: 'a', metadata: { line: 3, column: 40, source: undefined } }],
             body: []
           }
         ]
@@ -314,7 +314,7 @@ vows.describe('source-maps/analyzer')
           },
           {
             kind: 'selector',
-            value: [{ value: 'a', metadata: { line: 1, column: 6 } }],
+            value: [{ value: 'a', metadata: { line: 1, column: 6, source: undefined } }],
             body: []
           }
         ]
@@ -328,7 +328,7 @@ vows.describe('source-maps/analyzer')
           },
           {
             kind: 'selector',
-            value: [{ value: 'a', metadata: { line: 3, column: 6 } }],
+            value: [{ value: 'a', metadata: { line: 3, column: 6, source: undefined } }],
             body: []
           }
         ]
@@ -338,10 +338,10 @@ vows.describe('source-maps/analyzer')
         [{
           kind: 'selector',
           value: [
-            { value: 'div[data-type=__ESCAPED_FREE_TEXT_CLEAN_CSS0(1,3)__]', metadata: { line: 1, column: 1 } },
-            { value: 'div[data-id=__ESCAPED_FREE_TEXT_CLEAN_CSS1(0,7)__]', metadata: { line: 2, column: 6 } }
+            { value: 'div[data-type=__ESCAPED_FREE_TEXT_CLEAN_CSS0(1,3)__]', metadata: { line: 1, column: 1, source: undefined } },
+            { value: 'div[data-id=__ESCAPED_FREE_TEXT_CLEAN_CSS1(0,7)__]', metadata: { line: 2, column: 6, source: undefined } }
           ],
-          body: [{ value: 'color:red', metadata: { line: 2, column: 27 } }]
+          body: [{ value: 'color:red', metadata: { line: 2, column: 27, source: undefined } }]
         }]
       ],
       'in properties': [
@@ -349,19 +349,19 @@ vows.describe('source-maps/analyzer')
         [
           {
             kind: 'selector',
-            value: [{ value: 'div', metadata: { line: 1, column: 1 } }],
+            value: [{ value: 'div', metadata: { line: 1, column: 1, source: undefined } }],
             body: [
-              { value: '__ESCAPED_COMMENT_CLEAN_CSS0(2,5)__', metadata: { line: 1, column: 5 }},
-              { value: 'background:url(__ESCAPED_URL_CLEAN_CSS0(0,20)__)', metadata: { line: 3, column: 6 } },
-              { value: 'color:blue', metadata: { line: 3, column: 43 } }
+              { value: '__ESCAPED_COMMENT_CLEAN_CSS0(2,5)__', metadata: { line: 1, column: 5, source: undefined }},
+              { value: 'background:url(__ESCAPED_URL_CLEAN_CSS0(0,20)__)', metadata: { line: 3, column: 6, source: undefined } },
+              { value: 'color:blue', metadata: { line: 3, column: 43, source: undefined } }
             ]
           },
           {
             kind: 'selector',
-            value: [{ value: 'a', metadata: { line: 3, column: 54 } }],
+            value: [{ value: 'a', metadata: { line: 3, column: 54, source: undefined } }],
             body: [
-              { value: 'font-family:__ESCAPED_FREE_TEXT_CLEAN_CSS0(1,3)__', metadata: { line: 3, column: 56 } },
-              { value: 'color:red', metadata: { line: 4, column: 5 } }
+              { value: 'font-family:__ESCAPED_FREE_TEXT_CLEAN_CSS0(1,3)__', metadata: { line: 3, column: 56, source: undefined } },
+              { value: 'color:red', metadata: { line: 4, column: 5, source: undefined } }
             ]
           }
         ]
@@ -372,11 +372,11 @@ vows.describe('source-maps/analyzer')
           {
             kind: 'at-rule',
             value: '@charset __ESCAPED_FREE_TEXT_CLEAN_CSS0(1, 5)__;',
-            metadata: { line: 1, column: 1 }
+            metadata: { line: 1, column: 1, source: undefined }
           },
           {
             kind: 'selector',
-            value: [{ value: 'div', metadata: { line: 2, column: 8 } }],
+            value: [{ value: 'div', metadata: { line: 2, column: 8, source: undefined } }],
             body: []
           }
         ]
@@ -387,16 +387,47 @@ vows.describe('source-maps/analyzer')
           {
             kind: 'block',
             value: '@media (__ESCAPED_COMMENT_CLEAN_CSS0(2, 1)__min-width:980px)',
-            metadata: { line: 1, column: 1 },
+            metadata: { line: 1, column: 1, source: undefined },
             isFlatBlock: false,
             body: [{
               kind: 'selector',
-              value: [{ value: 'a', metadata: { line: 3, column: 19 } }],
-              body: [{ value: 'color:red', metadata: { line: 3, column: 21 } }]
+              value: [{ value: 'a', metadata: { line: 3, column: 19, source: undefined } }],
+              body: [{ value: 'color:red', metadata: { line: 3, column: 21, source: undefined } }]
             }]
           }
         ]
       ]
     })
   )
+  .addBatch(
+    sourceMapContext('sources', {
+      'one': [
+        '__ESCAPED_SOURCE_CLEAN_CSS(one.css)__a{}',
+        [{
+          kind: 'selector',
+          value: [{ value: 'a', metadata: { line: 1, column: 1, source: 'one.css' } }],
+          body: []
+        }]
+      ],
+      'two': [
+        '__ESCAPED_SOURCE_CLEAN_CSS(one.css)__a{}\n__ESCAPED_SOURCE_CLEAN_CSS(two.css)__a{color:red}',
+        [
+          {
+            kind: 'selector',
+            value: [
+              { value: 'a', metadata: { line: 1, column: 1, source: 'one.css' } }
+            ],
+            body: []
+          },
+          {
+            kind: 'selector',
+            value: [
+              { value: 'a', metadata: { line: 2, column: 1, source: 'two.css' } }
+            ],
+            body: [{ value: 'color:red', metadata: { line: 2, column: 3, source: 'two.css' } }]
+          }
+        ]
+      ]
+    })
+  )
   .export(module);