js-build-tools 6.6.0 → 6.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/LICENSE +674 -674
  2. package/README.md +762 -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/clean.js +5 -5
  20. package/dist/partials/copyFor.js +9 -9
  21. package/dist/partials/distFor.js +6 -6
  22. package/dist/partials/distForSrc.js +5 -5
  23. package/dist/partials/distSeries.js +7 -7
  24. package/dist/partials/imagesFor.js +93 -93
  25. package/dist/partials/jsdocDocsFor.js +46 -46
  26. package/dist/partials/lintSource.js +51 -51
  27. package/dist/partials/loadPeer.js +99 -99
  28. package/dist/partials/loadPlaywright.js +14 -14
  29. package/dist/partials/minifyFor.js +20 -20
  30. package/dist/partials/neostandardLint.js +175 -175
  31. package/dist/partials/readmeTemplate.js +4 -4
  32. package/dist/partials/removeDirectory.js +11 -11
  33. package/dist/partials/resolveDocsMethod.js +6 -6
  34. package/dist/partials/runOnChange.js +31 -31
  35. package/dist/partials/sassFor.js +6 -6
  36. package/dist/partials/serveStatic.js +9 -9
  37. package/dist/partials/tsFor.js +32 -32
  38. package/dist/partials/typeDocsFor.js +264 -264
  39. package/dist/partials.js +176 -176
  40. package/dist/sourceLint.js +18 -18
  41. package/dist/test-helpers/isolateGulpCache.js +24 -24
  42. package/dist/test-helpers/setUp.js +4 -4
  43. package/dist/testFull.js +5 -5
  44. package/dist/testQuick.js +5 -5
  45. package/dist/typeDocs.js +5 -5
  46. package/dist/typeScript.js +4 -4
  47. package/dist/utilities/convertMjsFilesForDocs.js +12 -12
  48. package/dist/utilities/dotGet.js +54 -54
  49. package/dist/utilities/dotNotate.js +79 -79
  50. package/dist/utilities/dotSet.js +45 -45
  51. package/dist/utilities/esmNamedExportsToCjs.js +15 -15
  52. package/dist/utilities/getBundleConfigs.js +9 -9
  53. package/dist/utilities/isObject.js +6 -6
  54. package/dist/utilities/strAfter.js +7 -7
  55. package/dist/utilities/strBefore.js +7 -7
  56. package/dist/watchFull.js +4 -4
  57. package/dist/watchTest.js +4 -4
  58. package/functions/build.mjs +72 -72
  59. package/functions/build.test.mjs +763 -759
  60. package/functions/bundle.mjs +44 -44
  61. package/functions/bundle.test.mjs +219 -219
  62. package/functions/bundleMinify.mjs +16 -16
  63. package/functions/bundleMinify.test.mjs +37 -37
  64. package/functions/compileReadme.mjs +9 -9
  65. package/functions/compileReadme.test.mjs +18 -18
  66. package/functions/copyFiles.mjs +32 -32
  67. package/functions/copyFiles.test.mjs +78 -78
  68. package/functions/copyFonts.mjs +9 -9
  69. package/functions/copyFonts.test.mjs +32 -32
  70. package/functions/default.mjs +12 -12
  71. package/functions/default.test.mjs +33 -33
  72. package/functions/dist.mjs +8 -8
  73. package/functions/dist.test.mjs +44 -44
  74. package/functions/distMinify.mjs +9 -9
  75. package/functions/distMinify.test.mjs +15 -15
  76. package/functions/docs.mjs +13 -13
  77. package/functions/docs.test.mjs +45 -45
  78. package/functions/gulpConfigEntries.test.mjs +23 -23
  79. package/functions/images.mjs +8 -8
  80. package/functions/images.test.mjs +142 -142
  81. package/functions/jsdocDocs.mjs +10 -10
  82. package/functions/jsdocEsmExports.test.mjs +24 -24
  83. package/functions/lint.mjs +9 -9
  84. package/functions/partials/addToReadme.mjs +25 -25
  85. package/functions/partials/addToReadme.test.mjs +34 -34
  86. package/functions/partials/beginWatcher.mjs +9 -9
  87. package/functions/partials/beginWatcher.test.mjs +19 -19
  88. package/functions/partials/clean.mjs +13 -13
  89. package/functions/partials/clean.test.mjs +22 -22
  90. package/functions/partials/copyFor.mjs +15 -15
  91. package/functions/partials/copyFor.test.mjs +53 -53
  92. package/functions/partials/distFor.mjs +22 -22
  93. package/functions/partials/distFor.test.mjs +195 -195
  94. package/functions/partials/distForSrc.mjs +11 -11
  95. package/functions/partials/distForSrc.test.mjs +18 -18
  96. package/functions/partials/distSeries.mjs +21 -21
  97. package/functions/partials/distSeries.test.mjs +34 -34
  98. package/functions/partials/imagesFor.mjs +83 -83
  99. package/functions/partials/imagesFor.test.mjs +287 -287
  100. package/functions/partials/jsdocDocsFor.mjs +163 -152
  101. package/functions/partials/jsdocDocsFor.test.mjs +182 -152
  102. package/functions/partials/lintSource.mjs +41 -41
  103. package/functions/partials/loadPeer.mjs +76 -76
  104. package/functions/partials/loadPeer.test.mjs +58 -58
  105. package/functions/partials/loadPlaywright.mjs +23 -23
  106. package/functions/partials/loadPlaywright.test.mjs +70 -70
  107. package/functions/partials/minifyFor.mjs +15 -15
  108. package/functions/partials/minifyFor.test.mjs +49 -49
  109. package/functions/partials/neostandardLint.mjs +142 -142
  110. package/functions/partials/neostandardLint.test.mjs +131 -131
  111. package/functions/partials/readmeTemplate.mjs +12 -12
  112. package/functions/partials/readmeTemplate.test.mjs +34 -34
  113. package/functions/partials/removeDirectory.mjs +34 -34
  114. package/functions/partials/removeDirectory.test.mjs +72 -72
  115. package/functions/partials/resolveDocsMethod.mjs +10 -10
  116. package/functions/partials/resolveDocsMethod.test.mjs +33 -33
  117. package/functions/partials/runOnChange.mjs +54 -54
  118. package/functions/partials/runOnChange.test.mjs +95 -95
  119. package/functions/partials/sassFor.mjs +25 -25
  120. package/functions/partials/sassFor.test.mjs +81 -81
  121. package/functions/partials/serveStatic.mjs +47 -47
  122. package/functions/partials/serveStatic.test.mjs +71 -71
  123. package/functions/partials/tsFor.mjs +92 -92
  124. package/functions/partials/tsFor.test.mjs +88 -88
  125. package/functions/partials/typeDocsFor.mjs +231 -231
  126. package/functions/partials/typeDocsFor.test.mjs +263 -263
  127. package/functions/partials.mjs +31 -31
  128. package/functions/partials.test.mjs +7 -7
  129. package/functions/sass.mjs +4 -4
  130. package/functions/sass.test.mjs +31 -31
  131. package/functions/sourceLint.mjs +13 -13
  132. package/functions/sourceLint.test.mjs +166 -166
  133. package/functions/test-helpers/isolateGulpCache.mjs +16 -16
  134. package/functions/test-helpers/neostandardLintWithRealNeostandard.mjs +40 -40
  135. package/functions/test-helpers/setUp.mjs +100 -100
  136. package/functions/test-helpers/setUp.test.mjs +19 -19
  137. package/functions/testFull.mjs +17 -17
  138. package/functions/testFull.test.mjs +17 -17
  139. package/functions/testHelpers.mjs +10 -10
  140. package/functions/testHelpers.test.mjs +7 -7
  141. package/functions/testQuick.mjs +17 -17
  142. package/functions/testQuick.test.mjs +17 -17
  143. package/functions/typeDocs.mjs +9 -9
  144. package/functions/typeDocs.test.mjs +11 -11
  145. package/functions/typeScript.mjs +8 -8
  146. package/functions/typeScript.test.mjs +11 -11
  147. package/functions/utilities/convertMjsFilesForDocs.mjs +34 -34
  148. package/functions/utilities/convertMjsFilesForDocs.test.mjs +58 -58
  149. package/functions/utilities/dotGet.mjs +49 -49
  150. package/functions/utilities/dotNotate.mjs +73 -73
  151. package/functions/utilities/dotNotate.test.mjs +41 -41
  152. package/functions/utilities/dotSet.mjs +40 -40
  153. package/functions/utilities/esmNamedExportsToCjs.mjs +30 -30
  154. package/functions/utilities/esmNamedExportsToCjs.test.mjs +47 -47
  155. package/functions/utilities/getBundleConfigs.mjs +30 -30
  156. package/functions/utilities/isObject.mjs +8 -8
  157. package/functions/utilities/strAfter.mjs +12 -12
  158. package/functions/utilities/strBefore.mjs +12 -12
  159. package/functions/watchFull.mjs +9 -9
  160. package/functions/watchFull.test.mjs +41 -41
  161. package/functions/watchTest.mjs +10 -10
  162. package/functions/watchTest.test.mjs +49 -49
  163. package/gulp.config.js +4 -4
  164. package/gulp.config.mjs +344 -340
  165. package/gulpfile.base.js +51 -51
  166. package/gulpfile.base.mjs +29 -29
  167. package/jsdoc.base.js +16 -16
  168. package/jsdoc.esmExports.js +17 -17
  169. package/package.json +146 -145
