diff --git a/lib/assert.js b/lib/assert.js index 3c1435d4a..b3b1d47d7 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -2,8 +2,7 @@ const concordance = require('concordance'); const isError = require('is-error'); const isPromise = require('is-promise'); -const concordanceOptions = require('./concordance-options').default; -const concordanceDiffOptions = require('./concordance-options').diff; +const {default: concordanceOptions, diff: concordanceDiffOptions} = require('./concordance-options').resolve(); const snapshotManager = require('./snapshot-manager'); function formatDescriptorDiff(actualDescriptor, expectedDescriptor, options) { diff --git a/lib/cli.js b/lib/cli.js index e85be8c3e..a3b5296d9 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -180,6 +180,7 @@ exports.run = async () => { // eslint-disable-line complexity const chalkOptions = {level: combined.color === false ? 0 : require('chalk').level}; const chalk = require('./chalk').set(chalkOptions); + require('./concordance-options').configure(); if (confError) { if (confError.parent) { diff --git a/lib/concordance-options.js b/lib/concordance-options.js index 5af411cc9..47859194a 100644 --- a/lib/concordance-options.js +++ b/lib/concordance-options.js @@ -3,14 +3,9 @@ const util = require('util'); const ansiStyles = require('ansi-styles'); const stripAnsi = require('strip-ansi'); const cloneDeepWith = require('lodash/cloneDeepWith'); -const reactPlugin = require('@concordance/react'); +const merge = require('lodash/merge'); const chalk = require('./chalk').get(); -// Wrap Concordance's React plugin. Change the name to avoid collisions if in -// the future users can register plugins themselves. -const avaReactPlugin = {...reactPlugin, name: 'ava-plugin-react'}; -const plugins = [avaReactPlugin]; - const forceColor = new chalk.Instance({level: Math.max(chalk.level, 1)}); const colorTheme = { @@ -52,34 +47,6 @@ const colorTheme = { keyBracket: {open: forceColor.grey('['), close: forceColor.grey(']')}, valueFallback: forceColor.grey('…') }, - react: { - functionType: forceColor.grey('\u235F'), - openTag: { - start: forceColor.grey('<'), - end: forceColor.grey('>'), - selfClose: forceColor.grey('/'), - selfCloseVoid: ' ' + forceColor.grey('/') - }, - closeTag: { - open: forceColor.grey('') - }, - tagName: ansiStyles.magenta, - attribute: { - separator: '=', - value: { - openBracket: forceColor.grey('{'), - closeBracket: forceColor.grey('}'), - string: { - line: {open: forceColor.blue('"'), close: forceColor.blue('"'), escapeQuote: '"'} - } - } - }, - child: { - openBracket: forceColor.grey('{'), - closeBracket: forceColor.grey('}') - } - }, regexp: { source: {open: ansiStyles.blue.open + '/', close: '/' + ansiStyles.blue.close}, flags: ansiStyles.yellow @@ -118,22 +85,55 @@ const colorTheme = { undefined: ansiStyles.yellow }; -const plainTheme = cloneDeepWith(colorTheme, value => { - if (typeof value === 'string') { - return stripAnsi(value); +let resolved = null; +exports.resolve = () => { + if (!resolved) { + throw new Error('Concordance options have not yet been configured'); } -}); -const theme = chalk.level > 0 ? colorTheme : plainTheme; + return resolved; +}; -exports.default = { - // Use Node's object inspection depth, clamped to a minimum of 3 - get maxDepth() { - return Math.max(3, util.inspect.defaultOptions.depth); - }, - plugins, - theme +exports.configure = plugins => { + if (resolved) { + throw new Error('Concordance options have already been configured'); + } + + // TODO: Remove in the next major release. + if (plugins === undefined) { + const avaReactPlugin = require('./legacy-react'); + + plugins = [avaReactPlugin]; + } else { + // TODO: Resolve plugins + } + + const resolvedTheme = plugins.reduce((theme, {themeOverride}) => { + return merge(theme, themeOverride); + }, colorTheme); + + const plainTheme = cloneDeepWith(resolvedTheme, value => { + if (typeof value === 'string') { + return stripAnsi(value); + } + }); + + const theme = chalk.level > 0 ? resolvedTheme : plainTheme; + + plugins = plugins.map(({themeOverride: _, ...plugin}) => plugin); + + resolved = { + default: { + // Use Node's object inspection depth, clamped to a minimum of 3 + get maxDepth() { + return Math.max(3, util.inspect.defaultOptions.depth); + }, + plugins, + theme + }, + + diff: {maxDepth: 1, plugins, theme}, + snapshotManager: {plugins, theme: plainTheme} + }; }; -exports.diff = {maxDepth: 1, plugins, theme}; -exports.snapshotManager = {plugins, theme: plainTheme}; diff --git a/lib/legacy-react.js b/lib/legacy-react.js new file mode 100644 index 000000000..2774777b9 --- /dev/null +++ b/lib/legacy-react.js @@ -0,0 +1,41 @@ +'use strict'; +const ansiStyles = require('ansi-styles'); +const reactPlugin = require('@concordance/react'); +const chalk = require('./chalk').get(); + +const forceColor = new chalk.Instance({level: Math.max(chalk.level, 1)}); + +module.exports = { + ...reactPlugin, + name: 'ava-plugin-react', + themeOverride: { + react: { + functionType: forceColor.grey('\u235F'), + openTag: { + start: forceColor.grey('<'), + end: forceColor.grey('>'), + selfClose: forceColor.grey('/'), + selfCloseVoid: ' ' + forceColor.grey('/') + }, + closeTag: { + open: forceColor.grey('') + }, + tagName: ansiStyles.magenta, + attribute: { + separator: '=', + value: { + openBracket: forceColor.grey('{'), + closeBracket: forceColor.grey('}'), + string: { + line: {open: forceColor.blue('"'), close: forceColor.blue('"'), escapeQuote: '"'} + } + } + }, + child: { + openBracket: forceColor.grey('{'), + closeBracket: forceColor.grey('}') + } + } + } +}; diff --git a/lib/serialize-error.js b/lib/serialize-error.js index 114b9a28e..eefacf627 100644 --- a/lib/serialize-error.js +++ b/lib/serialize-error.js @@ -6,7 +6,7 @@ const isError = require('is-error'); const StackUtils = require('stack-utils'); const assert = require('./assert'); const beautifyStack = require('./beautify-stack'); -const concordanceOptions = require('./concordance-options').default; +const {default: concordanceOptions} = require('./concordance-options').resolve(); function isAvaAssertionError(source) { return source instanceof assert.AssertionError; diff --git a/lib/snapshot-manager.js b/lib/snapshot-manager.js index bcb448c01..ad0604a0b 100644 --- a/lib/snapshot-manager.js +++ b/lib/snapshot-manager.js @@ -12,7 +12,7 @@ const convertSourceMap = require('convert-source-map'); const slash = require('slash'); const writeFileAtomic = require('write-file-atomic'); -const concordanceOptions = require('./concordance-options').snapshotManager; +const {snapshotManager: concordanceOptions} = require('./concordance-options').resolve(); // Increment if encoding layout or Concordance serialization versions change. Previous AVA versions will not be able to // decode buffers generated by a newer version, so changing this value will require a major version bump of AVA itself. diff --git a/lib/test.js b/lib/test.js index 096978c9f..c23a9da92 100644 --- a/lib/test.js +++ b/lib/test.js @@ -5,7 +5,7 @@ const plur = require('plur'); const assert = require('./assert'); const nowAndTimers = require('./now-and-timers'); const parseTestArgs = require('./parse-test-args'); -const concordanceOptions = require('./concordance-options').default; +const {default: concordanceOptions} = require('./concordance-options').resolve(); function formatErrorValue(label, error) { const formatted = concordance.format(error, concordanceOptions); diff --git a/lib/worker/subprocess.js b/lib/worker/subprocess.js index b0e8f45c1..07a3bf994 100644 --- a/lib/worker/subprocess.js +++ b/lib/worker/subprocess.js @@ -19,6 +19,7 @@ ipc.send({type: 'ready-for-options'}); ipc.options.then(async options => { require('./options').set(options); require('../chalk').set(options.chalkOptions); + require('../concordance-options').configure(options.plugins); if (options.chalkOptions.level > 0) { const {stdout, stderr} = process; diff --git a/test/api.js b/test/api.js index ec96546e5..057fe4d57 100644 --- a/test/api.js +++ b/test/api.js @@ -1,5 +1,6 @@ 'use strict'; require('../lib/chalk').set(); +require('../lib/concordance-options').configure(); const path = require('path'); const fs = require('fs'); diff --git a/test/assert.js b/test/assert.js index 48d5dd4c9..fff65aec1 100644 --- a/test/assert.js +++ b/test/assert.js @@ -1,5 +1,6 @@ 'use strict'; require('../lib/chalk').set(); +require('../lib/concordance-options').configure(); require('../lib/worker/options').set({chalkOptions: {level: 0}}); const path = require('path'); diff --git a/test/beautify-stack.js b/test/beautify-stack.js index c8ef34032..f9c49f7b6 100644 --- a/test/beautify-stack.js +++ b/test/beautify-stack.js @@ -1,5 +1,6 @@ 'use strict'; require('../lib/chalk').set(); +require('../lib/concordance-options').configure(); require('../lib/worker/options').set({}); const proxyquire = require('proxyquire').noPreserveCache(); diff --git a/test/code-excerpt.js b/test/code-excerpt.js index cff1b3c48..506b61289 100644 --- a/test/code-excerpt.js +++ b/test/code-excerpt.js @@ -1,5 +1,6 @@ 'use strict'; require('../lib/chalk').set({level: 1}); +require('../lib/concordance-options').configure(); const fs = require('fs'); const tempWrite = require('temp-write'); diff --git a/test/helper/fix-reporter-env.js b/test/helper/fix-reporter-env.js index a40f37f40..1d89416d7 100644 --- a/test/helper/fix-reporter-env.js +++ b/test/helper/fix-reporter-env.js @@ -22,6 +22,7 @@ module.exports = () => { fixColors(); require('../../lib/chalk').set({level: 3}); + require('../../lib/concordance-options').configure(); return { restoreClock() { diff --git a/test/hooks.js b/test/hooks.js index 86d2007b4..ac8babb4e 100644 --- a/test/hooks.js +++ b/test/hooks.js @@ -1,5 +1,6 @@ 'use strict'; require('../lib/chalk').set(); +require('../lib/concordance-options').configure(); require('../lib/worker/options').set({}); const {test} = require('tap'); diff --git a/test/observable.js b/test/observable.js index 6ae86bc32..2fd1218c1 100644 --- a/test/observable.js +++ b/test/observable.js @@ -1,5 +1,6 @@ 'use strict'; require('../lib/chalk').set(); +require('../lib/concordance-options').configure(); require('../lib/worker/options').set({}); const {test} = require('tap'); diff --git a/test/promise.js b/test/promise.js index b38bf2444..8c8f5b25d 100644 --- a/test/promise.js +++ b/test/promise.js @@ -1,5 +1,6 @@ 'use strict'; require('../lib/chalk').set({level: 0}); +require('../lib/concordance-options').configure(); require('../lib/worker/options').set({}); const {test} = require('tap'); diff --git a/test/runner.js b/test/runner.js index d93ecb627..bf20fa899 100644 --- a/test/runner.js +++ b/test/runner.js @@ -1,5 +1,6 @@ 'use strict'; require('../lib/chalk').set(); +require('../lib/concordance-options').configure(); require('../lib/worker/options').set({}); const {test} = require('tap'); diff --git a/test/serialize-error.js b/test/serialize-error.js index 4f4874dae..ad9b86c50 100644 --- a/test/serialize-error.js +++ b/test/serialize-error.js @@ -1,5 +1,6 @@ 'use strict'; require('../lib/chalk').set(); +require('../lib/concordance-options').configure(); require('../lib/worker/options').set({}); const fs = require('fs'); diff --git a/test/test-try-commit.js b/test/test-try-commit.js index adc0ce44e..4fd2f0a21 100644 --- a/test/test-try-commit.js +++ b/test/test-try-commit.js @@ -1,5 +1,6 @@ 'use strict'; require('../lib/chalk').set(); +require('../lib/concordance-options').configure(); require('../lib/worker/options').set({chalkOptions: {level: 0}}); const {test} = require('tap'); diff --git a/test/test.js b/test/test.js index e602e0308..89b6491c4 100644 --- a/test/test.js +++ b/test/test.js @@ -1,5 +1,6 @@ 'use strict'; require('../lib/chalk').set({level: 0}); +require('../lib/concordance-options').configure(); require('../lib/worker/options').set({}); const path = require('path'); diff --git a/test/try-snapshot.js b/test/try-snapshot.js index e15bf1f01..4006ae71d 100644 --- a/test/try-snapshot.js +++ b/test/try-snapshot.js @@ -1,5 +1,6 @@ 'use strict'; require('../lib/chalk').set(); +require('../lib/concordance-options').configure(); require('../lib/worker/options').set({chalkOptions: {level: 0}}); const path = require('path'); diff --git a/test/watcher.js b/test/watcher.js index 205cb033e..d77177522 100644 --- a/test/watcher.js +++ b/test/watcher.js @@ -11,6 +11,7 @@ const {normalizeGlobs} = require('../lib/globs'); const {setImmediate} = require('../lib/now-and-timers'); require('../lib/chalk').set({}); +require('../lib/concordance-options').configure(); // Helper to make using beforeEach less arduous function makeGroup(test) {