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.
Files changed (47) hide show
  1. package/README.md +10 -3
  2. package/dist/lint.js +17 -0
  3. package/dist/lint.min.js +1 -0
  4. package/dist/partials/imagesFor.js +42 -43
  5. package/dist/partials/jsdocDocsFor.js +128 -128
  6. package/dist/partials/lintSource.js +52 -0
  7. package/dist/partials/loadPeer.js +71 -70
  8. package/dist/partials/minifyFor.js +16 -16
  9. package/dist/partials/neostandardLint.js +134 -123
  10. package/dist/partials.js +176 -169
  11. package/dist/partials.min.js +1 -1
  12. package/dist/sourceLint.js +11 -27
  13. package/dist/sourceLint.min.js +1 -1
  14. package/dist/test-helpers/isolateGulpCache.js +25 -0
  15. package/dist/utilities/dotGet.js +46 -46
  16. package/dist/utilities/dotNotate.js +48 -48
  17. package/dist/utilities/dotSet.js +37 -37
  18. package/functions/build.test.mjs +17 -7
  19. package/functions/bundle.test.mjs +0 -1
  20. package/functions/images.test.mjs +4 -1
  21. package/functions/lint.mjs +9 -0
  22. package/functions/partials/addToReadme.test.mjs +2 -1
  23. package/functions/partials/imagesFor.mjs +0 -1
  24. package/functions/partials/imagesFor.test.mjs +5 -2
  25. package/functions/partials/lintSource.mjs +41 -0
  26. package/functions/partials/loadPeer.mjs +1 -0
  27. package/functions/partials/loadPlaywright.test.mjs +1 -2
  28. package/functions/partials/minifyFor.mjs +1 -1
  29. package/functions/partials/neostandardLint.mjs +14 -4
  30. package/functions/partials/neostandardLint.test.mjs +14 -0
  31. package/functions/partials/runOnChange.test.mjs +5 -4
  32. package/functions/partials/tsFor.test.mjs +1 -0
  33. package/functions/partials.mjs +1 -0
  34. package/functions/partials.test.mjs +1 -1
  35. package/functions/sourceLint.mjs +4 -15
  36. package/functions/sourceLint.test.mjs +69 -0
  37. package/functions/test-helpers/isolateGulpCache.mjs +16 -0
  38. package/functions/test-helpers/setUp.mjs +7 -7
  39. package/functions/testFull.test.mjs +1 -1
  40. package/functions/testQuick.test.mjs +1 -1
  41. package/functions/utilities/convertMjsFilesForDocs.test.mjs +1 -0
  42. package/functions/utilities/dotGet.mjs +2 -2
  43. package/functions/utilities/dotNotate.mjs +2 -2
  44. package/functions/utilities/dotNotate.test.mjs +7 -0
  45. package/functions/utilities/dotSet.mjs +1 -1
  46. package/gulpfile.base.mjs +1 -0
  47. 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
- createTempDir,
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
- beforeEach,
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
- afterEach,
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
- countMatches,
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
- fileExists,
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
- logObject,
93
+ logObject,
94
94
  /**
95
95
  * Delete a directory and subcontents.
96
96
  * @memberOf module:testHelpers
97
97
  * @returns {Promise<*>}
98
98
  */
99
- removeDirectory,
99
+ removeDirectory,
100
100
  } from 'test-filesystem'
@@ -5,7 +5,7 @@ import { testFull } from './testFull.mjs'
5
5
  const gulpConfig = testHelpers.gulpConfig
6
6
 
7
7
  jest.mock('jest', () => ({
8
- 'runCLI': jest.fn(() => Promise.resolve(true))
8
+ runCLI: jest.fn(() => Promise.resolve(true))
9
9
  }))
10
10
 
11
11
  describe('testFull', () => {
@@ -5,7 +5,7 @@ import { testQuick } from './testQuick.mjs'
5
5
  const gulpConfig = testHelpers.gulpConfig
6
6
 
7
7
  jest.mock('jest', () => ({
8
- 'runCLI': jest.fn(() => Promise.resolve(true))
8
+ runCLI: jest.fn(() => Promise.resolve(true))
9
9
  }))
10
10
 
11
11
  describe('testQuick', () => {
@@ -1,3 +1,4 @@
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'
3
4
  import { convertMjsFilesForDocs } from './convertMjsFilesForDocs.mjs'
@@ -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 (let wildKey in arrayObject) {
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.replace('\.', '\\.'))
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 (let key in arrayObject) {
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
  })
@@ -18,7 +18,7 @@ export const dotSet = (arrayObject, dotNotation, value = null) => {
18
18
  key = dotNotation
19
19
  }
20
20
  if (key === '*') {
21
- for (let wildKey in arrayObject) {
21
+ for (const wildKey in arrayObject) {
22
22
  if (lastKey) {
23
23
  arrayObject[wildKey] = value
24
24
  continue
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.1",
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": "~1.62.1",
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
  }