@@ -7,13 +7,13 @@ exports.loadPlaywright = exports.launchBrowser = void 0;
7
7
  var _loadPeer = require("./loadPeer.js");
8
8
  const installHint = 'Install it in your project with: npm install --save-dev playwright';
9
9
 
10
- /**
11
- * Find Playwright (headless-browser automation) of the project being built, an optional peer dependency only
12
- * needed by whatever actually drives a real browser - projects which never do never need it installed.
13
- * @memberOf module:partials
14
- * @param {string} [projectPath=process.cwd()] The folder of the project (which has the package.json) being built.
15
- * @returns {Object} The Playwright module.
16
- * @throws {Error} With install instructions when playwright is not installed.
10
+ /**
11
+ * Find Playwright (headless-browser automation) of the project being built, an optional peer dependency only
12
+ * needed by whatever actually drives a real browser - projects which never do never need it installed.
13
+ * @memberOf module:partials
14
+ * @param {string} [projectPath=process.cwd()] The folder of the project (which has the package.json) being built.
15
+ * @returns {Object} The Playwright module.
16
+ * @throws {Error} With install instructions when playwright is not installed.
17
17
  */
18
18
  const loadPlaywright = (projectPath = process.cwd()) => (0, _loadPeer.requirePeer)('playwright', {
19
19
  task: 'browser automation',
@@ -21,13 +21,13 @@ const loadPlaywright = (projectPath = process.cwd()) => (0, _loadPeer.requirePee
21
21
  projectPath
22
22
  });
23
23
 
24
- /**
25
- * Launch a real headless Chromium browser via Playwright. See {@link loadPlaywright}.
26
- * @memberOf module:partials
27
- * @param {Function} [load=loadPlaywright] Which Playwright to launch - swappable in tests.
28
- * @param {string} [projectPath=process.cwd()] The folder of the project (which has the package.json) being built.
29
- * @returns {Promise<Browser>} The running Playwright browser - close it yourself (browser.close()) once done with it.
30
- * @throws {Error} With install instructions when playwright is not installed.
24
+ /**
25
+ * Launch a real headless Chromium browser via Playwright. See {@link loadPlaywright}.
26
+ * @memberOf module:partials
27
+ * @param {Function} [load=loadPlaywright] Which Playwright to launch - swappable in tests.
28
+ * @param {string} [projectPath=process.cwd()] The folder of the project (which has the package.json) being built.
29
+ * @returns {Promise<Browser>} The running Playwright browser - close it yourself (browser.close()) once done with it.
30
+ * @throws {Error} With install instructions when playwright is not installed.
31
31
  */
32
32
  exports.loadPlaywright = loadPlaywright;
33
33
  const launchBrowser = (load = loadPlaywright, projectPath = process.cwd()) => load(projectPath).chromium.launch();
@@ -1,21 +1,21 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.minifyFor = void 0;
7
- var _gulp = require("gulp");
8
- var _gulpUglifyEs = _interopRequireDefault(require("gulp-uglify-es"));
9
- var _gulpRename = _interopRequireDefault(require("gulp-rename"));
10
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
- const uglify = Object.hasOwn(_gulpUglifyEs.default, 'default') ? _gulpUglifyEs.default.default : _gulpUglifyEs.default;
12
-
13
- /**
14
- * Minify files and rename the output with '.min' extension.
15
- * @memberOf module:partials
16
- * @returns {*}
17
- */
18
- const minifyFor = (srcSearch, destination) => (0, _gulp.src)(srcSearch).pipe(uglify()).pipe((0, _gulpRename.default)({
19
- extname: '.min.js'
20
- })).pipe((0, _gulp.dest)(destination));
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.minifyFor = void 0;
7
+ var _gulp = require("gulp");
8
+ var _gulpUglifyEs = _interopRequireDefault(require("gulp-uglify-es"));
9
+ var _gulpRename = _interopRequireDefault(require("gulp-rename"));
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ const uglify = Object.hasOwn(_gulpUglifyEs.default, 'default') ? _gulpUglifyEs.default.default : _gulpUglifyEs.default;
12
+
13
+ /**
14
+ * Minify files and rename the output with '.min' extension.
15
+ * @memberOf module:partials
16
+ * @returns {*}
17
+ */
18
+ const minifyFor = (srcSearch, destination) => (0, _gulp.src)(srcSearch).pipe(uglify()).pipe((0, _gulpRename.default)({
19
+ extname: '.min.js'
20
+ })).pipe((0, _gulp.dest)(destination));
21
21
  exports.minifyFor = minifyFor;
@@ -1,176 +1,176 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.neostandardLint = void 0;
7
- require("core-js/modules/esnext.iterator.constructor.js");
8
- require("core-js/modules/esnext.iterator.for-each.js");
9
- var _nodeFs = _interopRequireDefault(require("node:fs"));
10
- var _nodePath = _interopRequireDefault(require("node:path"));
11
- var _through = _interopRequireDefault(require("through2"));
12
- var _eslint = require("eslint");
13
- var _loadPeer = require("./loadPeer.js");
14
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
- // neostandard (js-build-tools' chosen style - a maintained, TypeScript-aware successor to `standard`, see
16
- // https://github.com/neostandard/neostandard) ships ESM-only, see importModule for how it is imported.
17
- const importNeostandard = () => (0, _loadPeer.importModule)('neostandard');
18
-
19
- /**
20
- * Read the `env` a project already declared for Standard (the `standard` field in its package.json), so a project
21
- * migrating from `standard` keeps its globals (jest, browser, ...) without touching package.json.
22
- * @param {string} cwd
23
- * @returns {Array<string>}
24
- * @private
25
- */
26
- const readEnv = cwd => {
27
- try {
28
- return JSON.parse(_nodeFs.default.readFileSync(_nodePath.default.join(cwd, 'package.json'), 'utf8')).standard?.env ?? [];
29
- } catch {
30
- return [];
31
- }
32
- };
33
-
34
- /**
35
- * Build an ESLint instance configured with neostandard, honoring the project's own package.json `standard.env`,
36
- * plus an optional layer of rule overrides (see gulp.config.mjs's `lint.rules`) for a rule that is wrong for this
37
- * project specifically rather than something to fix in its code - for example a test fixture whose content
38
- * neostandard mistakes for a real syntax problem. Scoped to the same files neostandard itself lints (its own
39
- * `defaultFilePatterns.all`), per neostandard's own guidance: an unscoped rule-tweak layer would otherwise apply
40
- * to every lintable file, including ones from an unrelated plugin this project never defined.
41
- * @param {Object} options
42
- * @param {string} options.cwd
43
- * @param {boolean} options.ts
44
- * @param {boolean} options.fix
45
- * @param {Object<string, *>} [options.rules={}]
46
- * @returns {Promise<ESLint>} eslint's ESLint instance
47
- * @private
48
- */
49
- const buildEslint = async ({
50
- cwd,
51
- ts,
52
- fix,
53
- rules = {}
54
- }) => {
55
- const {
56
- neostandard,
57
- defaultFilePatterns
58
- } = await importNeostandard();
59
- const baseConfig = neostandard({
60
- ts,
61
- env: readEnv(cwd)
62
- });
63
- if (Object.keys(rules).length) {
64
- baseConfig.push({
65
- files: defaultFilePatterns.all,
66
- rules
67
- });
68
- }
69
- return new _eslint.ESLint({
70
- cwd,
71
- fix,
72
- overrideConfigFile: true,
73
- baseConfig
74
- });
75
- };
76
-
77
- /**
78
- * Print a file's lint messages, if it has any.
79
- * @memberOf module:partials
80
- * @param {Vinyl} file
81
- * @param {{messages: Array<{line: number, column: number, message: string}>, errorCount: number, warningCount: number}} result
82
- * @returns {undefined}
83
- */
84
- const printFileReport = (file, result) => {
85
- if (!result.messages.length) {
86
- return;
87
- }
88
- console.log(_nodePath.default.relative(file.cwd, file.path));
89
- result.messages.forEach(({
90
- line,
91
- column,
92
- message
93
- }) => console.log(`line ${line}:${column}\t${message}`));
94
- console.log(`✖ ${result.errorCount} error\t⚠ ${result.warningCount} warning\n`);
95
- };
96
-
97
- /**
98
- * Lint every file streaming through with neostandard and, unless `fix` is false, apply the automatic fixes to the
99
- * file's contents so a following `dest()` writes the fixed version. Remaining problems are printed along with a
100
- * summary once the stream ends; they only fail the stream when `failOnError` is set (the standalone `lint` task),
101
- * never during `build`.
102
- *
103
- * One ESLint instance is built from the first file's own cwd and reused for the rest of the stream, since every
104
- * file in a given lint pass shares the same project (and so the same config).
105
- * @memberOf module:partials
106
- * @param {Object} [options={}]
107
- * @param {boolean} [options.fix=true] - Apply neostandard's automatic fixes to the file contents.
108
- * @param {boolean} [options.ts=false] - Lint `.ts` files too, with type-aware rules (see neostandard's `ts` option).
109
- * @param {Object<string, *>} [options.rules={}] - ESLint rule overrides layered on top of neostandard's own rules
110
- * (see gulp.config.mjs's `lint.rules`).
111
- * @param {boolean} [options.failOnError=false] - Emit an error once the stream ends if any lint errors remain after
112
- * fixing, so a command-line run exits non-zero.
113
- * @param {function(Object): Promise<{lintText: Function}>} [loadEslint] - Resolves an ESLint-shaped linter. Real
114
- * callers should never need to pass this - it exists so tests can supply a stand-in, since this project's
115
- * CommonJS-transform-based Jest setup cannot execute a real dynamic import() of neostandard (ESM-only).
116
- * @returns {stream.Transform} With a `totals` property ({errors, warnings}), complete once the stream ends.
117
- */
118
- const neostandardLint = ({
119
- fix = true,
120
- ts = false,
121
- rules = {},
122
- failOnError = false
123
- } = {}, loadEslint = buildEslint) => {
124
- const totals = {
125
- errors: 0,
126
- warnings: 0
127
- };
128
- let eslintPromise = null;
129
- const linter = _through.default.obj(function (file, enc, callback) {
130
- if (file.isNull()) {
131
- callback(null, file);
132
- return;
133
- }
134
- if (file.isStream()) {
135
- callback(new Error('neostandardLint: streaming file contents are not supported.'));
136
- return;
137
- }
138
- if (!eslintPromise) {
139
- eslintPromise = loadEslint({
140
- cwd: file.cwd,
141
- ts,
142
- fix,
143
- rules
144
- });
145
- }
146
- eslintPromise.then(eslint => eslint.lintText(file.contents.toString(), {
147
- filePath: file.path
148
- })).then(results => {
149
- // No result at all means the file is ignored by the project's ESLint configuration.
150
- const [result] = results;
151
- if (result) {
152
- if (typeof result.output === 'string') {
153
- file.contents = Buffer.from(result.output);
154
- }
155
- totals.errors += result.errorCount;
156
- totals.warnings += result.warningCount;
157
- printFileReport(file, result);
158
- }
159
- callback(null, file);
160
- }, callback);
161
- }, function (callback) {
162
- console.log('neostandard linter results');
163
- console.log('======================================');
164
- console.log(`✖ Errors total: ${totals.errors}`);
165
- console.log(`⚠ Warnings total: ${totals.warnings}\n`);
166
- if (failOnError && totals.errors) {
167
- callback(new Error(`neostandard found ${totals.errors} lint error(s) that could not be fixed automatically.`));
168
- return;
169
- }
170
- callback();
171
- });
172
- // Read by lintSource, which can only fail once the fixed files have been written, after this stream has ended.
173
- linter.totals = totals;
174
- return linter;
175
- };
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.neostandardLint = void 0;
7
+ require("core-js/modules/esnext.iterator.constructor.js");
8
+ require("core-js/modules/esnext.iterator.for-each.js");
9
+ var _nodeFs = _interopRequireDefault(require("node:fs"));
10
+ var _nodePath = _interopRequireDefault(require("node:path"));
11
+ var _through = _interopRequireDefault(require("through2"));
12
+ var _eslint = require("eslint");
13
+ var _loadPeer = require("./loadPeer.js");
14
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
+ // neostandard (js-build-tools' chosen style - a maintained, TypeScript-aware successor to `standard`, see
16
+ // https://github.com/neostandard/neostandard) ships ESM-only, see importModule for how it is imported.
17
+ const importNeostandard = () => (0, _loadPeer.importModule)('neostandard');
18
+
19
+ /**
20
+ * Read the `env` a project already declared for Standard (the `standard` field in its package.json), so a project
21
+ * migrating from `standard` keeps its globals (jest, browser, ...) without touching package.json.
22
+ * @param {string} cwd
23
+ * @returns {Array<string>}
24
+ * @private
25
+ */
26
+ const readEnv = cwd => {
27
+ try {
28
+ return JSON.parse(_nodeFs.default.readFileSync(_nodePath.default.join(cwd, 'package.json'), 'utf8')).standard?.env ?? [];
29
+ } catch {
30
+ return [];
31
+ }
32
+ };
33
+
34
+ /**
35
+ * Build an ESLint instance configured with neostandard, honoring the project's own package.json `standard.env`,
36
+ * plus an optional layer of rule overrides (see gulp.config.mjs's `lint.rules`) for a rule that is wrong for this
37
+ * project specifically rather than something to fix in its code - for example a test fixture whose content
38
+ * neostandard mistakes for a real syntax problem. Scoped to the same files neostandard itself lints (its own
39
+ * `defaultFilePatterns.all`), per neostandard's own guidance: an unscoped rule-tweak layer would otherwise apply
40
+ * to every lintable file, including ones from an unrelated plugin this project never defined.
41
+ * @param {Object} options
42
+ * @param {string} options.cwd
43
+ * @param {boolean} options.ts
44
+ * @param {boolean} options.fix
45
+ * @param {Object<string, *>} [options.rules={}]
46
+ * @returns {Promise<ESLint>} eslint's ESLint instance
47
+ * @private
48
+ */
49
+ const buildEslint = async ({
50
+ cwd,
51
+ ts,
52
+ fix,
53
+ rules = {}
54
+ }) => {
55
+ const {
56
+ neostandard,
57
+ defaultFilePatterns
58
+ } = await importNeostandard();
59
+ const baseConfig = neostandard({
60
+ ts,
61
+ env: readEnv(cwd)
62
+ });
63
+ if (Object.keys(rules).length) {
64
+ baseConfig.push({
65
+ files: defaultFilePatterns.all,
66
+ rules
67
+ });
68
+ }
69
+ return new _eslint.ESLint({
70
+ cwd,
71
+ fix,
72
+ overrideConfigFile: true,
73
+ baseConfig
74
+ });
75
+ };
76
+
77
+ /**
78
+ * Print a file's lint messages, if it has any.
79
+ * @memberOf module:partials
80
+ * @param {Vinyl} file
81
+ * @param {{messages: Array<{line: number, column: number, message: string}>, errorCount: number, warningCount: number}} result
82
+ * @returns {undefined}
83
+ */
84
+ const printFileReport = (file, result) => {
85
+ if (!result.messages.length) {
86
+ return;
87
+ }
88
+ console.log(_nodePath.default.relative(file.cwd, file.path));
89
+ result.messages.forEach(({
90
+ line,
91
+ column,
92
+ message
93
+ }) => console.log(`line ${line}:${column}\t${message}`));
94
+ console.log(`✖ ${result.errorCount} error\t⚠ ${result.warningCount} warning\n`);
95
+ };
96
+
97
+ /**
98
+ * Lint every file streaming through with neostandard and, unless `fix` is false, apply the automatic fixes to the
99
+ * file's contents so a following `dest()` writes the fixed version. Remaining problems are printed along with a
100
+ * summary once the stream ends; they only fail the stream when `failOnError` is set (the standalone `lint` task),
101
+ * never during `build`.
102
+ *
103
+ * One ESLint instance is built from the first file's own cwd and reused for the rest of the stream, since every
104
+ * file in a given lint pass shares the same project (and so the same config).
105
+ * @memberOf module:partials
106
+ * @param {Object} [options={}]
107
+ * @param {boolean} [options.fix=true] - Apply neostandard's automatic fixes to the file contents.
108
+ * @param {boolean} [options.ts=false] - Lint `.ts` files too, with type-aware rules (see neostandard's `ts` option).
109
+ * @param {Object<string, *>} [options.rules={}] - ESLint rule overrides layered on top of neostandard's own rules
110
+ * (see gulp.config.mjs's `lint.rules`).
111
+ * @param {boolean} [options.failOnError=false] - Emit an error once the stream ends if any lint errors remain after
112
+ * fixing, so a command-line run exits non-zero.
113
+ * @param {function(Object): Promise<{lintText: Function}>} [loadEslint] - Resolves an ESLint-shaped linter. Real
114
+ * callers should never need to pass this - it exists so tests can supply a stand-in, since this project's
115
+ * CommonJS-transform-based Jest setup cannot execute a real dynamic import() of neostandard (ESM-only).
116
+ * @returns {stream.Transform} With a `totals` property ({errors, warnings}), complete once the stream ends.
117
+ */
118
+ const neostandardLint = ({
119
+ fix = true,
120
+ ts = false,
121
+ rules = {},
122
+ failOnError = false
123
+ } = {}, loadEslint = buildEslint) => {
124
+ const totals = {
125
+ errors: 0,
126
+ warnings: 0
127
+ };
128
+ let eslintPromise = null;
129
+ const linter = _through.default.obj(function (file, enc, callback) {
130
+ if (file.isNull()) {
131
+ callback(null, file);
132
+ return;
133
+ }
134
+ if (file.isStream()) {
135
+ callback(new Error('neostandardLint: streaming file contents are not supported.'));
136
+ return;
137
+ }
138
+ if (!eslintPromise) {
139
+ eslintPromise = loadEslint({
140
+ cwd: file.cwd,
141
+ ts,
142
+ fix,
143
+ rules
144
+ });
145
+ }
146
+ eslintPromise.then(eslint => eslint.lintText(file.contents.toString(), {
147
+ filePath: file.path
148
+ })).then(results => {
149
+ // No result at all means the file is ignored by the project's ESLint configuration.
150
+ const [result] = results;
151
+ if (result) {
152
+ if (typeof result.output === 'string') {
153
+ file.contents = Buffer.from(result.output);
154
+ }
155
+ totals.errors += result.errorCount;
156
+ totals.warnings += result.warningCount;
157
+ printFileReport(file, result);
158
+ }
159
+ callback(null, file);
160
+ }, callback);
161
+ }, function (callback) {
162
+ console.log('neostandard linter results');
163
+ console.log('======================================');
164
+ console.log(`✖ Errors total: ${totals.errors}`);
165
+ console.log(`⚠ Warnings total: ${totals.warnings}\n`);
166
+ if (failOnError && totals.errors) {
167
+ callback(new Error(`neostandard found ${totals.errors} lint error(s) that could not be fixed automatically.`));
168
+ return;
169
+ }
170
+ callback();
171
+ });
172
+ // Read by lintSource, which can only fail once the fixed files have been written, after this stream has ended.
173
+ linter.totals = totals;
174
+ return linter;
175
+ };
176
176
  exports.neostandardLint = neostandardLint;
@@ -11,10 +11,10 @@ var _gulpRename = _interopRequireDefault(require("gulp-rename"));
11
11
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
12
  var cache;
13
13
  function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var r, c, a = Object.defineProperty, n = { __proto__: null, default: e }; if (Object(e) !== e) return n; if (cache || "function" != typeof WeakMap || (cache = new WeakMap()), cache) { if (cache.has(e)) return cache.get(e); cache.set(e, n); } for (c in e) "default" !== c && {}.hasOwnProperty.call(e, c) && ((r = a && Object.getOwnPropertyDescriptor(e, c)) && (r.get || r.set) ? a(n, c, r) : n[c] = e[c]); return n; }
