From 760ac857c8b89bcbaf31896607692a8316be7911 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowicz Date: Sat, 17 Dec 2016 13:14:16 +0100 Subject: [PATCH] Fixes #840 - allows input source map as map object. Why: * It's been always odd that we required a serialized JSON when user may already had it parsed. --- History.md | 1 + lib/reader/read-sources.js | 8 ++-- test/source-map-test.js | 76 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 3 deletions(-) diff --git a/History.md b/History.md index 35890919..542ae3c7 100644 --- a/History.md +++ b/History.md @@ -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) diff --git a/lib/reader/read-sources.js b/lib/reader/read-sources.js index 7581e785..7a3d21e6 100644 --- a/lib/reader/read-sources.js +++ b/lib/reader/read-sources.js @@ -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; diff --git a/test/source-map-test.js b/test/source-map-test.js index f4a4fd49..5f504c6d 100644 --- a/test/source-map-test.js +++ b/test/source-map-test.js @@ -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({ -- 2.34.1