js-build-tools 6.6.0 → 6.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/LICENSE +674 -674
- package/README.md +768 -701
- 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/cacheFiles.js +121 -0
- 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 +155 -93
- package/dist/partials/jsdocDocsFor.js +64 -51
- 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 +264 -264
- package/dist/partials.js +183 -176
- package/dist/partials.min.js +1 -1
- package/dist/sourceLint.js +18 -18
- package/dist/test-helpers/setUp.js +6 -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 +760 -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 +140 -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/cacheFiles.mjs +114 -0
- package/functions/partials/cacheFiles.test.mjs +151 -0
- 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 +147 -83
- package/functions/partials/imagesFor.test.mjs +311 -287
- 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 -231
- package/functions/partials/typeDocsFor.test.mjs +263 -263
- package/functions/partials.mjs +32 -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/neostandardLintWithRealNeostandard.mjs +40 -40
- package/functions/test-helpers/setUp.mjs +102 -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 +349 -340
- 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
- package/dist/test-helpers/isolateGulpCache.js +0 -25
- package/functions/test-helpers/isolateGulpCache.mjs +0 -16
package/functions/sass.test.mjs
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import * as setUp from './test-helpers/setUp.mjs'
|
|
3
|
-
import { sass } from './sass.mjs'
|
|
4
|
-
|
|
5
|
-
setUp.setDefaults('test-sass')
|
|
6
|
-
const gulpConfig = setUp.gulpConfig
|
|
7
|
-
|
|
8
|
-
beforeEach(() => setUp.beforeEach().then(
|
|
9
|
-
() => {
|
|
10
|
-
const sassPath = gulpConfig.get('sass.path')
|
|
11
|
-
return fs.mkdirSync(sassPath, { recursive: true })
|
|
12
|
-
}
|
|
13
|
-
))
|
|
14
|
-
|
|
15
|
-
afterEach(setUp.afterEach)
|
|
16
|
-
|
|
17
|
-
describe('sass', () => {
|
|
18
|
-
test('uses the configured paths', done => {
|
|
19
|
-
const sassPath = gulpConfig.get('sass.path')
|
|
20
|
-
expect.assertions(1)
|
|
21
|
-
sass()
|
|
22
|
-
.on('finish', () => {
|
|
23
|
-
expect(fs.existsSync(sassPath)).toBeTruthy()
|
|
24
|
-
done()
|
|
25
|
-
})
|
|
26
|
-
.on('error', error => {
|
|
27
|
-
console.error('Encountered error', error)
|
|
28
|
-
done()
|
|
29
|
-
})
|
|
30
|
-
}, 10000)
|
|
31
|
-
})
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import * as setUp from './test-helpers/setUp.mjs'
|
|
3
|
+
import { sass } from './sass.mjs'
|
|
4
|
+
|
|
5
|
+
setUp.setDefaults('test-sass')
|
|
6
|
+
const gulpConfig = setUp.gulpConfig
|
|
7
|
+
|
|
8
|
+
beforeEach(() => setUp.beforeEach().then(
|
|
9
|
+
() => {
|
|
10
|
+
const sassPath = gulpConfig.get('sass.path')
|
|
11
|
+
return fs.mkdirSync(sassPath, { recursive: true })
|
|
12
|
+
}
|
|
13
|
+
))
|
|
14
|
+
|
|
15
|
+
afterEach(setUp.afterEach)
|
|
16
|
+
|
|
17
|
+
describe('sass', () => {
|
|
18
|
+
test('uses the configured paths', done => {
|
|
19
|
+
const sassPath = gulpConfig.get('sass.path')
|
|
20
|
+
expect.assertions(1)
|
|
21
|
+
sass()
|
|
22
|
+
.on('finish', () => {
|
|
23
|
+
expect(fs.existsSync(sassPath)).toBeTruthy()
|
|
24
|
+
done()
|
|
25
|
+
})
|
|
26
|
+
.on('error', error => {
|
|
27
|
+
console.error('Encountered error', error)
|
|
28
|
+
done()
|
|
29
|
+
})
|
|
30
|
+
}, 10000)
|
|
31
|
+
})
|
package/functions/sourceLint.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { lintSource } from './partials/lintSource.mjs'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Applies neostandard linting (js-build-tools' chosen style) to the real, hand-written source - not the compiled
|
|
5
|
-
* dist/browser output, which is generated and so was never going to pass a hand-authored-code style check (every
|
|
6
|
-
* compiler/bundler emits its own boilerplate - import aliasing, interop headers - that only looks like a style
|
|
7
|
-
* violation). Includes test files: there is no reason to hold tests to a lower style bar than the rest of the
|
|
8
|
-
* source. When typescript.enabled, the real TypeScript source is linted too, with type-aware rules. Runs as part of
|
|
9
|
-
* `build`, where remaining errors are reported but never fail it.
|
|
10
|
-
* @memberOf module:js-build-tools
|
|
11
|
-
* @returns {*}
|
|
12
|
-
*/
|
|
13
|
-
export const sourceLint = () => lintSource()
|
|
1
|
+
import { lintSource } from './partials/lintSource.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Applies neostandard linting (js-build-tools' chosen style) to the real, hand-written source - not the compiled
|
|
5
|
+
* dist/browser output, which is generated and so was never going to pass a hand-authored-code style check (every
|
|
6
|
+
* compiler/bundler emits its own boilerplate - import aliasing, interop headers - that only looks like a style
|
|
7
|
+
* violation). Includes test files: there is no reason to hold tests to a lower style bar than the rest of the
|
|
8
|
+
* source. When typescript.enabled, the real TypeScript source is linted too, with type-aware rules. Runs as part of
|
|
9
|
+
* `build`, where remaining errors are reported but never fail it.
|
|
10
|
+
* @memberOf module:js-build-tools
|
|
11
|
+
* @returns {*}
|
|
12
|
+
*/
|
|
13
|
+
export const sourceLint = () => lintSource()
|
|
@@ -1,166 +1,166 @@
|
|
|
1
|
-
/* eslint-disable no-template-curly-in-string -- fixture source code, the ${...} is meant to stay literal */
|
|
2
|
-
import fs from 'fs'
|
|
3
|
-
import * as setUp from './test-helpers/setUp.mjs'
|
|
4
|
-
import { lint } from './lint.mjs'
|
|
5
|
-
import { sourceLint } from './sourceLint.mjs'
|
|
6
|
-
import { countMatches } from 'test-filesystem'
|
|
7
|
-
|
|
8
|
-
// Run the real neostandard (in a subprocess) - Jest's CommonJS transform can't load the ESM-only package itself.
|
|
9
|
-
jest.mock('./partials/neostandardLint.mjs', () => require('./test-helpers/neostandardLintWithRealNeostandard.mjs'))
|
|
10
|
-
|
|
11
|
-
setUp.setDefaults('test-source-lint')
|
|
12
|
-
const gulpConfig = setUp.gulpConfig
|
|
13
|
-
|
|
14
|
-
const lintableContents = 'const x = "a";\n' +
|
|
15
|
-
'\n' +
|
|
16
|
-
'module.exports = x;\n'
|
|
17
|
-
|
|
18
|
-
const lintableTestContents = 'const y = "b";\n' +
|
|
19
|
-
'\n' +
|
|
20
|
-
'module.exports = y;\n'
|
|
21
|
-
|
|
22
|
-
beforeEach(
|
|
23
|
-
() => setUp.beforeEach()
|
|
24
|
-
.then(
|
|
25
|
-
async () => {
|
|
26
|
-
const srcPath = gulpConfig.get('srcPath')
|
|
27
|
-
await fs.mkdirSync(srcPath, { recursive: true })
|
|
28
|
-
fs.writeFileSync(`${srcPath}/example.js`, lintableContents)
|
|
29
|
-
return fs.writeFileSync(`${srcPath}/example.test.js`, lintableTestContents)
|
|
30
|
-
}
|
|
31
|
-
)
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
afterEach(setUp.afterEach)
|
|
35
|
-
|
|
36
|
-
describe('sourceLint', () => {
|
|
37
|
-
test('fixes the real source in place, including test files', done => {
|
|
38
|
-
const srcPath = gulpConfig.get('srcPath')
|
|
39
|
-
expect.assertions(4)
|
|
40
|
-
sourceLint()
|
|
41
|
-
.on('finish', () => {
|
|
42
|
-
const linted = fs.readFileSync(`${srcPath}/example.js`).toString()
|
|
43
|
-
expect(countMatches(linted, '"')).toEqual(0)
|
|
44
|
-
expect(countMatches(linted, ';')).toEqual(0)
|
|
45
|
-
const lintedTest = fs.readFileSync(`${srcPath}/example.test.js`).toString()
|
|
46
|
-
expect(countMatches(lintedTest, '"')).toEqual(0)
|
|
47
|
-
expect(countMatches(lintedTest, ';')).toEqual(0)
|
|
48
|
-
done()
|
|
49
|
-
})
|
|
50
|
-
.on('error', error => {
|
|
51
|
-
console.error('Encountered error', error)
|
|
52
|
-
done(error)
|
|
53
|
-
})
|
|
54
|
-
}, 20000)
|
|
55
|
-
|
|
56
|
-
test('also lints .mjs and .cjs source, not just .js', done => {
|
|
57
|
-
const srcPath = gulpConfig.get('srcPath')
|
|
58
|
-
fs.writeFileSync(`${srcPath}/example.mjs`, 'const m = "d";\n\nexport default m;\n')
|
|
59
|
-
fs.writeFileSync(`${srcPath}/example.cjs`, 'const c = "e";\n\nmodule.exports = c;\n')
|
|
60
|
-
expect.assertions(2)
|
|
61
|
-
sourceLint()
|
|
62
|
-
.on('finish', () => {
|
|
63
|
-
expect(fs.readFileSync(`${srcPath}/example.mjs`).toString()).toEqual('const m = \'d\'\n\nexport default m\n')
|
|
64
|
-
expect(fs.readFileSync(`${srcPath}/example.cjs`).toString()).toEqual('const c = \'e\'\n\nmodule.exports = c\n')
|
|
65
|
-
done()
|
|
66
|
-
})
|
|
67
|
-
.on('error', error => {
|
|
68
|
-
console.error('Encountered error', error)
|
|
69
|
-
done(error)
|
|
70
|
-
})
|
|
71
|
-
}, 20000)
|
|
72
|
-
|
|
73
|
-
test('lint.rules actually suppresses a real neostandard finding', done => {
|
|
74
|
-
const srcPath = gulpConfig.get('srcPath')
|
|
75
|
-
// A fixture string containing literal ${...} text (simulating real module source, not an accidental
|
|
76
|
-
// non-template string) - neostandard's no-template-curly-in-string rule flags this as an error by default.
|
|
77
|
-
const fixtureContents = 'const fixture = \'import(`imagemin-${pluginName}`)\'\n\nmodule.exports = fixture\n'
|
|
78
|
-
fs.writeFileSync(`${srcPath}/fixture.js`, fixtureContents)
|
|
79
|
-
gulpConfig.set('lint.rules', { 'no-template-curly-in-string': 'off' })
|
|
80
|
-
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {})
|
|
81
|
-
expect.assertions(1)
|
|
82
|
-
sourceLint()
|
|
83
|
-
.on('finish', () => {
|
|
84
|
-
gulpConfig.set('lint.rules', {})
|
|
85
|
-
expect(logSpy.mock.calls.flat().join('\n')).not.toMatch(/no-template-curly-in-string|template string expression/)
|
|
86
|
-
logSpy.mockRestore()
|
|
87
|
-
done()
|
|
88
|
-
})
|
|
89
|
-
.on('error', error => {
|
|
90
|
-
gulpConfig.set('lint.rules', {})
|
|
91
|
-
logSpy.mockRestore()
|
|
92
|
-
console.error('Encountered error', error)
|
|
93
|
-
done(error)
|
|
94
|
-
})
|
|
95
|
-
}, 20000)
|
|
96
|
-
|
|
97
|
-
test('also lints .ts source when typescript.enabled', done => {
|
|
98
|
-
const srcPath = gulpConfig.get('srcPath')
|
|
99
|
-
gulpConfig.set('typescript.enabled', true)
|
|
100
|
-
fs.writeFileSync(`${srcPath}/example.ts`, 'const z: string = "c";\n\nexport default z;\n')
|
|
101
|
-
expect.assertions(2)
|
|
102
|
-
sourceLint()
|
|
103
|
-
.on('finish', () => {
|
|
104
|
-
gulpConfig.set('typescript.enabled', false)
|
|
105
|
-
const linted = fs.readFileSync(`${srcPath}/example.ts`).toString()
|
|
106
|
-
expect(countMatches(linted, '"')).toEqual(0)
|
|
107
|
-
expect(countMatches(linted, ';')).toEqual(0)
|
|
108
|
-
done()
|
|
109
|
-
})
|
|
110
|
-
.on('error', error => {
|
|
111
|
-
gulpConfig.set('typescript.enabled', false)
|
|
112
|
-
console.error('Encountered error', error)
|
|
113
|
-
done(error)
|
|
114
|
-
})
|
|
115
|
-
}, 20000)
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
describe('lint', () => {
|
|
119
|
-
test('fixes the source and finishes without error when nothing unfixable remains', done => {
|
|
120
|
-
const srcPath = gulpConfig.get('srcPath')
|
|
121
|
-
expect.assertions(1)
|
|
122
|
-
lint()
|
|
123
|
-
.on('finish', () => {
|
|
124
|
-
expect(countMatches(fs.readFileSync(`${srcPath}/example.js`).toString(), ';')).toEqual(0)
|
|
125
|
-
done()
|
|
126
|
-
})
|
|
127
|
-
.on('error', error => done(error))
|
|
128
|
-
}, 20000)
|
|
129
|
-
|
|
130
|
-
test('fails when an error remains that neostandard cannot fix', done => {
|
|
131
|
-
const srcPath = gulpConfig.get('srcPath')
|
|
132
|
-
fs.writeFileSync(`${srcPath}/unfixable.js`, 'const unused = 1\n')
|
|
133
|
-
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {})
|
|
134
|
-
expect.assertions(1)
|
|
135
|
-
lint()
|
|
136
|
-
.on('error', error => {
|
|
137
|
-
logSpy.mockRestore()
|
|
138
|
-
expect(error.message).toMatch('neostandard found 1 lint error(s)')
|
|
139
|
-
done()
|
|
140
|
-
})
|
|
141
|
-
.on('finish', () => {
|
|
142
|
-
logSpy.mockRestore()
|
|
143
|
-
done(new Error('lint should have failed on the unused variable'))
|
|
144
|
-
})
|
|
145
|
-
}, 20000)
|
|
146
|
-
|
|
147
|
-
test('only fails once every fixed file has been written back', done => {
|
|
148
|
-
// gulp exits as soon as a task fails, so failing while a file is still being written can leave that file empty.
|
|
149
|
-
const srcPath = gulpConfig.get('srcPath')
|
|
150
|
-
const fixable = ['a', 'b', 'c'].map(name => `${srcPath}/fixable-${name}.js`)
|
|
151
|
-
fixable.forEach(file => fs.writeFileSync(file, 'const x = "y";\n\nmodule.exports = x;\n'))
|
|
152
|
-
fs.writeFileSync(`${srcPath}/unfixable.js`, 'const unused = 1\n')
|
|
153
|
-
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {})
|
|
154
|
-
expect.assertions(fixable.length)
|
|
155
|
-
lint()
|
|
156
|
-
.on('error', () => {
|
|
157
|
-
logSpy.mockRestore()
|
|
158
|
-
fixable.forEach(file => expect(fs.readFileSync(file).toString()).toEqual('const x = \'y\'\n\nmodule.exports = x\n'))
|
|
159
|
-
done()
|
|
160
|
-
})
|
|
161
|
-
.on('finish', () => {
|
|
162
|
-
logSpy.mockRestore()
|
|
163
|
-
done(new Error('lint should have failed on the unused variable'))
|
|
164
|
-
})
|
|
165
|
-
}, 30000)
|
|
166
|
-
})
|
|
1
|
+
/* eslint-disable no-template-curly-in-string -- fixture source code, the ${...} is meant to stay literal */
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import * as setUp from './test-helpers/setUp.mjs'
|
|
4
|
+
import { lint } from './lint.mjs'
|
|
5
|
+
import { sourceLint } from './sourceLint.mjs'
|
|
6
|
+
import { countMatches } from 'test-filesystem'
|
|
7
|
+
|
|
8
|
+
// Run the real neostandard (in a subprocess) - Jest's CommonJS transform can't load the ESM-only package itself.
|
|
9
|
+
jest.mock('./partials/neostandardLint.mjs', () => require('./test-helpers/neostandardLintWithRealNeostandard.mjs'))
|
|
10
|
+
|
|
11
|
+
setUp.setDefaults('test-source-lint')
|
|
12
|
+
const gulpConfig = setUp.gulpConfig
|
|
13
|
+
|
|
14
|
+
const lintableContents = 'const x = "a";\n' +
|
|
15
|
+
'\n' +
|
|
16
|
+
'module.exports = x;\n'
|
|
17
|
+
|
|
18
|
+
const lintableTestContents = 'const y = "b";\n' +
|
|
19
|
+
'\n' +
|
|
20
|
+
'module.exports = y;\n'
|
|
21
|
+
|
|
22
|
+
beforeEach(
|
|
23
|
+
() => setUp.beforeEach()
|
|
24
|
+
.then(
|
|
25
|
+
async () => {
|
|
26
|
+
const srcPath = gulpConfig.get('srcPath')
|
|
27
|
+
await fs.mkdirSync(srcPath, { recursive: true })
|
|
28
|
+
fs.writeFileSync(`${srcPath}/example.js`, lintableContents)
|
|
29
|
+
return fs.writeFileSync(`${srcPath}/example.test.js`, lintableTestContents)
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
afterEach(setUp.afterEach)
|
|
35
|
+
|
|
36
|
+
describe('sourceLint', () => {
|
|
37
|
+
test('fixes the real source in place, including test files', done => {
|
|
38
|
+
const srcPath = gulpConfig.get('srcPath')
|
|
39
|
+
expect.assertions(4)
|
|
40
|
+
sourceLint()
|
|
41
|
+
.on('finish', () => {
|
|
42
|
+
const linted = fs.readFileSync(`${srcPath}/example.js`).toString()
|
|
43
|
+
expect(countMatches(linted, '"')).toEqual(0)
|
|
44
|
+
expect(countMatches(linted, ';')).toEqual(0)
|
|
45
|
+
const lintedTest = fs.readFileSync(`${srcPath}/example.test.js`).toString()
|
|
46
|
+
expect(countMatches(lintedTest, '"')).toEqual(0)
|
|
47
|
+
expect(countMatches(lintedTest, ';')).toEqual(0)
|
|
48
|
+
done()
|
|
49
|
+
})
|
|
50
|
+
.on('error', error => {
|
|
51
|
+
console.error('Encountered error', error)
|
|
52
|
+
done(error)
|
|
53
|
+
})
|
|
54
|
+
}, 20000)
|
|
55
|
+
|
|
56
|
+
test('also lints .mjs and .cjs source, not just .js', done => {
|
|
57
|
+
const srcPath = gulpConfig.get('srcPath')
|
|
58
|
+
fs.writeFileSync(`${srcPath}/example.mjs`, 'const m = "d";\n\nexport default m;\n')
|
|
59
|
+
fs.writeFileSync(`${srcPath}/example.cjs`, 'const c = "e";\n\nmodule.exports = c;\n')
|
|
60
|
+
expect.assertions(2)
|
|
61
|
+
sourceLint()
|
|
62
|
+
.on('finish', () => {
|
|
63
|
+
expect(fs.readFileSync(`${srcPath}/example.mjs`).toString()).toEqual('const m = \'d\'\n\nexport default m\n')
|
|
64
|
+
expect(fs.readFileSync(`${srcPath}/example.cjs`).toString()).toEqual('const c = \'e\'\n\nmodule.exports = c\n')
|
|
65
|
+
done()
|
|
66
|
+
})
|
|
67
|
+
.on('error', error => {
|
|
68
|
+
console.error('Encountered error', error)
|
|
69
|
+
done(error)
|
|
70
|
+
})
|
|
71
|
+
}, 20000)
|
|
72
|
+
|
|
73
|
+
test('lint.rules actually suppresses a real neostandard finding', done => {
|
|
74
|
+
const srcPath = gulpConfig.get('srcPath')
|
|
75
|
+
// A fixture string containing literal ${...} text (simulating real module source, not an accidental
|
|
76
|
+
// non-template string) - neostandard's no-template-curly-in-string rule flags this as an error by default.
|
|
77
|
+
const fixtureContents = 'const fixture = \'import(`imagemin-${pluginName}`)\'\n\nmodule.exports = fixture\n'
|
|
78
|
+
fs.writeFileSync(`${srcPath}/fixture.js`, fixtureContents)
|
|
79
|
+
gulpConfig.set('lint.rules', { 'no-template-curly-in-string': 'off' })
|
|
80
|
+
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {})
|
|
81
|
+
expect.assertions(1)
|
|
82
|
+
sourceLint()
|
|
83
|
+
.on('finish', () => {
|
|
84
|
+
gulpConfig.set('lint.rules', {})
|
|
85
|
+
expect(logSpy.mock.calls.flat().join('\n')).not.toMatch(/no-template-curly-in-string|template string expression/)
|
|
86
|
+
logSpy.mockRestore()
|
|
87
|
+
done()
|
|
88
|
+
})
|
|
89
|
+
.on('error', error => {
|
|
90
|
+
gulpConfig.set('lint.rules', {})
|
|
91
|
+
logSpy.mockRestore()
|
|
92
|
+
console.error('Encountered error', error)
|
|
93
|
+
done(error)
|
|
94
|
+
})
|
|
95
|
+
}, 20000)
|
|
96
|
+
|
|
97
|
+
test('also lints .ts source when typescript.enabled', done => {
|
|
98
|
+
const srcPath = gulpConfig.get('srcPath')
|
|
99
|
+
gulpConfig.set('typescript.enabled', true)
|
|
100
|
+
fs.writeFileSync(`${srcPath}/example.ts`, 'const z: string = "c";\n\nexport default z;\n')
|
|
101
|
+
expect.assertions(2)
|
|
102
|
+
sourceLint()
|
|
103
|
+
.on('finish', () => {
|
|
104
|
+
gulpConfig.set('typescript.enabled', false)
|
|
105
|
+
const linted = fs.readFileSync(`${srcPath}/example.ts`).toString()
|
|
106
|
+
expect(countMatches(linted, '"')).toEqual(0)
|
|
107
|
+
expect(countMatches(linted, ';')).toEqual(0)
|
|
108
|
+
done()
|
|
109
|
+
})
|
|
110
|
+
.on('error', error => {
|
|
111
|
+
gulpConfig.set('typescript.enabled', false)
|
|
112
|
+
console.error('Encountered error', error)
|
|
113
|
+
done(error)
|
|
114
|
+
})
|
|
115
|
+
}, 20000)
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
describe('lint', () => {
|
|
119
|
+
test('fixes the source and finishes without error when nothing unfixable remains', done => {
|
|
120
|
+
const srcPath = gulpConfig.get('srcPath')
|
|
121
|
+
expect.assertions(1)
|
|
122
|
+
lint()
|
|
123
|
+
.on('finish', () => {
|
|
124
|
+
expect(countMatches(fs.readFileSync(`${srcPath}/example.js`).toString(), ';')).toEqual(0)
|
|
125
|
+
done()
|
|
126
|
+
})
|
|
127
|
+
.on('error', error => done(error))
|
|
128
|
+
}, 20000)
|
|
129
|
+
|
|
130
|
+
test('fails when an error remains that neostandard cannot fix', done => {
|
|
131
|
+
const srcPath = gulpConfig.get('srcPath')
|
|
132
|
+
fs.writeFileSync(`${srcPath}/unfixable.js`, 'const unused = 1\n')
|
|
133
|
+
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {})
|
|
134
|
+
expect.assertions(1)
|
|
135
|
+
lint()
|
|
136
|
+
.on('error', error => {
|
|
137
|
+
logSpy.mockRestore()
|
|
138
|
+
expect(error.message).toMatch('neostandard found 1 lint error(s)')
|
|
139
|
+
done()
|
|
140
|
+
})
|
|
141
|
+
.on('finish', () => {
|
|
142
|
+
logSpy.mockRestore()
|
|
143
|
+
done(new Error('lint should have failed on the unused variable'))
|
|
144
|
+
})
|
|
145
|
+
}, 20000)
|
|
146
|
+
|
|
147
|
+
test('only fails once every fixed file has been written back', done => {
|
|
148
|
+
// gulp exits as soon as a task fails, so failing while a file is still being written can leave that file empty.
|
|
149
|
+
const srcPath = gulpConfig.get('srcPath')
|
|
150
|
+
const fixable = ['a', 'b', 'c'].map(name => `${srcPath}/fixable-${name}.js`)
|
|
151
|
+
fixable.forEach(file => fs.writeFileSync(file, 'const x = "y";\n\nmodule.exports = x;\n'))
|
|
152
|
+
fs.writeFileSync(`${srcPath}/unfixable.js`, 'const unused = 1\n')
|
|
153
|
+
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {})
|
|
154
|
+
expect.assertions(fixable.length)
|
|
155
|
+
lint()
|
|
156
|
+
.on('error', () => {
|
|
157
|
+
logSpy.mockRestore()
|
|
158
|
+
fixable.forEach(file => expect(fs.readFileSync(file).toString()).toEqual('const x = \'y\'\n\nmodule.exports = x\n'))
|
|
159
|
+
done()
|
|
160
|
+
})
|
|
161
|
+
.on('finish', () => {
|
|
162
|
+
logSpy.mockRestore()
|
|
163
|
+
done(new Error('lint should have failed on the unused variable'))
|
|
164
|
+
})
|
|
165
|
+
}, 30000)
|
|
166
|
+
})
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
import { execFileSync } from 'node:child_process'
|
|
2
|
-
import fs from 'node:fs'
|
|
3
|
-
import path from 'node:path'
|
|
4
|
-
|
|
5
|
-
// Jest's CommonJS transform cannot load `neostandard` (ESM-only) or run a real dynamic import(), so tests that need
|
|
6
|
-
// genuine neostandard behavior run the actual package in a plain Node subprocess instead of faking it.
|
|
7
|
-
const script = 'import { readFileSync } from \'node:fs\'\n' +
|
|
8
|
-
'import { ESLint } from \'eslint\'\n' +
|
|
9
|
-
'import { neostandard, defaultFilePatterns } from \'neostandard\'\n' +
|
|
10
|
-
'const { text, filePath, cwd, fix, ts, env, rules } = JSON.parse(readFileSync(0, \'utf8\'))\n' +
|
|
11
|
-
'const baseConfig = neostandard({ ts, env })\n' +
|
|
12
|
-
'if (Object.keys(rules).length) { baseConfig.push({ files: defaultFilePatterns.all, rules }) }\n' +
|
|
13
|
-
'const eslint = new ESLint({ cwd, fix, overrideConfigFile: true, baseConfig })\n' +
|
|
14
|
-
'process.stdout.write(JSON.stringify(await eslint.lintText(text, { filePath })))\n'
|
|
15
|
-
|
|
16
|
-
const readEnv = cwd => {
|
|
17
|
-
try {
|
|
18
|
-
return JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8')).standard?.env ?? []
|
|
19
|
-
} catch {
|
|
20
|
-
return []
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export const loadEslintViaSubprocess = ({ cwd, ts, fix, rules = {} }) => Promise.resolve({
|
|
25
|
-
lintText: (text, { filePath }) => Promise.resolve().then(() => JSON.parse(execFileSync(
|
|
26
|
-
process.execPath,
|
|
27
|
-
['--input-type=module', '--eval', script],
|
|
28
|
-
{
|
|
29
|
-
input: JSON.stringify({ text, filePath, cwd, fix, ts, env: readEnv(cwd), rules }),
|
|
30
|
-
encoding: 'utf8',
|
|
31
|
-
cwd,
|
|
32
|
-
maxBuffer: 256 * 1024 * 1024
|
|
33
|
-
}
|
|
34
|
-
)))
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
const actual = jest.requireActual('../partials/neostandardLint.mjs')
|
|
38
|
-
|
|
39
|
-
// Drop-in replacement for the partial module (see jest.mock in the lint/build tests): same API, real neostandard.
|
|
40
|
-
export const neostandardLint = (options) => actual.neostandardLint(options, loadEslintViaSubprocess)
|
|
1
|
+
import { execFileSync } from 'node:child_process'
|
|
2
|
+
import fs from 'node:fs'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
|
|
5
|
+
// Jest's CommonJS transform cannot load `neostandard` (ESM-only) or run a real dynamic import(), so tests that need
|
|
6
|
+
// genuine neostandard behavior run the actual package in a plain Node subprocess instead of faking it.
|
|
7
|
+
const script = 'import { readFileSync } from \'node:fs\'\n' +
|
|
8
|
+
'import { ESLint } from \'eslint\'\n' +
|
|
9
|
+
'import { neostandard, defaultFilePatterns } from \'neostandard\'\n' +
|
|
10
|
+
'const { text, filePath, cwd, fix, ts, env, rules } = JSON.parse(readFileSync(0, \'utf8\'))\n' +
|
|
11
|
+
'const baseConfig = neostandard({ ts, env })\n' +
|
|
12
|
+
'if (Object.keys(rules).length) { baseConfig.push({ files: defaultFilePatterns.all, rules }) }\n' +
|
|
13
|
+
'const eslint = new ESLint({ cwd, fix, overrideConfigFile: true, baseConfig })\n' +
|
|
14
|
+
'process.stdout.write(JSON.stringify(await eslint.lintText(text, { filePath })))\n'
|
|
15
|
+
|
|
16
|
+
const readEnv = cwd => {
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8')).standard?.env ?? []
|
|
19
|
+
} catch {
|
|
20
|
+
return []
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const loadEslintViaSubprocess = ({ cwd, ts, fix, rules = {} }) => Promise.resolve({
|
|
25
|
+
lintText: (text, { filePath }) => Promise.resolve().then(() => JSON.parse(execFileSync(
|
|
26
|
+
process.execPath,
|
|
27
|
+
['--input-type=module', '--eval', script],
|
|
28
|
+
{
|
|
29
|
+
input: JSON.stringify({ text, filePath, cwd, fix, ts, env: readEnv(cwd), rules }),
|
|
30
|
+
encoding: 'utf8',
|
|
31
|
+
cwd,
|
|
32
|
+
maxBuffer: 256 * 1024 * 1024
|
|
33
|
+
}
|
|
34
|
+
)))
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const actual = jest.requireActual('../partials/neostandardLint.mjs')
|
|
38
|
+
|
|
39
|
+
// Drop-in replacement for the partial module (see jest.mock in the lint/build tests): same API, real neostandard.
|
|
40
|
+
export const neostandardLint = (options) => actual.neostandardLint(options, loadEslintViaSubprocess)
|