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.
Files changed (173) hide show
  1. package/LICENSE +674 -674
  2. package/README.md +768 -701
  3. package/babel.config.js +28 -28
  4. package/dist/build.js +75 -75
  5. package/dist/bundle.js +19 -19
  6. package/dist/bundleMinify.js +7 -7
  7. package/dist/compileReadme.js +4 -4
  8. package/dist/copyFiles.js +17 -17
  9. package/dist/copyFonts.js +4 -4
  10. package/dist/default.js +5 -5
  11. package/dist/dist.js +4 -4
  12. package/dist/distMinify.js +4 -4
  13. package/dist/docs.js +7 -7
  14. package/dist/images.js +4 -4
  15. package/dist/jsdocDocs.js +6 -6
  16. package/dist/lint.js +16 -16
  17. package/dist/partials/addToReadme.js +9 -9
  18. package/dist/partials/beginWatcher.js +4 -4
  19. package/dist/partials/cacheFiles.js +121 -0
  20. package/dist/partials/clean.js +5 -5
  21. package/dist/partials/copyFor.js +9 -9
  22. package/dist/partials/distFor.js +6 -6
  23. package/dist/partials/distForSrc.js +5 -5
  24. package/dist/partials/distSeries.js +7 -7
  25. package/dist/partials/imagesFor.js +155 -93
  26. package/dist/partials/jsdocDocsFor.js +64 -51
  27. package/dist/partials/lintSource.js +51 -51
  28. package/dist/partials/loadPeer.js +99 -99
  29. package/dist/partials/loadPlaywright.js +14 -14
  30. package/dist/partials/minifyFor.js +20 -20
  31. package/dist/partials/neostandardLint.js +175 -175
  32. package/dist/partials/readmeTemplate.js +4 -4
  33. package/dist/partials/removeDirectory.js +11 -11
  34. package/dist/partials/resolveDocsMethod.js +6 -6
  35. package/dist/partials/runOnChange.js +31 -31
  36. package/dist/partials/sassFor.js +6 -6
  37. package/dist/partials/serveStatic.js +9 -9
  38. package/dist/partials/tsFor.js +32 -32
  39. package/dist/partials/typeDocsFor.js +264 -264
  40. package/dist/partials.js +183 -176
  41. package/dist/partials.min.js +1 -1
  42. package/dist/sourceLint.js +18 -18
  43. package/dist/test-helpers/setUp.js +6 -4
  44. package/dist/testFull.js +5 -5
  45. package/dist/testQuick.js +5 -5
  46. package/dist/typeDocs.js +5 -5
  47. package/dist/typeScript.js +4 -4
  48. package/dist/utilities/convertMjsFilesForDocs.js +12 -12
  49. package/dist/utilities/dotGet.js +54 -54
  50. package/dist/utilities/dotNotate.js +79 -79
  51. package/dist/utilities/dotSet.js +45 -45
  52. package/dist/utilities/esmNamedExportsToCjs.js +15 -15
  53. package/dist/utilities/getBundleConfigs.js +9 -9
  54. package/dist/utilities/isObject.js +6 -6
  55. package/dist/utilities/strAfter.js +7 -7
  56. package/dist/utilities/strBefore.js +7 -7
  57. package/dist/watchFull.js +4 -4
  58. package/dist/watchTest.js +4 -4
  59. package/functions/build.mjs +72 -72
  60. package/functions/build.test.mjs +760 -759
  61. package/functions/bundle.mjs +44 -44
  62. package/functions/bundle.test.mjs +219 -219
  63. package/functions/bundleMinify.mjs +16 -16
  64. package/functions/bundleMinify.test.mjs +37 -37
  65. package/functions/compileReadme.mjs +9 -9
  66. package/functions/compileReadme.test.mjs +18 -18
  67. package/functions/copyFiles.mjs +32 -32
  68. package/functions/copyFiles.test.mjs +78 -78
  69. package/functions/copyFonts.mjs +9 -9
  70. package/functions/copyFonts.test.mjs +32 -32
  71. package/functions/default.mjs +12 -12
  72. package/functions/default.test.mjs +33 -33
  73. package/functions/dist.mjs +8 -8
  74. package/functions/dist.test.mjs +44 -44
  75. package/functions/distMinify.mjs +9 -9
  76. package/functions/distMinify.test.mjs +15 -15
  77. package/functions/docs.mjs +13 -13
  78. package/functions/docs.test.mjs +45 -45
  79. package/functions/gulpConfigEntries.test.mjs +23 -23
  80. package/functions/images.mjs +8 -8
  81. package/functions/images.test.mjs +140 -142
  82. package/functions/jsdocDocs.mjs +10 -10
  83. package/functions/jsdocEsmExports.test.mjs +24 -24
  84. package/functions/lint.mjs +9 -9
  85. package/functions/partials/addToReadme.mjs +25 -25
  86. package/functions/partials/addToReadme.test.mjs +34 -34
  87. package/functions/partials/beginWatcher.mjs +9 -9
  88. package/functions/partials/beginWatcher.test.mjs +19 -19
  89. package/functions/partials/cacheFiles.mjs +114 -0
  90. package/functions/partials/cacheFiles.test.mjs +151 -0
  91. package/functions/partials/clean.mjs +13 -13
  92. package/functions/partials/clean.test.mjs +22 -22
  93. package/functions/partials/copyFor.mjs +15 -15
  94. package/functions/partials/copyFor.test.mjs +53 -53
  95. package/functions/partials/distFor.mjs +22 -22
  96. package/functions/partials/distFor.test.mjs +195 -195
  97. package/functions/partials/distForSrc.mjs +11 -11
  98. package/functions/partials/distForSrc.test.mjs +18 -18
  99. package/functions/partials/distSeries.mjs +21 -21
  100. package/functions/partials/distSeries.test.mjs +34 -34
  101. package/functions/partials/imagesFor.mjs +147 -83
  102. package/functions/partials/imagesFor.test.mjs +311 -287
  103. package/functions/partials/jsdocDocsFor.mjs +163 -152
  104. package/functions/partials/jsdocDocsFor.test.mjs +182 -152
  105. package/functions/partials/lintSource.mjs +41 -41
  106. package/functions/partials/loadPeer.mjs +76 -76
  107. package/functions/partials/loadPeer.test.mjs +58 -58
  108. package/functions/partials/loadPlaywright.mjs +23 -23
  109. package/functions/partials/loadPlaywright.test.mjs +70 -70
  110. package/functions/partials/minifyFor.mjs +15 -15
  111. package/functions/partials/minifyFor.test.mjs +49 -49
  112. package/functions/partials/neostandardLint.mjs +142 -142
  113. package/functions/partials/neostandardLint.test.mjs +131 -131
  114. package/functions/partials/readmeTemplate.mjs +12 -12
  115. package/functions/partials/readmeTemplate.test.mjs +34 -34
  116. package/functions/partials/removeDirectory.mjs +34 -34
  117. package/functions/partials/removeDirectory.test.mjs +72 -72
  118. package/functions/partials/resolveDocsMethod.mjs +10 -10
  119. package/functions/partials/resolveDocsMethod.test.mjs +33 -33
  120. package/functions/partials/runOnChange.mjs +54 -54
  121. package/functions/partials/runOnChange.test.mjs +95 -95
  122. package/functions/partials/sassFor.mjs +25 -25
  123. package/functions/partials/sassFor.test.mjs +81 -81
  124. package/functions/partials/serveStatic.mjs +47 -47
  125. package/functions/partials/serveStatic.test.mjs +71 -71
  126. package/functions/partials/tsFor.mjs +92 -92
  127. package/functions/partials/tsFor.test.mjs +88 -88
  128. package/functions/partials/typeDocsFor.mjs +231 -231
  129. package/functions/partials/typeDocsFor.test.mjs +263 -263
  130. package/functions/partials.mjs +32 -31
  131. package/functions/partials.test.mjs +7 -7
  132. package/functions/sass.mjs +4 -4
  133. package/functions/sass.test.mjs +31 -31
  134. package/functions/sourceLint.mjs +13 -13
  135. package/functions/sourceLint.test.mjs +166 -166
  136. package/functions/test-helpers/neostandardLintWithRealNeostandard.mjs +40 -40
  137. package/functions/test-helpers/setUp.mjs +102 -100
  138. package/functions/test-helpers/setUp.test.mjs +19 -19
  139. package/functions/testFull.mjs +17 -17
  140. package/functions/testFull.test.mjs +17 -17
  141. package/functions/testHelpers.mjs +10 -10
  142. package/functions/testHelpers.test.mjs +7 -7
  143. package/functions/testQuick.mjs +17 -17
  144. package/functions/testQuick.test.mjs +17 -17
  145. package/functions/typeDocs.mjs +9 -9
  146. package/functions/typeDocs.test.mjs +11 -11
  147. package/functions/typeScript.mjs +8 -8
  148. package/functions/typeScript.test.mjs +11 -11
  149. package/functions/utilities/convertMjsFilesForDocs.mjs +34 -34
  150. package/functions/utilities/convertMjsFilesForDocs.test.mjs +58 -58
  151. package/functions/utilities/dotGet.mjs +49 -49
  152. package/functions/utilities/dotNotate.mjs +73 -73
  153. package/functions/utilities/dotNotate.test.mjs +41 -41
  154. package/functions/utilities/dotSet.mjs +40 -40
  155. package/functions/utilities/esmNamedExportsToCjs.mjs +30 -30
  156. package/functions/utilities/esmNamedExportsToCjs.test.mjs +47 -47
  157. package/functions/utilities/getBundleConfigs.mjs +30 -30
  158. package/functions/utilities/isObject.mjs +8 -8
  159. package/functions/utilities/strAfter.mjs +12 -12
  160. package/functions/utilities/strBefore.mjs +12 -12
  161. package/functions/watchFull.mjs +9 -9
  162. package/functions/watchFull.test.mjs +41 -41
  163. package/functions/watchTest.mjs +10 -10
  164. package/functions/watchTest.test.mjs +49 -49
  165. package/gulp.config.js +4 -4
  166. package/gulp.config.mjs +349 -340
  167. package/gulpfile.base.js +51 -51
  168. package/gulpfile.base.mjs +29 -29
  169. package/jsdoc.base.js +16 -16
  170. package/jsdoc.esmExports.js +17 -17
  171. package/package.json +146 -145
  172. package/dist/test-helpers/isolateGulpCache.js +0 -25
  173. package/functions/test-helpers/isolateGulpCache.mjs +0 -16