14
- /**
15
- * Copy a readme template into the README.md file.
16
- * @memberOf module:partials
17
- * @returns {*}
14
+ /**
15
+ * Copy a readme template into the README.md file.
16
+ * @memberOf module:partials
17
+ * @returns {*}
18
18
  */
19
19
  const readmeTemplate = () => (0, _gulp.src)(gulpConfig.get('readme.template')).pipe((0, _gulpRename.default)(gulpConfig.get('readme.file'))).pipe((0, _gulp.dest)(gulpConfig.get('readme.to')));
20
20
  exports.readmeTemplate = readmeTemplate;
@@ -9,17 +9,17 @@ var _promises2 = require("node:timers/promises");
9
9
  const attempts = 4;
10
10
  const exists = dirPath => (0, _promises.access)(dirPath).then(() => true, () => false);
11
11
 
12
- /**
13
- * Delete a directory and everything in it, resolving only once it is really gone.
14
- *
15
- * A single rm can leave a directory behind - most often when something is still writing into it (a build task, a
16
- * watcher, a dev server) or has it briefly locked (EBUSY/EPERM/ENOTEMPTY) - which silently leaves stale output for
17
- * the next build. So: Node's own retry-with-back-off handles the transient errors, then the directory is checked and
18
- * removed again if it was recreated, and a clear error is raised rather than carrying on with stale output.
19
- * @memberOf module:partials
20
- * @param {string} dirPath
21
- * @returns {Promise<string>} Resolves with dirPath once the directory no longer exists (or already didn't).
22
- * @throws {Error} If the directory still exists after several attempts.
12
+ /**
13
+ * Delete a directory and everything in it, resolving only once it is really gone.
14
+ *
15
+ * A single rm can leave a directory behind - most often when something is still writing into it (a build task, a
16
+ * watcher, a dev server) or has it briefly locked (EBUSY/EPERM/ENOTEMPTY) - which silently leaves stale output for
17
+ * the next build. So: Node's own retry-with-back-off handles the transient errors, then the directory is checked and
18
+ * removed again if it was recreated, and a clear error is raised rather than carrying on with stale output.
19
+ * @memberOf module:partials
20
+ * @param {string} dirPath
21
+ * @returns {Promise<string>} Resolves with dirPath once the directory no longer exists (or already didn't).
22
+ * @throws {Error} If the directory still exists after several attempts.
23
23
  */
