eslint-docgen 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -116,6 +116,14 @@ When defined, will try to use a rule specific template instead of [`index.ejs`](
116
116
  #### `globalTemplatePath`
117
117
  When defined, templates in this path will override the global templates defined in [`src/templates`](src/templates).
118
118
 
119
+ #### `readmeTemplate` (default `'README.md.template'`)
120
+ File path containing a README template, with placeholders for a generated rules list (`<!-- rules -->`), and optionally deprecated rules (`<!-- deprecated -->`).
121
+
122
+ Invoke by running `eslint-docgen-build-readme`.
123
+
124
+ #### `readmeTarget` (default `'README.md'`)
125
+ File path to write generated README to, after compiling `readmeTemplate`.
126
+
119
127
  #### `docLink` (default `false`)
120
128
  Add a link to the documentation source in the "Resources" section.
121
129
 
@@ -158,7 +166,7 @@ Number of spaces to convert tabs to in code examples. Tabs in examples are alway
158
166
 
159
167
  ## 🔍 Rules index
160
168
 
161
- To assist with building an index of your rules, for example to put in a root README, this package exports `rulesWithConfig`. The value is a Map much like the one returned by [Linter#getRules](https://eslint.org/docs/developer-guide/nodejs-api#linter-getrules) but each rule has an additional `configMap` property that describes which configs include the rule and the options used (`null` if no options are used).
169
+ To assist with building an index of your rules, for example to put in a root README, this package exports `rulesWithConfig`. The value is a Map much like the one returned by [Linter#getRules](https://eslint.org/docs/developer-guide/nodejs-api#linter-getrules) but each rule has an additional `configMap` property that describes which configs include the rule, the severity (normalised to a string) and options used (`null` if none are used).
162
170
 
163
171
  Note that the rule names do not include the plugin prefix.
164
172
 
@@ -170,8 +178,9 @@ require( 'eslint-docgen' ).rulesWithConfig.get( 'no-event-shorthand' );
170
178
  meta: [Object],
171
179
  create: [Function],
172
180
  configMap: Map {
173
- 'deprecated-3.5' => null,
174
- 'deprecated-3.3' => [ { allowAjaxEvents: true } ]
181
+ 'deprecated-4.0' => { severity: 'error', options: null },
182
+ 'deprecated-3.5' => { severity: 'warn', options: null },
183
+ 'deprecated-3.3' => { severity: 'warn', options: [ { allowAjaxEvents: true } ] }
175
184
  }
176
185
  }
177
186
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-docgen",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "Automatically generate ESLint plugin documentation from rule metadata and test cases.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,6 +12,9 @@
12
12
  "documentation"
13
13
  ],
14
14
  "main": "src/index.js",
15
+ "bin": {
16
+ "eslint-docgen-build-readme": "src/build-readme.js"
17
+ },
15
18
  "files": [
16
19
  "src"
17
20
  ],
@@ -20,25 +23,24 @@
20
23
  "report": "nyc report --reporter=html"
21
24
  },
22
25
  "engines": {
23
- "node": ">=12.0.0"
26
+ "node": ">=20.0.0"
24
27
  },
25
28
  "dependencies": {
26
29
  "chalk": "^4.1.2",
27
- "ejs": "^3.1.8",
30
+ "ejs": "^4.0.1",
28
31
  "eslint": ">=8.0.0",
29
- "import-fresh": "^3.3.0",
30
- "jsonschema": "^1.4.1",
32
+ "import-fresh": "^3.3.1",
33
+ "jsonschema": "^1.5.0",
31
34
  "merge-options": "^3.0.4",
32
- "mkdirp": "^1.0.4",
35
+ "mkdirp": "^3.0.1",
33
36
  "pkg-dir": "^5.0.0",
34
37
  "pluralize": "^8.0.0",
35
38
  "simple-mock": "^0.8.0",
36
39
  "upath": "^2.0.1"
37
40
  },
