eslint-docgen 0.4.5 → 0.6.2
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 +10 -1
- package/package.json +5 -5
- package/src/build-docs-from-tests.js +62 -27
- package/src/config-schema.json +1 -0
- package/src/default-config.js +1 -0
- package/src/rule-tester.js +9 -14
- package/src/templates/inConfig.ejs +1 -1
- package/src/templates/index.ejs +2 -0
- package/src/templates/optionsAndSettings.ejs +3 -1
- package/src/write-docs-from-tests.js +24 -26
- package/Changelog.md +0 -78
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ To migrate an existing plugin with manually built documentation you can use the
|
|
|
63
63
|
|
|
64
64
|
## ⚙️ Configuration
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
Configuration for all rules in a project is controlled by creating a JSON/JavaScript file called `.eslintdocgenrc.json`/`.eslintdocgenrc.js` in your project root:
|
|
67
67
|
|
|
68
68
|
#### JSON
|
|
69
69
|
```jsonc
|
|
@@ -81,6 +81,12 @@ module.exports = {
|
|
|
81
81
|
};
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
+
#### Overriding
|
|
85
|
+
|
|
86
|
+
The project-wide rules configuration can be overridden for individual rules by adding a `docgenConfig` property to the tests object passed to RuleTester.run(). All configuration options that are supported project-wide can be changed.
|
|
87
|
+
|
|
88
|
+
### Options
|
|
89
|
+
|
|
84
90
|
The following config options are available:
|
|
85
91
|
|
|
86
92
|
#### `docPath` (*required*)
|
|
@@ -123,6 +129,9 @@ Shows config comments at the top of code examples:
|
|
|
123
129
|
#### `showFixExamples` (default `true`)
|
|
124
130
|
Show examples of how code is fixed by the rule.
|
|
125
131
|
|
|
132
|
+
#### `showFilenames` (default: `false`)
|
|
133
|
+
Show the relevant file name for test cases.
|
|
134
|
+
|
|
126
135
|
#### `excludeExamplesByDefault` (default `false`)
|
|
127
136
|
Exclude tests from being used as examples by default. When this is `true` users must set `docgen: true` on any test they want to be included in examples.
|
|
128
137
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-docgen",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Automatically generate ESLint plugin documentation from rule metadata and test cases.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
"report": "nyc report --reporter=html"
|
|
21
21
|
},
|
|
22
22
|
"engines": {
|
|
23
|
-
"node": ">=
|
|
23
|
+
"node": ">=12.0.0"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"chalk": "^4.1.
|
|
26
|
+
"chalk": "^4.1.2",
|
|
27
27
|
"ejs": "^3.1.6",
|
|
28
28
|
"eslint": ">=5.0.0",
|
|
29
29
|
"import-fresh": "^3.3.0",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"upath": "^2.0.1"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"eslint-config-wikimedia": "^0.
|
|
39
|
+
"eslint-config-wikimedia": "^0.21.0",
|
|
40
40
|
"eslint-plugin-node": "^11.1.0",
|
|
41
|
-
"mocha": "^
|
|
41
|
+
"mocha": "^9.1.3",
|
|
42
42
|
"nyc": "^15.1.0"
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
const pluralize = require( 'pluralize' );
|
|
4
4
|
const path = require( 'upath' );
|
|
5
|
+
// Mapping from extension to language name for markdown
|
|
6
|
+
// Default language is 'js'
|
|
7
|
+
const languageFromExtension = {
|
|
8
|
+
'.html': 'html',
|
|
9
|
+
'.ts': 'ts',
|
|
10
|
+
'.vue': 'vue'
|
|
11
|
+
};
|
|
5
12
|
|
|
6
13
|
/**
|
|
7
14
|
* Format a list of items with natural language
|
|
@@ -59,7 +66,25 @@ function buildDocsFromTests(
|
|
|
59
66
|
return typeof test === 'string' ? test : test.code;
|
|
60
67
|
}
|
|
61
68
|
|
|
62
|
-
|
|
69
|
+
/**
|
|
70
|
+
* @param {string|Object} test Test case
|
|
71
|
+
* @return {string|null} The base file name, or null if not set
|
|
72
|
+
*/
|
|
73
|
+
function getFilename( test ) {
|
|
74
|
+
if ( typeof test === 'string' || test.filename === undefined ) {
|
|
75
|
+
// Either the test is just a code snippet, or no file name is set
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
return path.basename( test.filename );
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function buildRuleDetails( testList, isValid, showFixes ) {
|
|
82
|
+
testList = testList.filter( ( test ) =>
|
|
83
|
+
test.docgen === undefined ?
|
|
84
|
+
!config.excludeExamplesByDefault :
|
|
85
|
+
test.docgen
|
|
86
|
+
);
|
|
87
|
+
|
|
63
88
|
let fixedCode, fixedOutput, maxCodeLength;
|
|
64
89
|
const testsByOptions = {};
|
|
65
90
|
|
|
@@ -96,30 +121,37 @@ function buildDocsFromTests(
|
|
|
96
121
|
const codeSet = {};
|
|
97
122
|
let previousMultiLine = false;
|
|
98
123
|
testList.forEach( function ( test, i ) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
124
|
+
const filename = getFilename( test );
|
|
125
|
+
let lang = 'js';
|
|
126
|
+
// Switch to Vue if we are showing file names and its a Vue file.
|
|
127
|
+
// optionsAndSettings.filename is only set if it should be shown
|
|
128
|
+
// TODO should we add other languages too?
|
|
129
|
+
if ( filename ) {
|
|
130
|
+
const ext = path.extname( filename );
|
|
131
|
+
if ( ext in languageFromExtension ) {
|
|
132
|
+
lang = languageFromExtension[ ext ];
|
|
133
|
+
}
|
|
105
134
|
}
|
|
106
135
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
136
|
+
// Keys are in reverse sort order, e.g. examples with options
|
|
137
|
+
// are shown before examples with settings
|
|
138
|
+
const optionsAndSettings = {
|
|
139
|
+
// Always separate tests by language for syntax highlighting
|
|
140
|
+
lang: lang,
|
|
141
|
+
settings: test.settings,
|
|
142
|
+
options: test.options,
|
|
143
|
+
// Only group by filename if filenames are shown
|
|
144
|
+
filename: config.showFilenames && filename
|
|
145
|
+
};
|
|
146
|
+
const hashObject = {};
|
|
147
|
+
// Ensure examples without a specific key are shown first
|
|
148
|
+
Object.keys( optionsAndSettings ).forEach( ( key ) => {
|
|
149
|
+
hashObject[ key ] = optionsAndSettings[ key ] ?
|
|
150
|
+
[ '1', optionsAndSettings[ key ] ] :
|
|
151
|
+
[ '0', optionsAndSettings[ key ] ];
|
|
152
|
+
} );
|
|
114
153
|
|
|
115
|
-
|
|
116
|
-
if ( test.options || test.settings ) {
|
|
117
|
-
optionsAndSettings = {
|
|
118
|
-
options: test.options,
|
|
119
|
-
settings: test.settings
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
const hash = optionsAndSettings ? JSON.stringify( optionsAndSettings ) : '';
|
|
154
|
+
const hash = JSON.stringify( hashObject );
|
|
123
155
|
|
|
124
156
|
codeSet[ hash ] = codeSet[ hash ] || {};
|
|
125
157
|
|
|
@@ -144,9 +176,8 @@ function buildDocsFromTests(
|
|
|
144
176
|
};
|
|
145
177
|
|
|
146
178
|
if ( showFixes && test.output ) {
|
|
147
|
-
const output = fixedOutput[ i ];
|
|
148
179
|
const codeLines = code.split( '\n' );
|
|
149
|
-
const outputLines =
|
|
180
|
+
const outputLines = fixedOutput[ i ].split( '\n' );
|
|
150
181
|
const maxLines = Math.max( codeLines.length, outputLines.length );
|
|
151
182
|
const exampleLines = [];
|
|
152
183
|
for ( let l = 0; l < maxLines; l++ ) {
|
|
@@ -164,7 +195,8 @@ function buildDocsFromTests(
|
|
|
164
195
|
example = code;
|
|
165
196
|
multiLine = code.split( '\n' ).length > 1;
|
|
166
197
|
}
|
|
167
|
-
|
|
198
|
+
// Put linebreaks around multi-line examples
|
|
199
|
+
if ( testsByOptions[ hash ].tests.length && ( multiLine || previousMultiLine ) ) {
|
|
168
200
|
example = '\n' + example;
|
|
169
201
|
}
|
|
170
202
|
testsByOptions[ hash ].tests.push( example );
|
|
@@ -190,10 +222,12 @@ function buildDocsFromTests(
|
|
|
190
222
|
return Object.keys( testsByOptions ).map( ( key, i ) => {
|
|
191
223
|
const section = testsByOptions[ key ];
|
|
192
224
|
const optionsAndSettings = section.optionsAndSettings;
|
|
225
|
+
const lang = optionsAndSettings && optionsAndSettings.lang;
|
|
193
226
|
const options = optionsAndSettings && optionsAndSettings.options;
|
|
194
227
|
const settings = optionsAndSettings && optionsAndSettings.settings;
|
|
228
|
+
const filename = optionsAndSettings && optionsAndSettings.filename;
|
|
195
229
|
|
|
196
|
-
let examples = '```
|
|
230
|
+
let examples = '```' + lang + '\n';
|
|
197
231
|
if ( config.showConfigComments ) {
|
|
198
232
|
examples += comments[ i ] + '\n';
|
|
199
233
|
}
|
|
@@ -202,9 +236,10 @@ function buildDocsFromTests(
|
|
|
202
236
|
|
|
203
237
|
return {
|
|
204
238
|
key: key,
|
|
205
|
-
valid:
|
|
239
|
+
valid: isValid,
|
|
206
240
|
options: options ? JSON.stringify( options ) : '',
|
|
207
241
|
settings: settings ? JSON.stringify( settings ) : '',
|
|
242
|
+
filename: filename || '',
|
|
208
243
|
examples: examples,
|
|
209
244
|
testCount: section.tests.length
|
|
210
245
|
};
|
package/src/config-schema.json
CHANGED
package/src/default-config.js
CHANGED
package/src/rule-tester.js
CHANGED
|
@@ -3,37 +3,32 @@
|
|
|
3
3
|
const packagePath = require( './package-path' );
|
|
4
4
|
// Use plugin's version of ESLint
|
|
5
5
|
const ESLintRuleTester = require( packagePath( 'node_modules/eslint' ) ).RuleTester;
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
if ( process.argv.includes( '--doc' ) ) {
|
|
9
|
-
const formatter = require( './formatter' );
|
|
10
|
-
console.log(
|
|
11
|
-
formatter.warn( '--doc is deprecated, use the DOCGEN=1 environment variable instead.' )
|
|
12
|
-
);
|
|
13
|
-
}
|
|
6
|
+
const inDocMode = !!process.env.DOCGEN;
|
|
14
7
|
|
|
15
8
|
/**
|
|
16
9
|
* Extends ESLint's RuleTester to also build documentation
|
|
17
10
|
*/
|
|
18
11
|
class RuleTester extends ESLintRuleTester {
|
|
19
12
|
run( name, rule, tests ) {
|
|
20
|
-
if (
|
|
13
|
+
if ( inDocMode ) {
|
|
21
14
|
RuleTester.it( name, ( done ) => {
|
|
22
15
|
const writeDocsFromTests = require( './write-docs-from-tests' );
|
|
23
16
|
writeDocsFromTests( name, rule, tests, this.testerConfig, done );
|
|
24
17
|
} );
|
|
25
18
|
} else {
|
|
26
|
-
// Filter out invalid
|
|
19
|
+
// Filter out invalid property "docgen"
|
|
20
|
+
// (used in documentation building mode).
|
|
27
21
|
tests.valid.forEach( ( test ) => {
|
|
28
22
|
delete test.docgen;
|
|
29
|
-
// Deprecated
|
|
30
|
-
delete test.noDoc;
|
|
31
23
|
} );
|
|
32
24
|
tests.invalid.forEach( ( test ) => {
|
|
33
25
|
delete test.docgen;
|
|
34
|
-
// Deprecated
|
|
35
|
-
delete test.noDoc;
|
|
36
26
|
} );
|
|
27
|
+
|
|
28
|
+
// Filter out invalid top level property "docgenConfig"
|
|
29
|
+
// (used in documentation building mode).
|
|
30
|
+
delete tests.docgenConfig;
|
|
31
|
+
|
|
37
32
|
return super.run.call( this, name, rule, tests );
|
|
38
33
|
}
|
|
39
34
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
📋 This rule is enabled in `plugin:<%- pluginName %>/<%- inConfig.config %>`<%- include( 'optionsAndSettings', { data: inConfig } ) %>.
|
package/src/templates/index.ejs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<% if ( data.options || data.settings ) { _%>
|
|
2
2
|
with<% if ( data.options ) { %> `<%- data.options %>` options<% } _%>
|
|
3
3
|
<% if ( data.settings ) { %><% if ( data.options ) { %> and<% } %> `<%- data.settings %>` settings<% } _%>
|
|
4
|
-
<% } %>
|
|
4
|
+
<% } _%>
|
|
5
|
+
<% if ( data.filename ) { _%>
|
|
6
|
+
for a file named `<%- data.filename %>`<% } %>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
/* eslint-disable no-process-exit */
|
|
4
3
|
const fs = require( 'fs' );
|
|
5
4
|
const mkdirp = require( 'mkdirp' );
|
|
6
5
|
const path = require( 'upath' );
|
|
@@ -14,21 +13,19 @@ let config, configPath;
|
|
|
14
13
|
try {
|
|
15
14
|
( { config, configPath } = getConfig() );
|
|
16
15
|
} catch ( e ) {
|
|
17
|
-
|
|
18
|
-
console.log( formatter.error( e.message ) );
|
|
19
|
-
console.log();
|
|
20
|
-
process.exit( 1 );
|
|
16
|
+
throw new Error( [ formatter.heading( 'eslint-docgen' ), formatter.error( e.message ) ].join( '\n' ) );
|
|
21
17
|
}
|
|
22
18
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
process.exit( 1 );
|
|
19
|
+
const configValidator = require( './validate-config' );
|
|
20
|
+
function assertValidConfig( maybeValidConfig, configSource ) {
|
|
21
|
+
const configErrors = configValidator( maybeValidConfig );
|
|
22
|
+
if ( configErrors.length ) {
|
|
23
|
+
throw new Error( [ formatter.heading( configSource ), ...configErrors.map( formatter.error ) ].join( '\n' ) );
|
|
24
|
+
}
|
|
30
25
|
}
|
|
31
26
|
|
|
27
|
+
assertValidConfig( config, configPath );
|
|
28
|
+
|
|
32
29
|
const packagePath = require( './package-path' );
|
|
33
30
|
|
|
34
31
|
const loadTemplates = require( './load-templates' );
|
|
@@ -39,28 +36,27 @@ if ( config.globalTemplatePath ) {
|
|
|
39
36
|
const { globalTemplates, loadRuleTemplate } = loadTemplates( templatePaths );
|
|
40
37
|
|
|
41
38
|
function writeDocsFromTests( name, rule, tests, testerConfig, done ) {
|
|
42
|
-
|
|
39
|
+
// If the tests have a `docgenConfig` property, this overrides the global configuration
|
|
40
|
+
let configForRule = config;
|
|
41
|
+
if ( tests.docgenConfig !== undefined ) {
|
|
42
|
+
configForRule = Object.assign( {}, config, tests.docgenConfig );
|
|
43
|
+
assertValidConfig( configForRule, 'Rule specific config for ' + name );
|
|
44
|
+
delete tests.docgenConfig;
|
|
45
|
+
}
|
|
46
|
+
const outputPath = packagePath( configForRule.docPath.replace( '{name}', name ) );
|
|
43
47
|
const ruleWithConfig = rulesWithConfig.get( name );
|
|
44
48
|
if ( !ruleWithConfig ) {
|
|
45
|
-
|
|
46
|
-
console.log( formatter.heading( outputPath ) );
|
|
47
|
-
console.log( formatter.error( 'Rule not found.' ) );
|
|
48
|
-
console.log();
|
|
49
|
-
process.exit( 1 );
|
|
49
|
+
throw new Error( [ formatter.heading( outputPath ), formatter.error( 'Rule not found.' ) ].join( '\n' ) );
|
|
50
50
|
}
|
|
51
51
|
const configMap = rulesWithConfig.get( name ).configMap;
|
|
52
52
|
let output, messages;
|
|
53
53
|
try {
|
|
54
54
|
( { output, messages } = buildDocsFromTests(
|
|
55
|
-
name, rule.meta, tests, configMap,
|
|
55
|
+
name, rule.meta, tests, configMap, configForRule,
|
|
56
56
|
globalTemplates, loadRuleTemplate, testerConfig
|
|
57
57
|
) );
|
|
58
58
|
} catch ( e ) {
|
|
59
|
-
|
|
60
|
-
console.log( formatter.heading( outputPath ) );
|
|
61
|
-
console.log( formatter.error( e.message ) );
|
|
62
|
-
console.log();
|
|
63
|
-
process.exit( 1 );
|
|
59
|
+
throw new Error( [ formatter.heading( outputPath ), formatter.error( e.message ) ].join( '\n' ) );
|
|
64
60
|
}
|
|
65
61
|
|
|
66
62
|
const outputDir = path.dirname( outputPath );
|
|
@@ -81,8 +77,10 @@ function writeDocsFromTests( name, rule, tests, testerConfig, done ) {
|
|
|
81
77
|
console.log();
|
|
82
78
|
}
|
|
83
79
|
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
const errors = messages.filter( ( message ) => message.type === 'error' );
|
|
81
|
+
|
|
82
|
+
if ( errors.length ) {
|
|
83
|
+
throw new Error( errors.map( formatter.error ).join( '\n' ) );
|
|
86
84
|
}
|
|
87
85
|
|
|
88
86
|
done();
|
package/Changelog.md
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
# eslint-docgen release history
|
|
2
|
-
|
|
3
|
-
## v0.4.5
|
|
4
|
-
* Code: Update dependencies
|
|
5
|
-
|
|
6
|
-
## v0.4.4
|
|
7
|
-
|
|
8
|
-
* Code: Ensure config.docPath exists before writing output path. (Raine Revere)
|
|
9
|
-
* Code: Calculate outputDir from outputPath
|
|
10
|
-
* Code: Fix reporting of writeFile error messages
|
|
11
|
-
* Code: Output formatted error when rule not found (#92)
|
|
12
|
-
* Docs: Fix config param heading level in README (#91)
|
|
13
|
-
|
|
14
|
-
## v0.4.3
|
|
15
|
-
|
|
16
|
-
* Code: Run one test 'it' per rule
|
|
17
|
-
|
|
18
|
-
## v0.4.2
|
|
19
|
-
|
|
20
|
-
* New: Introduce excludeExamplesByDefault config
|
|
21
|
-
* Code: Remove some whitespace in config-schema
|
|
22
|
-
* Code: Add a 'report' script
|
|
23
|
-
|
|
24
|
-
## v0.4.1
|
|
25
|
-
|
|
26
|
-
* Code: Update mocha to 8.0.1
|
|
27
|
-
* Code: Replace path with upath for windows compatibility (#83)
|
|
28
|
-
* Code: Use DOCGEN environment variable instead of --doc flag
|
|
29
|
-
* Code: Add an editorconfig to make the tabs a reasonable width on GitHub (Jed Fox)
|
|
30
|
-
* Code: Allow package.main to be empty
|
|
31
|
-
* Code: Support scoped plugin names
|
|
32
|
-
* Docs: Add more method documentation
|
|
33
|
-
* Docs: Fix external links to examples
|
|
34
|
-
* Docs: Add Migration section to README and move some pieces around
|
|
35
|
-
|
|
36
|
-
## v0.4.0
|
|
37
|
-
|
|
38
|
-
* Breaking change: New: Add fix message to introduction (#49)
|
|
39
|
-
* Breaking change: New: Format long lists correctly ("a, b, and c")
|
|
40
|
-
* Breaking change: New: Sort examples by options *then* valid/invalid (#48)
|
|
41
|
-
* New: Refactor rulesData to rulesWithConfig and expose (#16)
|
|
42
|
-
* New: Add ruleTemplatePath config (#14)
|
|
43
|
-
* New: Add showFixExamples config (#49)
|
|
44
|
-
* Code: Update eslint-config-wikimedia to 0.16.1 and use /mocha
|
|
45
|
-
* Code: Use pkg-dir
|
|
46
|
-
* Code: Create a JSON-schema to validate configs (#63)
|
|
47
|
-
* Code: Update various dependencies
|
|
48
|
-
* Tests: Separate config tests into get/validate
|
|
49
|
-
* Tests: Increase timeout
|
|
50
|
-
* Tests: Separate buildDocsFromTests cases
|
|
51
|
-
* Docs: Fix example docpath
|
|
52
|
-
|
|
53
|
-
## v0.3.1
|
|
54
|
-
|
|
55
|
-
* Fix: Use plugin's version of ESLint
|
|
56
|
-
|
|
57
|
-
## v0.3.0
|
|
58
|
-
|
|
59
|
-
* Breaking change: New: Support multi-line test cases (#34)
|
|
60
|
-
* New: Support multiple lines in formatter
|
|
61
|
-
* New: Add min/maxExamples to config (#29)
|
|
62
|
-
* New: Use chalk to do pretty output of warnings/errors (#38)
|
|
63
|
-
* Code: Bump node dependency to 10 (#44)
|
|
64
|
-
* Code: Use strict mode
|
|
65
|
-
* Code: Use eslint-plugin-node/recommended
|
|
66
|
-
* Code: Removed fixed length truncation from rules-data.js
|
|
67
|
-
* Tests: Add tests for most utils (#39)
|
|
68
|
-
* Tests: Increase code coverage to 100%
|
|
69
|
-
* Docs: Add "plugin" to description
|
|
70
|
-
|
|
71
|
-
## v0.2.0
|
|
72
|
-
|
|
73
|
-
* Breaking change: Refactor templates. Users with existing template overrides will need to rewrite them.
|
|
74
|
-
* Release: Update ejs to 3.1.3
|
|
75
|
-
|
|
76
|
-
## v0.1.0
|
|
77
|
-
|
|
78
|
-
* Initial release.
|