js-build-tools 6.3.1 → 6.4.1
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 -3
- package/dist/lint.js +17 -0
- package/dist/lint.min.js +1 -0
- package/dist/partials/imagesFor.js +42 -43
- package/dist/partials/jsdocDocsFor.js +128 -128
- package/dist/partials/lintSource.js +52 -0
- package/dist/partials/loadPeer.js +71 -70
- package/dist/partials/minifyFor.js +16 -16
- package/dist/partials/neostandardLint.js +134 -123
- package/dist/partials.js +176 -169
- package/dist/partials.min.js +1 -1
- package/dist/sourceLint.js +11 -27
- package/dist/sourceLint.min.js +1 -1
- package/dist/test-helpers/isolateGulpCache.js +25 -0
- package/dist/utilities/dotGet.js +46 -46
- package/dist/utilities/dotNotate.js +48 -48
- package/dist/utilities/dotSet.js +37 -37
- package/functions/build.test.mjs +17 -7
- package/functions/bundle.test.mjs +0 -1
- package/functions/images.test.mjs +4 -1
- package/functions/lint.mjs +9 -0
- package/functions/partials/addToReadme.test.mjs +2 -1
- package/functions/partials/imagesFor.mjs +0 -1
- package/functions/partials/imagesFor.test.mjs +5 -2
- package/functions/partials/lintSource.mjs +41 -0
- package/functions/partials/loadPeer.mjs +1 -0
- package/functions/partials/loadPlaywright.test.mjs +1 -2
- package/functions/partials/minifyFor.mjs +1 -1
- package/functions/partials/neostandardLint.mjs +14 -4
- package/functions/partials/neostandardLint.test.mjs +14 -0
- package/functions/partials/runOnChange.test.mjs +5 -4
- package/functions/partials/tsFor.test.mjs +1 -0
- package/functions/partials.mjs +1 -0
- package/functions/partials.test.mjs +1 -1
- package/functions/sourceLint.mjs +4 -15
- package/functions/sourceLint.test.mjs +69 -0
- package/functions/test-helpers/isolateGulpCache.mjs +16 -0
- package/functions/test-helpers/setUp.mjs +7 -7
- package/functions/testFull.test.mjs +1 -1
- package/functions/testQuick.test.mjs +1 -1
- package/functions/utilities/convertMjsFilesForDocs.test.mjs +1 -0
- package/functions/utilities/dotGet.mjs +2 -2
- package/functions/utilities/dotNotate.mjs +2 -2
- package/functions/utilities/dotNotate.test.mjs +7 -0
- package/functions/utilities/dotSet.mjs +1 -1
- package/gulpfile.base.mjs +1 -0
- package/package.json +12 -2
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
/* eslint-disable no-template-curly-in-string -- fixture source code, the ${...} is meant to stay literal */
|
|
1
2
|
import fs from 'fs'
|
|
2
3
|
import * as setUp from './test-helpers/setUp.mjs'
|
|
4
|
+
import { lint } from './lint.mjs'
|
|
3
5
|
import { sourceLint } from './sourceLint.mjs'
|
|
4
6
|
import { countMatches } from 'test-filesystem'
|
|
5
7
|
|
|
@@ -51,6 +53,23 @@ describe('sourceLint', () => {
|
|
|
51
53
|
})
|
|
52
54
|
}, 20000)
|
|
53
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
|
+
|
|
54
73
|
test('lint.rules actually suppresses a real neostandard finding', done => {
|
|
55
74
|
const srcPath = gulpConfig.get('srcPath')
|
|
56
75
|
// A fixture string containing literal ${...} text (simulating real module source, not an accidental
|
|
@@ -95,3 +114,53 @@ describe('sourceLint', () => {
|
|
|
95
114
|
})
|
|
96
115
|
}, 20000)
|
|
97
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
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import cache from 'gulp-cache'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Give this test file its own gulp-cache folder, and return a function that clears only that folder. gulp-cache
|
|
5
|
+
* otherwise keeps one cache in os.tmpdir() for every process, so a cache.clearAll() in one Jest worker could wipe it
|
|
6
|
+
* while another worker's images task was still using it, and gulp-cache then silently dropped that worker's
|
|
7
|
+
* images. Jest loads gulp-cache separately for each test file, so this only changes the copy that file uses.
|
|
8
|
+
* @memberOf module:testHelpers
|
|
9
|
+
* @param {string} name - Unique per test file, used in the cache folder name.
|
|
10
|
+
* @returns {function(): Promise<void>} Clears this test file's cache.
|
|
11
|
+
*/
|
|
12
|
+
export const isolateGulpCache = name => {
|
|
13
|
+
const fileCache = new cache.Cache({ cacheDirName: `js-build-tools-test-${name}` })
|
|
14
|
+
cache.defaultOptions.fileCache = fileCache
|
|
15
|
+
return () => new Promise((resolve, reject) => fileCache.clear(null, error => error ? reject(error) : resolve()))
|
|
16
|
+
}
|
|
@@ -60,41 +60,41 @@ export {
|
|
|
60
60
|
* @param {boolean} [exists=true]
|
|
61
61
|
* @returns {Promise<*|void>}
|
|
62
62
|
*/
|
|
63
|
-
|
|
63
|
+
createTempDir,
|
|
64
64
|
/**
|
|
65
65
|
* In the Jest.beforeEach function call this one to set up the temp directory.
|
|
66
66
|
* @memberOf module:testHelpers
|
|
67
67
|
* @returns {Promise<*|void>}
|
|
68
68
|
*/
|
|
69
|
-
|
|
69
|
+
beforeEach,
|
|
70
70
|
/**
|
|
71
71
|
* In the Jest.afterEach function call this one to clean up and remove the temp directory.
|
|
72
72
|
* @memberOf module:testHelpers
|
|
73
73
|
* @returns {Promise<*>}
|
|
74
74
|
*/
|
|
75
|
-
|
|
75
|
+
afterEach,
|
|
76
76
|
/**
|
|
77
77
|
* Return number of occurrences of substring in another string.
|
|
78
78
|
* @memberOf module:testHelpers
|
|
79
79
|
* @returns {int}
|
|
80
80
|
*/
|
|
81
|
-
|
|
81
|
+
countMatches,
|
|
82
82
|
/**
|
|
83
83
|
* Returns true if the given file or directory exists, otherwise false.
|
|
84
84
|
* @memberOf module:testHelpers
|
|
85
85
|
* @returns {boolean}
|
|
86
86
|
*/
|
|
87
|
-
|
|
87
|
+
fileExists,
|
|
88
88
|
/**
|
|
89
89
|
* Console log objects in a readable format, returns the given object.
|
|
90
90
|
* @memberOf module:testHelpers
|
|
91
91
|
* @returns {*}
|
|
92
92
|
*/
|
|
93
|
-
|
|
93
|
+
logObject,
|
|
94
94
|
/**
|
|
95
95
|
* Delete a directory and subcontents.
|
|
96
96
|
* @memberOf module:testHelpers
|
|
97
97
|
* @returns {Promise<*>}
|
|
98
98
|
*/
|
|
99
|
-
|
|
99
|
+
removeDirectory,
|
|
100
100
|
} from 'test-filesystem'
|
|
@@ -11,7 +11,7 @@ import { strBefore } from './strBefore.mjs'
|
|
|
11
11
|
* @returns {*} The value of the property
|
|
12
12
|
* @private
|
|
13
13
|
*/
|
|
14
|
-
export const dotGet = (arrayObject = {}, dotNotation= '', defaultValue = null) => {
|
|
14
|
+
export const dotGet = (arrayObject = {}, dotNotation = '', defaultValue = null) => {
|
|
15
15
|
if (!dotNotation) {
|
|
16
16
|
return arrayObject
|
|
17
17
|
}
|
|
@@ -22,7 +22,7 @@ export const dotGet = (arrayObject = {}, dotNotation= '', defaultValue = null) =
|
|
|
22
22
|
}
|
|
23
23
|
if (key === '*') {
|
|
24
24
|
const result = []
|
|
25
|
-
for (
|
|
25
|
+
for (const wildKey in arrayObject) {
|
|
26
26
|
const wildValue = arrayObject[wildKey]
|
|
27
27
|
if (lastKey) {
|
|
28
28
|
result[wildKey] = wildValue
|
|
@@ -15,7 +15,7 @@ const handleRetainObjects = (retainObjects = []) => {
|
|
|
15
15
|
*/
|
|
16
16
|
return (currentKey, value, results) => false
|
|
17
17
|
}
|
|
18
|
-
retainObjects = retainObjects.map(key => key.
|
|
18
|
+
retainObjects = retainObjects.map(key => key.replaceAll('.', '\\.'))
|
|
19
19
|
const retainRegex = new RegExp(`(${retainObjects.join('|')})$`)
|
|
20
20
|
/**
|
|
21
21
|
* Test if a key should be retained as an object.
|
|
@@ -44,7 +44,7 @@ const handleRetainObjects = (retainObjects = []) => {
|
|
|
44
44
|
* @private
|
|
45
45
|
*/
|
|
46
46
|
const performDotNotate = (arrayObject, didRetain, prepend = '', results = {}) => {
|
|
47
|
-
for (
|
|
47
|
+
for (const key in arrayObject) {
|
|
48
48
|
const value = arrayObject[key]
|
|
49
49
|
const currentKey = `${prepend}${key}`
|
|
50
50
|
if (didRetain(currentKey, value, results)) {
|
|
@@ -31,4 +31,11 @@ describe('dotNotate', () => {
|
|
|
31
31
|
options: { fix: true }
|
|
32
32
|
})
|
|
33
33
|
})
|
|
34
|
+
|
|
35
|
+
test('treats every dot in a retained key literally, not as a regex wildcard', () => {
|
|
36
|
+
expect(dotNotate({ a: { bXc: { d: 1 }, b: { c: { d: 2 } } } }, ['a.b.c'])).toEqual({
|
|
37
|
+
'a.bXc.d': 1,
|
|
38
|
+
'a.b.c': { d: 2 }
|
|
39
|
+
})
|
|
40
|
+
})
|
|
34
41
|
})
|
package/gulpfile.base.mjs
CHANGED
|
@@ -16,6 +16,7 @@ export { distMinify } from './functions/distMinify.mjs'
|
|
|
16
16
|
export * as gulpConfig from './gulp.config.mjs'
|
|
17
17
|
export { images } from './functions/images.mjs'
|
|
18
18
|
export { jsdocDocs } from './functions/jsdocDocs.mjs'
|
|
19
|
+
export { lint } from './functions/lint.mjs'
|
|
19
20
|
export * as partials from './functions/partials.mjs'
|
|
20
21
|
export { sass } from './functions/sass.mjs'
|
|
21
22
|
export { sourceLint } from './functions/sourceLint.mjs'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "js-build-tools",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.4.1",
|
|
4
4
|
"description": "Standardised build process with gulp.",
|
|
5
5
|
"main": "gulpfile.base.js",
|
|
6
6
|
"exports": {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"build": "gulp build",
|
|
22
22
|
"dev": "gulp",
|
|
23
23
|
"docs": "gulp docs",
|
|
24
|
+
"lint": "gulp lint",
|
|
24
25
|
"readme": "gulp readme",
|
|
25
26
|
"release": "release-it",
|
|
26
27
|
"release:dry-run": "release-it --dry-run",
|
|
@@ -124,12 +125,21 @@
|
|
|
124
125
|
"clean-jsdoc-theme": "^4.3.3",
|
|
125
126
|
"gulp-imagemin": "github:jheagle/gulp-imagemin#common-js-compatibility",
|
|
126
127
|
"jsdoc": "^4.0.5",
|
|
127
|
-
"playwright": "
|
|
128
|
+
"playwright": "^1.64.1",
|
|
128
129
|
"release-it": "^21.1.1",
|
|
129
130
|
"typedoc": "^0.28.20",
|
|
130
131
|
"typescript": "^6.0.3"
|
|
131
132
|
},
|
|
132
133
|
"engines": {
|
|
133
134
|
"node": ">=22.12.0"
|
|
135
|
+
},
|
|
136
|
+
"allowScripts": {
|
|
137
|
+
"gifsicle@5.3.0": true,
|
|
138
|
+
"mozjpeg@8.0.0": true,
|
|
139
|
+
"optipng-bin@7.0.1": true,
|
|
140
|
+
"core-js": false,
|
|
141
|
+
"core-js-pure": false,
|
|
142
|
+
"@parcel/watcher": false,
|
|
143
|
+
"unrs-resolver": false
|
|
134
144
|
}
|
|
135
145
|
}
|