Fixes #840 - allows input source map as map object.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Sat, 17 Dec 2016 12:14:16 +0000 (13:14 +0100)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Sat, 17 Dec 2016 12:19:05 +0000 (13:19 +0100)
Why:

* It's been always odd that we required a serialized JSON when
  user may already had it parsed.

History.md
lib/reader/read-sources.js
test/source-map-test.js

index 3589091..542ae3c 100644 (file)
@@ -7,6 +7,7 @@
 * Replaces the old tokenizer with a new one which doesn't use any escaping.
 * Replaces the old `@import` inlining with one on top of the new tokenizer.
 * Simplifies URL rebasing with a single `rebaseTo` option in API or inferred from `--output` in CLI.
+* Fixed issue [#840](https://github.com/jakubpawlowicz/clean-css/issues/840) - allows input source map as map object.
 * Fixed issue [#843](https://github.com/jakubpawlowicz/clean-css/issues/843) - regression in selector handling.
 
 [3.4.22 / 2016-12-12](https://github.com/jakubpawlowicz/clean-css/compare/v3.4.21...v3.4.22)
index 7581e78..7a3d21e 100644 (file)
@@ -46,7 +46,7 @@ function fromString(input, context, parentInlinerContext, callback) {
 
   inputAsHash[UNKNOWN_URI] = {
     styles: input,
-    sourceMap: (typeof context.options.sourceMap === 'string') ? context.options.sourceMap : null
+    sourceMap: (typeof context.options.sourceMap !== 'boolean') ? context.options.sourceMap : null
   };
 
   return fromHash(inputAsHash, context, parentInlinerContext, callback);
@@ -92,11 +92,13 @@ function fromHash(input, context, parentInlinerContext, callback) {
     source = input[uri];
 
     if (source.sourceMap) {
-      parsedMap = JSON.parse(source.sourceMap);
+      parsedMap = typeof source.sourceMap == 'string' ?
+        JSON.parse(source.sourceMap) :
+        source.sourceMap;
       rebasedMap = isRemoteResource(uri) ?
         rebaseRemoteMap(parsedMap, uri) :
         rebaseLocalMap(parsedMap, uri, context.options.rebaseTo);
-      context.inputSourceMapTracker.track(uri, rebasedMap);
+      context.inputSourceMapTracker.track(uri == UNKNOWN_URI ? undefined : uri, rebasedMap);
     }
 
     context.source = uri !== UNKNOWN_URI ? uri : undefined;
index f4a4fd4..5f504c6 100644 (file)
@@ -476,6 +476,47 @@ vows.describe('source-map')
         assert.deepEqual(minified.sourceMap._mappings._array[2], mapping);
       }
     },
+    'input map as source map object': {
+      'topic': function () {
+        return new CleanCSS({ sourceMap: JSON.parse(inputMap) }).minify('div > a {\n  color: red;\n}');
+      },
+      'has 3 mappings': function (minified) {
+        assert.lengthOf(minified.sourceMap._mappings._array, 3);
+      },
+      'has `div > a` mapping': function (minified) {
+        var mapping = {
+          generatedLine: 1,
+          generatedColumn: 0,
+          originalLine: 1,
+          originalColumn: 4,
+          source: 'styles.less',
+          name: null
+        };
+        assert.deepEqual(minified.sourceMap._mappings._array[0], mapping);
+      },
+      'has `color` mapping': function (minified) {
+        var mapping = {
+          generatedLine: 1,
+          generatedColumn: 6,
+          originalLine: 2,
+          originalColumn: 2,
+          source: 'styles.less',
+          name: null
+        };
+        assert.deepEqual(minified.sourceMap._mappings._array[1], mapping);
+      },
+      'has `red` mapping': function (minified) {
+        var mapping = {
+          generatedLine: 1,
+          generatedColumn: 12,
+          originalLine: 2,
+          originalColumn: 2,
+          source: 'styles.less',
+          name: null
+        };
+        assert.deepEqual(minified.sourceMap._mappings._array[2], mapping);
+      }
+    },
     'input map from source': {
       'topic': function () {
         return new CleanCSS({ sourceMap: true }).minify('div > a {\n  color: red;\n}/*# sourceMappingURL=' + inputMapPath + ' */');
@@ -1491,6 +1532,41 @@ vows.describe('source-map')
           ]);
         }
       },
+      'multiple with map passed as source map object': {
+        'topic': function () {
+          return new CleanCSS({ sourceMap: true, sourceMapInlineSources: true }).minify({
+            'test/fixtures/source-maps/some.css': {
+              styles: 'div {\n  color: red;\n}',
+              sourceMap: { version:3, sources: ['some.less'], names: [], mappings: 'AAAA;EACE,UAAA', file: 'some.css', sourcesContent: ['div {\n  color: red;\n}\n'] }
+            },
+            'test/fixtures/source-maps/styles.css': {
+              styles: 'div > a {\n  color: blue;\n}',
+              sourceMap: { version:3, sources: ['styles.less'], names: [], mappings: 'AAAA,GAAI;EACF,WAAA', file: 'styles.css', sourcesContent: ['div > a {\n  color: blue;\n}\n'] }
+            },
+            'test/fixtures/source-maps/nested/once.css': {
+              styles: 'section > div a {\n  color: red;\n}',
+              sourceMap: { version:3, sources: ['once.less'], names: [], mappings: 'AAAA,OACE,MAAM;EACJ,UAAA', file: 'once.css', sourcesContent: ['section {\n  > div a {\n    color:red;\n  }\n}\n'] }
+            }
+          });
+        },
+        'has 7 mappings': function (minified) {
+          assert.lengthOf(minified.sourceMap._mappings._array, 7);
+        },
+        'has embedded sources': function (minified) {
+          assert.deepEqual(JSON.parse(minified.sourceMap.toString()).sources, [
+            path.join('test', 'fixtures', 'source-maps', 'some.less'),
+            path.join('test', 'fixtures', 'source-maps', 'nested', 'once.less'),
+            path.join('test', 'fixtures', 'source-maps', 'styles.less')
+          ]);
+        },
+        'has embedded sources content': function (minified) {
+          assert.deepEqual(JSON.parse(minified.sourceMap.toString()).sourcesContent, [
+            'div {\n  color: red;\n}\n',
+            'section {\n  > div a {\n    color:red;\n  }\n}\n',
+            'div > a {\n  color: blue;\n}\n'
+          ]);
+        }
+      },
       'multiple relative to rebaseTo path': {
         'topic': function () {
           return new CleanCSS({ sourceMap: true, sourceMapInlineSources: true, rebaseTo: './test' }).minify({