24
24
  const removeDirectory = async dirPath => {
25
25
  for (let attempt = 1; attempt <= attempts; attempt++) {
@@ -8,12 +8,12 @@ exports.resolveDocsMethod = void 0;
8
8
  var gulpConfig = _interopRequireWildcard(require("../../gulp.config.js"));
9
9
  var cache;
10
10
  function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var r, c, a = Object.defineProperty, n = { __proto__: null, default: e }; if (Object(e) !== e) return n; if (cache || "function" != typeof WeakMap || (cache = new WeakMap()), cache) { if (cache.has(e)) return cache.get(e); cache.set(e, n); } for (c in e) "default" !== c && {}.hasOwnProperty.call(e, c) && ((r = a && Object.getOwnPropertyDescriptor(e, c)) && (r.get || r.set) ? a(n, c, r) : n[c] = e[c]); return n; }
11
- /**
12
- * Pick which engine generates the HTML documentation: docs.method picks it explicitly; left unset (false, the
13
- * default), it's inferred from typescript.enabled - every existing TypeScript project's config, which never
14
- * sets method, keeps producing TypeDoc output exactly as it always has.
15
- * @memberOf module:partials
16
- * @returns {'typedoc'|'jsdoc'}
11
+ /**
12
+ * Pick which engine generates the HTML documentation: docs.method picks it explicitly; left unset (false, the
13
+ * default), it's inferred from typescript.enabled - every existing TypeScript project's config, which never
14
+ * sets method, keeps producing TypeDoc output exactly as it always has.
15
+ * @memberOf module:partials
16
+ * @returns {'typedoc'|'jsdoc'}
17
17
  */
18
18
  const resolveDocsMethod = () => gulpConfig.get('docs.method') || (gulpConfig.get('typescript.enabled') ? 'typedoc' : 'jsdoc');
19
19
  exports.resolveDocsMethod = resolveDocsMethod;
@@ -12,42 +12,42 @@ var _gulp = require("gulp");
12
12
  var _testQuick = require("../testQuick.js");
13
13
  var cache;
14
14
  function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var r, c, a = Object.defineProperty, n = { __proto__: null, default: e }; if (Object(e) !== e) return n; if (cache || "function" != typeof WeakMap || (cache = new WeakMap()), cache) { if (cache.has(e)) return cache.get(e); cache.set(e, n); } for (c in e) "default" !== c && {}.hasOwnProperty.call(e, c) && ((r = a && Object.getOwnPropertyDescriptor(e, c)) && (r.get || r.set) ? a(n, c, r) : n[c] = e[c]); return n; }