package/README.md CHANGED
@@ -1,691 +1,700 @@
1
- # [js-build-tools](https://www.npmjs.com/package/js-build-tools)
2
-
3
- Centralize the build process for Node.js, JS and TypeScript projects into a single tool suite.
4
-
5
- ### Goals
6
-
7
- Using this tool suite, you can:
8
-
9
- * Parse TypeScript into JS distribution files
10
- * Create formatted distribution files to be used in a node / commonjs environment.
11
- * Bundle your distribution files to be used in a browser environment.
12
- * Run tests and watch for changes.
13
- * Generate jsdoc readme files.
14
- * Generate real HTML documentation straight from your source - TypeDoc for a TypeScript project (a module for
15
- each of your folders), or jsdoc with a modern theme for a plain JavaScript one.
16
- * Copy files (a bundle, or anything else) to another location, on demand.
17
-
18
- ## Installation
19
-
20
- In your project's root directory, run: `npm install --save-dev gulp js-build-tools`
21
- (or `yarn add --dev gulp js-build-tools` if you use Yarn).
22
-
23
- It is recommended to install gulp with the `-g` flag, so that you can run it with `gulp` instead
24
- of `node_modules/.bin/gulp`.
25
-
26
- ## Configuration
27
-
28
- In your project's root directory, create a `build-tools.config.json` file. This can contain any of the following (values
29
- provided are the defaults):
30
-
31
- ```json
32
- {
33
- "browser": {
34
- // 'true' to generate browser bundled files; 'false' for node environment only
35
- "enabled": true,
36
- // The name to use for the browser-bundled output file (.js will be appended).
37
- "name": "my-package",
38
- // The search pattern used for retrieving compiled distribution files.
39
- "from": "dist/**/*.js",
40
- // Module names or file paths which resolve to an empty object ({}) in the bundle instead of their real contents.
41
- "ignore": [],
42
- // Module names or file paths left out of the bundle entirely (requiring one at runtime throws, unless something
43
- // else provides it, for example a script tag which loads it separately).
44
- "exclude": [],
45
- // Additional bundles to produce alongside the primary one above (see 'Configure additional browser bundles').
46
- "bundles": [],
47
- // The output directory for browser-bundled files.
48
- "to": "browser"
49
- },
50
- // The paths for directories to delete before build.
51
- "cleanPaths": [
52
- "dist",
53
- "browser"
54
- ],
55
- "dist": {
56
- // Name of the entry the distribution file.
57
- "main": "dist/main",
58
- // The search pattern used for gathering source files for distribution.
59
- "from": "src/**/!(*.test).js",
60
- // The output directory for the distribution files.
61
- "to": "dist"
62
- },
63
- "docs": {
64
- // Toggle generating the HTML documentation from the TypeScript source (see 'Configure TypeScript documentation').
65
- // When on, the build does this instead of generating the readme from the jsdoc comments.
66
- "enabled": false,
67
- // The directory holding the TypeScript source, each folder in it becomes a module of the documentation.
68
- "from": "src",
69
- // The markdown file used as the front page of the documentation.
70
- "index": "MAIN.md",
71
- // How much TypeDoc reports: Verbose, Info, Warn, Error or None.
72
- "logLevel": "Warn",
73
- // The name of the documentation, defaults to the name in your package.json.
74
- "title": "",
75
- // The directory to generate the documentation in (it is cleared first).
76
- "to": "docs",
77
- // The tsconfig file to read the source with, false to use the one of 'typescript.config'.
78
- "tsconfig": false
79
- },
80
- "fonts": {
81
- // Toggle copy directory of fonts on
82
- "enabled": false,
83
- // Path to search for fonts
84
- "from": "src/fonts/**/*",
85
- // Path to output fonts
86
- "to": "browser/fonts"
87
- },
88
- "images": {
89
- // Toggle image minify and copy process
90
- "enabled": false,
91
- // Path to search for images
92
- "from": "src/img/**/*.+(png|jpg|jpeg|gif|svg)",
93
- // The JPEG quality (0 to 100) to compress to, false keeps mozjpeg's own default (75)
94
- "jpegQuality": false,
95
- // Path to output images
96
- "to": "browser/img"
97
- },
98
- "readme": {
99
- // The file which will be pre-fixed to your README.md output.
100
- "template": "MAIN.md",
101
- // Options for formatting the output readme.
102
- "options": "utf8",
103
- // The name of the output documentation markdown file.
104
- "file": "README.md",
105
- // Location of files to use for compiling documentation into the readme.
106
- "from": [
107
- "src/**/!(*.test).js"
108
- ],
109
- // Additional .mjs files to document alongside 'from' (see 'Configure including ESM files in the generated
110
- // readme'). Empty by default: a project that never sets this gets exactly the readme it always did.
111
- "fromEsm": [],
112
- // The directory to output the readme file in.
113
- "to": "./"
114
- },
115
- // Base directory of the project.
116
- "rootPath": "./",
117
- "sass": {
118
- // Toggle SASS to CSS process on.
119
- "enabled": false,
120
- // The pattern for finding all sass files.
121
- "from": "sass/**/*.+(scss|sass)",
122
- // The directory were sass files will be stored.
123
- "path": "sass",
124
- // The destination path for where generated CSS (from SASS files) should go.
125
- "to": "browser/css"
126
- },
127
- // The directory where your source files are stored (the files you manually created).
128
- "srcPath": "src",
129
- "test": {
130
- // Additional flags for programmatically running Jest Cli.
131
- "options": null,
132
- // The directory where Jest test files are stored.
133
- // By default, stored as *.test.js adjacent to the files they are testing.
134
- "path": [
135
- "src"
136
- ],
137
- // The search pattern for watching files for changes.
138
- "watch": "src/**/*.js"
139
- },
140
- "typescript": {
141
- // The path the tsconfig file for running typescript or false if no ts file given.
142
- "config": false,
143
- // Toggle usage of typescript parsing.
144
- "enabled": false,
145
- // Pattern for finding the TypeScript files.
146
- "from": "src/**/*.ts",
147
- // Directory where parsed typescript files go.
148
- "to": "dist"
149
- }
150
- }
151
- ```
152
-
153
- ### Create your local gulpfile.js
154
-
155
- In your project's root directory, create a `gulpfile.js` file, in here you can require any of the functions you need.
156
- For example:
157
-
158
- #### Common JS
159
-
160
- ```js
161
- // Your local gulpfile.js
162
- const {
163
- build,
164
- defaultCmd,
165
- docs,
166
- partials,
167
- readme,
168
- sass,
169
- testFull,
170
- testQuick,
171
- typescript,
172
- watchFull,
173
- watchTest
174
- } = require('js-build-tools/gulpfile.base.js')
175
-
176
- // Everything you export will be created as a gulp task.
177
- // You can build your own tasks here as well by using some of the functions `js-build-tools/functions`.
178
- // You can list your available tasks by running `gulp --tasks`.
179
- exports.build = build
180
- exports.default = defaultCmd
181
- exports.docs = docs
182
- exports.readme = readme
183
- exports.sass = sass
184
- exports.testFull = testFull
185
- exports.testQuick = testQuick
186
- exports.watchFull = watchFull
187
- exports.watchTest = watchTest
188
- ```
189
-
190
- #### ES Module
191
-
192
- ```js
193
- // Your local gulpfile.mjs
194
- // Everything you export will be created as a gulp task.
195
- export {
196
- build,
197
- defaultCmd,
198
- docs,
199
- partials,
200
- readme,
201
- sass,
202
- testFull,
203
- testQuick,
204
- typescript,
205
- watchFull,
206
- watchTest
207
- } from 'js-build-tools/gulpfile.base.mjs'
208
-
209
- // You can build your own tasks here as well by using some of the functions `js-build-tools/functions`.
210
- // You can list your available tasks by running `gulp --tasks`.
211
-
212
- ```
213
-
214
- Verify your tasks are available by running `gulp --tasks`.
215
-
216
- ### Configure Babel
217
-
218
- Depending on how you wrote your test files, Jest may require some Babel configuration.
219
- Create a `babel.config.js` file in the root directory of your project.
220
- You can then use the recommended configuration by requiring the `babel.config.js` file into your own configuration file.
221
- Example:
222
-
223
- ```js
224
- const babelConfig = require('js-build-tools/babel.config')
225
- // You may add additional configuration here. Example: babelConfig.presets.push('@babel/preset-env')
226
- module.exports = babelConfig
227
- ```
228
-
229
- ### Configure ES Modules (.mjs)
230
-
231
- It is not recommended to use `"type": "module"` in the `package.json` to enable ES Modules.
232
- This is because some dependencies still rely on common JS syntax (ex: babel, jest, jsdoc).
233
- So, to use ES Modules, you can use the `.mjs` extension on your files instead.
234
- There are different downsides to using the `.mjs` extension to consider.
235
- The `jsdoc` generation can only read `.js` files, and the provided test runner `Jest` will need to be configured.
236
- Update the test config as follows:
237
-
238
- ```json
239
- {
240
- "dist": {
241
- // Use .mjs files for from and main
242
- "main": "src/main.mjs",
243
- "from": "src/**/!(*.test).mjs",
244
- "to": "dist"
245
- },
246
- "readme": {
247
- "template": "MAIN.md",
248
- "options": "utf8",
249
- "file": "README.md",
250
- "from": [
251
- // Use the dist directory files to generate the jsdocs - dist is always .js regardless of source
252
- // extension, since Babel compiles .mjs source down to it, so this is enough on its own. If you instead
253
- // have a handful of standalone .mjs files that never go through the normal dist compile (for example a
254
- // config file read directly by the build itself), see 'Configure including ESM files in the generated
255
- // readme' for readme.fromEsm instead - a lighter option than switching your whole project's dist/test
256
- // config over to .mjs just to document a few files.
257
- "dist/!(*.test).js"
258
- ],
259
- "to": "./"
260
- },
261
- "test": {
262
- "options": {
263
- // The below helps to find the .mjs files (rather than default .js files)
264
- "testMatch": [
265
- "**/?(*.)+(spec|test).mjs?(x)"
266
- ]
267
- },
268
- "path": "functions",
269
- // Include watching for .mjs files
270
- "watch": "functions/**/*.[cm]?[jt]s"
271
- }
272
- }
273
- ```
274
-
275
- There is an additional file you need to get Jest working, add a `jest.config.js` file.
276
- While we have already added these configurations above in the "options",
277
- there seems to be a bug where the "transform" does not work in that context. Add the following to your `jest.config.js`:
278
-
279
- ```js
280
- module.exports = {
281
- // The transform will instruct jest to run the files through babel so it can interpret them
282
- transform: {
283
- '^.+\\.[cm]?[jt]sx?$': 'babel-jest'
284
- }
285
- }
286
- ```
287
-
288
- ### Configure HTML JS Documentation, full manual control (optional, advanced)
289
-
290
- For most projects, `docs.enabled` with `docs.method: 'jsdoc'` (see 'Configure HTML documentation' below) is the
291
- simpler path - no `.jsdoc.conf.js` file to maintain by hand, wired straight into `gulp build`/`gulp docs`. This
292
- section is for when you want full, direct control over jsdoc's own config instead (a plugin or option this
293
- project's own generated config does not expose, for example).
294
-
295
- Create a `.jsdoc.conf.js` file and add the following:
296
-
297
- ```js
298
- const jsDocBase = require('js-build-tools/jsdoc.base')
299
- /* You will get a jsdoc config object with the following:
300
- * {
301
- * plugins: ['plugins/markdown'],
302
- * source: {
303
- * include: [your configured distPath],
304
- * includePattern: '.+\\.js(doc|x)?$',
305
- * excludePattern: '((^|\\/|\\\\)_|.+\\.test\\..*)'
306
- * }
307
- * }
308
- * You can manipulate the properties before returning in module.exports.
309
- * This searches the defined 'distPath' for building the HTML JS Documentation
310
- */
311
- module.exports = jsDocBase
312
- ```
313
-
314
- ### Configure what the browser bundle leaves out (optional)
315
-
316
- A dependency can be reached from your code without being needed in the browser, and bundling it can add a lot of size.
317
- Two settings in `browser` handle this, both take module names or file paths (see browserify's `b.ignore(file)` and
318
- `b.exclude(file)`):
319
-
320
- ```json
321
- {
322
- "browser": {
323
- // Resolves to an empty object ({}) in the bundle instead of the real module. This suits a dependency which is only
324
- // reached because it is the default value of an option you always override with your own (for example a selector
325
- // engine's default DOM adapter). Anything only that module requires is left out too. Your code must never actually
326
- // use the real module, so keep overriding that option.
327
- "ignore": ["some-default-adapter"],
328
- // Left out of the bundle entirely. Requiring it at runtime throws unless something else provides it, for example a
329
- // script tag which loads it separately, so this suits a large library which the page already loads.
330
- "exclude": ["a-library-the-page-loads"]
331
- }
332
- }
333
- ```
334
-
335
- ### Configure additional browser bundles (optional)
336
-
337
- By default a project produces exactly one browser bundle, from `dist.main`/`browser.name`/`browser.ignore`/
338
- `browser.exclude` above. `browser.bundles` adds more bundles alongside it - for example a render-only variant built
339
- from a different entry point than the full bundle. Each entry only needs to specify what's actually different about
340
- that bundle; anything left out falls back to the primary bundle's own value:
341
-
342
- ```json
343
- {
344
- "browser": {
345
- "bundles": [
346
- {
347
- // Required, and must be unique among all of a project's bundles: the name for this bundle's own output file
348
- // and standalone export.
349
- "name": "render-only",
350
- // This bundle's own entry point. Falls back to dist.main when omitted.
351
- "main": "dist/renderOnly.js",
352
- // This bundle's own ignore list. Falls back to browser.ignore when omitted.
353
- "ignore": [],
354
- // This bundle's own exclude list. Falls back to browser.exclude when omitted.
355
- "exclude": []
356
- }
357
- ]
358
- }
359
- }
360
- ```
361
-
362
- For the `gulpConfig` module's own `get`/`set` functions (read or override a resolved configuration value from your
363
- own code, by the same dot-notation path a setting has in the JSON above), see the generated reference below.
364
-
365
- ### Configure including ESM files in the generated readme (optional)
366
-
367
- The readme generator (`jsdoc-to-markdown`) only recognizes `.js` files, even though it parses real ESM `import`/
368
- `export` syntax just fine once it reads one - the file extension is the only thing it filters on, not the content.
369
- `readme.fromEsm` names `.mjs` files to document anyway: each one is read, rewritten (every top-level `export const`/
370
- `export function`/`export class` becomes a plain declaration plus a trailing `module.exports = { ... }` - the same
371
- shape `jsdoc-to-markdown` already documents cleanly, since that rewrite is exactly what this project's own
372
- `gulp.config.mjs` needs it for) and written to a temp `.js` file outside your project entirely, which is cleaned up
373
- again once the readme generator has read it. Other export forms (`export default`, re-exports, `export { a, b }`
374
- lists) are left untouched in whatever way `jsdoc-to-markdown` already handles ESM - restructure a file to use named
375
- exports if you want it documented this cleanly:
376
-
377
- ```json
378
- {
379
- "readme": {
380
- "fromEsm": ["src/myEsmOnlyModule.mjs"]
381
- }
382
- }
383
- ```
384
-
385
- ### Configure copy files (optional)
386
-
387
- Copy files (a bundle, or anything else) to another location - any number of entries, each independent. Unlike
388
- every other task here, this is never run automatically as part of `gulp build` - what this copies is often the
389
- live, publicly-reachable version of something, so publishing it should be a deliberate step your own script
390
- opts into, not a side effect of a routine local build.
391
-
392
- Add the following to the exports in your `build-tools.config.json`:
393
-
394
- ```json
395
- {
396
- "copyFiles": [
397
- {
398
- // The glob pattern(s) of files to copy
399
- "from": "browser/**/*.js",
400
- // The directory to copy them into
401
- "to": "../my-other-project/vendor",
402
- // Optional - preserves this glob's own subdirectory structure in the destination, instead of flattening it
403
- "base": "browser"
404
- }
405
- ]
406
- }
407
- ```
408
-
409
- If you also export `copyFiles` from your gulpfile you can run it on its own with `gulp copyFiles`, and can then
410
- add your own script for it, for example `"publish:bundle": "gulp copyFiles"`.
411
-
412
- ### Configure move fonts (optional)
413
-
414
- Be able to copy a source directory of fonts into the distribution path.
415
-
416
- Add the following to the exports in your `build-tools.config.json`:
417
-
418
- ```json
419
- {
420
- "fonts": {
421
- // Enable fonts process
422
- "enabled": false,
423
- // Search pattern to find your font files
424
- "from": "src/fonts/**/*",
425
- // Output directory for your font files
426
- "to": "browser/fonts"
427
- }
428
- }
429
- ```
430
-
431
- ### Configure move and minify images (optional)
432
-
433
- Be able to copy and reduce the file size of images into an output path.
434
-
435
- Add the following to the exports in your `build-tools.config.json`:
436
-
437
- ```json
438
- {
439
- "images": {
440
- // Enable image process
441
- "enabled": false,
442
- // Search pattern to find your images
443
- "from": "src/img/**/*.+(png|jpg|jpeg|gif|svg)",
444
- // The JPEG quality (0 to 100) to compress to. Left false, mozjpeg uses its own default of 75, which can
445
- // visibly band smooth gradients in photos; 85 is usually indistinguishable from the original
446
- "jpegQuality": false,
447
- // Output directory for your images files
448
- "to": "browser/img"
449
- }
450
- }
451
- ```
452
-
453
- ### Configure SASS (optional)
454
-
455
- SASS support is built-in, this enables conversion of SASS files to CSS for web projects.
456
-
457
- Add the following to the exports in your `build-tools.config.json`:
458
-
459
- ```json
460
- {
461
- "sass": {
462
- // Enable SASS process
463
- "enabled": false,
464
- // Search pattern to find your SASS files (the below would be files ending in .scss or .sass in a directory called 'sass')
465
- "from": "sass/**/*.+(scss|sass)",
466
- // Optional but nice to add (future support), add the directory where your sass files exist
467
- "path": "sass",
468
- // Output directory for your compiled css files, recommend css directory within your browser output directory
469
- "to": "browser/css"
470
- }
471
- }
472
- ```
473
-
474
- ### Configure TypeScript (optional)
475
-
476
- Create a `tsconfig.json` file in your project root with the following:
477
-
478
- ```json
479
- {
480
- "include": ["src/**/*.ts"],
481
- "exclude": ["src/**/*.test.*"],
482
- "compilerOptions": {
483
- "strict": true,
484
- "target": "es2020",
485
- "module": "commonjs",
486
- "moduleResolution": "node10",
487
- "ignoreDeprecations": "6.0",
488
- "skipLibCheck": true,
489
- "esModuleInterop": true,
490
- "declaration": true,
491
- "types": []
492
- }
493
- }
494
- ```
495
-
496
- The pattern for `"include"` should match your .ts files (and leave out the tests, which can stay `.test.js` files).
497
- The actual pattern used to compile comes from `build-tools.config.json` as the `'typescript.from'` setting.
498
- To create the ts declaration files, you must add the `"declaration": true`. The `typescript` package is an optional peer
499
- dependency, install it in your project with `npm install --save-dev typescript` (versions 5.0 up to, but not including,
500
- 7 are supported). When you write relative imports, leave the `.js` extension off (`import a from './a'`), because
501
- they stop resolving once the target is a `.ts` file. The compile only builds `.ts` files while `typescript.enabled` is
502
- on, so convert a whole library at once.
503
-
504
- Add the following to the exports in your `build-tools.config.json`:
505
-
506
- ```json
507
- {
508
- "readme": {
509
- // Location of files to use for compiling documentation into the readme.
510
- "from": "dist/**/!(*.min).js"
511
- },
512
- "typescript": {
513
- // The path the tsconfig file for running typescript or false if no ts file given.
514
- "config": "tsconfig.json",
515
- // Toggle usage of typescript parsing
516
- "enabled": true,
517
- // Pattern for finding the TypeScript files
518
- "from": "src/**/*.ts",
519
- // Directory where parsed typescript files go
520
- "to": "dist"
521
- }
522
- }
523
- ```
524
-
525
- The `js-to-markdown` only works on .js files, so we run the readme search on the built dist files. Also, we want to
526
- register the tsconfig.json we created earlier and will alter the processes to build for TypeScript.
527
-
528
- Update `babel.config.js` with the following:
529
-
530
- ```js
531
- const babelConfig = require('js-build-tools/babel.config')
532
- // This is the important line, we need to add compatibility for Jest to run tests on .ts files
533
- babelConfig.presets.push('@babel/preset-typescript')
534
- module.exports = babelConfig
535
- ```
536
-
537
- ### Configure HTML documentation (optional)
538
-
539
- `jsdoc-to-markdown` (the readme generator) only reads `.js` files, so the types in your `.ts` files (and the
540
- comments on them) never reach the readme it generates, and even for a plain JavaScript project a single
541
- markdown readme is a thinner result than a real browsable site. Instead, `docs.enabled` generates real HTML
542
- documentation straight from your source, with either engine:
543
-
544
- * **TypeDoc** (for a TypeScript project) - every folder in your source directory becomes a module of the
545
- documentation, the default export of each file (one function per file) is listed under the name of the file,
546
- and everything else a file exports (for example the types in a `types.ts`) is listed as it is. Index files,
547
- tests and declaration files are left out. A file which sits directly in the source directory, beside the
548
- folders, is a module of its own (unless it is `index` or `main`). The first comment of a folder's `index.ts`
549
- (or the header comment of such a file) describes its module. The comments on your code are the documentation,
550
- and the types come from the code itself, so `@module`, `@memberOf`, `@typedef` and the `{Type}` of `@param`
551
- are not needed. `typedoc` is an optional peer dependency (like `typescript`), install it in your project with
552
- `npm install --save-dev typedoc` (this needs a `typescript` version it supports).
553
- * **jsdoc** (for a plain JavaScript project, where TypeDoc has no real types to read) - scans your source
554
- (`.js`, `.mjs` and `.cjs` files, leaving out tests and minified `.min.js` copies) recursively with jsdoc itself, rendered with a modern theme (`clean-jsdoc-theme` by default, used instead of
555
- jsdoc's own classic default template) instead of the manual `.jsdoc.conf.js` setup described further below.
556
- `jsdoc` and whichever theme you configure are optional peer dependencies, install them with
557
- `npm install --save-dev jsdoc clean-jsdoc-theme` (or your own chosen theme package).
558
-
559
- Add the following to the exports in your `build-tools.config.json`:
560
-
561
- ```json
562
- {
563
- "docs": {
564
- // Generate the documentation from the source
565
- "enabled": true,
566
- // The directory holding the source, each folder in it becomes a module (TypeDoc) or is scanned recursively (jsdoc).
567
- // jsdoc also takes a list of directories and files, for example ["functions", "gulpfile.base.mjs"]
568
- "from": "src",
569
- // TypeDoc only: the git revision the "Defined in" source links point to. Left false, TypeDoc uses the current
570
- // commit, so every commit changes every page; a branch name such as "main" keeps them the same until the
571
- // documentation itself changes
572
- "gitRevision": false,
573
- // Generate the documentation as part of build (the default). Set it to false to only generate it when you run
574
- // the docs task yourself (see below)
575
- "inBuild": true,
576
- // The markdown file used as the front page of the documentation (a short overview of your project)
577
- "index": "MAIN.md",
578
- // 'typedoc' or 'jsdoc'. Left out (or false), it's inferred from typescript.enabled - 'typedoc' when your
579
- // project is TypeScript, 'jsdoc' when it is not - so most projects never need to set this at all. Set it
580
- // explicitly to override that inference either way.
581
- "method": false,
582
- // Only meaningful when method is (or resolves to) 'jsdoc' - the theme package to render with. TypeDoc
583
- // always keeps its own default regardless of this setting.
584
- "theme": "clean-jsdoc-theme",
585
- // The name of the documentation (TypeDoc's title, the theme's title for jsdoc), defaults to the package name
586
- "title": "",
587
- // Where the HTML is generated (the directory is cleared first)
588
- "to": "docs"
589
- }
590
- }
591
- ```
592
-
593
- While `docs.enabled` is on, `gulp build` generates the documentation instead of the readme, so your `README.md` stays
594
- hand-written (a short overview which links to the documentation). If you also export `docs` from your gulpfile you can
595
- run it on its own with `gulp docs`, and can then add the script `"docs": "gulp docs"`.
596
-
597
- To make generating the documentation a deliberate step instead, set `docs.inBuild` to `false`: `gulp build` then
598
- generates neither the documentation nor the readme, and `gulp docs` is the only thing that writes to `docs.to`. This
599
- suits a `docs.to` which points into another repository (a website, say): a build on a work-in-progress branch no
600
- longer rewrites the published documentation, which you regenerate when you release instead. For example with
601
- release-it, in `.release-it.json`:
602
-
603
- ```json
604
- {
605
- "hooks": {
606
- "after:bump": "npm run docs"
607
- }
608
- }
609
- ```
610
-
611
- ### Browser automation (optional)
612
-
613
- Unlike the rest of this file, this isn't a `build-tools.config.json`-driven feature with its own task - it's a pair
614
- of plain functions (`partials.loadPlaywright`/`partials.launchBrowser` and `partials.serveStatic`) for whatever your
615
- own script needs a real browser for: verifying a page that only works correctly in a real browser (for example one
616
- using `<script type="module">`, which no DOM-simulation library executes at all), or taking a real screenshot.
617
-
618
- `playwright` is an optional peer dependency, install it in your project with `npm install --save-dev playwright`,
619
- then fetch a real browser binary once per machine (not per project) with `npx playwright install chromium` - if
620
- that fails with "Playwright does not support chromium on <your distro>", your OS is too old for the current
621
- release; either upgrade it or pin an older `playwright` version known to still support it (confirmed: `1.62.1`
622
- is the newest release that still installs and runs real headless Chromium on Ubuntu 20.04).
623
-
624
- ```js
625
- const { launchBrowser, serveStatic } = require('js-build-tools').partials
626
-
627
- const { server, url } = await serveStatic('browser') // serves ./browser/ over a real local HTTP server
628
- const browser = await launchBrowser()
629
- const page = await browser.newPage()
630
- await page.goto(`${url}/index.html`)
631
- await page.screenshot({ path: 'homepage.png' }) // a real screenshot, to actually look at
632
- await browser.close()
633
- server.close()
634
- ```
635
-
636
- `serveStatic` exists because a page loaded directly from a `file://` path resolves any root-relative asset path
637
- (`/browser/...`) against the filesystem root instead of the page's own directory - serving it over real HTTP avoids
638
- that entirely, and is also the right fix for the exact same problem in a jsdom-based test.
639
-
640
- ### Configure lint rule overrides (optional)
641
-
642
- `sourceLint` lints your real source directly (not the compiled dist/browser output) with
643
- [neostandard](https://github.com/neostandard/neostandard). Occasionally a rule is wrong for your project
644
- specifically, rather than something to fix in your code - for example a test which deliberately contains a string
645
- of literal `${...}` text (simulating another module's real source, not a mistaken non-template string), which
646
- trips neostandard's `no-template-curly-in-string` rule as a false positive. `lint.rules` layers ESLint rule
647
- overrides on top of neostandard's own rules, scoped to the same files neostandard itself lints:
648
-
649
- ```json
650
- {
651
- "lint": {
652
- // ESLint rule overrides, keyed and valued exactly as ESLint's own "rules" object.
653
- "rules": {
654
- "no-template-curly-in-string": "off"
655
- }
656
- }
657
- }
658
- ```
659
-
660
- Empty by default, so a project that never sets this gets exactly neostandard's own rules, unchanged. Prefer fixing
661
- the actual code (or, for one specific line, an `eslint-disable-next-line` comment) over this when the finding is
662
- real - reach for `lint.rules` only when the rule itself doesn't fit your project.
663
-
664
- ### Configure Scripts
665
-
666
- In your `package.json` file, add the following scripts:
667
-
668
- ```json
669
- {
670
- "scripts": {
671
- "build": "gulp build",
672
- "dev": "gulp",
673
- "docs": "gulp docs",
674
- "publish:bundle": "gulp copyFiles",
675
- "readme": "gulp readme",
676
- "sass": "gulp sass",
677
- "test": "gulp testFull",
678
- "test:quick": "gulp testQuick",
679
- "watch": "gulp watchFull",
680
- "watch:test": "gulp watchTest"
681
- }
682
- }
683
- ```
684
-
685
- ## Usage
686
-
687
- Run any of the above commands with `gulp` or `npm run`.
688
-
1
+ # [js-build-tools](https://www.npmjs.com/package/js-build-tools)
2
+
3
+ Centralize the build process for Node.js, JS and TypeScript projects into a single tool suite.
4
+
5
+ ### Goals
6
+
7
+ Using this tool suite, you can:
8
+
9
+ * Parse TypeScript into JS distribution files
10
+ * Create formatted distribution files to be used in a node / commonjs environment.
11
+ * Bundle your distribution files to be used in a browser environment.
12
+ * Run tests and watch for changes.
13
+ * Generate jsdoc readme files.
14
+ * Generate real HTML documentation straight from your source - TypeDoc for a TypeScript project (a module for
15
+ each of your folders), or jsdoc with a modern theme for a plain JavaScript one.
16
+ * Copy files (a bundle, or anything else) to another location, on demand.
17
+
18
+ ## Installation
19
+
20
+ In your project's root directory, run: `npm install --save-dev gulp js-build-tools`
21
+ (or `yarn add --dev gulp js-build-tools` if you use Yarn).
22
+
23
+ It is recommended to install gulp with the `-g` flag, so that you can run it with `gulp` instead
24
+ of `node_modules/.bin/gulp`.
25
+
26
+ ## Configuration
27
+
28
+ In your project's root directory, create a `build-tools.config.json` file. This can contain any of the following (values
29
+ provided are the defaults):
30
+
31
+ ```json
32
+ {
33
+ "browser": {
34
+ // 'true' to generate browser bundled files; 'false' for node environment only
35
+ "enabled": true,
36
+ // The name to use for the browser-bundled output file (.js will be appended).
37
+ "name": "my-package",
38
+ // The search pattern used for retrieving compiled distribution files.
39
+ "from": "dist/**/*.js",
40
+ // Module names or file paths which resolve to an empty object ({}) in the bundle instead of their real contents.
41
+ "ignore": [],
42
+ // Module names or file paths left out of the bundle entirely (requiring one at runtime throws, unless something
43
+ // else provides it, for example a script tag which loads it separately).
44
+ "exclude": [],
45
+ // Additional bundles to produce alongside the primary one above (see 'Configure additional browser bundles').
46
+ "bundles": [],
47
+ // The output directory for browser-bundled files.
48
+ "to": "browser"
49
+ },
50
+ // The paths for directories to delete before build.
51
+ "cleanPaths": [
52
+ "dist",
53
+ "browser"
54
+ ],
55
+ "dist": {
56
+ // Name of the entry the distribution file.
57
+ "main": "dist/main",
58
+ // The search pattern used for gathering source files for distribution.
59
+ "from": "src/**/!(*.test).js",
60
+ // The output directory for the distribution files.
61
+ "to": "dist"
62
+ },
63
+ "docs": {
64
+ // Toggle generating the HTML documentation from the TypeScript source (see 'Configure TypeScript documentation').
65
+ // When on, the build does this instead of generating the readme from the jsdoc comments.
66
+ "enabled": false,
67
+ // The directory holding the TypeScript source, each folder in it becomes a module of the documentation.
68
+ "from": "src",
69
+ // The markdown file used as the front page of the documentation.
70
+ "index": "MAIN.md",
71
+ // How much TypeDoc reports: Verbose, Info, Warn, Error or None.
72
+ "logLevel": "Warn",
73
+ // The name of the documentation, defaults to the name in your package.json.
74
+ "title": "",
75
+ // The directory to generate the documentation in (it is cleared first).
76
+ "to": "docs",
77
+ // The tsconfig file to read the source with, false to use the one of 'typescript.config'.
78
+ "tsconfig": false
79
+ },
80
+ "fonts": {
81
+ // Toggle copy directory of fonts on
82
+ "enabled": false,
83
+ // Path to search for fonts
84
+ "from": "src/fonts/**/*",
85
+ // Path to output fonts
86
+ "to": "browser/fonts"
87
+ },
88
+ "images": {
89
+ // Where optimized images are cached between runs (an unchanged image isn't optimized again)
90
+ "cacheDir": "node_modules/.cache/js-build-tools/images",
91
+ // Toggle image minify and copy process
92
+ "enabled": false,
93
+ // Path to search for images
94
+ "from": "src/img/**/*.+(png|jpg|jpeg|gif|svg)",
95
+ // The JPEG quality (0 to 100) to compress to, false keeps mozjpeg's own default (75)
96
+ "jpegQuality": false,
97
+ // Path to output images
98
+ "to": "browser/img"
99
+ },
100
+ "readme": {
101
+ // The file which will be pre-fixed to your README.md output.
102
+ "template": "MAIN.md",
103
+ // Options for formatting the output readme.
104
+ "options": "utf8",
105
+ // The name of the output documentation markdown file.
106
+ "file": "README.md",
107
+ // Location of files to use for compiling documentation into the readme.
108
+ "from": [
109
+ "src/**/!(*.test).js"
110
+ ],
111
+ // Additional .mjs files to document alongside 'from' (see 'Configure including ESM files in the generated
112
+ // readme'). Empty by default: a project that never sets this gets exactly the readme it always did.
113
+ "fromEsm": [],
114
+ // The directory to output the readme file in.
115
+ "to": "./"
116
+ },
117
+ // Base directory of the project.
118
+ "rootPath": "./",
119
+ "sass": {
120
+ // Toggle SASS to CSS process on.
121
+ "enabled": false,
122
+ // The pattern for finding all sass files.
123
+ "from": "sass/**/*.+(scss|sass)",
124
+ // The directory were sass files will be stored.
125
+ "path": "sass",
126
+ // The destination path for where generated CSS (from SASS files) should go.
127
+ "to": "browser/css"
128
+ },
129
+ // The directory where your source files are stored (the files you manually created).
130
+ "srcPath": "src",
131
+ "test": {
132
+ // Additional flags for programmatically running Jest Cli.
133
+ "options": null,
134
+ // The directory where Jest test files are stored.
135
+ // By default, stored as *.test.js adjacent to the files they are testing.
136
+ "path": [
137
+ "src"
138
+ ],
139
+ // The search pattern for watching files for changes.
140
+ "watch": "src/**/*.js"
141
+ },
142
+ "typescript": {
143
+ // The path the tsconfig file for running typescript or false if no ts file given.
144
+ "config": false,
145
+ // Toggle usage of typescript parsing.
146
+ "enabled": false,
147
+ // Pattern for finding the TypeScript files.
148
+ "from": "src/**/*.ts",
149
+ // Directory where parsed typescript files go.
150
+ "to": "dist"
151
+ }
152
+ }
153
+ ```
154
+
155
+ ### Create your local gulpfile.js
156
+
157
+ In your project's root directory, create a `gulpfile.js` file, in here you can require any of the functions you need.
158
+ For example:
159
+
160
+ #### Common JS
161
+
162
+ ```js
163
+ // Your local gulpfile.js
164
+ const {
165
+ build,
166
+ defaultCmd,
167
+ docs,
168
+ partials,
169
+ readme,
170
+ sass,
171
+ testFull,
172
+ testQuick,
173
+ typescript,
174
+ watchFull,
175
+ watchTest
176
+ } = require('js-build-tools/gulpfile.base.js')
177
+
178
+ // Everything you export will be created as a gulp task.
179
+ // You can build your own tasks here as well by using some of the functions `js-build-tools/functions`.
180
+ // You can list your available tasks by running `gulp --tasks`.
181
+ exports.build = build
182
+ exports.default = defaultCmd
183
+ exports.docs = docs
184
+ exports.readme = readme
185
+ exports.sass = sass
186
+ exports.testFull = testFull
187
+ exports.testQuick = testQuick
188
+ exports.watchFull = watchFull
189
+ exports.watchTest = watchTest
190
+ ```
191
+
192
+ #### ES Module
193
+
194
+ ```js
195
+ // Your local gulpfile.mjs
196
+ // Everything you export will be created as a gulp task.
197
+ export {
198
+ build,
199
+ defaultCmd,
200
+ docs,
201
+ partials,
202
+ readme,
203
+ sass,
204
+ testFull,
205
+ testQuick,
206
+ typescript,
207
+ watchFull,
208
+ watchTest
209
+ } from 'js-build-tools/gulpfile.base.mjs'
210
+
211
+ // You can build your own tasks here as well by using some of the functions `js-build-tools/functions`.
212
+ // You can list your available tasks by running `gulp --tasks`.
213
+
214
+ ```
215
+
216
+ Verify your tasks are available by running `gulp --tasks`.
217
+
218
+ ### Configure Babel
219
+
220
+ Depending on how you wrote your test files, Jest may require some Babel configuration.
221
+ Create a `babel.config.js` file in the root directory of your project.
222
+ You can then use the recommended configuration by requiring the `babel.config.js` file into your own configuration file.
223
+ Example:
224
+
225
+ ```js
226
+ const babelConfig = require('js-build-tools/babel.config')
227
+ // You may add additional configuration here. Example: babelConfig.presets.push('@babel/preset-env')
228
+ module.exports = babelConfig
229
+ ```
230
+
231
+ ### Configure ES Modules (.mjs)
232
+
233
+ It is not recommended to use `"type": "module"` in the `package.json` to enable ES Modules.
234
+ This is because some dependencies still rely on common JS syntax (ex: babel, jest, jsdoc).
235
+ So, to use ES Modules, you can use the `.mjs` extension on your files instead.
236
+ There are different downsides to using the `.mjs` extension to consider.
237
+ The `jsdoc` generation can only read `.js` files, and the provided test runner `Jest` will need to be configured.
238
+ Update the test config as follows:
239
+
240
+ ```json
241
+ {
242
+ "dist": {
243
+ // Use .mjs files for from and main
244
+ "main": "src/main.mjs",
245
+ "from": "src/**/!(*.test).mjs",
246
+ "to": "dist"
247
+ },
248
+ "readme": {
249
+ "template": "MAIN.md",
250
+ "options": "utf8",
251
+ "file": "README.md",
252
+ "from": [
253
+ // Use the dist directory files to generate the jsdocs - dist is always .js regardless of source
254
+ // extension, since Babel compiles .mjs source down to it, so this is enough on its own. If you instead
255
+ // have a handful of standalone .mjs files that never go through the normal dist compile (for example a
256
+ // config file read directly by the build itself), see 'Configure including ESM files in the generated
257
+ // readme' for readme.fromEsm instead - a lighter option than switching your whole project's dist/test
258
+ // config over to .mjs just to document a few files.
259
+ "dist/!(*.test).js"
260
+ ],
261
+ "to": "./"
262
+ },
263
+ "test": {
264
+ "options": {
265
+ // The below helps to find the .mjs files (rather than default .js files)
266
+ "testMatch": [
267
+ "**/?(*.)+(spec|test).mjs?(x)"
268
+ ]
269
+ },
270
+ "path": "functions",
271
+ // Include watching for .mjs files
272
+ "watch": "functions/**/*.[cm]?[jt]s"
273
+ }
274
+ }
275
+ ```
276
+
277
+ There is an additional file you need to get Jest working, add a `jest.config.js` file.
278
+ While we have already added these configurations above in the "options",
279
+ there seems to be a bug where the "transform" does not work in that context. Add the following to your `jest.config.js`:
280
+
281
+ ```js
282
+ module.exports = {
283
+ // The transform will instruct jest to run the files through babel so it can interpret them
284
+ transform: {
285
+ '^.+\\.[cm]?[jt]sx?$': 'babel-jest'
286
+ }
287
+ }
288
+ ```
289
+
290
+ ### Configure HTML JS Documentation, full manual control (optional, advanced)
291
+
292
+ For most projects, `docs.enabled` with `docs.method: 'jsdoc'` (see 'Configure HTML documentation' below) is the
293
+ simpler path - no `.jsdoc.conf.js` file to maintain by hand, wired straight into `gulp build`/`gulp docs`. This
294
+ section is for when you want full, direct control over jsdoc's own config instead (a plugin or option this
295
+ project's own generated config does not expose, for example).
296
+
297
+ Create a `.jsdoc.conf.js` file and add the following:
298
+
299
+ ```js
300
+ const jsDocBase = require('js-build-tools/jsdoc.base')
301
+ /* You will get a jsdoc config object with the following:
302
+ * {
303
+ * plugins: ['plugins/markdown'],
304
+ * source: {
305
+ * include: [your configured distPath],
306
+ * includePattern: '.+\\.js(doc|x)?$',
307
+ * excludePattern: '((^|\\/|\\\\)_|.+\\.test\\..*)'
308
+ * }
309
+ * }
310
+ * You can manipulate the properties before returning in module.exports.
311
+ * This searches the defined 'distPath' for building the HTML JS Documentation
312
+ */
313
+ module.exports = jsDocBase
314
+ ```
315
+
316
+ ### Configure what the browser bundle leaves out (optional)
317
+
318
+ A dependency can be reached from your code without being needed in the browser, and bundling it can add a lot of size.
319
+ Two settings in `browser` handle this, both take module names or file paths (see browserify's `b.ignore(file)` and
320
+ `b.exclude(file)`):
321
+
322
+ ```json
323
+ {
324
+ "browser": {
325
+ // Resolves to an empty object ({}) in the bundle instead of the real module. This suits a dependency which is only
326
+ // reached because it is the default value of an option you always override with your own (for example a selector
327
+ // engine's default DOM adapter). Anything only that module requires is left out too. Your code must never actually
328
+ // use the real module, so keep overriding that option.
329
+ "ignore": ["some-default-adapter"],
330
+ // Left out of the bundle entirely. Requiring it at runtime throws unless something else provides it, for example a
331
+ // script tag which loads it separately, so this suits a large library which the page already loads.
332
+ "exclude": ["a-library-the-page-loads"]
333
+ }
334
+ }
335
+ ```
336
+
337
+ ### Configure additional browser bundles (optional)
338
+
339
+ By default a project produces exactly one browser bundle, from `dist.main`/`browser.name`/`browser.ignore`/
340
+ `browser.exclude` above. `browser.bundles` adds more bundles alongside it - for example a render-only variant built
341
+ from a different entry point than the full bundle. Each entry only needs to specify what's actually different about
342
+ that bundle; anything left out falls back to the primary bundle's own value:
343
+
344
+ ```json
345
+ {
346
+ "browser": {
347
+ "bundles": [
348
+ {
349
+ // Required, and must be unique among all of a project's bundles: the name for this bundle's own output file
350
+ // and standalone export.
351
+ "name": "render-only",
352
+ // This bundle's own entry point. Falls back to dist.main when omitted.
353
+ "main": "dist/renderOnly.js",
354
+ // This bundle's own ignore list. Falls back to browser.ignore when omitted.
355
+ "ignore": [],
356
+ // This bundle's own exclude list. Falls back to browser.exclude when omitted.
357
+ "exclude": []
358
+ }
359
+ ]
360
+ }
361
+ }
362
+ ```
363
+
364
+ For the `gulpConfig` module's own `get`/`set` functions (read or override a resolved configuration value from your
365
+ own code, by the same dot-notation path a setting has in the JSON above), see the generated reference below.
366
+
367
+ ### Configure including ESM files in the generated readme (optional)
368
+
369
+ The readme generator (`jsdoc-to-markdown`) only recognizes `.js` files, even though it parses real ESM `import`/
370
+ `export` syntax just fine once it reads one - the file extension is the only thing it filters on, not the content.
371
+ `readme.fromEsm` names `.mjs` files to document anyway: each one is read, rewritten (every top-level `export const`/
372
+ `export function`/`export class` becomes a plain declaration plus a trailing `module.exports = { ... }` - the same
373
+ shape `jsdoc-to-markdown` already documents cleanly, since that rewrite is exactly what this project's own
374
+ `gulp.config.mjs` needs it for) and written to a temp `.js` file outside your project entirely, which is cleaned up
375
+ again once the readme generator has read it. Other export forms (`export default`, re-exports, `export { a, b }`
376
+ lists) are left untouched in whatever way `jsdoc-to-markdown` already handles ESM - restructure a file to use named
377
+ exports if you want it documented this cleanly:
378
+
379
+ ```json
380
+ {
381
+ "readme": {
382
+ "fromEsm": ["src/myEsmOnlyModule.mjs"]
383
+ }
384
+ }
385
+ ```
386
+
387
+ ### Configure copy files (optional)
388
+
389
+ Copy files (a bundle, or anything else) to another location - any number of entries, each independent. Unlike
390
+ every other task here, this is never run automatically as part of `gulp build` - what this copies is often the
391
+ live, publicly-reachable version of something, so publishing it should be a deliberate step your own script
392
+ opts into, not a side effect of a routine local build.
393
+
394
+ Add the following to the exports in your `build-tools.config.json`:
395
+
396
+ ```json
397
+ {
398
+ "copyFiles": [
399
+ {
400
+ // The glob pattern(s) of files to copy
401
+ "from": "browser/**/*.js",
402
+ // The directory to copy them into
403
+ "to": "../my-other-project/vendor",
404
+ // Optional - preserves this glob's own subdirectory structure in the destination, instead of flattening it
405
+ "base": "browser"
406
+ }
407
+ ]
408
+ }
409
+ ```
410
+
411
+ If you also export `copyFiles` from your gulpfile you can run it on its own with `gulp copyFiles`, and can then
412
+ add your own script for it, for example `"publish:bundle": "gulp copyFiles"`.
413
+
414
+ ### Configure move fonts (optional)
415
+
416
+ Be able to copy a source directory of fonts into the distribution path.
417
+
418
+ Add the following to the exports in your `build-tools.config.json`:
419
+
420
+ ```json
421
+ {
422
+ "fonts": {
423
+ // Enable fonts process
424
+ "enabled": false,
425
+ // Search pattern to find your font files
426
+ "from": "src/fonts/**/*",
427
+ // Output directory for your font files
428
+ "to": "browser/fonts"
429
+ }
430
+ }
431
+ ```
432
+
433
+ ### Configure move and minify images (optional)
434
+
435
+ Be able to copy and reduce the file size of images into an output path.
436
+
437
+ Add the following to the exports in your `build-tools.config.json`:
438
+
439
+ ```json
440
+ {
441
+ "images": {
442
+ // Where optimized images are cached between runs, so an image that hasn't changed isn't optimized again. Inside
443
+ // node_modules by default, so it's never committed; delete the folder to start over
444
+ "cacheDir": "node_modules/.cache/js-build-tools/images",
445
+ // Enable image process
446
+ "enabled": false,
447
+ // Search pattern to find your images
448
+ "from": "src/img/**/*.+(png|jpg|jpeg|gif|svg)",
449
+ // The JPEG quality (0 to 100) to compress to. Left false, mozjpeg uses its own default of 75, which can
450
+ // visibly band smooth gradients in photos; 85 is usually indistinguishable from the original
451
+ "jpegQuality": false,
452
+ // Output directory for your images files
453
+ "to": "browser/img"
454
+ }
455
+ }
456
+ ```
457
+
458
+ ### Configure SASS (optional)
459
+
460
+ SASS support is built-in, this enables conversion of SASS files to CSS for web projects.
461
+
462
+ Add the following to the exports in your `build-tools.config.json`:
463
+
464
+ ```json
465
+ {
466
+ "sass": {
467
+ // Enable SASS process
468
+ "enabled": false,
469
+ // Search pattern to find your SASS files (the below would be files ending in .scss or .sass in a directory called 'sass')
470
+ "from": "sass/**/*.+(scss|sass)",
471
+ // Optional but nice to add (future support), add the directory where your sass files exist
472
+ "path": "sass",
473
+ // Output directory for your compiled css files, recommend css directory within your browser output directory
474
+ "to": "browser/css"
475
+ }
476
+ }
477
+ ```
478
+
479
+ ### Configure TypeScript (optional)
480
+
481
+ Create a `tsconfig.json` file in your project root with the following:
482
+
483
+ ```json
484
+ {
485
+ "include": ["src/**/*.ts"],
486
+ "exclude": ["src/**/*.test.*"],
487
+ "compilerOptions": {
488
+ "strict": true,
489
+ "target": "es2020",
490
+ "module": "commonjs",
491
+ "moduleResolution": "node10",
492
+ "ignoreDeprecations": "6.0",
493
+ "skipLibCheck": true,
494
+ "esModuleInterop": true,
495
+ "declaration": true,
496
+ "types": []
497
+ }
498
+ }
499
+ ```
500
+
501
+ The pattern for `"include"` should match your .ts files (and leave out the tests, which can stay `.test.js` files).
502
+ The actual pattern used to compile comes from `build-tools.config.json` as the `'typescript.from'` setting.
503
+ To create the ts declaration files, you must add the `"declaration": true`. The `typescript` package is an optional peer
504
+ dependency, install it in your project with `npm install --save-dev typescript` (versions 5.0 up to, but not including,
505
+ 7 are supported). When you write relative imports, leave the `.js` extension off (`import a from './a'`), because
506
+ they stop resolving once the target is a `.ts` file. The compile only builds `.ts` files while `typescript.enabled` is
507
+ on, so convert a whole library at once.
508
+
509
+ Add the following to the exports in your `build-tools.config.json`:
510
+
511
+ ```json
512
+ {
513
+ "readme": {
514
+ // Location of files to use for compiling documentation into the readme.
515
+ "from": "dist/**/!(*.min).js"
516
+ },
517
+ "typescript": {
518
+ // The path the tsconfig file for running typescript or false if no ts file given.
519
+ "config": "tsconfig.json",
520
+ // Toggle usage of typescript parsing
521
+ "enabled": true,
522
+ // Pattern for finding the TypeScript files
523
+ "from": "src/**/*.ts",
524
+ // Directory where parsed typescript files go
525
+ "to": "dist"
526
+ }
527
+ }
528
+ ```
529
+
530
+ The `js-to-markdown` only works on .js files, so we run the readme search on the built dist files. Also, we want to
531
+ register the tsconfig.json we created earlier and will alter the processes to build for TypeScript.
532
+
533
+ Update `babel.config.js` with the following:
534
+
535
+ ```js
536
+ const babelConfig = require('js-build-tools/babel.config')
537
+ // This is the important line, we need to add compatibility for Jest to run tests on .ts files
538
+ babelConfig.presets.push('@babel/preset-typescript')
539
+ module.exports = babelConfig
540
+ ```
541
+
542
+ ### Configure HTML documentation (optional)
543
+
544
+ `jsdoc-to-markdown` (the readme generator) only reads `.js` files, so the types in your `.ts` files (and the
545
+ comments on them) never reach the readme it generates, and even for a plain JavaScript project a single
546
+ markdown readme is a thinner result than a real browsable site. Instead, `docs.enabled` generates real HTML
547
+ documentation straight from your source, with either engine:
548
+
549
+ * **TypeDoc** (for a TypeScript project) - every folder in your source directory becomes a module of the
550
+ documentation, the default export of each file (one function per file) is listed under the name of the file,
551
+ and everything else a file exports (for example the types in a `types.ts`) is listed as it is. Index files,
552
+ tests and declaration files are left out. A file which sits directly in the source directory, beside the
553
+ folders, is a module of its own (unless it is `index` or `main`). The first comment of a folder's `index.ts`
554
+ (or the header comment of such a file) describes its module. The comments on your code are the documentation,
555
+ and the types come from the code itself, so `@module`, `@memberOf`, `@typedef` and the `{Type}` of `@param`
556
+ are not needed. `typedoc` is an optional peer dependency (like `typescript`), install it in your project with
557
+ `npm install --save-dev typedoc` (this needs a `typescript` version it supports).
558
+ * **jsdoc** (for a plain JavaScript project, where TypeDoc has no real types to read) - scans your source
559
+ (`.js`, `.mjs` and `.cjs` files, leaving out tests and minified `.min.js` copies) recursively with jsdoc itself, rendered with a modern theme (`clean-jsdoc-theme` by default, used instead of
560
+ jsdoc's own classic default template) instead of the manual `.jsdoc.conf.js` setup described further below.
561
+ `jsdoc` and whichever theme you configure are optional peer dependencies, install them with
562
+ `npm install --save-dev jsdoc clean-jsdoc-theme` (or your own chosen theme package).
563
+
564
+ Add the following to the exports in your `build-tools.config.json`:
565
+
566
+ ```json
567
+ {
568
+ "docs": {
569
+ // jsdoc with clean-jsdoc-theme 5.x only: the path the documentation is served from, such as
570
+ // "/projects/my-lib/docs/". The theme's links start at the site root, so documentation served below it needs
571
+ // this. Left false, it is served from the site root
572
+ "basePath": false,
573
+ // Generate the documentation from the source
574
+ "enabled": true,
575
+ // The directory holding the source, each folder in it becomes a module (TypeDoc) or is scanned recursively (jsdoc).
576
+ // jsdoc also takes a list of directories and files, for example ["functions", "gulpfile.base.mjs"]
577
+ "from": "src",
578
+ // TypeDoc only: the git revision the "Defined in" source links point to. Left false, TypeDoc uses the current
579
+ // commit, so every commit changes every page; a branch name such as "main" keeps them the same until the
580
+ // documentation itself changes
581
+ "gitRevision": false,
582
+ // Generate the documentation as part of build (the default). Set it to false to only generate it when you run
583
+ // the docs task yourself (see below)
584
+ "inBuild": true,
585
+ // The markdown file used as the front page of the documentation (a short overview of your project)
586
+ "index": "MAIN.md",
587
+ // 'typedoc' or 'jsdoc'. Left out (or false), it's inferred from typescript.enabled - 'typedoc' when your
588
+ // project is TypeScript, 'jsdoc' when it is not - so most projects never need to set this at all. Set it
589
+ // explicitly to override that inference either way.
590
+ "method": false,
591
+ // Only meaningful when method is (or resolves to) 'jsdoc' - the theme package to render with. TypeDoc
592
+ // always keeps its own default regardless of this setting.
593
+ "theme": "clean-jsdoc-theme",
594
+ // The name of the documentation (TypeDoc's title, the theme's title for jsdoc), defaults to the package name
595
+ "title": "",
596
+ // Where the HTML is generated (the directory is cleared first)
597
+ "to": "docs"
598
+ }
599
+ }
600
+ ```
601
+
602
+ While `docs.enabled` is on, `gulp build` generates the documentation instead of the readme, so your `README.md` stays
603
+ hand-written (a short overview which links to the documentation). If you also export `docs` from your gulpfile you can
604
+ run it on its own with `gulp docs`, and can then add the script `"docs": "gulp docs"`.
605
+
606
+ To make generating the documentation a deliberate step instead, set `docs.inBuild` to `false`: `gulp build` then
607
+ generates neither the documentation nor the readme, and `gulp docs` is the only thing that writes to `docs.to`. This
608
+ suits a `docs.to` which points into another repository (a website, say): a build on a work-in-progress branch no
609
+ longer rewrites the published documentation, which you regenerate when you release instead. For example with
610
+ release-it, in `.release-it.json`:
611
+
612
+ ```json
613
+ {
614
+ "hooks": {
615
+ "after:bump": "npm run docs"
616
+ }
617
+ }
618
+ ```
619
+
620
+ ### Browser automation (optional)
621
+
622
+ Unlike the rest of this file, this isn't a `build-tools.config.json`-driven feature with its own task - it's a pair
623
+ of plain functions (`partials.loadPlaywright`/`partials.launchBrowser` and `partials.serveStatic`) for whatever your
624
+ own script needs a real browser for: verifying a page that only works correctly in a real browser (for example one
625
+ using `<script type="module">`, which no DOM-simulation library executes at all), or taking a real screenshot.
626
+
627
+ `playwright` is an optional peer dependency, install it in your project with `npm install --save-dev playwright`,
628
+ then fetch a real browser binary once per machine (not per project) with `npx playwright install chromium` - if
629
+ that fails with "Playwright does not support chromium on <your distro>", your OS is too old for the current
630
+ release; either upgrade it or pin an older `playwright` version known to still support it (confirmed: `1.62.1`
631
+ is the newest release that still installs and runs real headless Chromium on Ubuntu 20.04).
632
+
633
+ ```js
634
+ const { launchBrowser, serveStatic } = require('js-build-tools').partials
635
+
636
+ const { server, url } = await serveStatic('browser') // serves ./browser/ over a real local HTTP server
637
+ const browser = await launchBrowser()
638
+ const page = await browser.newPage()
639
+ await page.goto(`${url}/index.html`)
640
+ await page.screenshot({ path: 'homepage.png' }) // a real screenshot, to actually look at
641
+ await browser.close()
642
+ server.close()
643
+ ```
644
+
645
+ `serveStatic` exists because a page loaded directly from a `file://` path resolves any root-relative asset path
646
+ (`/browser/...`) against the filesystem root instead of the page's own directory - serving it over real HTTP avoids
647
+ that entirely, and is also the right fix for the exact same problem in a jsdom-based test.
648
+
649
+ ### Configure lint rule overrides (optional)
650
+
651
+ `sourceLint` lints your real source directly (not the compiled dist/browser output) with
652
+ [neostandard](https://github.com/neostandard/neostandard). Occasionally a rule is wrong for your project
653
+ specifically, rather than something to fix in your code - for example a test which deliberately contains a string
654
+ of literal `${...}` text (simulating another module's real source, not a mistaken non-template string), which
655
+ trips neostandard's `no-template-curly-in-string` rule as a false positive. `lint.rules` layers ESLint rule
656
+ overrides on top of neostandard's own rules, scoped to the same files neostandard itself lints:
657
+
658
+ ```json
659
+ {
660
+ "lint": {
661
+ // ESLint rule overrides, keyed and valued exactly as ESLint's own "rules" object.
662
+ "rules": {
663
+ "no-template-curly-in-string": "off"
664
+ }
665
+ }
666
+ }
667
+ ```
668
+
669
+ Empty by default, so a project that never sets this gets exactly neostandard's own rules, unchanged. Prefer fixing
670
+ the actual code (or, for one specific line, an `eslint-disable-next-line` comment) over this when the finding is
671
+ real - reach for `lint.rules` only when the rule itself doesn't fit your project.
672
+
673
+ ### Configure Scripts
674
+
675
+ In your `package.json` file, add the following scripts:
676
+
677
+ ```json
678
+ {
679
+ "scripts": {
680
+ "build": "gulp build",
681
+ "dev": "gulp",
682
+ "docs": "gulp docs",
683
+ "publish:bundle": "gulp copyFiles",
684
+ "readme": "gulp readme",
685
+ "sass": "gulp sass",
686
+ "test": "gulp testFull",
687
+ "test:quick": "gulp testQuick",
688
+ "watch": "gulp watchFull",
689
+ "watch:test": "gulp watchTest"
690
+ }
691
+ }
692
+ ```
693
+
694
+ ## Usage
695
+
696
+ Run any of the above commands with `gulp` or `npm run`.
697
+
689
698
  ## Modules
690
699
 
691
700
  <dl>
@@ -736,13 +745,16 @@ Simplified typescript task using tsFor.
736
745
  <a name="module_js-build-tools.typeDocs"></a>
737
746
 
738
747
  ### js-build-tools.typeDocs ⇒ <code>function</code>
739
- Generate the HTML documentation of a TypeScript project from its source, with the modules mirroring the source
748
+ Generate the HTML documentation of a TypeScript project from its source, with the modules mirroring the source
749
+ folders. Turn it on with docs.enabled, see [typeDocsFor](#module_partials.typeDocsFor).
740
750
 
741
751
  **Kind**: static constant of [<code>js-build-tools</code>](#module_js-build-tools)
742
752
  <a name="module_js-build-tools.jsdocDocs"></a>
743
753
 
744
754
  ### js-build-tools.jsdocDocs ⇒ <code>function</code>
745
- Generate the HTML documentation of a plain-JavaScript project from its source, with a modern jsdoc theme
755
+ Generate the HTML documentation of a plain-JavaScript project from its source, with a modern jsdoc theme
756
+ instead of jsdoc's own classic default. Turn it on with docs.enabled and docs.method: 'jsdoc' (the default
757
+ when typescript.enabled is off), see [module:partials.jsdocDocsFor](module:partials.jsdocDocsFor).
746
758
 
747
759
  **Kind**: static constant of [<code>js-build-tools</code>](#module_js-build-tools)
748
760
  <a name="module_js-build-tools.compileReadme"></a>
@@ -766,25 +778,33 @@ Watch for changes and run the distribution for the changed files, then bundle an
766
778
  <a name="module_js-build-tools.testQuick"></a>
767
779
 
768
780
  ### js-build-tools.testQuick() ⇒ <code>Promise.&lt;\*&gt;</code>
769
- Run the Jest tests for files which have been modified (based on git status).
781
+ Run the Jest tests for files which have been modified (based on git status).
782
+ Configure where tests are located by using 'testPath'.
770
783
 
771
784
  **Kind**: static method of [<code>js-build-tools</code>](#module_js-build-tools)
772
785
  <a name="module_js-build-tools.testFull"></a>
773
786
 
774
787
  ### js-build-tools.testFull() ⇒ <code>Promise.&lt;\*&gt;</code>
775
- Run all tests with jest.
788
+ Run all tests with jest.
789
+ Configure where tests are located by using 'testPath'.
776
790
 
777
791
  **Kind**: static method of [<code>js-build-tools</code>](#module_js-build-tools)
778
792
  <a name="module_js-build-tools.sourceLint"></a>
779
793
 
780
794
  ### js-build-tools.sourceLint() ⇒ <code>\*</code>
781
- Applies neostandard linting (js-build-tools' chosen style) to the real, hand-written source - not the compiled
795
+ Applies neostandard linting (js-build-tools' chosen style) to the real, hand-written source - not the compiled
796
+ dist/browser output, which is generated and so was never going to pass a hand-authored-code style check (every
797
+ compiler/bundler emits its own boilerplate - import aliasing, interop headers - that only looks like a style
798
+ violation). Includes test files: there is no reason to hold tests to a lower style bar than the rest of the
799
+ source. When typescript.enabled, the real TypeScript source is linted too, with type-aware rules. Runs as part of
800
+ `build`, where remaining errors are reported but never fail it.
782
801
 
783
802
  **Kind**: static method of [<code>js-build-tools</code>](#module_js-build-tools)
784
803
  <a name="module_js-build-tools.lint"></a>
785
804
 
786
805
  ### js-build-tools.lint() ⇒ <code>\*</code>
787
- The standalone lint command (`gulp lint`, or `npm run lint`): the same linting and fixing as sourceLint, but it
806
+ The standalone lint command (`gulp lint`, or `npm run lint`): the same linting and fixing as sourceLint, but it
807
+ fails (exits non-zero) when any errors remain that neostandard could not fix automatically.
788
808
 
789
809
  **Kind**: static method of [<code>js-build-tools</code>](#module_js-build-tools)
790
810
  <a name="module_js-build-tools.images"></a>
@@ -796,7 +816,9 @@ Move and optimize the images into the browser folder using configured settings.
796
816
  <a name="module_js-build-tools.docs"></a>
797
817
 
798
818
  ### js-build-tools.docs([done]) ⇒ <code>\*</code>
799
- Generate the HTML documentation with whichever engine docs.method (or its typescript.enabled-based default)
819
+ Generate the HTML documentation with whichever engine docs.method (or its typescript.enabled-based default)
820
+ resolves to - see [resolveDocsMethod](#module_partials.resolveDocsMethod). The standalone counterpart to build's own
821
+ internal branching, for running `gulp docs` directly instead of as part of a full build.
800
822
 
801
823
  **Kind**: static method of [<code>js-build-tools</code>](#module_js-build-tools)
802
824
 
@@ -836,25 +858,58 @@ Move the font files into the browser directory.
836
858
  <a name="module_js-build-tools.copyFiles"></a>
837
859
 
838
860
  ### js-build-tools.copyFiles() ⇒ <code>Promise.&lt;void&gt;</code>
839
- Copy files from one place to another - any number of { from, to, base? } entries, configured via copyFiles.
861
+ Copy files from one place to another - any number of { from, to, base? } entries, configured via copyFiles.
862
+ A project with no copyFiles entries gets a task that does nothing. Meant to be run explicitly (its own script,
863
+ e.g. `gulp copyFiles`), not folded into the default build - a bundle (or any other file this copies) is often
864
+ the live, publicly-reachable version of something, so publishing it elsewhere should be a deliberate step, not
865
+ a side effect of every routine local build.
866
+
867
+ Reuses copyFor (already shared with copyFonts) rather than a fresh src()/dest() pair - that keeps its existing
868
+ encoding: false fix (Gulp 5's default utf8 handling corrupts binary files such as fonts or a minified bundle)
869
+ instead of silently losing it in a parallel implementation.
870
+
871
+ Each entry runs as its own independent copyFor(), awaited via Promise.all rather than merged into one combined
872
+ stream (mergeStream, the pattern bundle.mjs uses) - that pattern assumes every merged stream ends up at the
873
+ same shared destination; here, each entry can have a genuinely different one, and merging streams that each
874
+ already terminate at their own separate dest() hit a real "write after end" error in practice.
840
875
 
841
876
  **Kind**: static method of [<code>js-build-tools</code>](#module_js-build-tools)
842
877
  <a name="module_js-build-tools.bundleMinify"></a>
843
878
 
844
879
  ### js-build-tools.bundleMinify() ⇒ <code>\*</code>
845
- Creates the minified file for every bundle (the primary bundle, plus any additional ones from
880
+ Creates the minified file for every bundle (the primary bundle, plus any additional ones from
881
+ browser.bundles). The minify step itself never varies per bundle, so this is one shared
882
+ src()/dest() pipeline (inside minifyFor) fed every bundle's filename at once, rather than one
883
+ pipeline per bundle - gulp's src() accepts an array of paths natively.
846
884
 
847
885
  **Kind**: static method of [<code>js-build-tools</code>](#module_js-build-tools)
848
886
  <a name="module_js-build-tools.bundle"></a>
849
887
 
850
888
  ### js-build-tools.bundle() ⇒ <code>stream.Stream</code>
851
- Starting at each bundle's own entry point (dist.main for the primary bundle, or its own
889
+ Starting at each bundle's own entry point (dist.main for the primary bundle, or its own
890
+ override from browser.bundles), bundle all the reachable files into a single file per bundle and
891
+ store them in the specified output directory. A project with no browser.bundles entries gets
892
+ exactly the one bundle it always did; each additional entry produces its own separate bundle
893
+ (for example, a render-only variant built from a different entry point than the full bundle).
894
+
895
+ A bundle's name does double duty: it names the output file (name.js) and, via browserify's
896
+ `standalone` option, is also the name its exports are exposed under - as a global when loaded
897
+ with a bare `<script>` tag, or as the module when required via CommonJS/AMD. Without this, a
898
+ bundle built from a real entry point (one that actually exports something) builds successfully
899
+ but exposes nothing a consumer can reach.
900
+
901
+ Two escape hatches from browser.config.json keep an unwanted dependency (or a dependency's dependency) out of the
902
+ bundle: 'ignore' replaces it with an empty object (safe when your code never actually calls into it - for example
903
+ a library's default option value you always override with your own) and 'exclude' leaves it out entirely (your
904
+ code must not require it, or provide it another way, such as a separate script tag).
852
905
 
853
906
  **Kind**: static method of [<code>js-build-tools</code>](#module_js-build-tools)
854
907
  <a name="module_js-build-tools.build"></a>
855
908
 
856
909
  ### js-build-tools.build() ⇒ <code>stream.Stream</code>
857
- Runs several processes to build and validate the project.
910
+ Runs several processes to build and validate the project.
911
+ Cleans and lints the source, distributes and minifies, bundles and minifies, creates the readme, then runs the
912
+ tests.
858
913
 
859
914
  **Kind**: static method of [<code>js-build-tools</code>](#module_js-build-tools)
860
915
  <a name="module_gulpConfig"></a>
@@ -872,11 +927,12 @@ Modify these configurations to match your project specifications.
872
927
  * _inner_
873
928
  * [~ArrayableSetting](#module_gulpConfig..ArrayableSetting) : <code>Array.&lt;string&gt;</code> \| <code>string</code>
874
929
  * [~BooleanSetting](#module_gulpConfig..BooleanSetting) : <code>boolean</code>
930
+ * [~FlagNumberSetting](#module_gulpConfig..FlagNumberSetting) : <code>false</code> \| <code>number</code>
875
931
  * [~FlagStringSetting](#module_gulpConfig..FlagStringSetting) : <code>false</code> \| <code>StringSetting</code>
876
932
  * [~FlagsSetting](#module_gulpConfig..FlagsSetting) : <code>Object.&lt;string, BooleanSetting&gt;</code>
877
933
  * [~JestTestFlags](#module_gulpConfig..JestTestFlags) : <code>FlagsSetting</code>
878
934
  * [~StringSetting](#module_gulpConfig..StringSetting) : <code>string</code>
879
- * [~Setting](#module_gulpConfig..Setting) : <code>ArrayableSetting</code> \| <code>BooleanSetting</code> \| <code>FlagsSetting</code> \| <code>StringSetting</code>
935
+ * [~Setting](#module_gulpConfig..Setting) : <code>ArrayableSetting</code> \| <code>BooleanSetting</code> \| <code>FlagNumberSetting</code> \| <code>FlagsSetting</code> \| <code>StringSetting</code>
880
936
  * [~CopyFilesEntry](#module_gulpConfig..CopyFilesEntry) : <code>Object</code>
881
937
  * [~BrowserConfig](#module_gulpConfig..BrowserConfig) : <code>Object.&lt;string, Setting&gt;</code>
882
938
  * [~AdditionalBundleConfig](#module_gulpConfig..AdditionalBundleConfig) : <code>Object.&lt;string, Setting&gt;</code>
@@ -926,6 +982,12 @@ A setting that may be an array of strings or a string only.
926
982
  ### gulpConfig~BooleanSetting : <code>boolean</code>
927
983
  A setting that may be true or false.
928
984
 
985
+ **Kind**: inner typedef of [<code>gulpConfig</code>](#module_gulpConfig)
986
+ <a name="module_gulpConfig..FlagNumberSetting"></a>
987
+
988
+ ### gulpConfig~FlagNumberSetting : <code>false</code> \| <code>number</code>
989
+ A setting that may be flag 'false' or provide a number
990
+
929
991
  **Kind**: inner typedef of [<code>gulpConfig</code>](#module_gulpConfig)
930
992
  <a name="module_gulpConfig..FlagStringSetting"></a>
931
993
 
@@ -967,7 +1029,7 @@ A setting that may only be a string.
967
1029
  **Kind**: inner typedef of [<code>gulpConfig</code>](#module_gulpConfig)
968
1030
  <a name="module_gulpConfig..Setting"></a>
969
1031
 
970
- ### gulpConfig~Setting : <code>ArrayableSetting</code> \| <code>BooleanSetting</code> \| <code>FlagsSetting</code> \| <code>StringSetting</code>
1032
+ ### gulpConfig~Setting : <code>ArrayableSetting</code> \| <code>BooleanSetting</code> \| <code>FlagNumberSetting</code> \| <code>FlagsSetting</code> \| <code>StringSetting</code>
971
1033
  Any single configuration option is a Setting.
972
1034
 
973
1035
  **Kind**: inner typedef of [<code>gulpConfig</code>](#module_gulpConfig)
@@ -1057,8 +1119,10 @@ Configurations to minify and copy the images.
1057
1119
 
1058
1120
  | Name | Type | Description |
1059
1121
  | --- | --- | --- |
1122
+ | cacheDir | <code>StringSetting</code> | Where optimized images are cached between runs, so an image that hasn't changed isn't optimized again. An upgrade of imagemin (or its plugins) or other settings starts new results. Inside node_modules by default, so it's never committed; old entries aren't pruned, so delete it now and then to start over. |
1060
1123
  | enabled | <code>BooleanSetting</code> | Toggle image minify and copy process. |
1061
1124
  | from | <code>StringSetting</code> | Path to search for images. |
1125
+ | jpegQuality | <code>FlagNumberSetting</code> | The JPEG quality (0 to 100) mozjpeg compresses to. False (the default) keeps mozjpeg's own default, 75. Raise it (85 is usually indistinguishable from the original) when 75 visibly bands smooth gradients. |
1062
1126
  | to | <code>StringSetting</code> | Path to output images. |
1063
1127
 
1064
1128
  <a name="module_gulpConfig..LintConfig"></a>
@@ -1101,8 +1165,11 @@ TypeScript types) or jsdoc (a modern theme over jsdoc's own classic default) - s
1101
1165
 
1102
1166
  | Name | Type | Description |
1103
1167
  | --- | --- | --- |
1168
+ | basePath | <code>FlagStringSetting</code> | The path the documentation is served from, such as '/projects/my-lib/docs/' (jsdoc with clean-jsdoc-theme 5.x only). The theme's links start at the site root, so documentation served below it needs this. False (the default) serves it from the site root. |
1104
1169
  | enabled | <code>BooleanSetting</code> | Toggle generating the documentation from the source. When it is on the build does this instead of generating the readme from the jsdoc comments of the compiled files. |
1105
1170
  | from | <code>ArrayableSetting</code> | The directory holding the source, each folder in it becomes a module (TypeDoc) or is scanned recursively (jsdoc). jsdoc also takes a list of directories and files. |
1171
+ | gitRevision | <code>FlagStringSetting</code> | The git revision TypeDoc's "Defined in" source links point to (TypeDoc only). False (the default) is TypeDoc's own: the current commit, which changes every page on every commit. A branch name such as 'main' keeps the pages unchanged until the documentation itself changes; '{branch}' is the branch being built. |
1172
+ | inBuild | <code>BooleanSetting</code> | Generate the documentation as part of build (the default). Turn it off to only generate it when you run the docs task yourself (gulp docs), for example when docs.to points into another repository and you only want to publish the documentation of a release. |
1106
1173
  | index | <code>StringSetting</code> | The markdown file used as the front page of the documentation. |
1107
1174
  | logLevel | <code>StringSetting</code> | How much TypeDoc reports: Verbose, Info, Warn, Error or None. Not used by jsdoc. |
1108
1175
  | method | <code>FlagStringSetting</code> | 'typedoc' or 'jsdoc'. False (the default) infers it from typescript.enabled - 'typedoc' when on, 'jsdoc' when off - so an existing TypeScript project's config needs no change to keep working exactly as it already does; set this explicitly to override that inference either way. |