38
41
  "devDependencies": {
39
- "eslint-config-wikimedia": "^0.22.1",
40
- "eslint-plugin-node": "^11.1.0",
41
- "mocha": "^9.2.0",
42
- "nyc": "^15.1.0"
42
+ "eslint-config-wikimedia": "^0.32.3",
43
+ "mocha": "^11.7.5",
44
+ "nyc": "^17.1.0"
43
45
  }
44
46
  }
@@ -21,9 +21,10 @@ const languageFromExtension = {
21
21
  * @return {string} Concatenated list
22
22
  */
23
23
  function listFormatter( list ) {
24
- return list.reduce( ( acc, cur, i, arr ) =>
25
- acc + ( i === 0 ? '' : ( ( i === arr.length - 1 ) ? ' and ' : ', ' ) ) + cur,
26
- '' );
24
+ return list.reduce(
25
+ ( acc, cur, i, arr ) => acc + ( i === 0 ? '' : ( ( i === arr.length - 1 ) ? ' and ' : ', ' ) ) + cur,
26
+ ''
27
+ );
27
28
  }
28
29
 
29
30
  /**
@@ -79,8 +80,8 @@ async function buildDocsFromTests(
79
80
  }
80
81
 
81
82
  async function buildRuleDetails( testList, isValid, showFixes ) {
82
- testList = testList.filter( ( test ) =>
83
- test.docgen === undefined ?
83
+ testList = testList.filter(
84
+ ( test ) => test.docgen === undefined ?
84
85
  !config.excludeExamplesByDefault :
85
86
  test.docgen
86
87
  );
@@ -100,12 +101,13 @@ async function buildDocsFromTests(
100
101
 
101
102
  if ( showFixes ) {
102
103
  // Calculate maxCodeLength for alignment
103
- maxCodeLength = fixedCode.reduce( ( acc, code ) =>
104
- code.split( '\n' ).reduce(
104
+ maxCodeLength = fixedCode.reduce(
105
+ ( acc, code ) => code.split( '\n' ).reduce(
105
106
  ( lineAcc, line ) => Math.max( lineAcc, line.length ),
106
107
  acc
107
108
  ),
108
- 0 );
109
+ 0
110
+ );
109
111
 
110
112
  const outputList = testList.map( ( test ) => test.output );
111
113
  if ( config.fixCodeExamples ) {
@@ -120,7 +122,7 @@ async function buildDocsFromTests(
120
122
 
121
123
  const codeSet = {};
122
124
  let previousMultiLine = false;
123
- testList.forEach( function ( test, i ) {
125
+ testList.forEach( ( test, i ) => {
124
126
  const filename = getFilename( test );
125
127
  let lang = 'js';
126
128
  // Switch to Vue if we are showing file names and its a Vue file.
@@ -260,10 +262,12 @@ async function buildDocsFromTests(
260
262
  let inConfigs = [];
261
263
  if ( configMap ) {
262
264
  inConfigs = Array.from( configMap.keys() ).map( ( configName ) => {
263
- const options = configMap.get( configName );
265
+ const { options, severity } = configMap.get( configName );
266
+
264
267
  return {
265
268
  config: configName,
266
- options: options && Object.keys( options[ 0 ] ).length ? JSON.stringify( options ) : ''
269
+ options: options && Object.keys( options[ 0 ] ).length ? JSON.stringify( options ) : '',
270
+ severity: severity
267
271
  };
268
272
  } );
269
273
  }
@@ -271,11 +275,12 @@ async function buildDocsFromTests(
271
275
  const invalid = await buildRuleDetails( tests.invalid, false );
272
276
  const valid = await buildRuleDetails( tests.valid, true );
273
277
 
274
- const validInvalid = invalid.concat( valid ).sort( ( a, b ) => {
275
- return a.key === b.key ?
278
+ const validInvalid = invalid.concat( valid ).sort(
279
+ // sort by key, then value
280
+ ( a, b ) => a.key === b.key ?
276
281
  ( a.valid < b.valid ? -1 : 1 ) :
277
- ( a.key < b.key ? -1 : 1 );
278
- } );
282
+ ( a.key < b.key ? -1 : 1 )
283
+ );
279
284
 
280
285
  let fixed = [];
281
286
  if ( ruleMeta.fixable && config.showFixExamples ) {
@@ -323,6 +328,7 @@ async function buildDocsFromTests(
323
328
  const fs = require( 'fs' );
324
329
  const packagePath = require( './package-path' );
325
330
  const ruleTemplatePath = packagePath( config.ruleTemplatePath.replace( '{name}', name ) );
331
+ // eslint-disable-next-line security/detect-non-literal-fs-filename
326
332
  if ( fs.existsSync( ruleTemplatePath ) ) {
327
333
  index = loadRuleTemplate( ruleTemplatePath );
328
334
  }
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const configRename = ( name ) => name.replace( 'deprecated-', '' );
5
+
6
+ /**
7
+ * Build the README contents from a template
8
+ *
9
+ * @param {Object} config Resolved eslint-docgen config
10
+ * @param {Map} rulesWithConfig Map of rule names to rule data (meta and configMap)
11
+ * @param {string} template README template containing `<!-- rules -->` and
12
+ * `<!-- deprecated -->` placeholders
13
+ * @return {string} README contents
14
+ */
15
+ function buildReadme( config, rulesWithConfig, template ) {
16
+ function getRules( deprecated ) {
17
+ return Array.from( rulesWithConfig.keys() ).map( ( rule ) => {
18
+ const fullRule = config.pluginName + '/' + rule;
19
+ const ruleData = rulesWithConfig.get( rule );
20
+ const docs = ruleData.meta.docs;
21
+ const configs = Array.from( ruleData.configMap.keys() ).map( ( name ) => {
22
+ const { options, severity } = ruleData.configMap.get( name );
23
+ // TODO: Create util to compare options to defaults
24
+ return {
25
+ name: configRename( name ),
26
+ hasOptions: !!( options && Object.keys( options[ 0 ] ).length ),
27
+ severity
28
+ };
29
+ } );
30
+ // Sort configs by name - sort numerical values by version number
31
+ configs.sort( ( a, b ) => {
32
+ if ( a.name.includes( '.' ) === -1 ) {
33
+ return a.name.localeCompare( b.name );
34
+ }
35
+ const aVersion = a.name.split( '.' ).map( ( n ) => parseInt( n, 10 ) );
36
+ const bVersion = b.name.split( '.' ).map( ( n ) => parseInt( n, 10 ) );
37
+ for ( let i = 0; i < Math.max( aVersion.length, bVersion.length ); i++ ) {
38
+ if ( aVersion[ i ] !== bVersion[ i ] ) {
39
+ return ( aVersion[ i ] || 0 ) - ( bVersion[ i ] || 0 );
40
+ }
41
+ }
42
+ return 0;
43
+ } );
44
+ if ( !!docs.deprecated === deprecated ) {
45
+ return '* [`' + fullRule + '`](' + config.docPath.replace( '{name}', rule ) + ')' +
46
+ (
47
+ ruleData.meta.schema.length ?
48
+ ' ⚙️' :
49
+ ''
50
+ ) +
51
+ (
52
+ ruleData.meta.fixable ?
53
+ ' 🔧' :
54
+ ''
55
+ ) +
56
+ (
57
+ docs.replacedBy ?
58
+ ' (use [`' + config.pluginName + '/' + docs.replacedBy + '`](' + config.docPath.replace( '{name}', docs.replacedBy ) + '))' :
59
+ ''
60
+ ) +
61
+ (
62
+ ruleData.configMap.size ?
63
+ ' ' +
64
+ Array.from( configs ).map(
65
+ ( c ) => ( c.severity === 'error' ? '**' : '' ) +
66
+ '`' + c.name + ( c.hasOptions ? '†' : '' ) + '`' +
67
+ ( c.severity === 'error' ? '**' : '' ) ).join( ', ' ) :
68
+ ''
69
+ );
70
+ }
71
+ return null;
72
+ } ).filter( ( rule ) => rule ).join( '\n' );
73
+ }
74
+
75
+ return `<!-- This file is built by eslint-docgen-build-readme. Do not edit it directly; edit ${ config.readmeTemplate } instead. -->\n` +
76
+ template
77
+ .replace( '<!-- rules -->', getRules( false ) )
78
+ .replace( '<!-- deprecated -->', getRules( true ) );
79
+ }
80
+
81
+ /* istanbul ignore next */
82
+ function main() {
83
+ const fs = require( 'fs' );
84
+ const rulesWithConfig = require( './rules-with-config' );
85
+ const getConfig = require( './get-config' );
86
+
87
+ const config = getConfig();
88
+ // eslint-disable-next-line security/detect-non-literal-fs-filename
89
+ const template = fs.readFileSync( config.readmeTemplate, { encoding: 'UTF8' } );
90
+
91
+ // eslint-disable-next-line security/detect-non-literal-fs-filename
92
+ fs.writeFile(
93
+ config.readmeTarget,
94
+ buildReadme( config, rulesWithConfig, template ),
95
+ ( err ) => {
96
+ if ( err ) {
97
+ throw err;
98
+ }
99
+ }
100
+ );
101
+ }
102
+
103
+ /* istanbul ignore next */
104
+ if ( require.main === module ) {
105
+ main();
106
+ }
107
+
108
+ module.exports = buildReadme;
@@ -21,6 +21,8 @@
21
21
  "type": "null",
22
22
  "message": "must be renamed to \"globalTemplatePath\""
23
23
  },