15
- /**
16
- * Run this function when the watched files are modified.
17
- * 1. Find the sub-folders within src path
18
- * 2. Maintain the folders, but use distPath for base
19
- * 3. Remove base folder and return dist path with correct sub-folders
20
- * @example
21
- * // Configured paths
22
- * distPath = 'dist'
23
- * srcPath = 'functions'
24
- *
25
- * // Path parameter
26
- * path = 'functions/some/path/file.js'
27
- *
28
- * // Generated regex using configured srcPath
29
- * pathRegex = '/^functions(.*\/).+\.js$/i'
30
- *
31
- * // Replace value using the configured distPath
32
- * replacePath = 'dist$1'
33
- *
34
- * // The resulting replaced path for the destination folder
35
- * distPathResult = 'dist/some/path/'
36
- * @memberOf module:partials
37
- * @param {string} path
38
- * @returns {stream.Stream}
15
+ /**
16
+ * Run this function when the watched files are modified.
17
+ * 1. Find the sub-folders within src path
18
+ * 2. Maintain the folders, but use distPath for base
19
+ * 3. Remove base folder and return dist path with correct sub-folders
20
+ * @example
21
+ * // Configured paths
22
+ * distPath = 'dist'
23
+ * srcPath = 'functions'
24
+ *
25
+ * // Path parameter
26
+ * path = 'functions/some/path/file.js'
27
+ *
28
+ * // Generated regex using configured srcPath
29
+ * pathRegex = '/^functions(.*\/).+\.js$/i'
30
+ *
31
+ * // Replace value using the configured distPath
32
+ * replacePath = 'dist$1'
33
+ *
34
+ * // The resulting replaced path for the destination folder
35
+ * distPathResult = 'dist/some/path/'
36
+ * @memberOf module:partials
37
+ * @param {string} path
38
+ * @returns {stream.Stream}
39
39
  */
