js-build-tools 5.3.0 → 5.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -1
- package/dist/build.js +63 -63
- package/dist/partials/imagesFor.js +7 -13
- package/dist/partials/loadPeer.js +99 -0
- package/dist/partials/standardLint.js +3 -5
- package/dist/partials/tsFor.js +8 -20
- package/dist/partials/typeDocsFor.js +61 -23
- package/dist/partials.js +136 -117
- package/dist/partials.min.js +1 -1
- package/dist/typeDocs.js +9 -9
- package/functions/partials/imagesFor.mjs +7 -13
- package/functions/partials/loadPeer.mjs +75 -0
- package/functions/partials/loadPeer.test.mjs +58 -0
- package/functions/partials/standardLint.mjs +3 -5
- package/functions/partials/tsFor.mjs +4 -20
- package/functions/partials/typeDocsFor.mjs +52 -23
- package/functions/partials/typeDocsFor.test.mjs +51 -5
- package/functions/partials.mjs +1 -0
- package/functions/partials.test.mjs +1 -1
- package/gulp.config.mjs +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,6 +35,11 @@ provided are the defaults):
|
|
|
35
35
|
"name": "my-package",
|
|
36
36
|
// The search pattern used for retrieving compiled distribution files.
|
|
37
37
|
"from": "dist/**/*.js",
|
|
38
|
+
// Module names or file paths which resolve to an empty object ({}) in the bundle instead of their real contents.
|
|
39
|
+
"ignore": [],
|
|
40
|
+
// Module names or file paths left out of the bundle entirely (requiring one at runtime throws, unless something
|
|
41
|
+
// else provides it, for example a script tag which loads it separately).
|
|
42
|
+
"exclude": [],
|
|
38
43
|
// The output directory for browser-bundled files.
|
|
39
44
|
"to": "browser"
|
|
40
45
|
},
|
|
@@ -290,6 +295,27 @@ const jsDocBase = require('js-build-tools/jsdoc.base')
|
|
|
290
295
|
module.exports = jsDocBase
|
|
291
296
|
```
|
|
292
297
|
|
|
298
|
+
### Configure what the browser bundle leaves out (optional)
|
|
299
|
+
|
|
300
|
+
A dependency can be reached from your code without being needed in the browser, and bundling it can add a lot of size.
|
|
301
|
+
Two settings in `browser` handle this, both take module names or file paths (see browserify's `b.ignore(file)` and
|
|
302
|
+
`b.exclude(file)`):
|
|
303
|
+
|
|
304
|
+
```json
|
|
305
|
+
{
|
|
306
|
+
"browser": {
|
|
307
|
+
// Resolves to an empty object ({}) in the bundle instead of the real module. This suits a dependency which is only
|
|
308
|
+
// reached because it is the default value of an option you always override with your own (for example a selector
|
|
309
|
+
// engine's default DOM adapter). Anything only that module requires is left out too. Your code must never actually
|
|
310
|
+
// use the real module, so keep overriding that option.
|
|
311
|
+
"ignore": ["some-default-adapter"],
|
|
312
|
+
// Left out of the bundle entirely. Requiring it at runtime throws unless something else provides it, for example a
|
|
313
|
+
// script tag which loads it separately, so this suits a large library which the page already loads.
|
|
314
|
+
"exclude": ["a-library-the-page-loads"]
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
293
319
|
### Configure move fonts (optional)
|
|
294
320
|
|
|
295
321
|
Be able to copy a source directory of fonts into the distribution path.
|
|
@@ -418,7 +444,9 @@ module.exports = babelConfig
|
|
|
418
444
|
the readme it generates. Instead, this can generate HTML documentation straight from the TypeScript source with
|
|
419
445
|
[TypeDoc](https://typedoc.org/). Every folder in your source directory becomes a module of the documentation, the default
|
|
420
446
|
export of each file (one function per file) is listed under the name of the file, and everything else a file exports (for
|
|
421
|
-
example the types in a `types.ts`) is listed as it is. Index files, tests and declaration files are left out.
|
|
447
|
+
example the types in a `types.ts`) is listed as it is. Index files, tests and declaration files are left out. A file
|
|
448
|
+
which sits directly in the source directory, beside the folders, is a module of its own (unless it is `index` or
|
|
449
|
+
`main`). The first comment of a folder's `index.ts` (or the header comment of such a file) describes its module. The
|
|
422
450
|
comments on your code are the documentation, and the types come from the code itself, so `@module`, `@memberOf`,
|
|
423
451
|
`@typedef` and the `{Type}` of `@param` are not needed.
|
|
424
452
|
|
package/dist/build.js
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
require('core-js/modules/esnext.weak-map.delete-all.js')
|
|
4
|
-
Object.defineProperty(exports, '__esModule', {
|
|
5
|
-
value: true
|
|
6
|
-
})
|
|
7
|
-
exports.build = void 0
|
|
8
|
-
const _bundle = require('./bundle.js')
|
|
9
|
-
const _bundleLint = require('./bundleLint.js')
|
|
10
|
-
const _bundleMinify = require('./bundleMinify.js')
|
|
11
|
-
const _partials = require('./partials.js')
|
|
12
|
-
const _compileReadme = require('./compileReadme.js')
|
|
13
|
-
const _typeDocs = require('./typeDocs.js')
|
|
14
|
-
const _distLint = require('./distLint.js')
|
|
15
|
-
const _distMinify = require('./distMinify.js')
|
|
16
|
-
const _gulp = require('gulp')
|
|
17
|
-
const gulpConfig = _interopRequireWildcard(require('../gulp.config.js'))
|
|
18
|
-
const _copyFonts = require('./copyFonts.js')
|
|
19
|
-
const _images = require('./images.js')
|
|
20
|
-
const _sass = require('./sass.js')
|
|
21
|
-
const _testFull = require('./testFull.js')
|
|
22
|
-
function _interopRequireWildcard (e, t) { if (typeof WeakMap === 'function') var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; let o; let i; const f = { __proto__: null, default: e }; if (e === null || typeof e !== 'object' && typeof e !== 'function') return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f) } for (const t in e) t !== 'default' && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f })(e, t) }
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
require('core-js/modules/esnext.weak-map.delete-all.js')
|
|
4
|
+
Object.defineProperty(exports, '__esModule', {
|
|
5
|
+
value: true
|
|
6
|
+
})
|
|
7
|
+
exports.build = void 0
|
|
8
|
+
const _bundle = require('./bundle.js')
|
|
9
|
+
const _bundleLint = require('./bundleLint.js')
|
|
10
|
+
const _bundleMinify = require('./bundleMinify.js')
|
|
11
|
+
const _partials = require('./partials.js')
|
|
12
|
+
const _compileReadme = require('./compileReadme.js')
|
|
13
|
+
const _typeDocs = require('./typeDocs.js')
|
|
14
|
+
const _distLint = require('./distLint.js')
|
|
15
|
+
const _distMinify = require('./distMinify.js')
|
|
16
|
+
const _gulp = require('gulp')
|
|
17
|
+
const gulpConfig = _interopRequireWildcard(require('../gulp.config.js'))
|
|
18
|
+
const _copyFonts = require('./copyFonts.js')
|
|
19
|
+
const _images = require('./images.js')
|
|
20
|
+
const _sass = require('./sass.js')
|
|
21
|
+
const _testFull = require('./testFull.js')
|
|
22
|
+
function _interopRequireWildcard (e, t) { if (typeof WeakMap === 'function') var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; let o; let i; const f = { __proto__: null, default: e }; if (e === null || typeof e !== 'object' && typeof e !== 'function') return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f) } for (const t in e) t !== 'default' && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f })(e, t) }
|
|
23
23
|
/**
|
|
24
24
|
* Runs several processes to build and validate the project.
|
|
25
25
|
* Cleans, distributes (lint and minify), bundles (lint and minify), creates the readme, then runs the tests.
|
|
26
26
|
* @memberOf module:js-build-tools
|
|
27
27
|
* @returns {stream.Stream}
|
|
28
|
-
*/
|
|
29
|
-
const build = (done = null) => {
|
|
30
|
-
const distLintMinify = (0, _gulp.parallel)(_distLint.distLint, _distMinify.distMinify)
|
|
31
|
-
const bundleLintMinify = (0, _gulp.parallel)(_bundleLint.bundleLint, _bundleMinify.bundleMinify)
|
|
32
|
-
const buildActions = [(0, _partials.distSeries)(), distLintMinify]
|
|
33
|
-
const generateDocs = gulpConfig.get('docs.enabled')
|
|
34
|
-
if (generateDocs) {
|
|
35
|
-
// The documentation is generated from the TypeScript source itself, the readme is written by hand
|
|
36
|
-
buildActions.push(_typeDocs.typeDocs)
|
|
37
|
-
} else if (gulpConfig.get('typescript.enabled')) {
|
|
38
|
-
// For ts usage, we need to run the readme on the dist directly since that is where the .js files are located
|
|
39
|
-
buildActions.push(_compileReadme.compileReadme)
|
|
40
|
-
}
|
|
41
|
-
if (gulpConfig.get('browser.enabled')) {
|
|
42
|
-
// If not 'nodeOnly' then we also want to bundle for browser after we complete the dist directory
|
|
43
|
-
buildActions.push(_bundle.bundle)
|
|
44
|
-
buildActions.push(bundleLintMinify)
|
|
45
|
-
}
|
|
46
|
-
const runActions = [(0, _gulp.series)(...buildActions)]
|
|
47
|
-
if (!generateDocs && !gulpConfig.get('typescript.enabled')) {
|
|
48
|
-
// Since we didn't run this in series after dist because of typescript, we need to run it now. Potentially faster here.
|
|
49
|
-
runActions.push(_compileReadme.compileReadme)
|
|
50
|
-
}
|
|
51
|
-
runActions.push(_testFull.testFull)
|
|
52
|
-
if (gulpConfig.get('fonts.enabled')) {
|
|
53
|
-
// Conditionally add Fonts process
|
|
54
|
-
runActions.push(_copyFonts.copyFonts)
|
|
55
|
-
}
|
|
56
|
-
if (gulpConfig.get('images.enabled')) {
|
|
57
|
-
// Conditionally add Images process
|
|
58
|
-
runActions.push(_images.images)
|
|
59
|
-
}
|
|
60
|
-
if (gulpConfig.get('sass.enabled')) {
|
|
61
|
-
// Conditionally add SASS process
|
|
62
|
-
runActions.push(_sass.sass)
|
|
63
|
-
}
|
|
64
|
-
// clean has to finish before anything writes into the output folders - images, fonts and sass all write into
|
|
65
|
-
// browser/, so running clean in parallel with them races (ENOTEMPTY errors from clean, or output deleted mid-write).
|
|
66
|
-
return (0, _gulp.series)(_partials.clean, (0, _gulp.parallel)(...runActions))(done)
|
|
67
|
-
}
|
|
68
|
-
exports.build = build
|
|
28
|
+
*/
|
|
29
|
+
const build = (done = null) => {
|
|
30
|
+
const distLintMinify = (0, _gulp.parallel)(_distLint.distLint, _distMinify.distMinify)
|
|
31
|
+
const bundleLintMinify = (0, _gulp.parallel)(_bundleLint.bundleLint, _bundleMinify.bundleMinify)
|
|
32
|
+
const buildActions = [(0, _partials.distSeries)(), distLintMinify]
|
|
33
|
+
const generateDocs = gulpConfig.get('docs.enabled')
|
|
34
|
+
if (generateDocs) {
|
|
35
|
+
// The documentation is generated from the TypeScript source itself, the readme is written by hand
|
|
36
|
+
buildActions.push(_typeDocs.typeDocs)
|
|
37
|
+
} else if (gulpConfig.get('typescript.enabled')) {
|
|
38
|
+
// For ts usage, we need to run the readme on the dist directly since that is where the .js files are located
|
|
39
|
+
buildActions.push(_compileReadme.compileReadme)
|
|
40
|
+
}
|
|
41
|
+
if (gulpConfig.get('browser.enabled')) {
|
|
42
|
+
// If not 'nodeOnly' then we also want to bundle for browser after we complete the dist directory
|
|
43
|
+
buildActions.push(_bundle.bundle)
|
|
44
|
+
buildActions.push(bundleLintMinify)
|
|
45
|
+
}
|
|
46
|
+
const runActions = [(0, _gulp.series)(...buildActions)]
|
|
47
|
+
if (!generateDocs && !gulpConfig.get('typescript.enabled')) {
|
|
48
|
+
// Since we didn't run this in series after dist because of typescript, we need to run it now. Potentially faster here.
|
|
49
|
+
runActions.push(_compileReadme.compileReadme)
|
|
50
|
+
}
|
|
51
|
+
runActions.push(_testFull.testFull)
|
|
52
|
+
if (gulpConfig.get('fonts.enabled')) {
|
|
53
|
+
// Conditionally add Fonts process
|
|
54
|
+
runActions.push(_copyFonts.copyFonts)
|
|
55
|
+
}
|
|
56
|
+
if (gulpConfig.get('images.enabled')) {
|
|
57
|
+
// Conditionally add Images process
|
|
58
|
+
runActions.push(_images.images)
|
|
59
|
+
}
|
|
60
|
+
if (gulpConfig.get('sass.enabled')) {
|
|
61
|
+
// Conditionally add SASS process
|
|
62
|
+
runActions.push(_sass.sass)
|
|
63
|
+
}
|
|
64
|
+
// clean has to finish before anything writes into the output folders - images, fonts and sass all write into
|
|
65
|
+
// browser/, so running clean in parallel with them races (ENOTEMPTY errors from clean, or output deleted mid-write).
|
|
66
|
+
return (0, _gulp.series)(_partials.clean, (0, _gulp.parallel)(...runActions))(done)
|
|
67
|
+
}
|
|
68
|
+
exports.build = build
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.loadImagemin = exports.imagesFor = void 0;
|
|
8
8
|
var _gulpCache = _interopRequireDefault(require("gulp-cache"));
|
|
9
|
-
var
|
|
9
|
+
var _loadPeer = require("./loadPeer.js");
|
|
10
10
|
var _gulp = require("gulp");
|
|
11
11
|
var _nodePath = _interopRequireDefault(require("node:path"));
|
|
12
12
|
var gulpConfig = _interopRequireWildcard(require("../../gulp.config.js"));
|
|
@@ -24,18 +24,12 @@ const installHint = 'Add it to your project with: npm install --save-dev github:
|
|
|
24
24
|
* @throws {Error} With install instructions when gulp-imagemin is missing or is the ESM-only upstream release.
|
|
25
25
|
*/
|
|
26
26
|
const loadImagemin = (projectPath = process.cwd()) => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
if (error.code === 'ERR_REQUIRE_ESM') {
|
|
35
|
-
throw new Error(`gulp-imagemin could not be loaded because it is ESM-only. ${installHint}`);
|
|
36
|
-
}
|
|
37
|
-
throw error;
|
|
38
|
-
}
|
|
27
|
+
const loaded = (0, _loadPeer.requirePeer)('gulp-imagemin', {
|
|
28
|
+
task: 'images',
|
|
29
|
+
installHint,
|
|
30
|
+
esmOnlyMessage: `gulp-imagemin could not be loaded because it is ESM-only. ${installHint}`,
|
|
31
|
+
projectPath
|
|
32
|
+
});
|
|
39
33
|
return loaded && (loaded.__esModule || loaded.default) ? loaded.default : loaded;
|
|
40
34
|
};
|
|
41
35
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.requirePeer = exports.importPeer = exports.importModule = void 0;
|
|
7
|
+
require("core-js/modules/es.array.includes.js");
|
|
8
|
+
var _nodeModule = require("node:module");
|
|
9
|
+
var _nodePath = _interopRequireDefault(require("node:path"));
|
|
10
|
+
var _nodeUrl = require("node:url");
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
// Several dependencies ship ESM-only (standard, gulp-ts-compile, typedoc), but this package also publishes a CommonJS
|
|
13
|
+
// build (dist/*.js) whose babel transform would turn even a dynamic import() into a require() that cannot load an ES
|
|
14
|
+
// module. Hiding the import() inside a Function constructor keeps it a genuine dynamic import that works from either
|
|
15
|
+
// build, because babel cannot see (and so cannot rewrite) an import expression which only exists as a runtime string.
|
|
16
|
+
const dynamicImport = new Function('specifier', 'return import(specifier)');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Import an ES module (or any module) with a real dynamic import(), whichever build (ESM or CommonJS) this runs from.
|
|
20
|
+
* @memberOf module:partials
|
|
21
|
+
* @param {string} specifier - The package name, or the URL of a file.
|
|
22
|
+
* @returns {Promise<Object>} The module namespace.
|
|
23
|
+
*/
|
|
24
|
+
const importModule = specifier => dynamicImport(specifier);
|
|
25
|
+
exports.importModule = importModule;
|
|
26
|
+
const isMissing = (error, name) => error.code === 'MODULE_NOT_FOUND' && error.message.includes(`'${name}'`);
|
|
27
|
+
const notInstalled = (name, {
|
|
28
|
+
task,
|
|
29
|
+
installHint
|
|
30
|
+
}) => new Error(`The ${task} task needs the optional peer dependency ${name}, which is not installed. ${installHint}`);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Load an optional peer dependency (one which is only needed once a task runs, so projects which never use that task
|
|
34
|
+
* do not have to install it) with require(), from the project being built rather than from this package. When it is
|
|
35
|
+
* missing the error explains how to install it.
|
|
36
|
+
* @memberOf module:partials
|
|
37
|
+
* @param {string} name - The package name.
|
|
38
|
+
* @param {Object} options
|
|
39
|
+
* @param {string} options.task - The task which needs the package, for the error message.
|
|
40
|
+
* @param {string} options.installHint - How to install it, for the error message.
|
|
41
|
+
* @param {string} [options.esmOnlyMessage] - The error message when the package turns out to be ESM-only (it cannot be require()d).
|
|
42
|
+
* @param {string} [options.projectPath=process.cwd()] - The folder of the project (which has the package.json) being built.
|
|
43
|
+
* @returns {*} Whatever the package exports.
|
|
44
|
+
* @throws {Error} With install instructions when the package is not installed.
|
|
45
|
+
*/
|
|
46
|
+
const requirePeer = (name, {
|
|
47
|
+
task,
|
|
48
|
+
installHint,
|
|
49
|
+
esmOnlyMessage,
|
|
50
|
+
projectPath = process.cwd()
|
|
51
|
+
}) => {
|
|
52
|
+
try {
|
|
53
|
+
return (0, _nodeModule.createRequire)(_nodePath.default.join(projectPath, 'package.json'))(name);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
if (isMissing(error, name)) {
|
|
56
|
+
throw notInstalled(name, {
|
|
57
|
+
task,
|
|
58
|
+
installHint
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (error.code === 'ERR_REQUIRE_ESM' && esmOnlyMessage) {
|
|
62
|
+
throw new Error(esmOnlyMessage);
|
|
63
|
+
}
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Import an optional peer dependency which ships ESM-only, from the project being built. See {@link requirePeer}.
|
|
70
|
+
* @memberOf module:partials
|
|
71
|
+
* @param {string} name - The package name.
|
|
72
|
+
* @param {Object} options
|
|
73
|
+
* @param {string} options.task - The task which needs the package, for the error message.
|
|
74
|
+
* @param {string} options.installHint - How to install it, for the error message.
|
|
75
|
+
* @param {string} [options.projectPath=process.cwd()] - The folder of the project (which has the package.json) being built.
|
|
76
|
+
* @returns {Promise<Object>} The module namespace.
|
|
77
|
+
* @throws {Error} With install instructions when the package is not installed.
|
|
78
|
+
*/
|
|
79
|
+
exports.requirePeer = requirePeer;
|
|
80
|
+
const importPeer = async (name, {
|
|
81
|
+
task,
|
|
82
|
+
installHint,
|
|
83
|
+
projectPath = process.cwd()
|
|
84
|
+
}) => {
|
|
85
|
+
let resolved;
|
|
86
|
+
try {
|
|
87
|
+
resolved = (0, _nodeModule.createRequire)(_nodePath.default.join(projectPath, 'package.json')).resolve(name);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
if (isMissing(error, name)) {
|
|
90
|
+
throw notInstalled(name, {
|
|
91
|
+
task,
|
|
92
|
+
installHint
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
return importModule((0, _nodeUrl.pathToFileURL)(resolved).href);
|
|
98
|
+
};
|
|
99
|
+
exports.importPeer = importPeer;
|
|
@@ -8,12 +8,10 @@ require("core-js/modules/esnext.iterator.constructor.js");
|
|
|
8
8
|
require("core-js/modules/esnext.iterator.for-each.js");
|
|
9
9
|
var _nodePath = _interopRequireDefault(require("node:path"));
|
|
10
10
|
var _through = _interopRequireDefault(require("through2"));
|
|
11
|
+
var _loadPeer = require("./loadPeer.js");
|
|
11
12
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
-
// `standard` (17+) ships ESM-only,
|
|
13
|
-
|
|
14
|
-
// inside a Function constructor keeps it a genuine dynamic import that works from either build (same escape hatch
|
|
15
|
-
// as tsFor.mjs uses for gulp-ts-compile).
|
|
16
|
-
const importStandard = new Function('return import(\'standard\')');
|
|
13
|
+
// `standard` (17+) ships ESM-only, see importModule for how it is imported.
|
|
14
|
+
const importStandard = () => (0, _loadPeer.importModule)('standard');
|
|
17
15
|
|
|
18
16
|
/**
|
|
19
17
|
* Print a file's lint messages, if it has any.
|
package/dist/partials/tsFor.js
CHANGED
|
@@ -8,18 +8,11 @@ exports.tsFor = exports.loadTypescript = void 0;
|
|
|
8
8
|
var _gulp = require("gulp");
|
|
9
9
|
var _nodePath = _interopRequireDefault(require("node:path"));
|
|
10
10
|
var gulpConfig = _interopRequireWildcard(require("../../gulp.config.js"));
|
|
11
|
-
var
|
|
11
|
+
var _loadPeer = require("./loadPeer.js");
|
|
12
12
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
13
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
-
// gulp-ts-compile ships ESM-only (no CJS build - see its own package.json)
|
|
15
|
-
|
|
16
|
-
// compiles itself to a CommonJS build (dist/*.js, this file's own compiled counterpart) for consumers using
|
|
17
|
-
// require() though, and even a dynamic `import()` gets downleveled by babel's CommonJS transform into a
|
|
18
|
-
// require() call - which can't load a real ES module. Hiding the import() call inside a Function constructor is
|
|
19
|
-
// the standard escape hatch: babel can't see (and so can't rewrite) an import expression that only exists as a
|
|
20
|
-
// runtime-evaluated string, so it survives as a genuine dynamic import, capable of loading gulp-ts-compile from
|
|
21
|
-
// either build.
|
|
22
|
-
const importGulpTsCompile = new Function('return import(\'gulp-ts-compile\')');
|
|
14
|
+
// gulp-ts-compile ships ESM-only (no CJS build - see its own package.json), see importModule for how it is imported.
|
|
15
|
+
const importGulpTsCompile = () => (0, _loadPeer.importModule)('gulp-ts-compile');
|
|
23
16
|
|
|
24
17
|
/**
|
|
25
18
|
* Wrap a stream in a promise that resolves once it finishes writing.
|
|
@@ -37,16 +30,11 @@ const installHint = 'Install it in your project with: npm install --save-dev typ
|
|
|
37
30
|
* @returns {Object} The TypeScript compiler API module.
|
|
38
31
|
* @throws {Error} With install instructions when typescript is not installed.
|
|
39
32
|
*/
|
|
40
|
-
const loadTypescript = (projectPath = process.cwd()) => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
throw new Error(`The typescript task needs the optional peer dependency typescript, which is not installed. ${installHint}`);
|
|
46
|
-
}
|
|
47
|
-
throw error;
|
|
48
|
-
}
|
|
49
|
-
};
|
|
33
|
+
const loadTypescript = (projectPath = process.cwd()) => (0, _loadPeer.requirePeer)('typescript', {
|
|
34
|
+
task: 'typescript',
|
|
35
|
+
installHint,
|
|
36
|
+
projectPath
|
|
37
|
+
});
|
|
50
38
|
exports.loadTypescript = loadTypescript;
|
|
51
39
|
const streamToPromise = stream => new Promise((resolve, reject) => {
|
|
52
40
|
stream.on('finish', resolve);
|
|
@@ -4,10 +4,11 @@ require("core-js/modules/esnext.weak-map.delete-all.js");
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.writeDocEntries = exports.typeDocsFor = exports.loadTypeDoc = exports.describeExports = void 0;
|
|
7
|
+
exports.writeDocEntries = exports.typeDocsFor = exports.loadTypeDoc = exports.describeFolder = exports.describeFile = exports.describeExports = void 0;
|
|
8
8
|
require("core-js/modules/es.json.stringify.js");
|
|
9
9
|
require("core-js/modules/esnext.iterator.constructor.js");
|
|
10
10
|
require("core-js/modules/esnext.iterator.filter.js");
|
|
11
|
+
require("core-js/modules/esnext.iterator.find.js");
|
|
11
12
|
require("core-js/modules/esnext.iterator.flat-map.js");
|
|
12
13
|
require("core-js/modules/esnext.iterator.for-each.js");
|
|
13
14
|
require("core-js/modules/esnext.iterator.map.js");
|
|
@@ -15,16 +16,12 @@ require("core-js/modules/esnext.iterator.some.js");
|
|
|
15
16
|
var _nodeFs = _interopRequireDefault(require("node:fs"));
|
|
16
17
|
var _nodeOs = _interopRequireDefault(require("node:os"));
|
|
17
18
|
var _nodePath = _interopRequireDefault(require("node:path"));
|
|
18
|
-
var _nodeModule = require("node:module");
|
|
19
|
-
var _nodeUrl = require("node:url");
|
|
20
19
|
var gulpConfig = _interopRequireWildcard(require("../../gulp.config.js"));
|
|
20
|
+
var _loadPeer = require("./loadPeer.js");
|
|
21
21
|
var _tsFor = require("./tsFor.js");
|
|
22
22
|
var _removeDirectory = require("./removeDirectory.js");
|
|
23
23
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
24
24
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
25
|
-
// TypeDoc ships ESM-only, and this project also compiles itself to a CommonJS build (see tsFor.mjs, which hides its
|
|
26
|
-
// own import of gulp-ts-compile the same way), so the import() is hidden from babel's CommonJS transform.
|
|
27
|
-
const importModule = new Function('specifier', 'return import(specifier)');
|
|
28
25
|
const installHint = 'Install it in your project with: npm install --save-dev typedoc';
|
|
29
26
|
|
|
30
27
|
/**
|
|
@@ -35,18 +32,11 @@ const installHint = 'Install it in your project with: npm install --save-dev typ
|
|
|
35
32
|
* @returns {Promise<Object>} The TypeDoc module.
|
|
36
33
|
* @throws {Error} With install instructions when typedoc is not installed.
|
|
37
34
|
*/
|
|
38
|
-
const loadTypeDoc =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (error.code === 'MODULE_NOT_FOUND') {
|
|
44
|
-
throw new Error(`The docs task needs the optional peer dependency typedoc, which is not installed. ${installHint}`);
|
|
45
|
-
}
|
|
46
|
-
throw error;
|
|
47
|
-
}
|
|
48
|
-
return importModule((0, _nodeUrl.pathToFileURL)(typeDocPath).href);
|
|
49
|
-
};
|
|
35
|
+
const loadTypeDoc = (projectPath = process.cwd()) => (0, _loadPeer.importPeer)('typedoc', {
|
|
36
|
+
task: 'docs',
|
|
37
|
+
installHint,
|
|
38
|
+
projectPath
|
|
39
|
+
});
|
|
50
40
|
exports.loadTypeDoc = loadTypeDoc;
|
|
51
41
|
const isSource = fileName => /\.(ts|tsx|mts|cts)$/.test(fileName) && !/\.d\.[cm]?ts$/.test(fileName) && !/\.(test|spec)\./.test(fileName);
|
|
52
42
|
const listSources = dirPath => _nodeFs.default.readdirSync(dirPath, {
|
|
@@ -102,19 +92,53 @@ const describeExports = (ts, filePath) => {
|
|
|
102
92
|
};
|
|
103
93
|
};
|
|
104
94
|
|
|
95
|
+
/**
|
|
96
|
+
* The description of a folder for its module: the first doc comment of the folder's index file, without its tags
|
|
97
|
+
* (@module, @file, ...), or an empty string when there is none.
|
|
98
|
+
* @memberOf module:partials
|
|
99
|
+
* @param {string} folderPath
|
|
100
|
+
* @returns {string}
|
|
101
|
+
*/
|
|
102
|
+
exports.describeExports = describeExports;
|
|
103
|
+
const describeFolder = folderPath => {
|
|
104
|
+
const indexFile = ['index.ts', 'index.tsx', 'index.mts', 'index.cts'].map(name => _nodePath.default.join(folderPath, name)).find(file => _nodeFs.default.existsSync(file));
|
|
105
|
+
return indexFile ? describeFile(indexFile) : '';
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The description of a source file for its module: its first doc comment without the tags (@module, @file, ...), when
|
|
110
|
+
* that comment is a header (it is followed by an import or export, so it does not document a declaration itself), or
|
|
111
|
+
* an empty string.
|
|
112
|
+
* @memberOf module:partials
|
|
113
|
+
* @param {string} filePath
|
|
114
|
+
* @returns {string}
|
|
115
|
+
*/
|
|
116
|
+
exports.describeFolder = describeFolder;
|
|
117
|
+
const describeFile = filePath => {
|
|
118
|
+
const comment = _nodeFs.default.readFileSync(filePath, 'utf8').match(/^\s*\/\*\*([\s\S]*?)\*\/\s*(import\b|export\s+(\*|\{[^}]*\}\s+from)|$)/);
|
|
119
|
+
if (!comment) {
|
|
120
|
+
return '';
|
|
121
|
+
}
|
|
122
|
+
const lines = comment[1].split('\n').map(line => line.replace(/^\s*\* ?/, '').trimEnd());
|
|
123
|
+
const tagAt = lines.findIndex(line => /^@\w+/.test(line));
|
|
124
|
+
return (tagAt === -1 ? lines : lines.slice(0, tagAt)).join('\n').trim();
|
|
125
|
+
};
|
|
126
|
+
|
|
105
127
|
/**
|
|
106
128
|
* Write one entry file per folder of the source directory into the entry directory. TypeDoc makes a module of every
|
|
107
129
|
* entry file, so the modules of the documentation mirror the folders. The default export of each source file is
|
|
108
130
|
* re-exported under the name of the file (the source files hold one function each), and anything else a file exports
|
|
109
131
|
* is re-exported as it is (that is where the types.ts files go). Index files (the barrels), tests and declaration
|
|
110
|
-
* files are left out
|
|
132
|
+
* files are left out, but the first doc comment of a folder's index file becomes the description of its module.
|
|
133
|
+
* A file which sits beside the folders (not an index or main file) is a module of its own, described by its header
|
|
134
|
+
* comment. A source directory with no folders gets a single entry called index.
|
|
111
135
|
* @memberOf module:partials
|
|
112
136
|
* @param {Object} ts - The TypeScript compiler API.
|
|
113
137
|
* @param {string} srcDir - The directory holding the TypeScript source.
|
|
114
138
|
* @param {string} entryDir - The directory to write the entry files into.
|
|
115
139
|
* @returns {Array<string>} The paths of the entry files.
|
|
116
140
|
*/
|
|
117
|
-
exports.
|
|
141
|
+
exports.describeFile = describeFile;
|
|
118
142
|
const writeDocEntries = (ts, srcDir, entryDir) => {
|
|
119
143
|
const absoluteSrc = _nodePath.default.resolve(srcDir);
|
|
120
144
|
_nodeFs.default.mkdirSync(entryDir, {
|
|
@@ -124,11 +148,22 @@ const writeDocEntries = (ts, srcDir, entryDir) => {
|
|
|
124
148
|
withFileTypes: true
|
|
125
149
|
}).filter(entry => entry.isDirectory() && entry.name !== 'node_modules').map(entry => ({
|
|
126
150
|
name: entry.name,
|
|
151
|
+
path: _nodePath.default.join(absoluteSrc, entry.name),
|
|
127
152
|
files: listSources(_nodePath.default.join(absoluteSrc, entry.name))
|
|
128
153
|
})).filter(folder => folder.files.length);
|
|
129
|
-
const
|
|
154
|
+
const rootFiles = _nodeFs.default.readdirSync(absoluteSrc, {
|
|
155
|
+
withFileTypes: true
|
|
156
|
+
}).filter(entry => entry.isFile() && isSource(entry.name) && !/^(index|main)\./.test(entry.name)).map(entry => _nodePath.default.join(absoluteSrc, entry.name));
|
|
157
|
+
// Folders make modules, and so do the files which sit beside them (except the barrel: index and main). A source
|
|
158
|
+
// directory with no folders gets a single module called index which holds its files.
|
|
159
|
+
const groups = folders.length ? [...folders, ...rootFiles.map(file => ({
|
|
160
|
+
name: toIdentifier(_nodePath.default.basename(file).replace(/\.[cm]?tsx?$/, '')),
|
|
161
|
+
files: [file],
|
|
162
|
+
description: describeFile(file)
|
|
163
|
+
})).filter(group => !folders.some(folder => folder.name === group.name))] : [{
|
|
130
164
|
name: 'index',
|
|
131
|
-
|
|
165
|
+
path: absoluteSrc,
|
|
166
|
+
files: rootFiles
|
|
132
167
|
}];
|
|
133
168
|
return groups.map(group => {
|
|
134
169
|
const lines = group.files.filter(file => !/^index\./.test(_nodePath.default.basename(file))).sort().flatMap(file => {
|
|
@@ -140,8 +175,11 @@ const writeDocEntries = (ts, srcDir, entryDir) => {
|
|
|
140
175
|
const fileName = _nodePath.default.basename(file).replace(/\.[cm]?tsx?$/, '');
|
|
141
176
|
return [...(hasDefault ? [`export { default as ${toIdentifier(fileName)} } from '${modulePath}'`] : []), ...(hasNamed ? [`export * from '${modulePath}'`] : [])];
|
|
142
177
|
});
|
|
178
|
+
const description = group.description ?? (group.path ? describeFolder(group.path) : '');
|
|
179
|
+
// TypeDoc takes the first comment of an entry file which has the @module tag as the description of the module
|
|
180
|
+
const moduleComment = description ? `/**\n${description.split('\n').map(line => ` * ${line}`.trimEnd()).join('\n')}\n * @module\n */\n\n` : '';
|
|
143
181
|
const entryPath = _nodePath.default.join(entryDir, `${group.name}.ts`);
|
|
144
|
-
_nodeFs.default.writeFileSync(entryPath, lines.join('\n') + '\n');
|
|
182
|
+
_nodeFs.default.writeFileSync(entryPath, moduleComment + lines.join('\n') + '\n');
|
|
145
183
|
return entryPath;
|
|
146
184
|
});
|
|
147
185
|
};
|