24
+ "readmeTemplate": { "type": "string" },
25
+ "readmeTarget": { "type": "string" },
24
26
  "docLink": { "type": "boolean" },
25
27
  "ruleLink": { "type": "boolean" },
26
28
  "testLink": { "type": "boolean" },
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const packagePath = require( './package-path' );
4
+ // eslint-disable-next-line security/detect-non-literal-require
4
5
  const packageName = require( packagePath( './package' ) ).name;
5
6
  const naming = require( './naming' );
6
7
  const pluginName = naming.getShorthandName( packageName, 'eslint-plugin' );
@@ -17,6 +18,8 @@ module.exports = {
17
18
  testPath: null,
18
19
  ruleTemplatePath: null,
19
20
  globalTemplatePath: null,
21
+ readmeTemplate: 'README.md.template',
22
+ readmeTarget: 'README.md',
20
23
  docLink: false,
21
24
  ruleLink: true,
22
25
  testLink: true,
package/src/fix.js CHANGED
@@ -4,7 +4,6 @@ const { Linter, ESLint } = require( 'eslint' );
4
4
  const linter = new Linter();
5
5
  const eslint = new ESLint();
6
6
  const mergeOptions = require( 'merge-options' );
7
- // eslint-disable-next-line node/no-missing-require
8
7
  const { builtinRules } = require( 'eslint/use-at-your-own-risk' );
9
8
 
10
9
  async function getConfig() {
@@ -12,7 +11,7 @@ async function getConfig() {
12
11
 
13
12
  // Optimization: Only use fixable rules
14
13
  const fixableRules = {};
15
- Object.keys( config.rules ).forEach( function ( ruleName ) {
14
+ Object.keys( config.rules ).forEach( ( ruleName ) => {
16
15
  if ( builtinRules.has( ruleName ) ) {
17
16
  const rule = builtinRules.get( ruleName );
18
17
  if ( rule.meta.fixable ) {
@@ -38,6 +37,7 @@ async function lintFix( code, testerConfig ) {
38
37
  // TODO
39
38
  // istanbul ignore next
40
39
  if ( typeof mergedConfig.parser === 'string' ) {
40
+ // eslint-disable-next-line security/detect-non-literal-require
41
41
  linter.defineParser( mergedConfig.parser, require( mergedConfig.parser ) );
42
42
  }
43
43
 
package/src/formatter.js CHANGED
@@ -20,8 +20,8 @@ function labelSuffix( label ) {
20
20
  * @return {string}
21
21
  */
22
22
  function indentAfterFirst( text, indent ) {
23
- return text.split( '\n' ).map( ( line, i ) =>
24
- i ? ' '.repeat( indent ) + line : line
23
+ return text.split( '\n' ).map(
24
+ ( line, i ) => i ? ' '.repeat( indent ) + line : line
25
25
  ).join( '\n' );
26
26
  }
27
27
 
package/src/get-config.js CHANGED
@@ -3,6 +3,8 @@
3
3
  const fs = require( 'fs' );
4
4
  const packagePath = require( './package-path' );
5
5
  const importFresh = require( 'import-fresh' );
6
+ const validateConfig = require( './validate-config' );
7
+ const formatter = require( './formatter' );
6
8
 
7
9
  const configFilenames = [
8
10
  '.eslintdocgenrc.js',
@@ -15,6 +17,7 @@ const configFilenames = [
15
17
  * Missing values are backfilled with the defaults
16
18
  *
17
19
  * @return {Object} Config
20
+ * @throws {Error} If no config file is found, or if the config is invalid
18
21
  */
19
22
  function getConfig() {
20
23
  let config, configPath;
@@ -22,6 +25,7 @@ function getConfig() {
22
25
  configFilenames.some( ( configFilename ) => {
23
26
  configPath = packagePath( configFilename );
24
27
 
28
+ // eslint-disable-next-line security/detect-non-literal-fs-filename
25
29
  if ( fs.existsSync( configPath ) ) {
26
30
  config = importFresh( configPath );
27
31
  return true;
@@ -30,16 +34,18 @@ function getConfig() {
30
34
  } );
31
35
 
32
36
  if ( !config ) {
33
- throw new Error( '.eslintdocgenrc not found' );
37
+ throw new Error( [ formatter.heading( 'eslint-docgen' ), formatter.error( '.eslintdocgenrc not found' ) ].join( '\n' ) );
34
38
  }
35
39
 
36
40
  const defaultConfig = require( './default-config.js' );
37
41
  config = Object.assign( {}, defaultConfig, config );
38
42
 
39
- return {
40
- config: config,
41
- configPath: configPath
42
- };
43
+ const configErrors = validateConfig( config );
44
+ if ( configErrors.length ) {
45
+ throw new Error( [ formatter.heading( configPath ), ...configErrors.map( formatter.error ) ].join( '\n' ) );
46
+ }
47
+
48
+ return config;
43
49
  }
44
50
 
45
51
  module.exports = getConfig;
@@ -5,10 +5,12 @@ const path = require( 'upath' );
5
5
  const ejs = require( 'ejs' );
6
6
 
7
7
  function loadTemplatesFromPath( dirPath ) {
8
+ // eslint-disable-next-line security/detect-non-literal-fs-filename
8
9
  const files = fs.readdirSync( dirPath );
9
10
  const templates = {};
10
11
  files.forEach( ( filename ) => {
11
12
  templates[ path.parse( filename ).name ] =
13
+ // eslint-disable-next-line security/detect-non-literal-fs-filename
12
14
  fs.readFileSync( path.join( dirPath, filename ) ).toString();
13
15
  } );
14
16
  return templates;
@@ -31,14 +33,13 @@ function loadTemplates( dirPaths ) {
31
33
 
32
34
  function compile( string, filename ) {
33
35
  const compiled = ejs.compile( string, { client: true } );
34
- return ( data ) =>
35
- compiled( data, null, function ( template, includeData ) {
36
- const mergedData = Object.assign( {}, data, includeData );
37
- if ( !hasOwn.call( templateStrings, template ) ) {
38
- throw new Error( 'Template `' + template + '` not found in template `' + filename + '`' );
39
- }
40
- return globalTemplates[ template ]( mergedData );
41
- } );
36
+ return ( data ) => compiled( data, null, ( template, includeData ) => {
37
+ const mergedData = Object.assign( {}, data, includeData );
38
+ if ( !hasOwn.call( templateStrings, template ) ) {
39
+ throw new Error( 'Template `' + template + '` not found in template `' + filename + '`' );
40
+ }
41
+ return globalTemplates[ template ]( mergedData );
42
+ } );
42
43
  }
43
44
 
44
45
  Object.keys( templateStrings ).forEach( ( filename ) => {
@@ -47,6 +48,7 @@ function loadTemplates( dirPaths ) {
47
48
 
48
49
  function loadRuleTemplate( ruleTemplatePath ) {
49
50
  return compile(
51
+ // eslint-disable-next-line security/detect-non-literal-fs-filename
50
52
  fs.readFileSync( ruleTemplatePath ).toString()
51
53
  );
52
54
  }
package/src/main.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const packagePath = require( './package-path' );
4
+ // eslint-disable-next-line security/detect-non-literal-require
4
5
  const main = require( packagePath( './package' ) ).main || 'index.js';
5
6
 
6
7
  module.exports = packagePath( main );
package/src/naming.js CHANGED
@@ -14,17 +14,19 @@
14
14
  */
15
15
  function getShorthandName( fullname, prefix ) {
16
16
  if ( fullname[ 0 ] === '@' ) {
17
- let matchResult = new RegExp( `^(@[^/]+)/${prefix}$`, 'u' ).exec( fullname );
17
+ // eslint-disable-next-line security/detect-non-literal-regexp
18
+ let matchResult = new RegExp( `^(@[^/]+)/${ prefix }$`, 'u' ).exec( fullname );
18
19
 
19
20
  if ( matchResult ) {
20
21
  return matchResult[ 1 ];
21
22
  }
22
23
 
23
- matchResult = new RegExp( `^(@[^/]+)/${prefix}-(.+)$`, 'u' ).exec( fullname );
24
+ // eslint-disable-next-line security/detect-non-literal-regexp
25
+ matchResult = new RegExp( `^(@[^/]+)/${ prefix }-(.+)$`, 'u' ).exec( fullname );
24
26
  if ( matchResult ) {
25
- return `${matchResult[ 1 ]}/${matchResult[ 2 ]}`;
27
+ return `${ matchResult[ 1 ] }/${ matchResult[ 2 ] }`;
26
28
  }
27
- } else if ( fullname.startsWith( `${prefix}-` ) ) {
29
+ } else if ( fullname.startsWith( `${ prefix }-` ) ) {
28
30
  return fullname.slice( prefix.length + 1 );
29
31
  }
30
32
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  const packagePath = require( './package-path' );
4
4
  // Use plugin's version of ESLint
5
+ // eslint-disable-next-line security/detect-non-literal-require
5
6
  const ESLintRuleTester = require( packagePath( 'node_modules/eslint' ) ).RuleTester;
6
7
  const inDocMode = !!process.env.DOCGEN;
7
8
 
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ // eslint-disable-next-line security/detect-non-literal-require
3
4
  const main = require( require( './main' ) );
4
- const pluginName = require( './get-config' )().config.pluginName;
5
+ const pluginName = require( './get-config' )().pluginName;
5
6
  const configs = main.configs;
6
7
  const rulesWithConfig = new Map( Object.entries( main.rules ) );
7
8
 
@@ -16,9 +17,26 @@ for ( const name in configs ) {
16
17
  for ( const fullName in rules ) {
17
18
  // Configs use the full rule name with the plugin prefix, so remove this
18
19
  const shortName = fullName.slice( pluginName.length + 1 );
20
+ let options, rawSeverity;
21
+
22
+ if ( Array.isArray( rules[ fullName ] ) ) {
23
+ options = rules[ fullName ].slice( 1 );
24
+ rawSeverity = rules[ fullName ][ 0 ];
25
+ } else {
26
+ options = null;
27
+ rawSeverity = rules[ fullName ];
28
+ }
29
+ const severityMap = [ 'off', 'warn', 'error' ];
30
+ const severity = typeof rawSeverity === 'number' ?
31
+ severityMap[ rawSeverity ] || 'error' :
32
+ rawSeverity;
33
+
19
34
  rulesWithConfig.get( shortName ).configMap.set(
20
35
  name,
21
- Array.isArray( rules[ fullName ] ) ? rules[ fullName ].slice( 1 ) : null
36
+ {
37
+ severity,
38
+ options
39
+ }
22
40
  );
23
41
  }
24
42
  }
@@ -1 +1 @@
1
- 📋 This rule is enabled in `plugin:<%- pluginName %>/<%- inConfig.config %>`<%- include( 'optionsAndSettings', { data: inConfig } ) %>.
1
+ 📋 This rule is enabled as <%- inConfig.severity === 'warn' ? 'a warning' : 'an error' %> in `plugin:<%- pluginName %>/<%- inConfig.config %>`<%- include( 'optionsAndSettings', { data: inConfig } ) %>.
@@ -11,8 +11,7 @@ const schema = require( './config-schema' );
11
11
  * @return {string[]} A list of errors found
12
12
  */
13
13
  function validateConfig( config ) {
14
- const errors = v.validate( config, schema ).errors.map( ( e ) =>
15
- e.schema.message ? e.property + ' ' + e.schema.message : e.stack );
14
+ const errors = v.validate( config, schema ).errors.map( ( e ) => e.schema.message ? e.property + ' ' + e.schema.message : e.stack );
16
15
 
17
16
  return errors;
18
17
  }
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const fs = require( 'fs' );
4
- const mkdirp = require( 'mkdirp' );
4
+ const { mkdirp } = require( 'mkdirp' );
5
5
  const path = require( 'upath' );
6
6
  const buildDocsFromTests = require( './build-docs-from-tests' );
7
7
 
@@ -9,23 +9,16 @@ const formatter = require( './formatter' );
9
9
  const rulesWithConfig = require( './rules-with-config' );
10
10
 
11
11
  const getConfig = require( './get-config' );
12
- let config, configPath;
13
- try {
14
- ( { config, configPath } = getConfig() );
15
- } catch ( e ) {
16
- throw new Error( [ formatter.heading( 'eslint-docgen' ), formatter.error( e.message ) ].join( '\n' ) );
17
- }
12
+ const config = getConfig();
18
13
 
19
- const configValidator = require( './validate-config' );
14
+ const validateConfig = require( './validate-config' );
20
15
  function assertValidConfig( maybeValidConfig, configSource ) {
21
- const configErrors = configValidator( maybeValidConfig );
16
+ const configErrors = validateConfig( maybeValidConfig );
22
17
  if ( configErrors.length ) {
23
18
  throw new Error( [ formatter.heading( configSource ), ...configErrors.map( formatter.error ) ].join( '\n' ) );
24
19
  }
25
20
  }
26
21
 
27
- assertValidConfig( config, configPath );
28
-
29
22
  const packagePath = require( './package-path' );
30
23
 
31
24
  const loadTemplates = require( './load-templates' );
@@ -61,6 +54,7 @@ async function writeDocsFromTests( name, rule, tests, testerConfig, done ) {
61
54
 
62
55
  const outputDir = path.dirname( outputPath );
63
56
  mkdirp( outputDir ).then( () => {
57
+ // eslint-disable-next-line security/detect-non-literal-fs-filename
64
58
  fs.writeFile(
65
59
  outputPath,
66
60
  output,
@@ -71,8 +65,8 @@ async function writeDocsFromTests( name, rule, tests, testerConfig, done ) {
71
65
  if ( messages.length ) {
72
66
  console.log();
73
67
  console.log( formatter.heading( outputPath ) );
74
- messages.forEach( ( message ) =>
75
- console.log( formatter[ message.type ]( message.text, message.label ) )
68
+ messages.forEach(
69
+ ( message ) => console.log( formatter[ message.type ]( message.text, message.label ) )
76
70
  );
77
71
  console.log();
78
72
  }