js-build-tools 6.2.2 → 6.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +180 -9
- package/dist/build.js +66 -66
- package/dist/bundle.js +1 -1
- package/dist/docs.js +11 -11
- package/dist/partials/jsdocDocsFor.js +133 -113
- package/dist/partials/loadPlaywright.js +34 -0
- package/dist/partials/neostandardLint.js +5 -3
- package/dist/partials/resolveDocsMethod.js +12 -12
- package/dist/partials/serveStatic.js +57 -0
- package/dist/partials/tsFor.js +2 -2
- package/dist/partials/typeDocsFor.js +28 -22
- package/dist/partials.js +169 -149
- package/dist/partials.min.js +1 -1
- package/dist/test-helpers/setUp.js +6 -0
- package/dist/utilities/convertMjsFilesForDocs.js +1 -0
- package/dist/utilities/dotGet.js +1 -0
- package/dist/utilities/dotNotate.js +5 -0
- package/dist/utilities/dotSet.js +1 -0
- package/dist/utilities/esmNamedExportsToCjs.js +1 -0
- package/dist/utilities/getBundleConfigs.js +1 -0
- package/dist/utilities/isObject.js +1 -0
- package/dist/utilities/strAfter.js +1 -0
- package/dist/utilities/strBefore.js +1 -0
- package/functions/bundle.mjs +1 -1
- package/functions/jsdocEsmExports.test.mjs +24 -0
- package/functions/partials/jsdocDocsFor.mjs +33 -13
- package/functions/partials/jsdocDocsFor.test.mjs +51 -0
- package/functions/partials/loadPlaywright.mjs +23 -0
- package/functions/partials/loadPlaywright.test.mjs +71 -0
- package/functions/partials/neostandardLint.mjs +5 -3
- package/functions/partials/serveStatic.mjs +47 -0
- package/functions/partials/serveStatic.test.mjs +71 -0
- package/functions/partials/tsFor.mjs +2 -2
- package/functions/partials/typeDocsFor.mjs +24 -20
- package/functions/partials/typeDocsFor.test.mjs +23 -0
- package/functions/partials.mjs +2 -0
- package/functions/partials.test.mjs +1 -1
- package/functions/test-helpers/setUp.mjs +6 -0
- package/functions/utilities/convertMjsFilesForDocs.mjs +1 -0
- package/functions/utilities/dotGet.mjs +1 -0
- package/functions/utilities/dotNotate.mjs +5 -0
- package/functions/utilities/dotSet.mjs +1 -0
- package/functions/utilities/esmNamedExportsToCjs.mjs +1 -0
- package/functions/utilities/getBundleConfigs.mjs +1 -0
- package/functions/utilities/isObject.mjs +1 -0
- package/functions/utilities/strAfter.mjs +1 -0
- package/functions/utilities/strBefore.mjs +1 -0
- package/gulp.config.mjs +2 -2
- package/gulpfile.base.mjs +1 -3
- package/jsdoc.base.js +9 -3
- package/jsdoc.esmExports.js +17 -0
- package/package.json +16 -10
|
@@ -1,35 +1,36 @@
|
|
|
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.resolveJsdocTheme = exports.resolveJsdocBin = exports.jsdocDocsFor = void 0;
|
|
8
|
-
require("core-js/modules/es.json.stringify.js");
|
|
9
|
-
require("core-js/modules/esnext.iterator.constructor.js");
|
|
10
|
-
require("core-js/modules/esnext.iterator.find.js");
|
|
11
|
-
require("core-js/modules/esnext.iterator.map.js");
|
|
12
|
-
var _nodeFs = _interopRequireDefault(require("node:fs"));
|
|
13
|
-
var _nodeOs = _interopRequireDefault(require("node:os"));
|
|
14
|
-
var _nodePath = _interopRequireDefault(require("node:path"));
|
|
15
|
-
var _nodeModule = require("node:module");
|
|
16
|
-
var _nodeChild_process = require("node:child_process");
|
|
17
|
-
var _nodeUtil = require("node:util");
|
|
18
|
-
var gulpConfig = _interopRequireWildcard(require("../../gulp.config.js"));
|
|
19
|
-
var _removeDirectory = require("./removeDirectory.js");
|
|
20
|
-
var _jsdocBase = _interopRequireDefault(require("../../jsdoc.base.js"));
|
|
21
|
-
var cache;
|
|
22
|
-
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; }
|
|
23
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
24
|
-
// jsdoc.base.js is CommonJS (it's also required directly by consuming projects' own .jsdoc.conf.js
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
const execFileAsync = (0, _nodeUtil.promisify)(_nodeChild_process.execFile);
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
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.resolveJsdocTheme = exports.resolveJsdocBin = exports.jsdocDocsFor = void 0;
|
|
8
|
+
require("core-js/modules/es.json.stringify.js");
|
|
9
|
+
require("core-js/modules/esnext.iterator.constructor.js");
|
|
10
|
+
require("core-js/modules/esnext.iterator.find.js");
|
|
11
|
+
require("core-js/modules/esnext.iterator.map.js");
|
|
12
|
+
var _nodeFs = _interopRequireDefault(require("node:fs"));
|
|
13
|
+
var _nodeOs = _interopRequireDefault(require("node:os"));
|
|
14
|
+
var _nodePath = _interopRequireDefault(require("node:path"));
|
|
15
|
+
var _nodeModule = require("node:module");
|
|
16
|
+
var _nodeChild_process = require("node:child_process");
|
|
17
|
+
var _nodeUtil = require("node:util");
|
|
18
|
+
var gulpConfig = _interopRequireWildcard(require("../../gulp.config.js"));
|
|
19
|
+
var _removeDirectory = require("./removeDirectory.js");
|
|
20
|
+
var _jsdocBase = _interopRequireDefault(require("../../jsdoc.base.js"));
|
|
21
|
+
var cache;
|
|
22
|
+
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; }
|
|
23
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
24
|
+
// jsdoc.base.js is CommonJS (it's also required directly by consuming projects' own .jsdoc.conf.js) - Node's ESM
|
|
25
|
+
// loader imports a CJS module's module.exports as the default export directly, no createRequire/import.meta needed
|
|
26
|
+
// (import.meta.url tripped up this project's own Babel CJS transform, which Jest relies on to run .mjs test files -
|
|
27
|
+
// confirmed by removing it and nothing else changing).
|
|
28
|
+
|
|
29
|
+
const execFileAsync = (0, _nodeUtil.promisify)(_nodeChild_process.execFile);
|
|
30
|
+
const escapeHtml = text => String(text).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
31
|
+
const jsdocInstallHint = 'Install it in your project with: npm install --save-dev jsdoc';
|
|
32
|
+
const themeInstallHint = name => `Install it in your project with: npm install --save-dev ${name}`;
|
|
33
|
+
|
|
33
34
|
/**
|
|
34
35
|
* Resolve the installed directory of an optional peer dependency, from the project being built rather than from
|
|
35
36
|
* this package. Deliberately not requirePeer/importPeer's own `require(name + '/package.json')` approach - that
|
|
@@ -47,20 +48,20 @@ const themeInstallHint = name => `Install it in your project with: npm install -
|
|
|
47
48
|
* @param {string} [options.projectPath=process.cwd()]
|
|
48
49
|
* @returns {string}
|
|
49
50
|
* @throws {Error} With install instructions when the package is not installed.
|
|
50
|
-
*/
|
|
51
|
-
const resolvePeerDir = (name, {
|
|
52
|
-
task,
|
|
53
|
-
installHint,
|
|
54
|
-
projectPath = process.cwd()
|
|
55
|
-
}) => {
|
|
56
|
-
const req = (0, _nodeModule.createRequire)(_nodePath.default.join(projectPath, 'package.json'));
|
|
57
|
-
const found = (req.resolve.paths(name) || []).map(dir => _nodePath.default.join(dir, name)).find(dir => _nodeFs.default.existsSync(_nodePath.default.join(dir, 'package.json')));
|
|
58
|
-
if (!found) {
|
|
59
|
-
throw new Error(`The ${task} task needs the optional peer dependency ${name}, which is not installed. ${installHint}`);
|
|
60
|
-
}
|
|
61
|
-
return found;
|
|
62
|
-
};
|
|
63
|
-
|
|
51
|
+
*/
|
|
52
|
+
const resolvePeerDir = (name, {
|
|
53
|
+
task,
|
|
54
|
+
installHint,
|
|
55
|
+
projectPath = process.cwd()
|
|
56
|
+
}) => {
|
|
57
|
+
const req = (0, _nodeModule.createRequire)(_nodePath.default.join(projectPath, 'package.json'));
|
|
58
|
+
const found = (req.resolve.paths(name) || []).map(dir => _nodePath.default.join(dir, name)).find(dir => _nodeFs.default.existsSync(_nodePath.default.join(dir, 'package.json')));
|
|
59
|
+
if (!found) {
|
|
60
|
+
throw new Error(`The ${task} task needs the optional peer dependency ${name}, which is not installed. ${installHint}`);
|
|
61
|
+
}
|
|
62
|
+
return found;
|
|
63
|
+
};
|
|
64
|
+
|
|
64
65
|
/**
|
|
65
66
|
* Resolve jsdoc's own CLI entry point. jsdoc has no stable programmatic Node API for generating HTML docs (unlike
|
|
66
67
|
* TypeDoc's Application.bootstrap()/convert()/generateDocs()) - gulp-jsdoc3, the established gulp wrapper, is
|
|
@@ -70,34 +71,33 @@ const resolvePeerDir = (name, {
|
|
|
70
71
|
* @memberOf module:partials
|
|
71
72
|
* @param {string} [projectPath=process.cwd()]
|
|
72
73
|
* @returns {string}
|
|
73
|
-
*/
|
|
74
|
-
const resolveJsdocBin = (projectPath = process.cwd()) => _nodePath.default.join(resolvePeerDir('jsdoc', {
|
|
75
|
-
task: 'docs',
|
|
76
|
-
installHint: jsdocInstallHint,
|
|
77
|
-
projectPath
|
|
78
|
-
}), 'jsdoc.js');
|
|
79
|
-
|
|
74
|
+
*/
|
|
75
|
+
const resolveJsdocBin = (projectPath = process.cwd()) => _nodePath.default.join(resolvePeerDir('jsdoc', {
|
|
76
|
+
task: 'docs',
|
|
77
|
+
installHint: jsdocInstallHint,
|
|
78
|
+
projectPath
|
|
79
|
+
}), 'jsdoc.js');
|
|
80
|
+
|
|
80
81
|
/**
|
|
81
|
-
* Resolve a jsdoc theme package's own template directory, for jsdoc's own opts.template config key
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* classic jsdoc template layout (a bare package root with its own tmpl/static folders) - clean-jsdoc-theme does
|
|
85
|
-
* not (it is a modern, self-contained, server-rendered theme with no such folders at its package root at all).
|
|
82
|
+
* Resolve a jsdoc theme package's own template directory, for jsdoc's own opts.template config key: the folder
|
|
83
|
+
* holding its publish.js. That is the package root for a classic jsdoc template (clean-jsdoc-theme 4.x included),
|
|
84
|
+
* but `dist` for a bundled one (clean-jsdoc-theme 5.x).
|
|
86
85
|
* @memberOf module:partials
|
|
87
86
|
* @param {string} name
|
|
88
87
|
* @param {string} [projectPath=process.cwd()]
|
|
89
88
|
* @returns {string}
|
|
90
|
-
*/
|
|
91
|
-
exports.resolveJsdocBin = resolveJsdocBin;
|
|
92
|
-
const resolveJsdocTheme = (name, projectPath = process.cwd()) => {
|
|
93
|
-
const packageDir = resolvePeerDir(name, {
|
|
94
|
-
task: 'docs',
|
|
95
|
-
installHint: themeInstallHint(name),
|
|
96
|
-
projectPath
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
89
|
+
*/
|
|
90
|
+
exports.resolveJsdocBin = resolveJsdocBin;
|
|
91
|
+
const resolveJsdocTheme = (name, projectPath = process.cwd()) => {
|
|
92
|
+
const packageDir = resolvePeerDir(name, {
|
|
93
|
+
task: 'docs',
|
|
94
|
+
installHint: themeInstallHint(name),
|
|
95
|
+
projectPath
|
|
96
|
+
});
|
|
97
|
+
const distDir = _nodePath.default.join(packageDir, 'dist');
|
|
98
|
+
return _nodeFs.default.existsSync(_nodePath.default.join(distDir, 'publish.js')) ? distDir : packageDir;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
101
|
/**
|
|
102
102
|
* Generate the HTML documentation of a plain-JavaScript project with jsdoc, using jsdoc.base.js's own shared
|
|
103
103
|
* config (plugins, includePattern/excludePattern) as the starting point rather than a parallel one - the same
|
|
@@ -105,51 +105,71 @@ const resolveJsdocTheme = (name, projectPath = process.cwd()) => {
|
|
|
105
105
|
* options generated here instead of hand-maintained per project. Configure this with 'docs.from', 'docs.to',
|
|
106
106
|
* 'docs.index', 'docs.theme' and 'docs.title'.
|
|
107
107
|
* @memberOf module:partials
|
|
108
|
-
* @param {string} [srcPath=gulpConfig.get('docs.from')] - The directory (or
|
|
108
|
+
* @param {string|Array<string>} [srcPath=gulpConfig.get('docs.from')] - The directory (or directories and files) holding
|
|
109
|
+
* the JS source.
|
|
109
110
|
* @param {string} [outPath=gulpConfig.get('docs.to')] - The directory the documentation is generated into (cleared first).
|
|
110
111
|
* @param {function(string, Array<string>): Promise<Object>} [runJsdoc] - Runs the jsdoc CLI, tests can inject a stand-in.
|
|
111
112
|
* @returns {Function} A gulp task, it accepts an optional callback and returns a promise.
|
|
112
|
-
*/
|
|
113
|
-
exports.resolveJsdocTheme = resolveJsdocTheme;
|
|
114
|
-
const jsdocDocsFor = (srcPath = gulpConfig.get('docs.from'), outPath = gulpConfig.get('docs.to'), runJsdoc = (bin, args) => execFileAsync(process.execPath, [bin, ...args])) => {
|
|
115
|
-
if (gulpConfig.get('docs.enabled') === false) {
|
|
116
|
-
return () => {};
|
|
117
|
-
}
|
|
118
|
-
return done => {
|
|
119
|
-
const generate = async () => {
|
|
120
|
-
const theme = gulpConfig.get('docs.theme') || 'clean-jsdoc-theme';
|
|
121
|
-
const themeDir = resolveJsdocTheme(theme);
|
|
122
|
-
const indexFile = gulpConfig.get('docs.index');
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
//
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
113
|
+
*/
|
|
114
|
+
exports.resolveJsdocTheme = resolveJsdocTheme;
|
|
115
|
+
const jsdocDocsFor = (srcPath = gulpConfig.get('docs.from'), outPath = gulpConfig.get('docs.to'), runJsdoc = (bin, args) => execFileAsync(process.execPath, [bin, ...args])) => {
|
|
116
|
+
if (gulpConfig.get('docs.enabled') === false) {
|
|
117
|
+
return () => {};
|
|
118
|
+
}
|
|
119
|
+
return done => {
|
|
120
|
+
const generate = async () => {
|
|
121
|
+
const theme = gulpConfig.get('docs.theme') || 'clean-jsdoc-theme';
|
|
122
|
+
const themeDir = resolveJsdocTheme(theme);
|
|
123
|
+
const indexFile = gulpConfig.get('docs.index');
|
|
124
|
+
const title = gulpConfig.get('docs.title');
|
|
125
|
+
await (0, _removeDirectory.removeDirectory)(outPath);
|
|
126
|
+
const config = {
|
|
127
|
+
..._jsdocBase.default,
|
|
128
|
+
source: {
|
|
129
|
+
..._jsdocBase.default.source,
|
|
130
|
+
include: [].concat(srcPath).map(includePath => _nodePath.default.resolve(includePath))
|
|
131
|
+
},
|
|
132
|
+
opts: {
|
|
133
|
+
destination: _nodePath.default.resolve(outPath),
|
|
134
|
+
// jsdoc does not recurse into source.include's own subdirectories by default - without this, only
|
|
135
|
+
// the top level of docs.from would ever be scanned. Confirmed from clean-jsdoc-theme's own README
|
|
136
|
+
// quick-start example, which sets this explicitly, not assumed from jsdoc's own classic defaults.
|
|
137
|
+
recurse: true,
|
|
138
|
+
template: themeDir,
|
|
139
|
+
// clean-jsdoc-theme's own options for the name in its header and the home page's <title> (otherwise "Home").
|
|
140
|
+
// The header is given as a link: a plain-text title links to the site root ("/"), while every page is in one
|
|
141
|
+
// folder, so index.html is the home page wherever they are served. Both are printed unescaped by the theme.
|
|
142
|
+
...(title ? {
|
|
143
|
+
theme_opts: {
|
|
144
|
+
title: `<a href="index.html" class="sidebar-title sidebar-title-anchor">${escapeHtml(title)}</a>`,
|
|
145
|
+
homepageTitle: escapeHtml(title)
|
|
146
|
+
}
|
|
147
|
+
} : {}),
|
|
148
|
+
...(indexFile && _nodeFs.default.existsSync(indexFile) ? {
|
|
149
|
+
readme: _nodePath.default.resolve(indexFile)
|
|
150
|
+
} : {})
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
const workDir = _nodeFs.default.mkdtempSync(_nodePath.default.join(_nodeOs.default.tmpdir(), 'jsdocdocs-'));
|
|
154
|
+
try {
|
|
155
|
+
const configPath = _nodePath.default.join(workDir, 'jsdoc.conf.json');
|
|
156
|
+
_nodeFs.default.writeFileSync(configPath, JSON.stringify(config));
|
|
157
|
+
const bin = resolveJsdocBin();
|
|
158
|
+
// Pass on what jsdoc and the theme report (warnings such as a page which failed to render), which would
|
|
159
|
+
// otherwise be lost with the captured output
|
|
160
|
+
const {
|
|
161
|
+
stdout = '',
|
|
162
|
+
stderr = ''
|
|
163
|
+
} = (await runJsdoc(bin, ['-c', configPath])) || {};
|
|
164
|
+
const report = `${stdout}${stderr}`.trim();
|
|
165
|
+
if (report) {
|
|
166
|
+
console.warn(report);
|
|
167
|
+
}
|
|
168
|
+
} finally {
|
|
169
|
+
await (0, _removeDirectory.removeDirectory)(workDir);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
return typeof done === 'function' ? generate().then(() => done(), done) : generate();
|
|
173
|
+
};
|
|
174
|
+
};
|
|
155
175
|
exports.jsdocDocsFor = jsdocDocsFor;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.loadPlaywright = exports.launchBrowser = void 0;
|
|
7
|
+
var _loadPeer = require("./loadPeer.js");
|
|
8
|
+
const installHint = 'Install it in your project with: npm install --save-dev playwright';
|
|
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.
|
|
17
|
+
*/
|
|
18
|
+
const loadPlaywright = (projectPath = process.cwd()) => (0, _loadPeer.requirePeer)('playwright', {
|
|
19
|
+
task: 'browser automation',
|
|
20
|
+
installHint,
|
|
21
|
+
projectPath
|
|
22
|
+
});
|
|
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.
|
|
31
|
+
*/
|
|
32
|
+
exports.loadPlaywright = loadPlaywright;
|
|
33
|
+
const launchBrowser = (load = loadPlaywright, projectPath = process.cwd()) => load(projectPath).chromium.launch();
|
|
34
|
+
exports.launchBrowser = launchBrowser;
|
|
@@ -21,6 +21,7 @@ const importNeostandard = () => (0, _loadPeer.importModule)('neostandard');
|
|
|
21
21
|
* migrating from `standard` keeps its globals (jest, browser, ...) without touching package.json.
|
|
22
22
|
* @param {string} cwd
|
|
23
23
|
* @returns {Array<string>}
|
|
24
|
+
* @private
|
|
24
25
|
*/
|
|
25
26
|
const readEnv = cwd => {
|
|
26
27
|
try {
|
|
@@ -42,7 +43,8 @@ const readEnv = cwd => {
|
|
|
42
43
|
* @param {boolean} options.ts
|
|
43
44
|
* @param {boolean} options.fix
|
|
44
45
|
* @param {Object<string, *>} [options.rules={}]
|
|
45
|
-
* @returns {Promise<
|
|
46
|
+
* @returns {Promise<ESLint>} eslint's ESLint instance
|
|
47
|
+
* @private
|
|
46
48
|
*/
|
|
47
49
|
const buildEslint = async ({
|
|
48
50
|
cwd,
|
|
@@ -75,7 +77,7 @@ const buildEslint = async ({
|
|
|
75
77
|
/**
|
|
76
78
|
* Print a file's lint messages, if it has any.
|
|
77
79
|
* @memberOf module:partials
|
|
78
|
-
* @param {
|
|
80
|
+
* @param {Vinyl} file
|
|
79
81
|
* @param {{messages: Array<{line: number, column: number, message: string}>, errorCount: number, warningCount: number}} result
|
|
80
82
|
* @returns {undefined}
|
|
81
83
|
*/
|
|
@@ -108,7 +110,7 @@ const printFileReport = (file, result) => {
|
|
|
108
110
|
* @param {function(Object): Promise<{lintText: Function}>} [loadEslint] - Resolves an ESLint-shaped linter. Real
|
|
109
111
|
* callers should never need to pass this - it exists so tests can supply a stand-in, since this project's
|
|
110
112
|
* CommonJS-transform-based Jest setup cannot execute a real dynamic import() of neostandard (ESM-only).
|
|
111
|
-
* @returns {
|
|
113
|
+
* @returns {stream.Transform}
|
|
112
114
|
*/
|
|
113
115
|
const neostandardLint = ({
|
|
114
116
|
fix = true,
|
|
@@ -1,19 +1,19 @@
|
|
|
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.resolveDocsMethod = void 0;
|
|
8
|
-
var gulpConfig = _interopRequireWildcard(require("../../gulp.config.js"));
|
|
9
|
-
var cache;
|
|
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; }
|
|
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.resolveDocsMethod = void 0;
|
|
8
|
+
var gulpConfig = _interopRequireWildcard(require("../../gulp.config.js"));
|
|
9
|
+
var cache;
|
|
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
11
|
/**
|
|
12
12
|
* Pick which engine generates the HTML documentation: docs.method picks it explicitly; left unset (false, the
|
|
13
13
|
* default), it's inferred from typescript.enabled - every existing TypeScript project's config, which never
|
|
14
14
|
* sets method, keeps producing TypeDoc output exactly as it always has.
|
|
15
15
|
* @memberOf module:partials
|
|
16
16
|
* @returns {'typedoc'|'jsdoc'}
|
|
17
|
-
*/
|
|
18
|
-
const resolveDocsMethod = () => gulpConfig.get('docs.method') || (gulpConfig.get('typescript.enabled') ? 'typedoc' : 'jsdoc');
|
|
17
|
+
*/
|
|
18
|
+
const resolveDocsMethod = () => gulpConfig.get('docs.method') || (gulpConfig.get('typescript.enabled') ? 'typedoc' : 'jsdoc');
|
|
19
19
|
exports.resolveDocsMethod = resolveDocsMethod;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.serveStatic = void 0;
|
|
7
|
+
var _nodeFs = _interopRequireDefault(require("node:fs"));
|
|
8
|
+
var _nodeHttp = _interopRequireDefault(require("node:http"));
|
|
9
|
+
var _nodePath = _interopRequireDefault(require("node:path"));
|
|
10
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
// A real, previously-undiscovered bug fixed here: without a Content-Type header, a browser enforces strict MIME
|
|
12
|
+
// checking on <script type="module"> and refuses to load it at all - exactly the case this partial exists for.
|
|
13
|
+
const contentTypes = {
|
|
14
|
+
'.css': 'text/css',
|
|
15
|
+
'.gif': 'image/gif',
|
|
16
|
+
'.html': 'text/html',
|
|
17
|
+
'.ico': 'image/x-icon',
|
|
18
|
+
'.jpeg': 'image/jpeg',
|
|
19
|
+
'.jpg': 'image/jpeg',
|
|
20
|
+
'.js': 'text/javascript',
|
|
21
|
+
'.json': 'application/json',
|
|
22
|
+
'.mjs': 'text/javascript',
|
|
23
|
+
'.png': 'image/png',
|
|
24
|
+
'.svg': 'image/svg+xml',
|
|
25
|
+
'.woff': 'font/woff',
|
|
26
|
+
'.woff2': 'font/woff2'
|
|
27
|
+
};
|
|
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.
|
|
38
|
+
*/
|
|
39
|
+
const serveStatic = (rootDir, port = 0) => new Promise((resolve, reject) => {
|
|
40
|
+
const server = _nodeHttp.default.createServer((req, res) => {
|
|
41
|
+
const filePath = _nodePath.default.join(rootDir, decodeURIComponent(req.url.split('?')[0]));
|
|
42
|
+
_nodeFs.default.readFile(filePath, (error, data) => {
|
|
43
|
+
if (error) {
|
|
44
|
+
res.statusCode = 404;
|
|
45
|
+
return res.end(`Not found: ${req.url}`);
|
|
46
|
+
}
|
|
47
|
+
res.setHeader('Content-Type', contentTypes[_nodePath.default.extname(filePath)] || 'application/octet-stream');
|
|
48
|
+
res.end(data);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
server.once('error', reject);
|
|
52
|
+
server.listen(port, '127.0.0.1', () => resolve({
|
|
53
|
+
server,
|
|
54
|
+
url: `http://127.0.0.1:${server.address().port}`
|
|
55
|
+
}));
|
|
56
|
+
});
|
|
57
|
+
exports.serveStatic = serveStatic;
|
package/dist/partials/tsFor.js
CHANGED
|
@@ -18,7 +18,7 @@ const importGulpTsCompile = () => (0, _loadPeer.importModule)('gulp-ts-compile')
|
|
|
18
18
|
/**
|
|
19
19
|
* Wrap a stream in a promise that resolves once it finishes writing.
|
|
20
20
|
* @memberOf module:partials
|
|
21
|
-
* @param {
|
|
21
|
+
* @param {stream.Stream} stream
|
|
22
22
|
* @returns {Promise<void>}
|
|
23
23
|
*/
|
|
24
24
|
const installHint = 'Install it in your project with: npm install --save-dev typescript';
|
|
@@ -49,7 +49,7 @@ const streamToPromise = stream => new Promise((resolve, reject) => {
|
|
|
49
49
|
* gulp-typescript when a removed API call started throwing under TypeScript 7.
|
|
50
50
|
* @memberOf module:partials
|
|
51
51
|
* @param {string} configPath - Path to a tsconfig.json file.
|
|
52
|
-
* @returns {
|
|
52
|
+
* @returns {ts.CompilerOptions} TypeScript's compiler options
|
|
53
53
|
*/
|
|
54
54
|
const readCompilerOptions = (ts, configPath) => {
|
|
55
55
|
const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
7
|
exports.writeDocEntries = exports.typeDocsFor = exports.loadTypeDoc = exports.describeFolder = exports.describeFile = exports.describeExports = void 0;
|
|
8
|
+
require("core-js/modules/es.array.includes.js");
|
|
8
9
|
require("core-js/modules/es.json.stringify.js");
|
|
9
10
|
require("core-js/modules/esnext.iterator.constructor.js");
|
|
10
11
|
require("core-js/modules/esnext.iterator.filter.js");
|
|
@@ -42,12 +43,19 @@ exports.loadTypeDoc = loadTypeDoc;
|
|
|
42
43
|
const isSource = fileName => /\.(ts|tsx|mts|cts)$/.test(fileName) && !/\.d\.[cm]?ts$/.test(fileName) && !/\.(test|spec)\./.test(fileName);
|
|
43
44
|
const listSources = dirPath => _nodeFs.default.readdirSync(dirPath, {
|
|
44
45
|
withFileTypes: true
|
|
45
|
-
}).
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
}).filter(entry => entry.isFile() && isSource(entry.name)).map(entry => _nodePath.default.join(dirPath, entry.name));
|
|
47
|
+
|
|
48
|
+
// Every folder below dirPath (at any depth), named by its path from dirPath, with the source files directly in it
|
|
49
|
+
const listFolders = (dirPath, prefix = '') => _nodeFs.default.readdirSync(dirPath, {
|
|
50
|
+
withFileTypes: true
|
|
51
|
+
}).filter(entry => entry.isDirectory() && entry.name !== 'node_modules').flatMap(entry => {
|
|
52
|
+
const folderPath = _nodePath.default.join(dirPath, entry.name);
|
|
53
|
+
const name = `${prefix}${entry.name}`;
|
|
54
|
+
return [{
|
|
55
|
+
name,
|
|
56
|
+
path: folderPath,
|
|
57
|
+
files: listSources(folderPath)
|
|
58
|
+
}, ...listFolders(folderPath, `${name}/`)];
|
|
51
59
|
});
|
|
52
60
|
const toIdentifier = fileName => fileName.replace(/[^\w$]+(\w)?/g, (match, letter) => (letter || '').toUpperCase()).replace(/^(\d)/, '_$1');
|
|
53
61
|
const toModulePath = filePath => filePath.replace(/\.[cm]?tsx?$/, '').split(_nodePath.default.sep).join('/');
|
|
@@ -127,11 +135,12 @@ const describeFile = filePath => {
|
|
|
127
135
|
|
|
128
136
|
/**
|
|
129
137
|
* Write one entry file per folder of the source directory into the entry directory. TypeDoc makes a module of every
|
|
130
|
-
* entry file, so the modules of the documentation mirror the folders.
|
|
138
|
+
* entry file, so the modules of the documentation mirror the folders. Nested folders are modules of their own, named
|
|
139
|
+
* by their path (utilities/parsers), and a folder's module holds only the files directly in it. The default export of each source file is
|
|
131
140
|
* re-exported under the name of the file (the source files hold one function each), and anything else a file exports
|
|
132
141
|
* is re-exported as it is (that is where the types.ts files go). Index files (the barrels), tests and declaration
|
|
133
142
|
* files are left out, but the first doc comment of a folder's index file becomes the description of its module.
|
|
134
|
-
* A file which sits beside the folders (not an index or
|
|
143
|
+
* A file which sits beside the folders (not an index, main or browser file) is a module of its own, described by its header
|
|
135
144
|
* comment. A source directory with no folders gets a single entry called index.
|
|
136
145
|
* @memberOf module:partials
|
|
137
146
|
* @param {Object} ts - The TypeScript compiler API.
|
|
@@ -145,18 +154,10 @@ const writeDocEntries = (ts, srcDir, entryDir) => {
|
|
|
145
154
|
_nodeFs.default.mkdirSync(entryDir, {
|
|
146
155
|
recursive: true
|
|
147
156
|
});
|
|
148
|
-
const folders =
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
path: _nodePath.default.join(absoluteSrc, entry.name),
|
|
153
|
-
files: listSources(_nodePath.default.join(absoluteSrc, entry.name))
|
|
154
|
-
})).filter(folder => folder.files.length);
|
|
155
|
-
const rootFiles = _nodeFs.default.readdirSync(absoluteSrc, {
|
|
156
|
-
withFileTypes: true
|
|
157
|
-
}).filter(entry => entry.isFile() && isSource(entry.name) && !/^(index|main)\./.test(entry.name)).map(entry => _nodePath.default.join(absoluteSrc, entry.name));
|
|
158
|
-
// Folders make modules, and so do the files which sit beside them (except the barrel: index and main). A source
|
|
159
|
-
// directory with no folders gets a single module called index which holds its files.
|
|
157
|
+
const folders = listFolders(absoluteSrc).filter(folder => folder.files.some(file => !/^index\./.test(_nodePath.default.basename(file))));
|
|
158
|
+
const rootFiles = listSources(absoluteSrc).filter(file => !/^(index|main|browser)\./.test(_nodePath.default.basename(file)));
|
|
159
|
+
// Folders make modules, and so do the files which sit beside them (except the barrels: index, main and browser, the
|
|
160
|
+
// browser bundle's entry). A source directory with no folders gets a single module called index which holds its files.
|
|
160
161
|
const groups = folders.length ? [...folders, ...rootFiles.map(file => ({
|
|
161
162
|
name: toIdentifier(_nodePath.default.basename(file).replace(/\.[cm]?tsx?$/, '')),
|
|
162
163
|
files: [file],
|
|
@@ -178,8 +179,13 @@ const writeDocEntries = (ts, srcDir, entryDir) => {
|
|
|
178
179
|
});
|
|
179
180
|
const description = group.description ?? (group.path ? describeFolder(group.path) : '');
|
|
180
181
|
// TypeDoc takes the first comment of an entry file which has the @module tag as the description of the module
|
|
181
|
-
|
|
182
|
+
// A nested folder's module is named by its path (utilities/parsers), so it is not mistaken for its parent's
|
|
183
|
+
const moduleName = group.name.includes('/') ? ` ${group.name}` : '';
|
|
184
|
+
const moduleComment = description || moduleName ? `/**\n${description ? description.split('\n').map(line => ` * ${line}`.trimEnd()).join('\n') + '\n' : ''} * @module${moduleName}\n */\n\n` : '';
|
|
182
185
|
const entryPath = _nodePath.default.join(entryDir, `${group.name}.ts`);
|
|
186
|
+
_nodeFs.default.mkdirSync(_nodePath.default.dirname(entryPath), {
|
|
187
|
+
recursive: true
|
|
188
|
+
});
|
|
183
189
|
_nodeFs.default.writeFileSync(entryPath, moduleComment + lines.join('\n') + '\n');
|
|
184
190
|
return entryPath;
|
|
185
191
|
});
|
|
@@ -225,7 +231,7 @@ const typeDocsFor = (srcPath = gulpConfig.get('docs.from'), outPath = gulpConfig
|
|
|
225
231
|
...(projectConfig ? {
|
|
226
232
|
extends: _nodePath.default.resolve(projectConfig)
|
|
227
233
|
} : {}),
|
|
228
|
-
include: [_nodePath.default.join(workDir, 'entries', '*.ts').split(_nodePath.default.sep).join('/'), _nodePath.default.resolve(srcPath).split(_nodePath.default.sep).join('/') + '/**/*.ts'],
|
|
234
|
+
include: [_nodePath.default.join(workDir, 'entries', '**', '*.ts').split(_nodePath.default.sep).join('/'), _nodePath.default.resolve(srcPath).split(_nodePath.default.sep).join('/') + '/**/*.ts'],
|
|
229
235
|
exclude: [_nodePath.default.resolve(srcPath).split(_nodePath.default.sep).join('/') + '/**/*.test.*']
|
|
230
236
|
}));
|
|
231
237
|
const indexFile = gulpConfig.get('docs.index');
|