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/dist/partials.js
CHANGED
|
@@ -1,117 +1,136 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', {
|
|
4
|
-
value: true
|
|
5
|
-
})
|
|
6
|
-
Object.defineProperty(exports, 'addToReadme', {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: function () {
|
|
9
|
-
return _addToReadme.addToReadme
|
|
10
|
-
}
|
|
11
|
-
})
|
|
12
|
-
Object.defineProperty(exports, 'beginWatcher', {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
get: function () {
|
|
15
|
-
return _beginWatcher.beginWatcher
|
|
16
|
-
}
|
|
17
|
-
})
|
|
18
|
-
Object.defineProperty(exports, 'clean', {
|
|
19
|
-
enumerable: true,
|
|
20
|
-
get: function () {
|
|
21
|
-
return _clean.clean
|
|
22
|
-
}
|
|
23
|
-
})
|
|
24
|
-
Object.defineProperty(exports, 'copyFor', {
|
|
25
|
-
enumerable: true,
|
|
26
|
-
get: function () {
|
|
27
|
-
return _copyFor.copyFor
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
Object.defineProperty(exports, 'distFor', {
|
|
31
|
-
enumerable: true,
|
|
32
|
-
get: function () {
|
|
33
|
-
return _distFor.distFor
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
Object.defineProperty(exports, 'distForSrc', {
|
|
37
|
-
enumerable: true,
|
|
38
|
-
get: function () {
|
|
39
|
-
return _distForSrc.distForSrc
|
|
40
|
-
}
|
|
41
|
-
})
|
|
42
|
-
Object.defineProperty(exports, 'distSeries', {
|
|
43
|
-
enumerable: true,
|
|
44
|
-
get: function () {
|
|
45
|
-
return _distSeries.distSeries
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
Object.defineProperty(exports, 'imagesFor', {
|
|
49
|
-
enumerable: true,
|
|
50
|
-
get: function () {
|
|
51
|
-
return _imagesFor.imagesFor
|
|
52
|
-
}
|
|
53
|
-
})
|
|
54
|
-
Object.defineProperty(exports, '
|
|
55
|
-
enumerable: true,
|
|
56
|
-
get: function () {
|
|
57
|
-
return
|
|
58
|
-
}
|
|
59
|
-
})
|
|
60
|
-
Object.defineProperty(exports, '
|
|
61
|
-
enumerable: true,
|
|
62
|
-
get: function () {
|
|
63
|
-
return
|
|
64
|
-
}
|
|
65
|
-
})
|
|
66
|
-
Object.defineProperty(exports, '
|
|
67
|
-
enumerable: true,
|
|
68
|
-
get: function () {
|
|
69
|
-
return
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
Object.defineProperty(exports, '
|
|
73
|
-
enumerable: true,
|
|
74
|
-
get: function () {
|
|
75
|
-
return
|
|
76
|
-
}
|
|
77
|
-
})
|
|
78
|
-
Object.defineProperty(exports, '
|
|
79
|
-
enumerable: true,
|
|
80
|
-
get: function () {
|
|
81
|
-
return
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
|
-
Object.defineProperty(exports, '
|
|
85
|
-
enumerable: true,
|
|
86
|
-
get: function () {
|
|
87
|
-
return
|
|
88
|
-
}
|
|
89
|
-
})
|
|
90
|
-
Object.defineProperty(exports, '
|
|
91
|
-
enumerable: true,
|
|
92
|
-
get: function () {
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
})
|
|
96
|
-
Object.defineProperty(exports, '
|
|
97
|
-
enumerable: true,
|
|
98
|
-
get: function () {
|
|
99
|
-
return
|
|
100
|
-
}
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', {
|
|
4
|
+
value: true
|
|
5
|
+
})
|
|
6
|
+
Object.defineProperty(exports, 'addToReadme', {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _addToReadme.addToReadme
|
|
10
|
+
}
|
|
11
|
+
})
|
|
12
|
+
Object.defineProperty(exports, 'beginWatcher', {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _beginWatcher.beginWatcher
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
Object.defineProperty(exports, 'clean', {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _clean.clean
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
Object.defineProperty(exports, 'copyFor', {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _copyFor.copyFor
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
Object.defineProperty(exports, 'distFor', {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return _distFor.distFor
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
Object.defineProperty(exports, 'distForSrc', {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () {
|
|
39
|
+
return _distForSrc.distForSrc
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
Object.defineProperty(exports, 'distSeries', {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function () {
|
|
45
|
+
return _distSeries.distSeries
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
Object.defineProperty(exports, 'imagesFor', {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () {
|
|
51
|
+
return _imagesFor.imagesFor
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
Object.defineProperty(exports, 'importModule', {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function () {
|
|
57
|
+
return _loadPeer.importModule
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
Object.defineProperty(exports, 'importPeer', {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function () {
|
|
63
|
+
return _loadPeer.importPeer
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
Object.defineProperty(exports, 'minifyFor', {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function () {
|
|
69
|
+
return _minifyFor.minifyFor
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
Object.defineProperty(exports, 'readmeTemplate', {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function () {
|
|
75
|
+
return _readmeTemplate.readmeTemplate
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
Object.defineProperty(exports, 'removeDirectory', {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: function () {
|
|
81
|
+
return _removeDirectory.removeDirectory
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
Object.defineProperty(exports, 'requirePeer', {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function () {
|
|
87
|
+
return _loadPeer.requirePeer
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
Object.defineProperty(exports, 'runOnChange', {
|
|
91
|
+
enumerable: true,
|
|
92
|
+
get: function () {
|
|
93
|
+
return _runOnChange.runOnChange
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
Object.defineProperty(exports, 'sassFor', {
|
|
97
|
+
enumerable: true,
|
|
98
|
+
get: function () {
|
|
99
|
+
return _sassFor.sassFor
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
Object.defineProperty(exports, 'standardLint', {
|
|
103
|
+
enumerable: true,
|
|
104
|
+
get: function () {
|
|
105
|
+
return _standardLint.standardLint
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
Object.defineProperty(exports, 'tsFor', {
|
|
109
|
+
enumerable: true,
|
|
110
|
+
get: function () {
|
|
111
|
+
return _tsFor.tsFor
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
Object.defineProperty(exports, 'typeDocsFor', {
|
|
115
|
+
enumerable: true,
|
|
116
|
+
get: function () {
|
|
117
|
+
return _typeDocsFor.typeDocsFor
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
var _addToReadme = require('./partials/addToReadme.js')
|
|
121
|
+
var _beginWatcher = require('./partials/beginWatcher.js')
|
|
122
|
+
var _clean = require('./partials/clean.js')
|
|
123
|
+
var _copyFor = require('./partials/copyFor.js')
|
|
124
|
+
var _distFor = require('./partials/distFor.js')
|
|
125
|
+
var _distForSrc = require('./partials/distForSrc.js')
|
|
126
|
+
var _distSeries = require('./partials/distSeries.js')
|
|
127
|
+
var _imagesFor = require('./partials/imagesFor.js')
|
|
128
|
+
var _loadPeer = require('./partials/loadPeer.js')
|
|
129
|
+
var _minifyFor = require('./partials/minifyFor.js')
|
|
130
|
+
var _readmeTemplate = require('./partials/readmeTemplate.js')
|
|
131
|
+
var _removeDirectory = require('./partials/removeDirectory.js')
|
|
132
|
+
var _runOnChange = require('./partials/runOnChange.js')
|
|
133
|
+
var _sassFor = require('./partials/sassFor.js')
|
|
134
|
+
var _standardLint = require('./partials/standardLint.js')
|
|
135
|
+
var _tsFor = require('./partials/tsFor.js')
|
|
136
|
+
var _typeDocsFor = require('./partials/typeDocsFor.js')
|
package/dist/partials.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"addToReadme",{enumerable:!0,get:function(){return _addToReadme.addToReadme}}),Object.defineProperty(exports,"beginWatcher",{enumerable:!0,get:function(){return _beginWatcher.beginWatcher}}),Object.defineProperty(exports,"clean",{enumerable:!0,get:function(){return _clean.clean}}),Object.defineProperty(exports,"copyFor",{enumerable:!0,get:function(){return _copyFor.copyFor}}),Object.defineProperty(exports,"distFor",{enumerable:!0,get:function(){return _distFor.distFor}}),Object.defineProperty(exports,"distForSrc",{enumerable:!0,get:function(){return _distForSrc.distForSrc}}),Object.defineProperty(exports,"distSeries",{enumerable:!0,get:function(){return _distSeries.distSeries}}),Object.defineProperty(exports,"imagesFor",{enumerable:!0,get:function(){return _imagesFor.imagesFor}}),Object.defineProperty(exports,"minifyFor",{enumerable:!0,get:function(){return _minifyFor.minifyFor}}),Object.defineProperty(exports,"readmeTemplate",{enumerable:!0,get:function(){return _readmeTemplate.readmeTemplate}}),Object.defineProperty(exports,"removeDirectory",{enumerable:!0,get:function(){return _removeDirectory.removeDirectory}}),Object.defineProperty(exports,"runOnChange",{enumerable:!0,get:function(){return _runOnChange.runOnChange}}),Object.defineProperty(exports,"sassFor",{enumerable:!0,get:function(){return _sassFor.sassFor}}),Object.defineProperty(exports,"standardLint",{enumerable:!0,get:function(){return _standardLint.standardLint}}),Object.defineProperty(exports,"tsFor",{enumerable:!0,get:function(){return _tsFor.tsFor}}),Object.defineProperty(exports,"typeDocsFor",{enumerable:!0,get:function(){return _typeDocsFor.typeDocsFor}});var _addToReadme=require("./partials/addToReadme.js"),_beginWatcher=require("./partials/beginWatcher.js"),_clean=require("./partials/clean.js"),_copyFor=require("./partials/copyFor.js"),_distFor=require("./partials/distFor.js"),_distForSrc=require("./partials/distForSrc.js"),_distSeries=require("./partials/distSeries.js"),_imagesFor=require("./partials/imagesFor.js"),_minifyFor=require("./partials/minifyFor.js"),_readmeTemplate=require("./partials/readmeTemplate.js"),_removeDirectory=require("./partials/removeDirectory.js"),_runOnChange=require("./partials/runOnChange.js"),_sassFor=require("./partials/sassFor.js"),_standardLint=require("./partials/standardLint.js"),_tsFor=require("./partials/tsFor.js"),_typeDocsFor=require("./partials/typeDocsFor.js");
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"addToReadme",{enumerable:!0,get:function(){return _addToReadme.addToReadme}}),Object.defineProperty(exports,"beginWatcher",{enumerable:!0,get:function(){return _beginWatcher.beginWatcher}}),Object.defineProperty(exports,"clean",{enumerable:!0,get:function(){return _clean.clean}}),Object.defineProperty(exports,"copyFor",{enumerable:!0,get:function(){return _copyFor.copyFor}}),Object.defineProperty(exports,"distFor",{enumerable:!0,get:function(){return _distFor.distFor}}),Object.defineProperty(exports,"distForSrc",{enumerable:!0,get:function(){return _distForSrc.distForSrc}}),Object.defineProperty(exports,"distSeries",{enumerable:!0,get:function(){return _distSeries.distSeries}}),Object.defineProperty(exports,"imagesFor",{enumerable:!0,get:function(){return _imagesFor.imagesFor}}),Object.defineProperty(exports,"importModule",{enumerable:!0,get:function(){return _loadPeer.importModule}}),Object.defineProperty(exports,"importPeer",{enumerable:!0,get:function(){return _loadPeer.importPeer}}),Object.defineProperty(exports,"minifyFor",{enumerable:!0,get:function(){return _minifyFor.minifyFor}}),Object.defineProperty(exports,"readmeTemplate",{enumerable:!0,get:function(){return _readmeTemplate.readmeTemplate}}),Object.defineProperty(exports,"removeDirectory",{enumerable:!0,get:function(){return _removeDirectory.removeDirectory}}),Object.defineProperty(exports,"requirePeer",{enumerable:!0,get:function(){return _loadPeer.requirePeer}}),Object.defineProperty(exports,"runOnChange",{enumerable:!0,get:function(){return _runOnChange.runOnChange}}),Object.defineProperty(exports,"sassFor",{enumerable:!0,get:function(){return _sassFor.sassFor}}),Object.defineProperty(exports,"standardLint",{enumerable:!0,get:function(){return _standardLint.standardLint}}),Object.defineProperty(exports,"tsFor",{enumerable:!0,get:function(){return _tsFor.tsFor}}),Object.defineProperty(exports,"typeDocsFor",{enumerable:!0,get:function(){return _typeDocsFor.typeDocsFor}});var _addToReadme=require("./partials/addToReadme.js"),_beginWatcher=require("./partials/beginWatcher.js"),_clean=require("./partials/clean.js"),_copyFor=require("./partials/copyFor.js"),_distFor=require("./partials/distFor.js"),_distForSrc=require("./partials/distForSrc.js"),_distSeries=require("./partials/distSeries.js"),_imagesFor=require("./partials/imagesFor.js"),_loadPeer=require("./partials/loadPeer.js"),_minifyFor=require("./partials/minifyFor.js"),_readmeTemplate=require("./partials/readmeTemplate.js"),_removeDirectory=require("./partials/removeDirectory.js"),_runOnChange=require("./partials/runOnChange.js"),_sassFor=require("./partials/sassFor.js"),_standardLint=require("./partials/standardLint.js"),_tsFor=require("./partials/tsFor.js"),_typeDocsFor=require("./partials/typeDocsFor.js");
|
package/dist/typeDocs.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', {
|
|
4
|
-
value: true
|
|
5
|
-
})
|
|
6
|
-
exports.typeDocs = void 0
|
|
7
|
-
const _typeDocsFor = require('./partials/typeDocsFor.js')
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', {
|
|
4
|
+
value: true
|
|
5
|
+
})
|
|
6
|
+
exports.typeDocs = void 0
|
|
7
|
+
const _typeDocsFor = require('./partials/typeDocsFor.js')
|
|
8
8
|
/**
|
|
9
9
|
* Generate the HTML documentation of a TypeScript project from its source, with the modules mirroring the source
|
|
10
10
|
* folders. Turn it on with docs.enabled, see {@link module:partials.typeDocsFor}.
|
|
11
11
|
* @memberOf module:js-build-tools
|
|
12
12
|
* @returns {Function}
|
|
13
|
-
*/
|
|
14
|
-
const typeDocs = exports.typeDocs = (0, _typeDocsFor.typeDocsFor)()
|
|
13
|
+
*/
|
|
14
|
+
const typeDocs = exports.typeDocs = (0, _typeDocsFor.typeDocsFor)()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import cache from 'gulp-cache'
|
|
2
|
-
import {
|
|
2
|
+
import { requirePeer } from './loadPeer.mjs'
|
|
3
3
|
import { dest, src } from 'gulp'
|
|
4
4
|
import path from 'node:path'
|
|
5
5
|
import * as gulpConfig from '../../gulp.config.mjs'
|
|
@@ -17,18 +17,12 @@ const installHint = 'Add it to your project with: npm install --save-dev github:
|
|
|
17
17
|
* @throws {Error} With install instructions when gulp-imagemin is missing or is the ESM-only upstream release.
|
|
18
18
|
*/
|
|
19
19
|
export const loadImagemin = (projectPath = process.cwd()) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
if (error.code === 'ERR_REQUIRE_ESM') {
|
|
28
|
-
throw new Error(`gulp-imagemin could not be loaded because it is ESM-only. ${installHint}`)
|
|
29
|
-
}
|
|
30
|
-
throw error
|
|
31
|
-
}
|
|
20
|
+
const loaded = requirePeer('gulp-imagemin', {
|
|
21
|
+
task: 'images',
|
|
22
|
+
installHint,
|
|
23
|
+
esmOnlyMessage: `gulp-imagemin could not be loaded because it is ESM-only. ${installHint}`,
|
|
24
|
+
projectPath
|
|
25
|
+
})
|
|
32
26
|
return loaded && (loaded.__esModule || loaded.default) ? loaded.default : loaded
|
|
33
27
|
}
|
|
34
28
|
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { pathToFileURL } from 'node:url'
|
|
4
|
+
|
|
5
|
+
// Several dependencies ship ESM-only (standard, gulp-ts-compile, typedoc), but this package also publishes a CommonJS
|
|
6
|
+
// build (dist/*.js) whose babel transform would turn even a dynamic import() into a require() that cannot load an ES
|
|
7
|
+
// module. Hiding the import() inside a Function constructor keeps it a genuine dynamic import that works from either
|
|
8
|
+
// build, because babel cannot see (and so cannot rewrite) an import expression which only exists as a runtime string.
|
|
9
|
+
const dynamicImport = new Function('specifier', 'return import(specifier)')
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Import an ES module (or any module) with a real dynamic import(), whichever build (ESM or CommonJS) this runs from.
|
|
13
|
+
* @memberOf module:partials
|
|
14
|
+
* @param {string} specifier - The package name, or the URL of a file.
|
|
15
|
+
* @returns {Promise<Object>} The module namespace.
|
|
16
|
+
*/
|
|
17
|
+
export const importModule = specifier => dynamicImport(specifier)
|
|
18
|
+
|
|
19
|
+
const isMissing = (error, name) => error.code === 'MODULE_NOT_FOUND' && error.message.includes(`'${name}'`)
|
|
20
|
+
|
|
21
|
+
const notInstalled = (name, { task, installHint }) => new Error(
|
|
22
|
+
`The ${task} task needs the optional peer dependency ${name}, which is not installed. ${installHint}`
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Load an optional peer dependency (one which is only needed once a task runs, so projects which never use that task
|
|
27
|
+
* do not have to install it) with require(), from the project being built rather than from this package. When it is
|
|
28
|
+
* missing the error explains how to install it.
|
|
29
|
+
* @memberOf module:partials
|
|
30
|
+
* @param {string} name - The package name.
|
|
31
|
+
* @param {Object} options
|
|
32
|
+
* @param {string} options.task - The task which needs the package, for the error message.
|
|
33
|
+
* @param {string} options.installHint - How to install it, for the error message.
|
|
34
|
+
* @param {string} [options.esmOnlyMessage] - The error message when the package turns out to be ESM-only (it cannot be require()d).
|
|
35
|
+
* @param {string} [options.projectPath=process.cwd()] - The folder of the project (which has the package.json) being built.
|
|
36
|
+
* @returns {*} Whatever the package exports.
|
|
37
|
+
* @throws {Error} With install instructions when the package is not installed.
|
|
38
|
+
*/
|
|
39
|
+
export const requirePeer = (name, { task, installHint, esmOnlyMessage, projectPath = process.cwd() }) => {
|
|
40
|
+
try {
|
|
41
|
+
return createRequire(path.join(projectPath, 'package.json'))(name)
|
|
42
|
+
} catch (error) {
|
|
43
|
+
if (isMissing(error, name)) {
|
|
44
|
+
throw notInstalled(name, { task, installHint })
|
|
45
|
+
}
|
|
46
|
+
if (error.code === 'ERR_REQUIRE_ESM' && esmOnlyMessage) {
|
|
47
|
+
throw new Error(esmOnlyMessage)
|
|
48
|
+
}
|
|
49
|
+
throw error
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Import an optional peer dependency which ships ESM-only, from the project being built. See {@link requirePeer}.
|
|
55
|
+
* @memberOf module:partials
|
|
56
|
+
* @param {string} name - The package name.
|
|
57
|
+
* @param {Object} options
|
|
58
|
+
* @param {string} options.task - The task which needs the package, for the error message.
|
|
59
|
+
* @param {string} options.installHint - How to install it, for the error message.
|
|
60
|
+
* @param {string} [options.projectPath=process.cwd()] - The folder of the project (which has the package.json) being built.
|
|
61
|
+
* @returns {Promise<Object>} The module namespace.
|
|
62
|
+
* @throws {Error} With install instructions when the package is not installed.
|
|
63
|
+
*/
|
|
64
|
+
export const importPeer = async (name, { task, installHint, projectPath = process.cwd() }) => {
|
|
65
|
+
let resolved
|
|
66
|
+
try {
|
|
67
|
+
resolved = createRequire(path.join(projectPath, 'package.json')).resolve(name)
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (isMissing(error, name)) {
|
|
70
|
+
throw notInstalled(name, { task, installHint })
|
|
71
|
+
}
|
|
72
|
+
throw error
|
|
73
|
+
}
|
|
74
|
+
return importModule(pathToFileURL(resolved).href)
|
|
75
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import * as setUp from '../test-helpers/setUp.mjs'
|
|
4
|
+
import { importModule, importPeer, requirePeer } from './loadPeer.mjs'
|
|
5
|
+
|
|
6
|
+
setUp.setDefaults('test-load-peer')
|
|
7
|
+
|
|
8
|
+
const options = { task: 'example', installHint: 'Install it with: npm install --save-dev fake-peer' }
|
|
9
|
+
|
|
10
|
+
// A project with its own node_modules, so the packages are found from the project rather than from this package
|
|
11
|
+
const projectWith = (name, files) => {
|
|
12
|
+
const project = path.resolve('test-load-peer/project')
|
|
13
|
+
fs.mkdirSync(`${project}/node_modules/${name}`, { recursive: true })
|
|
14
|
+
fs.writeFileSync(`${project}/package.json`, '{}')
|
|
15
|
+
Object.entries(files).forEach(([file, contents]) => fs.writeFileSync(`${project}/node_modules/${name}/${file}`, contents))
|
|
16
|
+
return project
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
beforeEach(setUp.beforeEach)
|
|
20
|
+
afterEach(setUp.afterEach)
|
|
21
|
+
|
|
22
|
+
describe('requirePeer', () => {
|
|
23
|
+
test('loads the package from the project being built', () => {
|
|
24
|
+
const project = projectWith('fake-peer', { 'package.json': '{"name":"fake-peer","main":"index.js"}', 'index.js': 'module.exports = { found: true }' })
|
|
25
|
+
expect(requirePeer('fake-peer', { ...options, projectPath: project })).toEqual({ found: true })
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('explains how to install the package when the project does not have it', () => {
|
|
29
|
+
expect(() => requirePeer('fake-peer', { ...options, projectPath: '/' })).toThrow(
|
|
30
|
+
'The example task needs the optional peer dependency fake-peer, which is not installed. Install it with: npm install --save-dev fake-peer'
|
|
31
|
+
)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('does not hide other errors, and explains a package which is ESM-only when it has a message for that', () => {
|
|
35
|
+
const project = projectWith('broken-peer', { 'package.json': '{"name":"broken-peer","main":"index.js"}', 'index.js': 'throw new Error("boom")' })
|
|
36
|
+
expect(() => requirePeer('broken-peer', { ...options, projectPath: project })).toThrow('boom')
|
|
37
|
+
// A missing dependency of the peer is not the peer being missing
|
|
38
|
+
const inner = projectWith('inner-peer', { 'package.json': '{"name":"inner-peer","main":"index.js"}', 'index.js': 'require("something-else-missing")' })
|
|
39
|
+
expect(() => requirePeer('inner-peer', { ...options, projectPath: inner })).toThrow(/something-else-missing/)
|
|
40
|
+
expect(() => requirePeer('inner-peer', { ...options, projectPath: inner })).not.toThrow(/optional peer dependency/)
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
describe('importPeer', () => {
|
|
45
|
+
test('explains how to install the package when the project does not have it', async () => {
|
|
46
|
+
await expect(importPeer('fake-peer', { ...options, projectPath: '/' })).rejects.toThrow(
|
|
47
|
+
/needs the optional peer dependency fake-peer, which is not installed. Install it with/
|
|
48
|
+
)
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe('importModule', () => {
|
|
53
|
+
// The real import() cannot run under this project's CommonJS-transform-based Jest setup (see tsFor.mjs), so the
|
|
54
|
+
// loaders are checked by running the tasks for real, see the pull request.
|
|
55
|
+
test('is a function', () => {
|
|
56
|
+
expect(importModule).toBeInstanceOf(Function)
|
|
57
|
+
})
|
|
58
|
+
})
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
2
|
import through from 'through2'
|
|
3
|
+
import { importModule } from './loadPeer.mjs'
|
|
3
4
|
|
|
4
|
-
// `standard` (17+) ships ESM-only,
|
|
5
|
-
|
|
6
|
-
// inside a Function constructor keeps it a genuine dynamic import that works from either build (same escape hatch
|
|
7
|
-
// as tsFor.mjs uses for gulp-ts-compile).
|
|
8
|
-
const importStandard = new Function('return import(\'standard\')')
|
|
5
|
+
// `standard` (17+) ships ESM-only, see importModule for how it is imported.
|
|
6
|
+
const importStandard = () => importModule('standard')
|
|
9
7
|
|
|
10
8
|
/**
|
|
11
9
|
* Print a file's lint messages, if it has any.
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
import { dest, src } from 'gulp'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import * as gulpConfig from '../../gulp.config.mjs'
|
|
4
|
-
import {
|
|
4
|
+
import { importModule, requirePeer } from './loadPeer.mjs'
|
|
5
5
|
|
|
6
|
-
// gulp-ts-compile ships ESM-only (no CJS build - see its own package.json)
|
|
7
|
-
|
|
8
|
-
// compiles itself to a CommonJS build (dist/*.js, this file's own compiled counterpart) for consumers using
|
|
9
|
-
// require() though, and even a dynamic `import()` gets downleveled by babel's CommonJS transform into a
|
|
10
|
-
// require() call - which can't load a real ES module. Hiding the import() call inside a Function constructor is
|
|
11
|
-
// the standard escape hatch: babel can't see (and so can't rewrite) an import expression that only exists as a
|
|
12
|
-
// runtime-evaluated string, so it survives as a genuine dynamic import, capable of loading gulp-ts-compile from
|
|
13
|
-
// either build.
|
|
14
|
-
const importGulpTsCompile = new Function('return import(\'gulp-ts-compile\')')
|
|
6
|
+
// gulp-ts-compile ships ESM-only (no CJS build - see its own package.json), see importModule for how it is imported.
|
|
7
|
+
const importGulpTsCompile = () => importModule('gulp-ts-compile')
|
|
15
8
|
|
|
16
9
|
/**
|
|
17
10
|
* Wrap a stream in a promise that resolves once it finishes writing.
|
|
@@ -29,16 +22,7 @@ const installHint = 'Install it in your project with: npm install --save-dev typ
|
|
|
29
22
|
* @returns {Object} The TypeScript compiler API module.
|
|
30
23
|
* @throws {Error} With install instructions when typescript is not installed.
|
|
31
24
|
*/
|
|
32
|
-
export const loadTypescript = (projectPath = process.cwd()) => {
|
|
33
|
-
try {
|
|
34
|
-
return createRequire(path.join(projectPath, 'package.json'))('typescript')
|
|
35
|
-
} catch (error) {
|
|
36
|
-
if (error.code === 'MODULE_NOT_FOUND' && /Cannot find module 'typescript'/.test(error.message)) {
|
|
37
|
-
throw new Error(`The typescript task needs the optional peer dependency typescript, which is not installed. ${installHint}`)
|
|
38
|
-
}
|
|
39
|
-
throw error
|
|
40
|
-
}
|
|
41
|
-
}
|
|
25
|
+
export const loadTypescript = (projectPath = process.cwd()) => requirePeer('typescript', { task: 'typescript', installHint, projectPath })
|
|
42
26
|
|
|
43
27
|
const streamToPromise = (stream) => new Promise((resolve, reject) => {
|
|
44
28
|
stream.on('finish', resolve)
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
import os from 'node:os'
|
|
3
3
|
import path from 'node:path'
|
|
4
|
-
import { createRequire } from 'node:module'
|
|
5
|
-
import { pathToFileURL } from 'node:url'
|
|
6
4
|
import * as gulpConfig from '../../gulp.config.mjs'
|
|
5
|
+
import { importPeer } from './loadPeer.mjs'
|
|
7
6
|
import { loadTypescript } from './tsFor.mjs'
|
|
8
7
|
import { removeDirectory } from './removeDirectory.mjs'
|
|
9
8
|
|
|
10
|
-
// TypeDoc ships ESM-only, and this project also compiles itself to a CommonJS build (see tsFor.mjs, which hides its
|
|
11
|
-
// own import of gulp-ts-compile the same way), so the import() is hidden from babel's CommonJS transform.
|
|
12
|
-
const importModule = new Function('specifier', 'return import(specifier)')
|
|
13
|
-
|
|
14
9
|
const installHint = 'Install it in your project with: npm install --save-dev typedoc'
|
|
15
10
|
|
|
16
11
|
/**
|
|
@@ -21,18 +16,7 @@ const installHint = 'Install it in your project with: npm install --save-dev typ
|
|
|
21
16
|
* @returns {Promise<Object>} The TypeDoc module.
|
|
22
17
|
* @throws {Error} With install instructions when typedoc is not installed.
|
|
23
18
|
*/
|
|
24
|
-
export const loadTypeDoc =
|
|
25
|
-
let typeDocPath
|
|
26
|
-
try {
|
|
27
|
-
typeDocPath = createRequire(path.join(projectPath, 'package.json')).resolve('typedoc')
|
|
28
|
-
} catch (error) {
|
|
29
|
-
if (error.code === 'MODULE_NOT_FOUND') {
|
|
30
|
-
throw new Error(`The docs task needs the optional peer dependency typedoc, which is not installed. ${installHint}`)
|
|
31
|
-
}
|
|
32
|
-
throw error
|
|
33
|
-
}
|
|
34
|
-
return importModule(pathToFileURL(typeDocPath).href)
|
|
35
|
-
}
|
|
19
|
+
export const loadTypeDoc = (projectPath = process.cwd()) => importPeer('typedoc', { task: 'docs', installHint, projectPath })
|
|
36
20
|
|
|
37
21
|
const isSource = fileName => /\.(ts|tsx|mts|cts)$/.test(fileName) && !/\.d\.[cm]?ts$/.test(fileName) && !/\.(test|spec)\./.test(fileName)
|
|
38
22
|
|
|
@@ -86,12 +70,44 @@ export const describeExports = (ts, filePath) => {
|
|
|
86
70
|
return { hasDefault, hasNamed }
|
|
87
71
|
}
|
|
88
72
|
|
|
73
|
+
/**
|
|
74
|
+
* The description of a folder for its module: the first doc comment of the folder's index file, without its tags
|
|
75
|
+
* (@module, @file, ...), or an empty string when there is none.
|
|
76
|
+
* @memberOf module:partials
|
|
77
|
+
* @param {string} folderPath
|
|
78
|
+
* @returns {string}
|
|
79
|
+
*/
|
|
80
|
+
export const describeFolder = folderPath => {
|
|
81
|
+
const indexFile = ['index.ts', 'index.tsx', 'index.mts', 'index.cts'].map(name => path.join(folderPath, name)).find(file => fs.existsSync(file))
|
|
82
|
+
return indexFile ? describeFile(indexFile) : ''
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The description of a source file for its module: its first doc comment without the tags (@module, @file, ...), when
|
|
87
|
+
* that comment is a header (it is followed by an import or export, so it does not document a declaration itself), or
|
|
88
|
+
* an empty string.
|
|
89
|
+
* @memberOf module:partials
|
|
90
|
+
* @param {string} filePath
|
|
91
|
+
* @returns {string}
|
|
92
|
+
*/
|
|
93
|
+
export const describeFile = filePath => {
|
|
94
|
+
const comment = fs.readFileSync(filePath, 'utf8').match(/^\s*\/\*\*([\s\S]*?)\*\/\s*(import\b|export\s+(\*|\{[^}]*\}\s+from)|$)/)
|
|
95
|
+
if (!comment) {
|
|
96
|
+
return ''
|
|
97
|
+
}
|
|
98
|
+
const lines = comment[1].split('\n').map(line => line.replace(/^\s*\* ?/, '').trimEnd())
|
|
99
|
+
const tagAt = lines.findIndex(line => /^@\w+/.test(line))
|
|
100
|
+
return (tagAt === -1 ? lines : lines.slice(0, tagAt)).join('\n').trim()
|
|
101
|
+
}
|
|
102
|
+
|
|
89
103
|
/**
|
|
90
104
|
* Write one entry file per folder of the source directory into the entry directory. TypeDoc makes a module of every
|
|
91
105
|
* entry file, so the modules of the documentation mirror the folders. The default export of each source file is
|
|
92
106
|
* re-exported under the name of the file (the source files hold one function each), and anything else a file exports
|
|
93
107
|
* is re-exported as it is (that is where the types.ts files go). Index files (the barrels), tests and declaration
|
|
94
|
-
* files are left out
|
|
108
|
+
* files are left out, but the first doc comment of a folder's index file becomes the description of its module.
|
|
109
|
+
* A file which sits beside the folders (not an index or main file) is a module of its own, described by its header
|
|
110
|
+
* comment. A source directory with no folders gets a single entry called index.
|
|
95
111
|
* @memberOf module:partials
|
|
96
112
|
* @param {Object} ts - The TypeScript compiler API.
|
|
97
113
|
* @param {string} srcDir - The directory holding the TypeScript source.
|
|
@@ -103,11 +119,21 @@ export const writeDocEntries = (ts, srcDir, entryDir) => {
|
|
|
103
119
|
fs.mkdirSync(entryDir, { recursive: true })
|
|
104
120
|
const folders = fs.readdirSync(absoluteSrc, { withFileTypes: true })
|
|
105
121
|
.filter(entry => entry.isDirectory() && entry.name !== 'node_modules')
|
|
106
|
-
.map(entry => ({ name: entry.name, files: listSources(path.join(absoluteSrc, entry.name)) }))
|
|
122
|
+
.map(entry => ({ name: entry.name, path: path.join(absoluteSrc, entry.name), files: listSources(path.join(absoluteSrc, entry.name)) }))
|
|
107
123
|
.filter(folder => folder.files.length)
|
|
124
|
+
const rootFiles = fs.readdirSync(absoluteSrc, { withFileTypes: true })
|
|
125
|
+
.filter(entry => entry.isFile() && isSource(entry.name) && !/^(index|main)\./.test(entry.name))
|
|
126
|
+
.map(entry => path.join(absoluteSrc, entry.name))
|
|
127
|
+
// Folders make modules, and so do the files which sit beside them (except the barrel: index and main). A source
|
|
128
|
+
// directory with no folders gets a single module called index which holds its files.
|
|
108
129
|
const groups = folders.length
|
|
109
|
-
?
|
|
110
|
-
|
|
130
|
+
? [
|
|
131
|
+
...folders,
|
|
132
|
+
...rootFiles
|
|
133
|
+
.map(file => ({ name: toIdentifier(path.basename(file).replace(/\.[cm]?tsx?$/, '')), files: [file], description: describeFile(file) }))
|
|
134
|
+
.filter(group => !folders.some(folder => folder.name === group.name))
|
|
135
|
+
]
|
|
136
|
+
: [{ name: 'index', path: absoluteSrc, files: rootFiles }]
|
|
111
137
|
return groups.map(group => {
|
|
112
138
|
const lines = group.files
|
|
113
139
|
.filter(file => !/^index\./.test(path.basename(file)))
|
|
@@ -121,8 +147,11 @@ export const writeDocEntries = (ts, srcDir, entryDir) => {
|
|
|
121
147
|
...(hasNamed ? [`export * from '${modulePath}'`] : [])
|
|
122
148
|
]
|
|
123
149
|
})
|
|
150
|
+
const description = group.description ?? (group.path ? describeFolder(group.path) : '')
|
|
151
|
+
// TypeDoc takes the first comment of an entry file which has the @module tag as the description of the module
|
|
152
|
+
const moduleComment = description ? `/**\n${description.split('\n').map(line => ` * ${line}`.trimEnd()).join('\n')}\n * @module\n */\n\n` : ''
|
|
124
153
|
const entryPath = path.join(entryDir, `${group.name}.ts`)
|
|
125
|
-
fs.writeFileSync(entryPath, lines.join('\n') + '\n')
|
|
154
|
+
fs.writeFileSync(entryPath, moduleComment + lines.join('\n') + '\n')
|
|
126
155
|
return entryPath
|
|
127
156
|
})
|
|
128
157
|
}
|