js-build-tools 6.5.0 → 6.7.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/LICENSE +674 -674
- package/README.md +762 -692
- package/babel.config.js +28 -28
- package/dist/build.js +75 -75
- package/dist/bundle.js +19 -19
- package/dist/bundleMinify.js +7 -7
- package/dist/compileReadme.js +4 -4
- package/dist/copyFiles.js +17 -17
- package/dist/copyFonts.js +4 -4
- package/dist/default.js +5 -5
- package/dist/dist.js +4 -4
- package/dist/distMinify.js +4 -4
- package/dist/docs.js +7 -7
- package/dist/images.js +4 -4
- package/dist/jsdocDocs.js +6 -6
- package/dist/lint.js +16 -16
- package/dist/partials/addToReadme.js +9 -9
- package/dist/partials/beginWatcher.js +4 -4
- package/dist/partials/clean.js +5 -5
- package/dist/partials/copyFor.js +9 -9
- package/dist/partials/distFor.js +6 -6
- package/dist/partials/distForSrc.js +5 -5
- package/dist/partials/distSeries.js +7 -7
- package/dist/partials/imagesFor.js +93 -56
- package/dist/partials/jsdocDocsFor.js +46 -46
- package/dist/partials/lintSource.js +51 -51
- package/dist/partials/loadPeer.js +99 -99
- package/dist/partials/loadPlaywright.js +14 -14
- package/dist/partials/minifyFor.js +20 -20
- package/dist/partials/neostandardLint.js +175 -175
- package/dist/partials/readmeTemplate.js +4 -4
- package/dist/partials/removeDirectory.js +11 -11
- package/dist/partials/resolveDocsMethod.js +6 -6
- package/dist/partials/runOnChange.js +31 -31
- package/dist/partials/sassFor.js +6 -6
- package/dist/partials/serveStatic.js +9 -9
- package/dist/partials/tsFor.js +32 -32
- package/dist/partials/typeDocsFor.js +57 -51
- package/dist/partials.js +176 -176
- package/dist/sourceLint.js +18 -18
- package/dist/test-helpers/isolateGulpCache.js +24 -24
- package/dist/test-helpers/setUp.js +4 -4
- package/dist/testFull.js +5 -5
- package/dist/testQuick.js +5 -5
- package/dist/typeDocs.js +5 -5
- package/dist/typeScript.js +4 -4
- package/dist/utilities/convertMjsFilesForDocs.js +12 -12
- package/dist/utilities/dotGet.js +54 -54
- package/dist/utilities/dotNotate.js +79 -79
- package/dist/utilities/dotSet.js +45 -45
- package/dist/utilities/esmNamedExportsToCjs.js +15 -15
- package/dist/utilities/getBundleConfigs.js +9 -9
- package/dist/utilities/isObject.js +6 -6
- package/dist/utilities/strAfter.js +7 -7
- package/dist/utilities/strBefore.js +7 -7
- package/dist/watchFull.js +4 -4
- package/dist/watchTest.js +4 -4
- package/functions/build.mjs +72 -72
- package/functions/build.test.mjs +763 -759
- package/functions/bundle.mjs +44 -44
- package/functions/bundle.test.mjs +219 -219
- package/functions/bundleMinify.mjs +16 -16
- package/functions/bundleMinify.test.mjs +37 -37
- package/functions/compileReadme.mjs +9 -9
- package/functions/compileReadme.test.mjs +18 -18
- package/functions/copyFiles.mjs +32 -32
- package/functions/copyFiles.test.mjs +78 -78
- package/functions/copyFonts.mjs +9 -9
- package/functions/copyFonts.test.mjs +32 -32
- package/functions/default.mjs +12 -12
- package/functions/default.test.mjs +33 -33
- package/functions/dist.mjs +8 -8
- package/functions/dist.test.mjs +44 -44
- package/functions/distMinify.mjs +9 -9
- package/functions/distMinify.test.mjs +15 -15
- package/functions/docs.mjs +13 -13
- package/functions/docs.test.mjs +45 -45
- package/functions/gulpConfigEntries.test.mjs +23 -23
- package/functions/images.mjs +8 -8
- package/functions/images.test.mjs +142 -142
- package/functions/jsdocDocs.mjs +10 -10
- package/functions/jsdocEsmExports.test.mjs +24 -24
- package/functions/lint.mjs +9 -9
- package/functions/partials/addToReadme.mjs +25 -25
- package/functions/partials/addToReadme.test.mjs +34 -34
- package/functions/partials/beginWatcher.mjs +9 -9
- package/functions/partials/beginWatcher.test.mjs +19 -19
- package/functions/partials/clean.mjs +13 -13
- package/functions/partials/clean.test.mjs +22 -22
- package/functions/partials/copyFor.mjs +15 -15
- package/functions/partials/copyFor.test.mjs +53 -53
- package/functions/partials/distFor.mjs +22 -22
- package/functions/partials/distFor.test.mjs +195 -195
- package/functions/partials/distForSrc.mjs +11 -11
- package/functions/partials/distForSrc.test.mjs +18 -18
- package/functions/partials/distSeries.mjs +21 -21
- package/functions/partials/distSeries.test.mjs +34 -34
- package/functions/partials/imagesFor.mjs +83 -50
- package/functions/partials/imagesFor.test.mjs +287 -229
- package/functions/partials/jsdocDocsFor.mjs +163 -152
- package/functions/partials/jsdocDocsFor.test.mjs +182 -152
- package/functions/partials/lintSource.mjs +41 -41
- package/functions/partials/loadPeer.mjs +76 -76
- package/functions/partials/loadPeer.test.mjs +58 -58
- package/functions/partials/loadPlaywright.mjs +23 -23
- package/functions/partials/loadPlaywright.test.mjs +70 -70
- package/functions/partials/minifyFor.mjs +15 -15
- package/functions/partials/minifyFor.test.mjs +49 -49
- package/functions/partials/neostandardLint.mjs +142 -142
- package/functions/partials/neostandardLint.test.mjs +131 -131
- package/functions/partials/readmeTemplate.mjs +12 -12
- package/functions/partials/readmeTemplate.test.mjs +34 -34
- package/functions/partials/removeDirectory.mjs +34 -34
- package/functions/partials/removeDirectory.test.mjs +72 -72
- package/functions/partials/resolveDocsMethod.mjs +10 -10
- package/functions/partials/resolveDocsMethod.test.mjs +33 -33
- package/functions/partials/runOnChange.mjs +54 -54
- package/functions/partials/runOnChange.test.mjs +95 -95
- package/functions/partials/sassFor.mjs +25 -25
- package/functions/partials/sassFor.test.mjs +81 -81
- package/functions/partials/serveStatic.mjs +47 -47
- package/functions/partials/serveStatic.test.mjs +71 -71
- package/functions/partials/tsFor.mjs +92 -92
- package/functions/partials/tsFor.test.mjs +88 -88
- package/functions/partials/typeDocsFor.mjs +231 -227
- package/functions/partials/typeDocsFor.test.mjs +263 -252
- package/functions/partials.mjs +31 -31
- package/functions/partials.test.mjs +7 -7
- package/functions/sass.mjs +4 -4
- package/functions/sass.test.mjs +31 -31
- package/functions/sourceLint.mjs +13 -13
- package/functions/sourceLint.test.mjs +166 -166
- package/functions/test-helpers/isolateGulpCache.mjs +16 -16
- package/functions/test-helpers/neostandardLintWithRealNeostandard.mjs +40 -40
- package/functions/test-helpers/setUp.mjs +100 -100
- package/functions/test-helpers/setUp.test.mjs +19 -19
- package/functions/testFull.mjs +17 -17
- package/functions/testFull.test.mjs +17 -17
- package/functions/testHelpers.mjs +10 -10
- package/functions/testHelpers.test.mjs +7 -7
- package/functions/testQuick.mjs +17 -17
- package/functions/testQuick.test.mjs +17 -17
- package/functions/typeDocs.mjs +9 -9
- package/functions/typeDocs.test.mjs +11 -11
- package/functions/typeScript.mjs +8 -8
- package/functions/typeScript.test.mjs +11 -11
- package/functions/utilities/convertMjsFilesForDocs.mjs +34 -34
- package/functions/utilities/convertMjsFilesForDocs.test.mjs +58 -58
- package/functions/utilities/dotGet.mjs +49 -49
- package/functions/utilities/dotNotate.mjs +73 -73
- package/functions/utilities/dotNotate.test.mjs +41 -41
- package/functions/utilities/dotSet.mjs +40 -40
- package/functions/utilities/esmNamedExportsToCjs.mjs +30 -30
- package/functions/utilities/esmNamedExportsToCjs.test.mjs +47 -47
- package/functions/utilities/getBundleConfigs.mjs +30 -30
- package/functions/utilities/isObject.mjs +8 -8
- package/functions/utilities/strAfter.mjs +12 -12
- package/functions/utilities/strBefore.mjs +12 -12
- package/functions/watchFull.mjs +9 -9
- package/functions/watchFull.test.mjs +41 -41
- package/functions/watchTest.mjs +10 -10
- package/functions/watchTest.test.mjs +49 -49
- package/gulp.config.js +4 -4
- package/gulp.config.mjs +344 -327
- package/gulpfile.base.js +51 -51
- package/gulpfile.base.mjs +29 -29
- package/jsdoc.base.js +16 -16
- package/jsdoc.esmExports.js +17 -17
- package/package.json +146 -145
|
@@ -1,142 +1,142 @@
|
|
|
1
|
-
import fs from 'node:fs'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import through from 'through2'
|
|
4
|
-
import { ESLint } from 'eslint'
|
|
5
|
-
import { importModule } from './loadPeer.mjs'
|
|
6
|
-
|
|
7
|
-
// neostandard (js-build-tools' chosen style - a maintained, TypeScript-aware successor to `standard`, see
|
|
8
|
-
// https://github.com/neostandard/neostandard) ships ESM-only, see importModule for how it is imported.
|
|
9
|
-
const importNeostandard = () => importModule('neostandard')
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Read the `env` a project already declared for Standard (the `standard` field in its package.json), so a project
|
|
13
|
-
* migrating from `standard` keeps its globals (jest, browser, ...) without touching package.json.
|
|
14
|
-
* @param {string} cwd
|
|
15
|
-
* @returns {Array<string>}
|
|
16
|
-
* @private
|
|
17
|
-
*/
|
|
18
|
-
const readEnv = cwd => {
|
|
19
|
-
try {
|
|
20
|
-
return JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8')).standard?.env ?? []
|
|
21
|
-
} catch {
|
|
22
|
-
return []
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Build an ESLint instance configured with neostandard, honoring the project's own package.json `standard.env`,
|
|
28
|
-
* plus an optional layer of rule overrides (see gulp.config.mjs's `lint.rules`) for a rule that is wrong for this
|
|
29
|
-
* project specifically rather than something to fix in its code - for example a test fixture whose content
|
|
30
|
-
* neostandard mistakes for a real syntax problem. Scoped to the same files neostandard itself lints (its own
|
|
31
|
-
* `defaultFilePatterns.all`), per neostandard's own guidance: an unscoped rule-tweak layer would otherwise apply
|
|
32
|
-
* to every lintable file, including ones from an unrelated plugin this project never defined.
|
|
33
|
-
* @param {Object} options
|
|
34
|
-
* @param {string} options.cwd
|
|
35
|
-
* @param {boolean} options.ts
|
|
36
|
-
* @param {boolean} options.fix
|
|
37
|
-
* @param {Object<string, *>} [options.rules={}]
|
|
38
|
-
* @returns {Promise<ESLint>} eslint's ESLint instance
|
|
39
|
-
* @private
|
|
40
|
-
*/
|
|
41
|
-
const buildEslint = async ({ cwd, ts, fix, rules = {} }) => {
|
|
42
|
-
const { neostandard, defaultFilePatterns } = await importNeostandard()
|
|
43
|
-
const baseConfig = neostandard({ ts, env: readEnv(cwd) })
|
|
44
|
-
if (Object.keys(rules).length) {
|
|
45
|
-
baseConfig.push({ files: defaultFilePatterns.all, rules })
|
|
46
|
-
}
|
|
47
|
-
return new ESLint({
|
|
48
|
-
cwd,
|
|
49
|
-
fix,
|
|
50
|
-
overrideConfigFile: true,
|
|
51
|
-
baseConfig
|
|
52
|
-
})
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Print a file's lint messages, if it has any.
|
|
57
|
-
* @memberOf module:partials
|
|
58
|
-
* @param {Vinyl} file
|
|
59
|
-
* @param {{messages: Array<{line: number, column: number, message: string}>, errorCount: number, warningCount: number}} result
|
|
60
|
-
* @returns {undefined}
|
|
61
|
-
*/
|
|
62
|
-
const printFileReport = (file, result) => {
|
|
63
|
-
if (!result.messages.length) {
|
|
64
|
-
return
|
|
65
|
-
}
|
|
66
|
-
console.log(path.relative(file.cwd, file.path))
|
|
67
|
-
result.messages.forEach(({ line, column, message }) => console.log(`line ${line}:${column}\t${message}`))
|
|
68
|
-
console.log(`✖ ${result.errorCount} error\t⚠ ${result.warningCount} warning\n`)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Lint every file streaming through with neostandard and, unless `fix` is false, apply the automatic fixes to the
|
|
73
|
-
* file's contents so a following `dest()` writes the fixed version. Remaining problems are printed along with a
|
|
74
|
-
* summary once the stream ends; they only fail the stream when `failOnError` is set (the standalone `lint` task),
|
|
75
|
-
* never during `build`.
|
|
76
|
-
*
|
|
77
|
-
* One ESLint instance is built from the first file's own cwd and reused for the rest of the stream, since every
|
|
78
|
-
* file in a given lint pass shares the same project (and so the same config).
|
|
79
|
-
* @memberOf module:partials
|
|
80
|
-
* @param {Object} [options={}]
|
|
81
|
-
* @param {boolean} [options.fix=true] - Apply neostandard's automatic fixes to the file contents.
|
|
82
|
-
* @param {boolean} [options.ts=false] - Lint `.ts` files too, with type-aware rules (see neostandard's `ts` option).
|
|
83
|
-
* @param {Object<string, *>} [options.rules={}] - ESLint rule overrides layered on top of neostandard's own rules
|
|
84
|
-
* (see gulp.config.mjs's `lint.rules`).
|
|
85
|
-
* @param {boolean} [options.failOnError=false] - Emit an error once the stream ends if any lint errors remain after
|
|
86
|
-
* fixing, so a command-line run exits non-zero.
|
|
87
|
-
* @param {function(Object): Promise<{lintText: Function}>} [loadEslint] - Resolves an ESLint-shaped linter. Real
|
|
88
|
-
* callers should never need to pass this - it exists so tests can supply a stand-in, since this project's
|
|
89
|
-
* CommonJS-transform-based Jest setup cannot execute a real dynamic import() of neostandard (ESM-only).
|
|
90
|
-
* @returns {stream.Transform} With a `totals` property ({errors, warnings}), complete once the stream ends.
|
|
91
|
-
*/
|
|
92
|
-
export const neostandardLint = (
|
|
93
|
-
{ fix = true, ts = false, rules = {}, failOnError = false } = {},
|
|
94
|
-
loadEslint = buildEslint
|
|
95
|
-
) => {
|
|
96
|
-
const totals = { errors: 0, warnings: 0 }
|
|
97
|
-
let eslintPromise = null
|
|
98
|
-
const linter = through.obj(
|
|
99
|
-
function (file, enc, callback) {
|
|
100
|
-
if (file.isNull()) {
|
|
101
|
-
callback(null, file)
|
|
102
|
-
return
|
|
103
|
-
}
|
|
104
|
-
if (file.isStream()) {
|
|
105
|
-
callback(new Error('neostandardLint: streaming file contents are not supported.'))
|
|
106
|
-
return
|
|
107
|
-
}
|
|
108
|
-
if (!eslintPromise) {
|
|
109
|
-
eslintPromise = loadEslint({ cwd: file.cwd, ts, fix, rules })
|
|
110
|
-
}
|
|
111
|
-
eslintPromise
|
|
112
|
-
.then(eslint => eslint.lintText(file.contents.toString(), { filePath: file.path }))
|
|
113
|
-
.then(results => {
|
|
114
|
-
// No result at all means the file is ignored by the project's ESLint configuration.
|
|
115
|
-
const [result] = results
|
|
116
|
-
if (result) {
|
|
117
|
-
if (typeof result.output === 'string') {
|
|
118
|
-
file.contents = Buffer.from(result.output)
|
|
119
|
-
}
|
|
120
|
-
totals.errors += result.errorCount
|
|
121
|
-
totals.warnings += result.warningCount
|
|
122
|
-
printFileReport(file, result)
|
|
123
|
-
}
|
|
124
|
-
callback(null, file)
|
|
125
|
-
}, callback)
|
|
126
|
-
},
|
|
127
|
-
function (callback) {
|
|
128
|
-
console.log('neostandard linter results')
|
|
129
|
-
console.log('======================================')
|
|
130
|
-
console.log(`✖ Errors total: ${totals.errors}`)
|
|
131
|
-
console.log(`⚠ Warnings total: ${totals.warnings}\n`)
|
|
132
|
-
if (failOnError && totals.errors) {
|
|
133
|
-
callback(new Error(`neostandard found ${totals.errors} lint error(s) that could not be fixed automatically.`))
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
callback()
|
|
137
|
-
}
|
|
138
|
-
)
|
|
139
|
-
// Read by lintSource, which can only fail once the fixed files have been written, after this stream has ended.
|
|
140
|
-
linter.totals = totals
|
|
141
|
-
return linter
|
|
142
|
-
}
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import through from 'through2'
|
|
4
|
+
import { ESLint } from 'eslint'
|
|
5
|
+
import { importModule } from './loadPeer.mjs'
|
|
6
|
+
|
|
7
|
+
// neostandard (js-build-tools' chosen style - a maintained, TypeScript-aware successor to `standard`, see
|
|
8
|
+
// https://github.com/neostandard/neostandard) ships ESM-only, see importModule for how it is imported.
|
|
9
|
+
const importNeostandard = () => importModule('neostandard')
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Read the `env` a project already declared for Standard (the `standard` field in its package.json), so a project
|
|
13
|
+
* migrating from `standard` keeps its globals (jest, browser, ...) without touching package.json.
|
|
14
|
+
* @param {string} cwd
|
|
15
|
+
* @returns {Array<string>}
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
const readEnv = cwd => {
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8')).standard?.env ?? []
|
|
21
|
+
} catch {
|
|
22
|
+
return []
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Build an ESLint instance configured with neostandard, honoring the project's own package.json `standard.env`,
|
|
28
|
+
* plus an optional layer of rule overrides (see gulp.config.mjs's `lint.rules`) for a rule that is wrong for this
|
|
29
|
+
* project specifically rather than something to fix in its code - for example a test fixture whose content
|
|
30
|
+
* neostandard mistakes for a real syntax problem. Scoped to the same files neostandard itself lints (its own
|
|
31
|
+
* `defaultFilePatterns.all`), per neostandard's own guidance: an unscoped rule-tweak layer would otherwise apply
|
|
32
|
+
* to every lintable file, including ones from an unrelated plugin this project never defined.
|
|
33
|
+
* @param {Object} options
|
|
34
|
+
* @param {string} options.cwd
|
|
35
|
+
* @param {boolean} options.ts
|
|
36
|
+
* @param {boolean} options.fix
|
|
37
|
+
* @param {Object<string, *>} [options.rules={}]
|
|
38
|
+
* @returns {Promise<ESLint>} eslint's ESLint instance
|
|
39
|
+
* @private
|
|
40
|
+
*/
|
|
41
|
+
const buildEslint = async ({ cwd, ts, fix, rules = {} }) => {
|
|
42
|
+
const { neostandard, defaultFilePatterns } = await importNeostandard()
|
|
43
|
+
const baseConfig = neostandard({ ts, env: readEnv(cwd) })
|
|
44
|
+
if (Object.keys(rules).length) {
|
|
45
|
+
baseConfig.push({ files: defaultFilePatterns.all, rules })
|
|
46
|
+
}
|
|
47
|
+
return new ESLint({
|
|
48
|
+
cwd,
|
|
49
|
+
fix,
|
|
50
|
+
overrideConfigFile: true,
|
|
51
|
+
baseConfig
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Print a file's lint messages, if it has any.
|
|
57
|
+
* @memberOf module:partials
|
|
58
|
+
* @param {Vinyl} file
|
|
59
|
+
* @param {{messages: Array<{line: number, column: number, message: string}>, errorCount: number, warningCount: number}} result
|
|
60
|
+
* @returns {undefined}
|
|
61
|
+
*/
|
|
62
|
+
const printFileReport = (file, result) => {
|
|
63
|
+
if (!result.messages.length) {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
console.log(path.relative(file.cwd, file.path))
|
|
67
|
+
result.messages.forEach(({ line, column, message }) => console.log(`line ${line}:${column}\t${message}`))
|
|
68
|
+
console.log(`✖ ${result.errorCount} error\t⚠ ${result.warningCount} warning\n`)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Lint every file streaming through with neostandard and, unless `fix` is false, apply the automatic fixes to the
|
|
73
|
+
* file's contents so a following `dest()` writes the fixed version. Remaining problems are printed along with a
|
|
74
|
+
* summary once the stream ends; they only fail the stream when `failOnError` is set (the standalone `lint` task),
|
|
75
|
+
* never during `build`.
|
|
76
|
+
*
|
|
77
|
+
* One ESLint instance is built from the first file's own cwd and reused for the rest of the stream, since every
|
|
78
|
+
* file in a given lint pass shares the same project (and so the same config).
|
|
79
|
+
* @memberOf module:partials
|
|
80
|
+
* @param {Object} [options={}]
|
|
81
|
+
* @param {boolean} [options.fix=true] - Apply neostandard's automatic fixes to the file contents.
|
|
82
|
+
* @param {boolean} [options.ts=false] - Lint `.ts` files too, with type-aware rules (see neostandard's `ts` option).
|
|
83
|
+
* @param {Object<string, *>} [options.rules={}] - ESLint rule overrides layered on top of neostandard's own rules
|
|
84
|
+
* (see gulp.config.mjs's `lint.rules`).
|
|
85
|
+
* @param {boolean} [options.failOnError=false] - Emit an error once the stream ends if any lint errors remain after
|
|
86
|
+
* fixing, so a command-line run exits non-zero.
|
|
87
|
+
* @param {function(Object): Promise<{lintText: Function}>} [loadEslint] - Resolves an ESLint-shaped linter. Real
|
|
88
|
+
* callers should never need to pass this - it exists so tests can supply a stand-in, since this project's
|
|
89
|
+
* CommonJS-transform-based Jest setup cannot execute a real dynamic import() of neostandard (ESM-only).
|
|
90
|
+
* @returns {stream.Transform} With a `totals` property ({errors, warnings}), complete once the stream ends.
|
|
91
|
+
*/
|
|
92
|
+
export const neostandardLint = (
|
|
93
|
+
{ fix = true, ts = false, rules = {}, failOnError = false } = {},
|
|
94
|
+
loadEslint = buildEslint
|
|
95
|
+
) => {
|
|
96
|
+
const totals = { errors: 0, warnings: 0 }
|
|
97
|
+
let eslintPromise = null
|
|
98
|
+
const linter = through.obj(
|
|
99
|
+
function (file, enc, callback) {
|
|
100
|
+
if (file.isNull()) {
|
|
101
|
+
callback(null, file)
|
|
102
|
+
return
|
|
103
|
+
}
|
|
104
|
+
if (file.isStream()) {
|
|
105
|
+
callback(new Error('neostandardLint: streaming file contents are not supported.'))
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
if (!eslintPromise) {
|
|
109
|
+
eslintPromise = loadEslint({ cwd: file.cwd, ts, fix, rules })
|
|
110
|
+
}
|
|
111
|
+
eslintPromise
|
|
112
|
+
.then(eslint => eslint.lintText(file.contents.toString(), { filePath: file.path }))
|
|
113
|
+
.then(results => {
|
|
114
|
+
// No result at all means the file is ignored by the project's ESLint configuration.
|
|
115
|
+
const [result] = results
|
|
116
|
+
if (result) {
|
|
117
|
+
if (typeof result.output === 'string') {
|
|
118
|
+
file.contents = Buffer.from(result.output)
|
|
119
|
+
}
|
|
120
|
+
totals.errors += result.errorCount
|
|
121
|
+
totals.warnings += result.warningCount
|
|
122
|
+
printFileReport(file, result)
|
|
123
|
+
}
|
|
124
|
+
callback(null, file)
|
|
125
|
+
}, callback)
|
|
126
|
+
},
|
|
127
|
+
function (callback) {
|
|
128
|
+
console.log('neostandard linter results')
|
|
129
|
+
console.log('======================================')
|
|
130
|
+
console.log(`✖ Errors total: ${totals.errors}`)
|
|
131
|
+
console.log(`⚠ Warnings total: ${totals.warnings}\n`)
|
|
132
|
+
if (failOnError && totals.errors) {
|
|
133
|
+
callback(new Error(`neostandard found ${totals.errors} lint error(s) that could not be fixed automatically.`))
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
callback()
|
|
137
|
+
}
|
|
138
|
+
)
|
|
139
|
+
// Read by lintSource, which can only fail once the fixed files have been written, after this stream has ended.
|
|
140
|
+
linter.totals = totals
|
|
141
|
+
return linter
|
|
142
|
+
}
|
|
@@ -1,131 +1,131 @@
|
|
|
1
|
-
import Vinyl from 'vinyl'
|
|
2
|
-
import { Readable } from 'node:stream'
|
|
3
|
-
import { neostandardLint } from './neostandardLint.mjs'
|
|
4
|
-
|
|
5
|
-
const makeFile = (contents, filePath = '/project/src/example.js') => new Vinyl({
|
|
6
|
-
cwd: '/project',
|
|
7
|
-
base: '/project/src',
|
|
8
|
-
path: filePath,
|
|
9
|
-
contents
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
const run = (transform, files) => new Promise((resolve, reject) => {
|
|
13
|
-
const out = []
|
|
14
|
-
transform.on('data', file => out.push(file)).on('end', () => resolve(out)).on('error', reject)
|
|
15
|
-
files.forEach(file => transform.write(file))
|
|
16
|
-
transform.end()
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
const fakeEslint = (resultFor) => ({
|
|
20
|
-
lintText: jest.fn((text, options) => Promise.resolve(resultFor(text, options)))
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
let logSpy
|
|
24
|
-
|
|
25
|
-
beforeEach(() => {
|
|
26
|
-
logSpy = jest.spyOn(console, 'log').mockImplementation(() => {})
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
afterEach(() => {
|
|
30
|
-
logSpy.mockRestore()
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
describe('neostandardLint', () => {
|
|
34
|
-
test('replaces file contents with the fixed output and hands ESLint the file path', async () => {
|
|
35
|
-
expect.assertions(3)
|
|
36
|
-
const eslint = fakeEslint((text) => [{ messages: [], errorCount: 0, warningCount: 0, output: text.replace(/"/g, '\'') }])
|
|
37
|
-
const [linted] = await run(neostandardLint({ fix: true }, () => Promise.resolve(eslint)), [makeFile(Buffer.from('const a = "b"'))])
|
|
38
|
-
expect(linted.contents.toString()).toEqual('const a = \'b\'')
|
|
39
|
-
expect(eslint.lintText).toHaveBeenCalledWith('const a = "b"', { filePath: '/project/src/example.js' })
|
|
40
|
-
expect(linted.path).toEqual('/project/src/example.js')
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
test('leaves the contents alone when ESLint has no fixed output (nothing needed fixing)', async () => {
|
|
44
|
-
expect.assertions(1)
|
|
45
|
-
const eslint = fakeEslint(() => [{ messages: [], errorCount: 0, warningCount: 0 }])
|
|
46
|
-
const [linted] = await run(neostandardLint({}, () => Promise.resolve(eslint)), [makeFile(Buffer.from('const a = 1'))])
|
|
47
|
-
expect(linted.contents.toString()).toEqual('const a = 1')
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
test('builds the linter once per stream, from the first file, and reuses it for the rest', async () => {
|
|
51
|
-
expect.assertions(1)
|
|
52
|
-
const loadEslint = jest.fn(() => Promise.resolve(fakeEslint(() => [{ messages: [], errorCount: 0, warningCount: 0 }])))
|
|
53
|
-
await run(
|
|
54
|
-
neostandardLint({}, loadEslint),
|
|
55
|
-
[makeFile(Buffer.from('a'), '/project/src/a.js'), makeFile(Buffer.from('b'), '/project/src/b.js')]
|
|
56
|
-
)
|
|
57
|
-
expect(loadEslint).toHaveBeenCalledTimes(1)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
test('passes fix and ts through to the loader', async () => {
|
|
61
|
-
expect.assertions(1)
|
|
62
|
-
const loadEslint = jest.fn(() => Promise.resolve(fakeEslint(() => [{ messages: [], errorCount: 0, warningCount: 0 }])))
|
|
63
|
-
await run(neostandardLint({ fix: false, ts: true }, loadEslint), [makeFile(Buffer.from('x'))])
|
|
64
|
-
expect(loadEslint).toHaveBeenCalledWith({ cwd: '/project', ts: true, fix: false, rules: {} })
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
test('passes rule overrides through to the loader', async () => {
|
|
68
|
-
expect.assertions(1)
|
|
69
|
-
const loadEslint = jest.fn(() => Promise.resolve(fakeEslint(() => [{ messages: [], errorCount: 0, warningCount: 0 }])))
|
|
70
|
-
const rules = { 'no-template-curly-in-string': 'off' }
|
|
71
|
-
await run(neostandardLint({ rules }, loadEslint), [makeFile(Buffer.from('x'))])
|
|
72
|
-
expect(loadEslint).toHaveBeenCalledWith({ cwd: '/project', ts: false, fix: true, rules })
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
test('passes a file through untouched when the project ignores it (ESLint returns no results)', async () => {
|
|
76
|
-
expect.assertions(2)
|
|
77
|
-
const eslint = fakeEslint(() => [])
|
|
78
|
-
const [linted] = await run(neostandardLint({}, () => Promise.resolve(eslint)), [makeFile(Buffer.from('var x=1'))])
|
|
79
|
-
expect(linted.contents.toString()).toEqual('var x=1')
|
|
80
|
-
expect(logSpy).toHaveBeenCalledWith('✖ Errors total: 0')
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
test('skips null-content files without linting them', async () => {
|
|
84
|
-
expect.assertions(2)
|
|
85
|
-
const eslint = fakeEslint(() => [])
|
|
86
|
-
const [passed] = await run(neostandardLint({}, () => Promise.resolve(eslint)), [makeFile(null)])
|
|
87
|
-
expect(passed.isNull()).toBeTruthy()
|
|
88
|
-
expect(eslint.lintText).not.toHaveBeenCalled()
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
test('errors on streaming file contents, which cannot be linted', async () => {
|
|
92
|
-
expect.assertions(1)
|
|
93
|
-
const streamFile = makeFile(Readable.from(['x']))
|
|
94
|
-
await expect(run(neostandardLint({}, () => Promise.resolve(fakeEslint(() => []))), [streamFile])).rejects.toThrow(/streaming/)
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
test('prints per-file problems and a summary of totals across all files, without failing', async () => {
|
|
98
|
-
expect.assertions(5)
|
|
99
|
-
const eslint = fakeEslint((text, { filePath }) => filePath.endsWith('a.js')
|
|
100
|
-
? [{ messages: [{ line: 2, column: 7, message: 'unused b' }, { line: 3, column: 1, message: 'bad thing' }], errorCount: 2, warningCount: 0 }]
|
|
101
|
-
: [{ messages: [{ line: 1, column: 1, message: 'just a warning' }], errorCount: 0, warningCount: 1 }])
|
|
102
|
-
const out = await run(
|
|
103
|
-
neostandardLint({}, () => Promise.resolve(eslint)),
|
|
104
|
-
[makeFile(Buffer.from('a'), '/project/src/a.js'), makeFile(Buffer.from('b'), '/project/src/b.js')]
|
|
105
|
-
)
|
|
106
|
-
expect(out).toHaveLength(2)
|
|
107
|
-
expect(logSpy).toHaveBeenCalledWith('src/a.js')
|
|
108
|
-
expect(logSpy).toHaveBeenCalledWith('line 2:7\tunused b')
|
|
109
|
-
expect(logSpy).toHaveBeenCalledWith('✖ Errors total: 2')
|
|
110
|
-
expect(logSpy).toHaveBeenCalledWith('⚠ Warnings total: 1\n')
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
test('with failOnError, fails the stream once it ends if any errors remain', async () => {
|
|
114
|
-
expect.assertions(2)
|
|
115
|
-
const eslint = fakeEslint(() => [{ messages: [{ line: 1, column: 1, message: 'bad thing' }], errorCount: 1, warningCount: 0 }])
|
|
116
|
-
await expect(run(neostandardLint({ failOnError: true }, () => Promise.resolve(eslint)), [makeFile(Buffer.from('a'))]))
|
|
117
|
-
.rejects.toThrow('neostandard found 1 lint error(s)')
|
|
118
|
-
expect(logSpy).toHaveBeenCalledWith('✖ Errors total: 1')
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
test('with failOnError, still passes when there are only warnings', async () => {
|
|
122
|
-
expect.assertions(1)
|
|
123
|
-
const eslint = fakeEslint(() => [{ messages: [{ line: 1, column: 1, message: 'just a warning' }], errorCount: 0, warningCount: 1 }])
|
|
124
|
-
await expect(run(neostandardLint({ failOnError: true }, () => Promise.resolve(eslint)), [makeFile(Buffer.from('a'))])).resolves.toHaveLength(1)
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
test('surfaces a failure to load or run the linter as a stream error', async () => {
|
|
128
|
-
expect.assertions(1)
|
|
129
|
-
await expect(run(neostandardLint({}, () => Promise.reject(new Error('cannot load'))), [makeFile(Buffer.from('x'))])).rejects.toThrow('cannot load')
|
|
130
|
-
})
|
|
131
|
-
})
|
|
1
|
+
import Vinyl from 'vinyl'
|
|
2
|
+
import { Readable } from 'node:stream'
|
|
3
|
+
import { neostandardLint } from './neostandardLint.mjs'
|
|
4
|
+
|
|
5
|
+
const makeFile = (contents, filePath = '/project/src/example.js') => new Vinyl({
|
|
6
|
+
cwd: '/project',
|
|
7
|
+
base: '/project/src',
|
|
8
|
+
path: filePath,
|
|
9
|
+
contents
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const run = (transform, files) => new Promise((resolve, reject) => {
|
|
13
|
+
const out = []
|
|
14
|
+
transform.on('data', file => out.push(file)).on('end', () => resolve(out)).on('error', reject)
|
|
15
|
+
files.forEach(file => transform.write(file))
|
|
16
|
+
transform.end()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const fakeEslint = (resultFor) => ({
|
|
20
|
+
lintText: jest.fn((text, options) => Promise.resolve(resultFor(text, options)))
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
let logSpy
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
logSpy = jest.spyOn(console, 'log').mockImplementation(() => {})
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
logSpy.mockRestore()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
describe('neostandardLint', () => {
|
|
34
|
+
test('replaces file contents with the fixed output and hands ESLint the file path', async () => {
|
|
35
|
+
expect.assertions(3)
|
|
36
|
+
const eslint = fakeEslint((text) => [{ messages: [], errorCount: 0, warningCount: 0, output: text.replace(/"/g, '\'') }])
|
|
37
|
+
const [linted] = await run(neostandardLint({ fix: true }, () => Promise.resolve(eslint)), [makeFile(Buffer.from('const a = "b"'))])
|
|
38
|
+
expect(linted.contents.toString()).toEqual('const a = \'b\'')
|
|
39
|
+
expect(eslint.lintText).toHaveBeenCalledWith('const a = "b"', { filePath: '/project/src/example.js' })
|
|
40
|
+
expect(linted.path).toEqual('/project/src/example.js')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('leaves the contents alone when ESLint has no fixed output (nothing needed fixing)', async () => {
|
|
44
|
+
expect.assertions(1)
|
|
45
|
+
const eslint = fakeEslint(() => [{ messages: [], errorCount: 0, warningCount: 0 }])
|
|
46
|
+
const [linted] = await run(neostandardLint({}, () => Promise.resolve(eslint)), [makeFile(Buffer.from('const a = 1'))])
|
|
47
|
+
expect(linted.contents.toString()).toEqual('const a = 1')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('builds the linter once per stream, from the first file, and reuses it for the rest', async () => {
|
|
51
|
+
expect.assertions(1)
|
|
52
|
+
const loadEslint = jest.fn(() => Promise.resolve(fakeEslint(() => [{ messages: [], errorCount: 0, warningCount: 0 }])))
|
|
53
|
+
await run(
|
|
54
|
+
neostandardLint({}, loadEslint),
|
|
55
|
+
[makeFile(Buffer.from('a'), '/project/src/a.js'), makeFile(Buffer.from('b'), '/project/src/b.js')]
|
|
56
|
+
)
|
|
57
|
+
expect(loadEslint).toHaveBeenCalledTimes(1)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('passes fix and ts through to the loader', async () => {
|
|
61
|
+
expect.assertions(1)
|
|
62
|
+
const loadEslint = jest.fn(() => Promise.resolve(fakeEslint(() => [{ messages: [], errorCount: 0, warningCount: 0 }])))
|
|
63
|
+
await run(neostandardLint({ fix: false, ts: true }, loadEslint), [makeFile(Buffer.from('x'))])
|
|
64
|
+
expect(loadEslint).toHaveBeenCalledWith({ cwd: '/project', ts: true, fix: false, rules: {} })
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test('passes rule overrides through to the loader', async () => {
|
|
68
|
+
expect.assertions(1)
|
|
69
|
+
const loadEslint = jest.fn(() => Promise.resolve(fakeEslint(() => [{ messages: [], errorCount: 0, warningCount: 0 }])))
|
|
70
|
+
const rules = { 'no-template-curly-in-string': 'off' }
|
|
71
|
+
await run(neostandardLint({ rules }, loadEslint), [makeFile(Buffer.from('x'))])
|
|
72
|
+
expect(loadEslint).toHaveBeenCalledWith({ cwd: '/project', ts: false, fix: true, rules })
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
test('passes a file through untouched when the project ignores it (ESLint returns no results)', async () => {
|
|
76
|
+
expect.assertions(2)
|
|
77
|
+
const eslint = fakeEslint(() => [])
|
|
78
|
+
const [linted] = await run(neostandardLint({}, () => Promise.resolve(eslint)), [makeFile(Buffer.from('var x=1'))])
|
|
79
|
+
expect(linted.contents.toString()).toEqual('var x=1')
|
|
80
|
+
expect(logSpy).toHaveBeenCalledWith('✖ Errors total: 0')
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test('skips null-content files without linting them', async () => {
|
|
84
|
+
expect.assertions(2)
|
|
85
|
+
const eslint = fakeEslint(() => [])
|
|
86
|
+
const [passed] = await run(neostandardLint({}, () => Promise.resolve(eslint)), [makeFile(null)])
|
|
87
|
+
expect(passed.isNull()).toBeTruthy()
|
|
88
|
+
expect(eslint.lintText).not.toHaveBeenCalled()
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
test('errors on streaming file contents, which cannot be linted', async () => {
|
|
92
|
+
expect.assertions(1)
|
|
93
|
+
const streamFile = makeFile(Readable.from(['x']))
|
|
94
|
+
await expect(run(neostandardLint({}, () => Promise.resolve(fakeEslint(() => []))), [streamFile])).rejects.toThrow(/streaming/)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
test('prints per-file problems and a summary of totals across all files, without failing', async () => {
|
|
98
|
+
expect.assertions(5)
|
|
99
|
+
const eslint = fakeEslint((text, { filePath }) => filePath.endsWith('a.js')
|
|
100
|
+
? [{ messages: [{ line: 2, column: 7, message: 'unused b' }, { line: 3, column: 1, message: 'bad thing' }], errorCount: 2, warningCount: 0 }]
|
|
101
|
+
: [{ messages: [{ line: 1, column: 1, message: 'just a warning' }], errorCount: 0, warningCount: 1 }])
|
|
102
|
+
const out = await run(
|
|
103
|
+
neostandardLint({}, () => Promise.resolve(eslint)),
|
|
104
|
+
[makeFile(Buffer.from('a'), '/project/src/a.js'), makeFile(Buffer.from('b'), '/project/src/b.js')]
|
|
105
|
+
)
|
|
106
|
+
expect(out).toHaveLength(2)
|
|
107
|
+
expect(logSpy).toHaveBeenCalledWith('src/a.js')
|
|
108
|
+
expect(logSpy).toHaveBeenCalledWith('line 2:7\tunused b')
|
|
109
|
+
expect(logSpy).toHaveBeenCalledWith('✖ Errors total: 2')
|
|
110
|
+
expect(logSpy).toHaveBeenCalledWith('⚠ Warnings total: 1\n')
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
test('with failOnError, fails the stream once it ends if any errors remain', async () => {
|
|
114
|
+
expect.assertions(2)
|
|
115
|
+
const eslint = fakeEslint(() => [{ messages: [{ line: 1, column: 1, message: 'bad thing' }], errorCount: 1, warningCount: 0 }])
|
|
116
|
+
await expect(run(neostandardLint({ failOnError: true }, () => Promise.resolve(eslint)), [makeFile(Buffer.from('a'))]))
|
|
117
|
+
.rejects.toThrow('neostandard found 1 lint error(s)')
|
|
118
|
+
expect(logSpy).toHaveBeenCalledWith('✖ Errors total: 1')
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test('with failOnError, still passes when there are only warnings', async () => {
|
|
122
|
+
expect.assertions(1)
|
|
123
|
+
const eslint = fakeEslint(() => [{ messages: [{ line: 1, column: 1, message: 'just a warning' }], errorCount: 0, warningCount: 1 }])
|
|
124
|
+
await expect(run(neostandardLint({ failOnError: true }, () => Promise.resolve(eslint)), [makeFile(Buffer.from('a'))])).resolves.toHaveLength(1)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
test('surfaces a failure to load or run the linter as a stream error', async () => {
|
|
128
|
+
expect.assertions(1)
|
|
129
|
+
await expect(run(neostandardLint({}, () => Promise.reject(new Error('cannot load'))), [makeFile(Buffer.from('x'))])).rejects.toThrow('cannot load')
|
|
130
|
+
})
|
|
131
|
+
})
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { dest, src } from 'gulp'
|
|
2
|
-
import * as gulpConfig from '../../gulp.config.mjs'
|
|
3
|
-
import rename from 'gulp-rename'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Copy a readme template into the README.md file.
|
|
7
|
-
* @memberOf module:partials
|
|
8
|
-
* @returns {*}
|
|
9
|
-
*/
|
|
10
|
-
export const readmeTemplate = () => src(gulpConfig.get('readme.template'))
|
|
11
|
-
.pipe(rename(gulpConfig.get('readme.file')))
|
|
12
|
-
.pipe(dest(gulpConfig.get('readme.to')))
|
|
1
|
+
import { dest, src } from 'gulp'
|
|
2
|
+
import * as gulpConfig from '../../gulp.config.mjs'
|
|
3
|
+
import rename from 'gulp-rename'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Copy a readme template into the README.md file.
|
|
7
|
+
* @memberOf module:partials
|
|
8
|
+
* @returns {*}
|
|
9
|
+
*/
|
|
10
|
+
export const readmeTemplate = () => src(gulpConfig.get('readme.template'))
|
|
11
|
+
.pipe(rename(gulpConfig.get('readme.file')))
|
|
12
|
+
.pipe(dest(gulpConfig.get('readme.to')))
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import * as setUp from '../test-helpers/setUp.mjs'
|
|
3
|
-
import { readmeTemplate } from './readmeTemplate.mjs'
|
|
4
|
-
|
|
5
|
-
setUp.setDefaults('test-readme-template')
|
|
6
|
-
const gulpConfig = setUp.gulpConfig
|
|
7
|
-
|
|
8
|
-
const mainMd = 'MAIN.md'
|
|
9
|
-
const mainTestPath = gulpConfig.get('readme.template')
|
|
10
|
-
|
|
11
|
-
beforeEach(() => setUp.beforeEach()
|
|
12
|
-
.then(() => fs.copyFileSync(mainMd, mainTestPath)))
|
|
13
|
-
|
|
14
|
-
afterEach(setUp.afterEach)
|
|
15
|
-
|
|
16
|
-
describe('readmeTemplate', () => {
|
|
17
|
-
test('copies the main contents into the new README.md', done => {
|
|
18
|
-
const readmeFilePath = gulpConfig.get('readme.to') + gulpConfig.get('readme.file')
|
|
19
|
-
const mainContents = fs.readFileSync(mainTestPath)
|
|
20
|
-
expect.assertions(2)
|
|
21
|
-
readmeTemplate()
|
|
22
|
-
.on('finish', async () => {
|
|
23
|
-
await expect(fs.existsSync(readmeFilePath)).toBeTruthy()
|
|
24
|
-
const readme = await fs.readFileSync(readmeFilePath)
|
|
25
|
-
// Confirm that the contents for MAIN.md are copied to README.md
|
|
26
|
-
await expect(readme).toEqual(mainContents)
|
|
27
|
-
done()
|
|
28
|
-
})
|
|
29
|
-
.on('error', error => {
|
|
30
|
-
console.error('Encountered error', error)
|
|
31
|
-
done()
|
|
32
|
-
})
|
|
33
|
-
})
|
|
34
|
-
})
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import * as setUp from '../test-helpers/setUp.mjs'
|
|
3
|
+
import { readmeTemplate } from './readmeTemplate.mjs'
|
|
4
|
+
|
|
5
|
+
setUp.setDefaults('test-readme-template')
|
|
6
|
+
const gulpConfig = setUp.gulpConfig
|
|
7
|
+
|
|
8
|
+
const mainMd = 'MAIN.md'
|
|
9
|
+
const mainTestPath = gulpConfig.get('readme.template')
|
|
10
|
+
|
|
11
|
+
beforeEach(() => setUp.beforeEach()
|
|
12
|
+
.then(() => fs.copyFileSync(mainMd, mainTestPath)))
|
|
13
|
+
|
|
14
|
+
afterEach(setUp.afterEach)
|
|
15
|
+
|
|
16
|
+
describe('readmeTemplate', () => {
|
|
17
|
+
test('copies the main contents into the new README.md', done => {
|
|
18
|
+
const readmeFilePath = gulpConfig.get('readme.to') + gulpConfig.get('readme.file')
|
|
19
|
+
const mainContents = fs.readFileSync(mainTestPath)
|
|
20
|
+
expect.assertions(2)
|
|
21
|
+
readmeTemplate()
|
|
22
|
+
.on('finish', async () => {
|
|
23
|
+
await expect(fs.existsSync(readmeFilePath)).toBeTruthy()
|
|
24
|
+
const readme = await fs.readFileSync(readmeFilePath)
|
|
25
|
+
// Confirm that the contents for MAIN.md are copied to README.md
|
|
26
|
+
await expect(readme).toEqual(mainContents)
|
|
27
|
+
done()
|
|
28
|
+
})
|
|
29
|
+
.on('error', error => {
|
|
30
|
+
console.error('Encountered error', error)
|
|
31
|
+
done()
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
})
|