40
40
  const runOnChange = path => {
41
41
  const useTs = gulpConfig.get('typescript.enabled');
42
42
  const distPath = gulpConfig.get('dist.to');
43
43
  const srcPath = gulpConfig.get('srcPath');
44
- /**
45
- * 1. The original path comes in from src and is a .ts
46
- * 2. Discover the outgoing dist path where that file should go
47
- * 3. Use the path and dist in tsFor
48
- * 4. Take the original path, convert to full file path in dist
49
- * 5. Use the dist path found previously in #2
50
- * 6. Use the full dist path and the dist outgoing path in distFor
44
+ /**
45
+ * 1. The original path comes in from src and is a .ts
46
+ * 2. Discover the outgoing dist path where that file should go
47
+ * 3. Use the path and dist in tsFor
48
+ * 4. Take the original path, convert to full file path in dist
49
+ * 5. Use the dist path found previously in #2
50
+ * 6. Use the full dist path and the dist outgoing path in distFor
51
51
  */
52
52
  const pathRegex = new RegExp(`^${srcPath}(.*\\/)(.+)\\.(js|ts)$`, 'i');
53
53
  const distPathResult = path.replace(pathRegex, `${distPath}$1`);
@@ -18,12 +18,12 @@ var cache;
18
18
  function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var r, c, a = Object.defineProperty, n = { __proto__: null, default: e }; if (Object(e) !== e) return n; if (cache || "function" != typeof WeakMap || (cache = new WeakMap()), cache) { if (cache.has(e)) return cache.get(e); cache.set(e, n); } for (c in e) "default" !== c && {}.hasOwnProperty.call(e, c) && ((r = a && Object.getOwnPropertyDescriptor(e, c)) && (r.get || r.set) ? a(n, c, r) : n[c] = e[c]); return n; }
