From f230d401647c86f422693a846ba123d9bdbc26bb Mon Sep 17 00:00:00 2001 From: Bob Matcuk Date: Sun, 9 Jun 2019 06:24:39 -1000 Subject: [PATCH] feat(src/index): support synchronous config loading (`rc.sync`) --- README.md | 17 +++++++ src/index.js | 109 ++++++++++++++++++++++++++++++-------------- src/plugins.js | 22 ++++----- test/Errors.test.js | 94 ++++++++++++++++++++++++++++++++++++++ test/js.test.js | 28 ++++++++++-- test/pkg.test.js | 14 +++++- test/rc.test.js | 14 +++++- 7 files changed, 242 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index f2625fa..0dfbb87 100644 --- a/README.md +++ b/README.md @@ -322,6 +322,8 @@ module.exports = (ctx) => ({ } ``` +### `Async` + ```js const { readFileSync } = require('fs') @@ -339,6 +341,21 @@ postcssrc(ctx).then(({ plugins, options }) => { }) ``` +### `Sync` + +```js +const { readFileSync } = require('fs') + +const postcss = require('postcss') +const postcssrc = require('postcss-load-config') + +const css = readFileSync('index.sss', 'utf8') + +const ctx = { parser: true, map: 'inline' } + +const { plugins, options } = postcssrc.sync(ctx) +``` +
diff --git a/src/index.js b/src/index.js index 8f06f6d..674bdc6 100644 --- a/src/index.js +++ b/src/index.js @@ -8,17 +8,42 @@ const loadOptions = require('./options.js') const loadPlugins = require('./plugins.js') /** - * Load Config + * Process the result from cosmiconfig * - * @method rc + * @param {Object} ctx Config Context + * @param {Object} result Cosmiconfig result + * + * @return {Object} PostCSS Config + */ +const processResult = (ctx, result) => { + let file = result.filepath || '' + let config = result.config || {} + + if (typeof config === 'function') { + config = config(ctx) + } else { + config = Object.assign({}, config, ctx) + } + + if (!config.plugins) { + config.plugins = [] + } + + return { + plugins: loadPlugins(config, file), + options: loadOptions(config, file), + file: file + } +} + +/** + * Builds the Config Context * * @param {Object} ctx Config Context - * @param {String} path Config Path - * @param {Object} options Config Options * - * @return {Promise} config PostCSS Config + * @return {Object} Config Context */ -const rc = (ctx, path, options) => { +const createContext = (ctx) => { /** * @type {Object} * @@ -29,24 +54,35 @@ const rc = (ctx, path, options) => { cwd: process.cwd(), env: process.env.NODE_ENV }, ctx) + + if (!ctx.env) { + process.env.NODE_ENV = 'development' + } + + return ctx +} + +/** + * Load Config + * + * @method rc + * + * @param {Object} ctx Config Context + * @param {String} path Config Path + * @param {Object} options Config Options + * + * @return {Promise} config PostCSS Config + */ +const rc = (ctx, path, options) => { /** - * @type {String} `process.cwd()` - * + * @type {Object} The full Config Context */ - path = path ? resolve(path) : process.cwd() + ctx = createContext(ctx) /** - * @type {Object} - * - * @prop {Boolean} rcExtensions=true + * @type {String} `process.cwd()` */ - options = Object.assign({ - rcExtensions: true - }, options) - - if (!ctx.env) { - process.env.NODE_ENV = 'development' - } + path = path ? resolve(path) : process.cwd() return config('postcss', options) .search(path) @@ -55,25 +91,28 @@ const rc = (ctx, path, options) => { throw new Error(`No PostCSS Config found in: ${path}`) } - let file = result.filepath || '' - let config = result.config || {} + return processResult(ctx, result) + }) +} - if (typeof config === 'function') { - config = config(ctx) - } else { - config = Object.assign({}, config, ctx) - } +rc.sync = (ctx, path, options) => { + /** + * @type {Object} The full Config Context + */ + ctx = createContext(ctx) - if (!config.plugins) { - config.plugins = [] - } + /** + * @type {String} `process.cwd()` + */ + path = path ? resolve(path) : process.cwd() - return { - plugins: loadPlugins(config, file), - options: loadOptions(config, file), - file: file - } - }) + const result = config('postcss', options).searchSync(path) + + if (!result) { + throw new Error(`No PostCSS Config found in: ${path}`) + } + + return processResult(ctx, result) } /** diff --git a/src/plugins.js b/src/plugins.js index 7795822..2db59d3 100644 --- a/src/plugins.js +++ b/src/plugins.js @@ -14,22 +14,18 @@ const req = require('import-cwd') * @return {Function} PostCSS Plugin */ const load = (plugin, options, file) => { - if ( - options === null || - options === undefined || - Object.keys(options).length === 0 - ) { - try { + try { + if ( + options === null || + options === undefined || + Object.keys(options).length === 0 + ) { return req(plugin) - } catch (err) { - throw new Error(`Loading PostCSS Plugin failed: ${err.message}\n\n(@${file})`) - } - } else { - try { + } else { return req(plugin)(options) - } catch (err) { - throw new Error(`Loading PostCSS Plugin failed: ${err.message}\n\n(@${file})`) } + } catch (err) { + throw new Error(`Loading PostCSS Plugin failed: ${err.message}\n\n(@${file})`) } } diff --git a/test/Errors.test.js b/test/Errors.test.js index 9472fd0..fa95fbe 100644 --- a/test/Errors.test.js +++ b/test/Errors.test.js @@ -10,6 +10,16 @@ test('Loading Config - {Error}', () => { }) }) +test('Loading Config - Sync - {Error}', () => { + try { + postcssrc.sync({}, 'test/err') + } catch (err) { + expect(err.message).toMatch( + /^No PostCSS Config found in: (.*)$/ + ) + } +}) + describe('Loading Plugins - {Error}', () => { test('Plugin - {Type} - Invalid', () => { return postcssrc({}, 'test/err/plugins').catch((err) => { @@ -52,6 +62,58 @@ describe('Loading Plugins - {Error}', () => { }) }) +describe('Loading Plugins - Sync - {Error}', () => { + test('Plugin - {Type} - Invalid', () => { + try { + postcssrc.sync({}, 'test/err/plugins') + } catch (err) { + expect(err.message).toMatch( + /^Invalid PostCSS Plugin found at: (.*)\n\n\(@.*\)$/ + ) + } + }) + + test('Plugin - {Object}', () => { + try { + postcssrc.sync({}, 'test/err/plugins/object') + } catch (err) { + expect(err.message).toMatch( + /^Loading PostCSS Plugin failed: (.*)\n\n\(@.*\)$/ + ) + } + }) + + test('Plugin - {Object} - Options', () => { + try { + postcssrc.sync({}, 'test/err/plugins/object/options') + } catch (err) { + expect(err.message).toMatch( + /^Loading PostCSS Plugin failed: (.*)\n\n\(@.*\)$/ + ) + } + }) + + test('Plugin - {Array}', () => { + try { + postcssrc.sync({}, 'test/err/plugins/array') + } catch (err) { + expect(err.message).toMatch( + /^Cannot find (.*)$/ + ) + } + }) + + test('Plugin - {Array} - Options', () => { + try { + postcssrc.sync({}, 'test/err/plugins/array/options') + } catch (err) { + expect(err.message).toMatch( + /^Cannot find (.*)$/ + ) + } + }) +}) + describe('Loading Options - {Error}', () => { test('Parser - {String}', () => { return postcssrc({}, 'test/err/options/parser').catch((err) => { @@ -77,3 +139,35 @@ describe('Loading Options - {Error}', () => { }) }) }) + +describe('Loading Options - Sync - {Error}', () => { + test('Parser - {String}', () => { + try { + postcssrc.sync({}, 'test/err/options/parser') + } catch (err) { + expect(err.message).toMatch( + /^Loading PostCSS Parser failed: (.*)\n\n\(@.*\)$/ + ) + } + }) + + test('Syntax - {String}', () => { + try { + postcssrc.sync({}, 'test/err/options/syntax') + } catch (err) { + expect(err.message).toMatch( + /^Loading PostCSS Syntax failed: (.*)\n\n\(@.*\)$/ + ) + } + }) + + test('Stringifier - {String}', () => { + try { + postcssrc.sync({}, 'test/err/options/stringifier') + } catch (err) { + expect(err.message).toMatch( + /^Loading PostCSS Stringifier failed: (.*)\n\n\(@.*\)$/ + ) + } + }) +}) diff --git a/test/js.test.js b/test/js.test.js index 522c59b..bc41972 100644 --- a/test/js.test.js +++ b/test/js.test.js @@ -7,13 +7,13 @@ const postcssrc = require('../src/index.js') const { fixture, expected } = require('./utils.js') -test('postcss.config.js - {Object} - Load Config', () => { +describe('postcss.config.js - {Object} - Load Config', () => { const ctx = { parser: true, syntax: true } - return postcssrc(ctx, 'test/js/object').then((config) => { + const expected = (config) => { expect(config.options.parser).toEqual(require('sugarss')) expect(config.options.syntax).toEqual(require('sugarss')) expect(config.options.map).toEqual(false) @@ -26,6 +26,16 @@ test('postcss.config.js - {Object} - Load Config', () => { expect(config.file) .toEqual(path.resolve('test/js/object', 'postcss.config.js')) + } + + test('Async', () => { + return postcssrc(ctx, 'test/js/object').then(expected) + }) + + test('Sync', () => { + const config = postcssrc.sync(ctx, 'test/js/object') + + expected(config) }) }) @@ -60,13 +70,13 @@ test('postcss.config.js - {Object} - Process SSS', () => { }) }) -test('postcss.config.js - {Array} - Load Config', () => { +describe('postcss.config.js - {Array} - Load Config', () => { const ctx = { parser: true, syntax: true } - return postcssrc(ctx, 'test/js/array').then((config) => { + const expected = (config) => { expect(config.options.parser).toEqual(require('sugarss')) expect(config.options.syntax).toEqual(require('sugarss')) expect(config.options.map).toEqual(false) @@ -79,6 +89,16 @@ test('postcss.config.js - {Array} - Load Config', () => { expect(config.file) .toEqual(path.resolve('test/js/array', 'postcss.config.js')) + } + + test('Async', () => { + return postcssrc(ctx, 'test/js/array').then(expected) + }) + + test('Sync', () => { + const config = postcssrc.sync(ctx, 'test/js/array') + + expected(config) }) }) diff --git a/test/pkg.test.js b/test/pkg.test.js index 2dae834..230960b 100644 --- a/test/pkg.test.js +++ b/test/pkg.test.js @@ -7,8 +7,8 @@ const postcssrc = require('../src/index.js') const { fixture, expected } = require('./utils.js') -test('package.json - {Object} - Load Config', () => { - return postcssrc({}, 'test/pkg').then((config) => { +describe('package.json - {Object} - Load Config', () => { + const expected = (config) => { expect(config.options.parser).toEqual(require('sugarss')) expect(config.options.syntax).toEqual(require('sugarss')) expect(config.options.map).toEqual(false) @@ -21,6 +21,16 @@ test('package.json - {Object} - Load Config', () => { expect(config.file) .toEqual(path.resolve('test/pkg', 'package.json')) + } + + test('Async', () => { + return postcssrc({}, 'test/pkg').then(expected) + }) + + test('Sync', () => { + const config = postcssrc.sync({}, 'test/pkg') + + expected(config) }) }) diff --git a/test/rc.test.js b/test/rc.test.js index d7dc657..5ac3c83 100644 --- a/test/rc.test.js +++ b/test/rc.test.js @@ -7,8 +7,8 @@ const postcssrc = require('../src/index.js') const { fixture, expected } = require('./utils.js') -test('.postcssrc - {Object} - Load Config', () => { - return postcssrc({}, 'test/rc').then((config) => { +describe('.postcssrc - {Object} - Load Config', () => { + const expected = (config) => { expect(config.options.parser).toEqual(require('sugarss')) expect(config.options.syntax).toEqual(require('sugarss')) expect(config.options.map).toEqual(false) @@ -21,6 +21,16 @@ test('.postcssrc - {Object} - Load Config', () => { expect(config.file) .toEqual(path.resolve('test/rc', '.postcssrc')) + } + + test('Async', () => { + return postcssrc({}, 'test/rc').then(expected) + }) + + test('Sync', () => { + const config = postcssrc.sync({}, 'test/rc') + + expected(config) }) })