From b6aecc86466b459dde56cc430ab1e50a56e69d83 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Mon, 7 Sep 2020 15:48:07 +0300 Subject: [PATCH 1/2] fix: resolve `from` and `to` from config and options --- src/index.js | 7 +-- src/utils.js | 39 +++++++++--- test/__snapshots__/config.test.js.snap | 34 +++++++++++ test/__snapshots__/postcssOptins.test.js.snap | 61 +++++++++++++++++-- test/config-autoload.test.js | 8 +-- test/config.test.js | 27 ++++++++ .../fixtures/config-autoload/pkg/package.json | 4 +- .../config-scope/from-to/postcss.config.js | 12 ++++ test/postcssOptins.test.js | 40 +++++++----- 9 files changed, 194 insertions(+), 38 deletions(-) create mode 100644 test/fixtures/config-scope/from-to/postcss.config.js diff --git a/src/index.js b/src/index.js index 09e26fec..1b575642 100644 --- a/src/index.js +++ b/src/index.js @@ -74,10 +74,7 @@ export default async function loader(content, sourceMap) { processOptions.map = { inline: false, annotation: false }; if (sourceMap) { - processOptions.map.prev = normalizeSourceMap( - sourceMap, - this.resourcePath - ); + processOptions.map.prev = normalizeSourceMap(sourceMap, this.context); } } else if (sourceMap && typeof processOptions.map !== 'undefined') { if (typeof processOptions.map === 'boolean') { @@ -128,7 +125,7 @@ export default async function loader(content, sourceMap) { let map = result.map ? result.map.toJSON() : undefined; if (map && useSourceMap) { - map = normalizeSourceMapAfterPostcss(map, this.resourcePath); + map = normalizeSourceMapAfterPostcss(map, this.context); } const ast = { diff --git a/src/utils.js b/src/utils.js index 04a15de3..dad9da4e 100644 --- a/src/utils.js +++ b/src/utils.js @@ -192,18 +192,45 @@ function getPostcssOptions(loaderContext, config, postcssOptions = {}) { const processOptionsFromConfig = { ...config }; + if (processOptionsFromConfig.from) { + processOptionsFromConfig.from = path.resolve( + path.dirname(config.file), + processOptionsFromConfig.from + ); + } + + if (processOptionsFromConfig.to) { + processOptionsFromConfig.to = path.resolve( + path.dirname(config.file), + processOptionsFromConfig.to + ); + } + // No need them for processOptions delete processOptionsFromConfig.plugins; delete processOptionsFromConfig.file; const processOptionsFromOptions = { ...normalizedPostcssOptions }; + if (processOptionsFromOptions.from) { + processOptionsFromOptions.from = path.resolve( + loaderContext.rootContext, + processOptionsFromOptions.from + ); + } + + if (processOptionsFromOptions.to) { + processOptionsFromOptions.to = path.resolve( + loaderContext.rootContext, + processOptionsFromOptions.to + ); + } + // No need them for processOptions delete processOptionsFromOptions.config; delete processOptionsFromOptions.plugins; const processOptions = { - // TODO path.resolve from: file, to: file, map: false, @@ -272,7 +299,7 @@ function getURLType(source) { return ABSOLUTE_SCHEME.test(source) ? 'absolute' : 'path-relative'; } -function normalizeSourceMap(map, resourcePath) { +function normalizeSourceMap(map, resourceContext) { let newMap = map; // Some loader emit source map as string @@ -298,7 +325,7 @@ function normalizeSourceMap(map, resourcePath) { ? path.resolve(sourceRoot, path.normalize(source)) : path.normalize(source); - return path.relative(path.dirname(resourcePath), absoluteSource); + return path.relative(resourceContext, absoluteSource); } return source; @@ -308,7 +335,7 @@ function normalizeSourceMap(map, resourcePath) { return newMap; } -function normalizeSourceMapAfterPostcss(map, resourcePath) { +function normalizeSourceMapAfterPostcss(map, resourceContext) { const newMap = map; // result.map.file is an optional property that provides the output filename. @@ -329,9 +356,7 @@ function normalizeSourceMapAfterPostcss(map, resourcePath) { // Do no touch `scheme-relative`, `path-absolute` and `absolute` types if (sourceType === 'path-relative') { - const dirname = path.dirname(resourcePath); - - return path.resolve(dirname, source); + return path.resolve(resourceContext, source); } return source; diff --git a/test/__snapshots__/config.test.js.snap b/test/__snapshots__/config.test.js.snap index ccf967cf..04f556d4 100644 --- a/test/__snapshots__/config.test.js.snap +++ b/test/__snapshots__/config.test.js.snap @@ -31,6 +31,40 @@ exports[`"config" option should work "String" value (relative path): errors 1`] exports[`"config" option should work "String" value (relative path): warnings 1`] = `Array []`; +exports[`"config" option should work resolve "from" and "to" options: css 1`] = ` +"a { color: black } + +.foo { + float: right; +} +" +`; + +exports[`"config" option should work resolve "from" and "to" options: errors 1`] = `Array []`; + +exports[`"config" option should work resolve "from" and "to" options: source map 1`] = ` +Object { + "file": "style.css", + "mappings": "AAAA,IAAI,aAAa;;AAEjB;EACE,YAAY;AACd", + "names": Array [], + "sourceRoot": "", + "sources": Array [ + "style.css", + ], + "sourcesContent": Array [ + "a { color: black } + +.foo { + float: right; +} +", + ], + "version": 3, +} +`; + +exports[`"config" option should work resolve "from" and "to" options: warnings 1`] = `Array []`; + exports[`"config" option should work with "String" value (absolute path): css 1`] = ` "a { color: rgba(0, 0, 0, 1.0) } diff --git a/test/__snapshots__/postcssOptins.test.js.snap b/test/__snapshots__/postcssOptins.test.js.snap index c1e06f21..08b55e2a 100644 --- a/test/__snapshots__/postcssOptins.test.js.snap +++ b/test/__snapshots__/postcssOptins.test.js.snap @@ -153,7 +153,7 @@ exports[`"postcssOptions" option should work "Function" value: errors 1`] = `Arr exports[`"postcssOptions" option should work "Function" value: warnings 1`] = `Array []`; -exports[`"postcssOptions" option should work with "from", "to" and "map" options: css 1`] = ` +exports[`"postcssOptions" option should work with "from", "to" and "map" options (absolute paths): css 1`] = ` "a { color: black; } @@ -200,11 +200,64 @@ a { " `; -exports[`"postcssOptions" option should work with "from", "to" and "map" options: errors 1`] = `Array []`; +exports[`"postcssOptions" option should work with "from", "to" and "map" options (absolute paths): errors 1`] = `Array []`; -exports[`"postcssOptions" option should work with "from", "to" and "map" options: map 1`] = `undefined`; +exports[`"postcssOptions" option should work with "from", "to" and "map" options (absolute paths): map 1`] = `undefined`; -exports[`"postcssOptions" option should work with "from", "to" and "map" options: warnings 1`] = `Array []`; +exports[`"postcssOptions" option should work with "from", "to" and "map" options (absolute paths): warnings 1`] = `Array []`; + +exports[`"postcssOptions" option should work with "from", "to" and "map" options (relative paths): css 1`] = ` +"a { + color: black; +} + +a { + color: red; +} + +a { + color: green; +} + +a { + color: blue; +} + +.class { + -x-border-color: blue blue *; + -x-color: * #fafafa; +} + +.class-foo { + -z-border-color: blue blue *; + -z-color: * #fafafa; +} + +.phone { + &_title { + width: 500px; + + @media (max-width: 500px) { + width: auto; + } + + body.is_dark & { + color: white; + } + } + + img { + display: block; + } +} +" +`; + +exports[`"postcssOptions" option should work with "from", "to" and "map" options (relative paths): errors 1`] = `Array []`; + +exports[`"postcssOptions" option should work with "from", "to" and "map" options (relative paths): map 1`] = `undefined`; + +exports[`"postcssOptions" option should work with "from", "to" and "map" options (relative paths): warnings 1`] = `Array []`; exports[`"postcssOptions" option should work with the "map" option and generate inlined source maps: css 1`] = ` "a { diff --git a/test/config-autoload.test.js b/test/config-autoload.test.js index 08353dba..5526f521 100644 --- a/test/config-autoload.test.js +++ b/test/config-autoload.test.js @@ -35,12 +35,8 @@ describe('autoload config', () => { expect(config.parser).toEqual(false); expect(config.syntax).toEqual(false); expect(config.map).toEqual(false); - expect(config.from).toEqual( - './test/fixtures/config-autoload/pkg/index.css' - ); - expect(config.to).toEqual( - './test/fixtures/config-autoload/pkg/expected/index.css' - ); + expect(config.from).toEqual('./index.css'); + expect(config.to).toEqual('./index.css'); expect(Object.keys(config.plugins).length).toEqual(2); expect(config.file).toEqual( path.resolve(testDirectory, 'pkg', 'package.json') diff --git a/test/config.test.js b/test/config.test.js index ade5b2d6..367140ac 100644 --- a/test/config.test.js +++ b/test/config.test.js @@ -191,4 +191,31 @@ describe('"config" option', () => { expect(getWarnings(stats)).toMatchSnapshot('warnings'); expect(getErrors(stats, true)).toMatchSnapshot('errors'); }); + + it('should work and resolve "from" and "to" options', async () => { + const compiler = getCompiler('./config-scope/css/index.js', { + postcssOptions: { + config: path.resolve( + __dirname, + './fixtures/config-scope/from-to/postcss.config.js' + ), + }, + }); + const stats = await compile(compiler); + + const { css, sourceMap } = getCodeFromBundle('style.css', stats); + + sourceMap.sourceRoot = ''; + sourceMap.sources = sourceMap.sources.map((source) => { + expect(path.isAbsolute(source)).toBe(false); + expect(source).toBe(path.normalize(source)); + + return source.replace(/\\/g, '/'); + }); + + expect(css).toMatchSnapshot('css'); + expect(sourceMap).toMatchSnapshot('source map'); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); + }); }); diff --git a/test/fixtures/config-autoload/pkg/package.json b/test/fixtures/config-autoload/pkg/package.json index cfa3a81b..14995d0f 100644 --- a/test/fixtures/config-autoload/pkg/package.json +++ b/test/fixtures/config-autoload/pkg/package.json @@ -5,8 +5,8 @@ "parser": false, "syntax": false, "map": false, - "from": "./test/fixtures/config-autoload/pkg/index.css", - "to": "./test/fixtures/config-autoload/pkg/expected/index.css", + "from": "./index.css", + "to": "./index.css", "plugins": [ "postcss-import", ["postcss-nested", {}] diff --git a/test/fixtures/config-scope/from-to/postcss.config.js b/test/fixtures/config-scope/from-to/postcss.config.js new file mode 100644 index 00000000..f61f621e --- /dev/null +++ b/test/fixtures/config-scope/from-to/postcss.config.js @@ -0,0 +1,12 @@ +module.exports = { + from: '../../css/style.css', + to: '../../css/style.css', + map: { + inline: false, + annotation: false, + sourcesContent: true, + }, + plugins: [ + ['postcss-short', { prefix: 'x' }] + ] +}; diff --git a/test/postcssOptins.test.js b/test/postcssOptins.test.js index f9aa7c84..cf0fa42c 100644 --- a/test/postcssOptins.test.js +++ b/test/postcssOptins.test.js @@ -7,7 +7,7 @@ import { } from './helpers'; describe('"postcssOptions" option', () => { - it('should work with "from", "to" and "map" options', async () => { + it('should work with "from", "to" and "map" options (absolute paths)', async () => { const compiler = getCompiler('./css/index.js', { postcssOptions: { from: '/test/from.css', @@ -16,25 +16,37 @@ describe('"postcssOptions" option', () => { }, }); const stats = await compile(compiler); - const codeFromBundle = getCodeFromBundle('style.css', stats); - const notNormalizecodeFromBundle = getCodeFromBundle( - 'style.css', - stats, - false - ); - - const toIsWork = notNormalizecodeFromBundle.sourceMap.file.endsWith( - 'to.css' - ); + const toIsWork = codeFromBundle.sourceMap.file.endsWith('to.css'); const fromIsWork = - notNormalizecodeFromBundle.sourceMap.sources.filter((i) => - i.endsWith('from.css') - ).length > 0; + codeFromBundle.sourceMap.sources.filter((i) => i.endsWith('from.css')) + .length > 0; expect(toIsWork).toBe(true); expect(fromIsWork).toBe(true); + expect(codeFromBundle.css).toMatchSnapshot('css'); + expect(codeFromBundle.map).toMatchSnapshot('map'); + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats)).toMatchSnapshot('errors'); + }); + + it('should work with "from", "to" and "map" options (relative paths)', async () => { + const compiler = getCompiler('./css/index.js', { + postcssOptions: { + from: './css/style.css', + to: './css/style.css', + map: { inline: false, annotation: false }, + }, + }); + const stats = await compile(compiler); + const codeFromBundle = getCodeFromBundle('style.css', stats); + const toIsWork = codeFromBundle.sourceMap.file.endsWith('style.css'); + const fromIsWork = + codeFromBundle.sourceMap.sources.filter((i) => i.endsWith('style.css')) + .length > 0; + expect(toIsWork).toBe(true); + expect(fromIsWork).toBe(true); expect(codeFromBundle.css).toMatchSnapshot('css'); expect(codeFromBundle.map).toMatchSnapshot('map'); expect(getWarnings(stats)).toMatchSnapshot('warnings'); From ef993bc306fa9ab9801498cd9f1bf2e32056c7f4 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Mon, 7 Sep 2020 15:51:15 +0300 Subject: [PATCH 2/2] test: fix --- test/__snapshots__/config.test.js.snap | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/__snapshots__/config.test.js.snap b/test/__snapshots__/config.test.js.snap index 04f556d4..25417a32 100644 --- a/test/__snapshots__/config.test.js.snap +++ b/test/__snapshots__/config.test.js.snap @@ -31,7 +31,7 @@ exports[`"config" option should work "String" value (relative path): errors 1`] exports[`"config" option should work "String" value (relative path): warnings 1`] = `Array []`; -exports[`"config" option should work resolve "from" and "to" options: css 1`] = ` +exports[`"config" option should work and resolve "from" and "to" options: css 1`] = ` "a { color: black } .foo { @@ -40,9 +40,9 @@ exports[`"config" option should work resolve "from" and "to" options: css 1`] = " `; -exports[`"config" option should work resolve "from" and "to" options: errors 1`] = `Array []`; +exports[`"config" option should work and resolve "from" and "to" options: errors 1`] = `Array []`; -exports[`"config" option should work resolve "from" and "to" options: source map 1`] = ` +exports[`"config" option should work and resolve "from" and "to" options: source map 1`] = ` Object { "file": "style.css", "mappings": "AAAA,IAAI,aAAa;;AAEjB;EACE,YAAY;AACd", @@ -63,7 +63,7 @@ Object { } `; -exports[`"config" option should work resolve "from" and "to" options: warnings 1`] = `Array []`; +exports[`"config" option should work and resolve "from" and "to" options: warnings 1`] = `Array []`; exports[`"config" option should work with "String" value (absolute path): css 1`] = ` "a { color: rgba(0, 0, 0, 1.0) }