19
19
  const runSass = (0, _gulpSass.default)(sass);
20
20
 
21
- /**
22
- * Build the CSS for a given source pattern.
23
- * @memberOf module:partials
24
- * @param {string|array} [srcSearch='src/config/path/sass/for']
25
- * @param {string} [cssPath='css/config/path']
26
- * @returns {stream.Stream}
21
+ /**
22
+ * Build the CSS for a given source pattern.
23
+ * @memberOf module:partials
24
+ * @param {string|array} [srcSearch='src/config/path/sass/for']
25
+ * @param {string} [cssPath='css/config/path']
26
+ * @returns {stream.Stream}
27
27
  */
28
28
  const sassFor = (srcSearch = gulpConfig.get('sass.from'), cssPath = gulpConfig.get('sass.to')) => (0, _gulp.src)(srcSearch).pipe(runSass().on('error', runSass.logError)) // Passes it through a gulp-sass, log errors to console
29
29
  .pipe((0, _gulp.dest)(cssPath))
@@ -26,15 +26,15 @@ const contentTypes = {
26
26
  '.woff2': 'font/woff2'
27
27
  };
28
28
 
29
- /**
30
- * Serve a directory's real files over plain HTTP, for anything that needs a page loaded from a real URL rather
31
- * than a bare file:// path - most commonly, a page using root-relative asset paths (/browser/...), which a
32
- * file:// load resolves against the filesystem root instead of the page's own directory.
33
- * @memberOf module:partials
34
- * @param {string} rootDir - The directory to serve.
35
- * @param {number} [port=0] - The port to listen on; 0 picks any free port.
36
- * @returns {Promise<{server: http.Server, url: string}>} The running server, and its base URL - close the
37
- * server yourself (server.close()) once done with it.
29
+ /**
30
+ * Serve a directory's real files over plain HTTP, for anything that needs a page loaded from a real URL rather
31
+ * than a bare file:// path - most commonly, a page using root-relative asset paths (/browser/...), which a
32
+ * file:// load resolves against the filesystem root instead of the page's own directory.
33
+ * @memberOf module:partials
34
+ * @param {string} rootDir - The directory to serve.
35
+ * @param {number} [port=0] - The port to listen on; 0 picks any free port.
36
+ * @returns {Promise<{server: http.Server, url: string}>} The running server, and its base URL - close the
37
+ * server yourself (server.close()) once done with it.
38
38
  */
39
39
  const serveStatic = (rootDir, port = 0) => new Promise((resolve, reject) => {
40
40
  const server = _nodeHttp.default.createServer((req, res) => {