From bb3973a52de6ec2a29860481864ee37bfbcffb18 Mon Sep 17 00:00:00 2001 From: Giuseppe Gurgone Date: Wed, 19 Aug 2020 10:52:52 +0200 Subject: [PATCH] Fix order for plugin set with config and cli --- package.json | 2 +- src/cfg-resolve.js | 26 +++++++++++++++++++++++++- test/expected/output-bem.html | 6 +++--- test/test-cfg-resolve.js | 12 ++++++++++++ test/test-cli.js | 28 ++++++++++++++-------------- 5 files changed, 55 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 3a4da82..c155738 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "build": "rimraf lib && babel src -d lib", "coverage": "nyc report --reporter=text-lcov | coveralls", "pretest": "npm run build", - "test": "nyc ava test/test-cli.js --timeout=1m --verbose" + "test": "nyc ava test/test-*.js --timeout=1m --verbose" }, "files": [ "lib/" diff --git a/src/cfg-resolve.js b/src/cfg-resolve.js index b55fb89..e530fcd 100644 --- a/src/cfg-resolve.js +++ b/src/cfg-resolve.js @@ -19,7 +19,31 @@ export default ({input, flags = {}}) => { } if (use) { - use = [].concat(use).reduce((cfg, key) => mergeOptions(cfg, {plugins: {[key]: flags[toCamelCase(key)] || {}}}), {}); + const configPluginOptions = config?.plugins ?? {}; + + // Plugins defined via CLI options take precedence over the ones from config file. + use = [].concat(use).reduce((cfg, name) => { + let cliOptions = flags[toCamelCase(name)]; + let configOptions = configPluginOptions[name]; + // We merge this way because options can be both strings and objects. + const merged = mergeOptions({ [name]: configOptions }, { [name]: cliOptions || {}}); + // Assigning as we loop `use` makes sure that the order in cfg.plugins is correct. + cfg.plugins[name] = merged[name]; + if (configOptions) { + delete configPluginOptions[name]; + } + return cfg; + }, { plugins: {} }); + + // Add the remaining plugins if there is any. + if (config && config.plugins) { + for (let name in configPluginOptions) { + use.plugins[name] = configPluginOptions[name]; + } + // Now all the plugins are in `use.plugins`. + // Delete `config.plugins` for correct merging later: mergeOptions(config, {...}, use) + delete config.plugins; + } } if (!config && !use) { diff --git a/test/expected/output-bem.html b/test/expected/output-bem.html index b93c9c0..ea71cd6 100644 --- a/test/expected/output-bem.html +++ b/test/expected/output-bem.html @@ -1,4 +1,4 @@ - - Super Title - Awesome Text + + Super Title + Awesome Text diff --git a/test/test-cfg-resolve.js b/test/test-cfg-resolve.js index 174a55b..ca06d69 100644 --- a/test/test-cfg-resolve.js +++ b/test/test-cfg-resolve.js @@ -145,3 +145,15 @@ test('should return config when CLI output param priority', t => { t.deepEqual(config.output, expected); }); + +test('should resolve plugins set via config and stdin (use) in order', async t => { + const input = 'input.html'; + const flags = { + use: ['posthtml-d', 'posthtml-bem'], + posthtmlBem: { foo: 'after' }, + posthtmlD: { bar: 'before' }, + config: 'test/config/.config-plugins' + }; + const config = cfgResolve({input, flags}); + t.deepEqual(Object.keys(config.plugins), ['posthtml-d', 'posthtml-bem']); +}); diff --git a/test/test-cli.js b/test/test-cli.js index b776349..4be10e0 100644 --- a/test/test-cli.js +++ b/test/test-cli.js @@ -25,7 +25,7 @@ test('Check version', async t => { t.is(stdout, version); }); -test('Transform html witch config in package.json', async t => { +test('Transform html with config in package.json', async t => { t.plan(2); const filename = tempfile('.html'); await execa(cli, ['test/fixtures/input.html', '-o', filename]); @@ -33,7 +33,7 @@ test('Transform html witch config in package.json', async t => { t.is((await read('test/expected/output-config-pkg.html')), (await read(filename))); }); -test('Transform html witch indent', async t => { +test('Transform html with indent', async t => { t.plan(2); const filename = tempfile('.html'); await execa(cli, ['test/fixtures/input-indent.html', '-o', filename]); @@ -41,7 +41,7 @@ test('Transform html witch indent', async t => { t.is((await read('test/expected/output-indent.html')), (await read(filename))); }); -test('Transform html witch config in file', async t => { +test('Transform html with config in file', async t => { t.plan(2); const filename = tempfile('.html'); await execa(cli, ['test/fixtures/input.html', '-o', filename, '-c', 'test/fixtures/config.json']); @@ -49,7 +49,7 @@ test('Transform html witch config in file', async t => { t.is((await read('test/expected/output-config-file.html')), (await read(filename))); }); -test('Transform html witch dot config in file', async t => { +test('Transform html with dot config in file', async t => { t.plan(2); const filename = tempfile('.html'); await execa(cli, ['test/fixtures/input.html', '-o', filename, '-c', 'test/fixtures/.config']); @@ -65,7 +65,7 @@ test('Transform html from two file', async t => { t.is((await read('test/expected/output-indent.html')), (await read(`${folder}/input-indent.html`))); }); -// test('Transform html witch options replace', async t => { +// test('Transform html with options replace', async t => { // t.plan(2); // const folder = await tempfile(); // await copy(['test/fixtures/input.html', 'test/fixtures/input-indent.html'], folder); @@ -74,7 +74,7 @@ test('Transform html from two file', async t => { // t.is((await read('test/expected/output-indent.html')), (await read(`${folder}/input-indent.html`))); // }); -test('Transform html witch config in file and stdin options use', async t => { +test('Transform html with config in file and stdin options use', async t => { t.plan(2); const filename = tempfile('.html'); await execa(cli, [ @@ -94,7 +94,7 @@ test('Transform html witch config in file and stdin options use', async t => { t.is((await read('test/expected/output-bem.html')), (await read(filename))); }); -test('Transform html witch stdin options use', async t => { +test('Transform html with stdin options use', async t => { t.plan(2); const filename = tempfile('.html'); await execa(cli, [ @@ -110,7 +110,7 @@ test('Transform html witch stdin options use', async t => { t.is((await read('test/expected/output-custom-elements.html')), (await read(filename))); }); -test('Transform html witch stdin options use two key', async t => { +test('Transform html with stdin options use two key', async t => { t.plan(2); const filename = tempfile('.html'); await execa(cli, [ @@ -118,21 +118,21 @@ test('Transform html witch stdin options use two key', async t => { '-o', filename, '-u', - 'posthtml-custom-elements', - '--posthtml-custom-elements.defaultTag', - 'span', - '-u', 'posthtml-bem', '--posthtml-bem.elemPrefix=--', '--posthtml-bem.modPrefix', '_', - '--posthtml-bem.modDlmtr' + '--posthtml-bem.modDlmtr', + '-u', + 'posthtml-custom-elements', + '--posthtml-custom-elements.defaultTag', + 'span' ]); t.true(await pathExists(filename)); t.is((await read('test/expected/output-bem.html')), (await read(filename))); }); -test('Transform html stdin options use witch modules', async t => { +test('Transform html stdin options use with modules', async t => { t.plan(2); const filename = tempfile('.html'); await execa(cli, [