js-build-tools 6.6.0 → 6.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/LICENSE +674 -674
  2. package/README.md +762 -701
  3. package/babel.config.js +28 -28
  4. package/dist/build.js +75 -75
  5. package/dist/bundle.js +19 -19
  6. package/dist/bundleMinify.js +7 -7
  7. package/dist/compileReadme.js +4 -4
  8. package/dist/copyFiles.js +17 -17
  9. package/dist/copyFonts.js +4 -4
  10. package/dist/default.js +5 -5
  11. package/dist/dist.js +4 -4
  12. package/dist/distMinify.js +4 -4
  13. package/dist/docs.js +7 -7
  14. package/dist/images.js +4 -4
  15. package/dist/jsdocDocs.js +6 -6
  16. package/dist/lint.js +16 -16
  17. package/dist/partials/addToReadme.js +9 -9
  18. package/dist/partials/beginWatcher.js +4 -4
  19. package/dist/partials/clean.js +5 -5
  20. package/dist/partials/copyFor.js +9 -9
  21. package/dist/partials/distFor.js +6 -6
  22. package/dist/partials/distForSrc.js +5 -5
  23. package/dist/partials/distSeries.js +7 -7
  24. package/dist/partials/imagesFor.js +93 -93
  25. package/dist/partials/jsdocDocsFor.js +46 -46
  26. package/dist/partials/lintSource.js +51 -51
  27. package/dist/partials/loadPeer.js +99 -99
  28. package/dist/partials/loadPlaywright.js +14 -14
  29. package/dist/partials/minifyFor.js +20 -20
  30. package/dist/partials/neostandardLint.js +175 -175
  31. package/dist/partials/readmeTemplate.js +4 -4
  32. package/dist/partials/removeDirectory.js +11 -11
  33. package/dist/partials/resolveDocsMethod.js +6 -6
  34. package/dist/partials/runOnChange.js +31 -31
  35. package/dist/partials/sassFor.js +6 -6
  36. package/dist/partials/serveStatic.js +9 -9
  37. package/dist/partials/tsFor.js +32 -32
  38. package/dist/partials/typeDocsFor.js +264 -264
  39. package/dist/partials.js +176 -176
  40. package/dist/sourceLint.js +18 -18
  41. package/dist/test-helpers/isolateGulpCache.js +24 -24
  42. package/dist/test-helpers/setUp.js +4 -4
  43. package/dist/testFull.js +5 -5
  44. package/dist/testQuick.js +5 -5
  45. package/dist/typeDocs.js +5 -5
  46. package/dist/typeScript.js +4 -4
  47. package/dist/utilities/convertMjsFilesForDocs.js +12 -12
  48. package/dist/utilities/dotGet.js +54 -54
  49. package/dist/utilities/dotNotate.js +79 -79
  50. package/dist/utilities/dotSet.js +45 -45
  51. package/dist/utilities/esmNamedExportsToCjs.js +15 -15
  52. package/dist/utilities/getBundleConfigs.js +9 -9
  53. package/dist/utilities/isObject.js +6 -6
  54. package/dist/utilities/strAfter.js +7 -7
  55. package/dist/utilities/strBefore.js +7 -7
  56. package/dist/watchFull.js +4 -4
  57. package/dist/watchTest.js +4 -4
  58. package/functions/build.mjs +72 -72
  59. package/functions/build.test.mjs +763 -759
  60. package/functions/bundle.mjs +44 -44
  61. package/functions/bundle.test.mjs +219 -219
  62. package/functions/bundleMinify.mjs +16 -16
  63. package/functions/bundleMinify.test.mjs +37 -37
  64. package/functions/compileReadme.mjs +9 -9
  65. package/functions/compileReadme.test.mjs +18 -18
  66. package/functions/copyFiles.mjs +32 -32
  67. package/functions/copyFiles.test.mjs +78 -78
  68. package/functions/copyFonts.mjs +9 -9
  69. package/functions/copyFonts.test.mjs +32 -32
  70. package/functions/default.mjs +12 -12
  71. package/functions/default.test.mjs +33 -33
  72. package/functions/dist.mjs +8 -8
  73. package/functions/dist.test.mjs +44 -44
  74. package/functions/distMinify.mjs +9 -9
  75. package/functions/distMinify.test.mjs +15 -15
  76. package/functions/docs.mjs +13 -13
  77. package/functions/docs.test.mjs +45 -45
  78. package/functions/gulpConfigEntries.test.mjs +23 -23
  79. package/functions/images.mjs +8 -8
  80. package/functions/images.test.mjs +142 -142
  81. package/functions/jsdocDocs.mjs +10 -10
  82. package/functions/jsdocEsmExports.test.mjs +24 -24
  83. package/functions/lint.mjs +9 -9
  84. package/functions/partials/addToReadme.mjs +25 -25
  85. package/functions/partials/addToReadme.test.mjs +34 -34
  86. package/functions/partials/beginWatcher.mjs +9 -9
  87. package/functions/partials/beginWatcher.test.mjs +19 -19
  88. package/functions/partials/clean.mjs +13 -13
  89. package/functions/partials/clean.test.mjs +22 -22
  90. package/functions/partials/copyFor.mjs +15 -15
  91. package/functions/partials/copyFor.test.mjs +53 -53
  92. package/functions/partials/distFor.mjs +22 -22
  93. package/functions/partials/distFor.test.mjs +195 -195
  94. package/functions/partials/distForSrc.mjs +11 -11
  95. package/functions/partials/distForSrc.test.mjs +18 -18
  96. package/functions/partials/distSeries.mjs +21 -21
  97. package/functions/partials/distSeries.test.mjs +34 -34
  98. package/functions/partials/imagesFor.mjs +83 -83
  99. package/functions/partials/imagesFor.test.mjs +287 -287
  100. package/functions/partials/jsdocDocsFor.mjs +163 -152
  101. package/functions/partials/jsdocDocsFor.test.mjs +182 -152
  102. package/functions/partials/lintSource.mjs +41 -41
  103. package/functions/partials/loadPeer.mjs +76 -76
  104. package/functions/partials/loadPeer.test.mjs +58 -58
  105. package/functions/partials/loadPlaywright.mjs +23 -23
  106. package/functions/partials/loadPlaywright.test.mjs +70 -70
  107. package/functions/partials/minifyFor.mjs +15 -15
  108. package/functions/partials/minifyFor.test.mjs +49 -49
  109. package/functions/partials/neostandardLint.mjs +142 -142
  110. package/functions/partials/neostandardLint.test.mjs +131 -131
  111. package/functions/partials/readmeTemplate.mjs +12 -12
  112. package/functions/partials/readmeTemplate.test.mjs +34 -34
  113. package/functions/partials/removeDirectory.mjs +34 -34
  114. package/functions/partials/removeDirectory.test.mjs +72 -72
  115. package/functions/partials/resolveDocsMethod.mjs +10 -10
  116. package/functions/partials/resolveDocsMethod.test.mjs +33 -33
  117. package/functions/partials/runOnChange.mjs +54 -54
  118. package/functions/partials/runOnChange.test.mjs +95 -95
  119. package/functions/partials/sassFor.mjs +25 -25
  120. package/functions/partials/sassFor.test.mjs +81 -81
  121. package/functions/partials/serveStatic.mjs +47 -47
  122. package/functions/partials/serveStatic.test.mjs +71 -71
  123. package/functions/partials/tsFor.mjs +92 -92
  124. package/functions/partials/tsFor.test.mjs +88 -88
  125. package/functions/partials/typeDocsFor.mjs +231 -231
  126. package/functions/partials/typeDocsFor.test.mjs +263 -263
  127. package/functions/partials.mjs +31 -31
  128. package/functions/partials.test.mjs +7 -7
  129. package/functions/sass.mjs +4 -4
  130. package/functions/sass.test.mjs +31 -31
  131. package/functions/sourceLint.mjs +13 -13
  132. package/functions/sourceLint.test.mjs +166 -166
  133. package/functions/test-helpers/isolateGulpCache.mjs +16 -16
  134. package/functions/test-helpers/neostandardLintWithRealNeostandard.mjs +40 -40
  135. package/functions/test-helpers/setUp.mjs +100 -100
  136. package/functions/test-helpers/setUp.test.mjs +19 -19
  137. package/functions/testFull.mjs +17 -17
  138. package/functions/testFull.test.mjs +17 -17
  139. package/functions/testHelpers.mjs +10 -10
  140. package/functions/testHelpers.test.mjs +7 -7
  141. package/functions/testQuick.mjs +17 -17
  142. package/functions/testQuick.test.mjs +17 -17
  143. package/functions/typeDocs.mjs +9 -9
  144. package/functions/typeDocs.test.mjs +11 -11
  145. package/functions/typeScript.mjs +8 -8
  146. package/functions/typeScript.test.mjs +11 -11
  147. package/functions/utilities/convertMjsFilesForDocs.mjs +34 -34
  148. package/functions/utilities/convertMjsFilesForDocs.test.mjs +58 -58
  149. package/functions/utilities/dotGet.mjs +49 -49
  150. package/functions/utilities/dotNotate.mjs +73 -73
  151. package/functions/utilities/dotNotate.test.mjs +41 -41
  152. package/functions/utilities/dotSet.mjs +40 -40
  153. package/functions/utilities/esmNamedExportsToCjs.mjs +30 -30
  154. package/functions/utilities/esmNamedExportsToCjs.test.mjs +47 -47
  155. package/functions/utilities/getBundleConfigs.mjs +30 -30
  156. package/functions/utilities/isObject.mjs +8 -8
  157. package/functions/utilities/strAfter.mjs +12 -12
  158. package/functions/utilities/strBefore.mjs +12 -12
  159. package/functions/watchFull.mjs +9 -9
  160. package/functions/watchFull.test.mjs +41 -41
  161. package/functions/watchTest.mjs +10 -10
  162. package/functions/watchTest.test.mjs +49 -49
  163. package/gulp.config.js +4 -4
  164. package/gulp.config.mjs +344 -340
  165. package/gulpfile.base.js +51 -51
  166. package/gulpfile.base.mjs +29 -29
  167. package/jsdoc.base.js +16 -16
  168. package/jsdoc.esmExports.js +17 -17
  169. package/package.json +146 -145
@@ -15,21 +15,21 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
15
15
  // gulp-ts-compile ships ESM-only (no CJS build - see its own package.json), see importModule for how it is imported.
16
16
  const importGulpTsCompile = () => (0, _loadPeer.importModule)('gulp-ts-compile');
17
17
 
18
- /**
19
- * Wrap a stream in a promise that resolves once it finishes writing.
20
- * @memberOf module:partials
21
- * @param {stream.Stream} stream
22
- * @returns {Promise<void>}
18
+ /**
19
+ * Wrap a stream in a promise that resolves once it finishes writing.
20
+ * @memberOf module:partials
21
+ * @param {stream.Stream} stream
22
+ * @returns {Promise<void>}
23
23
  */
24
24
  const installHint = 'Install it in your project with: npm install --save-dev typescript';
25
25
 
26
- /**
27
- * Load the project's own copy of TypeScript (an optional peer dependency, only needed when the typescript task is
28
- * enabled) from the project being built, so projects which do not use TypeScript never need it installed.
29
- * @memberOf module:partials
30
- * @param {string} [projectPath=process.cwd()] The folder of the project (which has the package.json) being built.
31
- * @returns {Object} The TypeScript compiler API module.
32
- * @throws {Error} With install instructions when typescript is not installed.
26
+ /**
27
+ * Load the project's own copy of TypeScript (an optional peer dependency, only needed when the typescript task is
28
+ * enabled) from the project being built, so projects which do not use TypeScript never need it installed.
29
+ * @memberOf module:partials
30
+ * @param {string} [projectPath=process.cwd()] The folder of the project (which has the package.json) being built.
31
+ * @returns {Object} The TypeScript compiler API module.
32
+ * @throws {Error} With install instructions when typescript is not installed.
33
33
  */
34
34
  const loadTypescript = (projectPath = process.cwd()) => (0, _loadPeer.requirePeer)('typescript', {
35
35
  task: 'typescript',
@@ -42,14 +42,14 @@ const streamToPromise = stream => new Promise((resolve, reject) => {
42
42
  stream.on('error', reject);
43
43
  });
44
44
 
45
- /**
46
- * Read a tsconfig.json file into real typescript.CompilerOptions values, using only TypeScript's stable, current,
47
- * public config-reading API (the same one `tsc --project` itself uses internally) - never
48
- * `ts.convertCompilerOptionsFromJson`, which is exactly the kind of internal/legacy surface that broke
49
- * gulp-typescript when a removed API call started throwing under TypeScript 7.
50
- * @memberOf module:partials
51
- * @param {string} configPath - Path to a tsconfig.json file.
52
- * @returns {ts.CompilerOptions} TypeScript's compiler options
45
+ /**
46
+ * Read a tsconfig.json file into real typescript.CompilerOptions values, using only TypeScript's stable, current,
47
+ * public config-reading API (the same one `tsc --project` itself uses internally) - never
48
+ * `ts.convertCompilerOptionsFromJson`, which is exactly the kind of internal/legacy surface that broke
49
+ * gulp-typescript when a removed API call started throwing under TypeScript 7.
50
+ * @memberOf module:partials
51
+ * @param {string} configPath - Path to a tsconfig.json file.
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);
@@ -57,18 +57,18 @@ const readCompilerOptions = (ts, configPath) => {
57
57
  return parsedConfig.options;
58
58
  };
59
59
 
60
- /**
61
- * Starting at the source directory, find all the ts files and convert them into the distribution directory.
62
- * @memberOf module:partials
63
- * @param {string|array} [srcPath='']
64
- * @param {string} [distPath='']
65
- * @param {function(): Promise<Function>} [loadTsCompile] - Resolves the `gulp-ts-compile` default export. Real
66
- * callers should never need to pass this - it exists so tests can inject a stand-in compiler, sidestepping the
67
- * genuine dynamic `import()` above that this project's current CommonJS-transform-based Jest setup cannot
68
- * execute without a broader (and riskier) migration to Jest's native ESM support. gulp-ts-compile's own test
69
- * suite already covers real TypeScript-compile correctness - this function's own tests only need to verify its
70
- * config resolution and stream wiring.
71
- * @returns {Function}
60
+ /**
61
+ * Starting at the source directory, find all the ts files and convert them into the distribution directory.
62
+ * @memberOf module:partials
63
+ * @param {string|array} [srcPath='']
64
+ * @param {string} [distPath='']
65
+ * @param {function(): Promise<Function>} [loadTsCompile] - Resolves the `gulp-ts-compile` default export. Real
66
+ * callers should never need to pass this - it exists so tests can inject a stand-in compiler, sidestepping the
67
+ * genuine dynamic `import()` above that this project's current CommonJS-transform-based Jest setup cannot
68
+ * execute without a broader (and riskier) migration to Jest's native ESM support. gulp-ts-compile's own test
69
+ * suite already covers real TypeScript-compile correctness - this function's own tests only need to verify its
70
+ * config resolution and stream wiring.
71
+ * @returns {Function}
72
72
  */
73
73
  const tsFor = (srcPath = gulpConfig.get('typescript.from'), distPath = gulpConfig.get('typescript.to'), loadTsCompile = () => importGulpTsCompile().then(({
74
74
  default: tsCompile
@@ -1,265 +1,265 @@
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.writeDocEntries = exports.typeDocsFor = exports.loadTypeDoc = exports.describeFolder = exports.describeFile = exports.describeExports = void 0;
8
- require("core-js/modules/es.array.includes.js");
9
- require("core-js/modules/es.json.stringify.js");
10
- require("core-js/modules/esnext.iterator.constructor.js");
11
- require("core-js/modules/esnext.iterator.filter.js");
12
- require("core-js/modules/esnext.iterator.find.js");
13
- require("core-js/modules/esnext.iterator.flat-map.js");
14
- require("core-js/modules/esnext.iterator.for-each.js");
15
- require("core-js/modules/esnext.iterator.map.js");
16
- require("core-js/modules/esnext.iterator.some.js");
17
- var _nodeFs = _interopRequireDefault(require("node:fs"));
18
- var _nodeOs = _interopRequireDefault(require("node:os"));
19
- var _nodePath = _interopRequireDefault(require("node:path"));
20
- var gulpConfig = _interopRequireWildcard(require("../../gulp.config.js"));
21
- var _loadPeer = require("./loadPeer.js");
22
- var _tsFor = require("./tsFor.js");
23
- var _removeDirectory = require("./removeDirectory.js");
24
- var cache;
25
- 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; }
26
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
27
- const installHint = 'Install it in your project with: npm install --save-dev typedoc';
28
-
29
- /**
30
- * Find the TypeDoc of the project being built (an optional peer dependency, only needed when the docs task is
31
- * enabled) and load it, so projects which do not document TypeScript never need it installed.
32
- * @memberOf module:partials
33
- * @param {string} [projectPath=process.cwd()] The folder of the project (which has the package.json) being built.
34
- * @returns {Promise<Object>} The TypeDoc module.
35
- * @throws {Error} With install instructions when typedoc is not installed.
36
- */
37
- const loadTypeDoc = (projectPath = process.cwd()) => (0, _loadPeer.importPeer)('typedoc', {
38
- task: 'docs',
39
- installHint,
40
- projectPath
41
- });
42
- exports.loadTypeDoc = loadTypeDoc;
43
- const isSource = fileName => /\.(ts|tsx|mts|cts)$/.test(fileName) && !/\.d\.[cm]?ts$/.test(fileName) && !/\.(test|spec)\./.test(fileName);
44
- const listSources = dirPath => _nodeFs.default.readdirSync(dirPath, {
45
- withFileTypes: true
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}/`)];
59
- });
60
- const toIdentifier = fileName => fileName.replace(/[^\w$]+(\w)?/g, (match, letter) => (letter || '').toUpperCase()).replace(/^(\d)/, '_$1');
61
- const toModulePath = filePath => filePath.replace(/\.[cm]?tsx?$/, '').split(_nodePath.default.sep).join('/');
62
-
63
- /**
64
- * Describe what a source file exports: whether it has a default export, and whether it has any named exports.
65
- * @memberOf module:partials
66
- * @param {Object} ts - The TypeScript compiler API.
67
- * @param {string} filePath
68
- * @returns {{hasDefault: boolean, hasNamed: boolean}}
69
- */
70
- const describeExports = (ts, filePath) => {
71
- const source = ts.createSourceFile(filePath, _nodeFs.default.readFileSync(filePath, 'utf8'), ts.ScriptTarget.Latest);
72
- let hasDefault = false;
73
- let hasNamed = false;
74
- source.statements.forEach(statement => {
75
- if (ts.isExportAssignment(statement)) {
76
- hasDefault = hasDefault || !statement.isExportEquals;
77
- return;
78
- }
79
- if (ts.isExportDeclaration(statement)) {
80
- const names = statement.exportClause && ts.isNamedExports(statement.exportClause) ? statement.exportClause.elements : null;
81
- if (names && names.some(element => element.name.text === 'default')) {
82
- hasDefault = true;
83
- }
84
- if (!names || names.some(element => element.name.text !== 'default')) {
85
- hasNamed = true;
86
- }
87
- return;
88
- }
89
- const modifiers = ts.canHaveModifiers(statement) ? ts.getModifiers(statement) || [] : [];
90
- if (modifiers.some(modifier => modifier.kind === ts.SyntaxKind.ExportKeyword)) {
91
- if (modifiers.some(modifier => modifier.kind === ts.SyntaxKind.DefaultKeyword)) {
92
- hasDefault = true;
93
- } else {
94
- hasNamed = true;
95
- }
96
- }
97
- });
98
- return {
99
- hasDefault,
100
- hasNamed
101
- };
102
- };
103
-
104
- /**
105
- * The description of a folder for its module: the first doc comment of the folder's index file, without its tags
106
- * (@module, @file, ...), or an empty string when there is none.
107
- * @memberOf module:partials
108
- * @param {string} folderPath
109
- * @returns {string}
110
- */
111
- exports.describeExports = describeExports;
112
- const describeFolder = folderPath => {
113
- const indexFile = ['index.ts', 'index.tsx', 'index.mts', 'index.cts'].map(name => _nodePath.default.join(folderPath, name)).find(file => _nodeFs.default.existsSync(file));
114
- return indexFile ? describeFile(indexFile) : '';
115
- };
116
-
117
- /**
118
- * The description of a source file for its module: its first doc comment without the tags (@module, @file, ...), when
119
- * that comment is a header (it is followed by an import or export, so it does not document a declaration itself), or
120
- * an empty string.
121
- * @memberOf module:partials
122
- * @param {string} filePath
123
- * @returns {string}
124
- */
125
- exports.describeFolder = describeFolder;
126
- const describeFile = filePath => {
127
- const comment = _nodeFs.default.readFileSync(filePath, 'utf8').match(/^\s*\/\*\*([\s\S]*?)\*\/\s*(import\b|export\s+(\*|\{[^}]*\}\s+from)|$)/);
128
- if (!comment) {
129
- return '';
130
- }
131
- const lines = comment[1].split('\n').map(line => line.replace(/^\s*\* ?/, '').trimEnd());
132
- const tagAt = lines.findIndex(line => /^@\w+/.test(line));
133
- return (tagAt === -1 ? lines : lines.slice(0, tagAt)).join('\n').trim();
134
- };
135
-
136
- /**
137
- * Write one entry file per folder of the source directory into the entry directory. TypeDoc makes a module of every
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
140
- * re-exported under the name of the file (the source files hold one function each), and anything else a file exports
141
- * is re-exported as it is (that is where the types.ts files go). Index files (the barrels), tests and declaration
142
- * files are left out, but the first doc comment of a folder's index file becomes the description of its module.
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
144
- * comment. A source directory with no folders gets a single entry called index.
145
- * @memberOf module:partials
146
- * @param {Object} ts - The TypeScript compiler API.
147
- * @param {string} srcDir - The directory holding the TypeScript source.
148
- * @param {string} entryDir - The directory to write the entry files into.
149
- * @returns {Array<string>} The paths of the entry files.
150
- */
151
- exports.describeFile = describeFile;
152
- const writeDocEntries = (ts, srcDir, entryDir) => {
153
- const absoluteSrc = _nodePath.default.resolve(srcDir);
154
- _nodeFs.default.mkdirSync(entryDir, {
155
- recursive: true
156
- });
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.
161
- const groups = folders.length ? [...folders, ...rootFiles.map(file => ({
162
- name: toIdentifier(_nodePath.default.basename(file).replace(/\.[cm]?tsx?$/, '')),
163
- files: [file],
164
- description: describeFile(file)
165
- })).filter(group => !folders.some(folder => folder.name === group.name))] : [{
166
- name: 'index',
167
- path: absoluteSrc,
168
- files: rootFiles
169
- }];
170
- return groups.map(group => {
171
- const lines = group.files.filter(file => !/^index\./.test(_nodePath.default.basename(file))).sort().flatMap(file => {
172
- const modulePath = toModulePath(file);
173
- const {
174
- hasDefault,
175
- hasNamed
176
- } = describeExports(ts, file);
177
- const fileName = _nodePath.default.basename(file).replace(/\.[cm]?tsx?$/, '');
178
- return [...(hasDefault ? [`export { default as ${toIdentifier(fileName)} } from '${modulePath}'`] : []), ...(hasNamed ? [`export * from '${modulePath}'`] : [])];
179
- });
180
- const description = group.description ?? (group.path ? describeFolder(group.path) : '');
181
- // TypeDoc takes the first comment of an entry file which has the @module tag as the description of the module
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` : '';
185
- const entryPath = _nodePath.default.join(entryDir, `${group.name}.ts`);
186
- _nodeFs.default.mkdirSync(_nodePath.default.dirname(entryPath), {
187
- recursive: true
188
- });
189
- _nodeFs.default.writeFileSync(entryPath, moduleComment + lines.join('\n') + '\n');
190
- return entryPath;
191
- });
192
- };
193
- exports.writeDocEntries = writeDocEntries;
194
- const projectName = () => {
195
- try {
196
- return JSON.parse(_nodeFs.default.readFileSync(_nodePath.default.join(process.cwd(), 'package.json'), 'utf8')).name;
197
- } catch (error) {
198
- return _nodePath.default.basename(process.cwd());
199
- }
200
- };
201
-
202
- /**
203
- * Generate the HTML documentation of a TypeScript project with TypeDoc, straight from the TypeScript source, so the
204
- * types (and the comments on them) are documented from where they are defined. The modules mirror the folders of the
205
- * source, see {@link writeDocEntries}. Configure this with 'docs.from', 'docs.to', 'docs.index', 'docs.title',
206
- * 'docs.tsconfig' and 'docs.logLevel'.
207
- * @memberOf module:partials
208
- * @param {string} [srcPath=gulpConfig.get('docs.from')] - The directory holding the TypeScript source.
209
- * @param {string} [outPath=gulpConfig.get('docs.to')] - The directory the documentation is generated into (cleared first).
210
- * @param {function(string): Promise<Object>} [loadDocs] - Resolves the TypeDoc module, tests can inject a stand-in.
211
- * @returns {Function} A gulp task, it accepts an optional callback and returns a promise.
212
- */
213
- const typeDocsFor = (srcPath = gulpConfig.get('docs.from'), outPath = gulpConfig.get('docs.to'), loadDocs = loadTypeDoc) => {
214
- if (gulpConfig.get('docs.enabled') === false) {
215
- return () => {};
216
- }
217
- return done => {
218
- const generate = async () => {
219
- const ts = (0, _tsFor.loadTypescript)();
220
- const {
221
- Application
222
- } = await loadDocs();
223
- const workDir = _nodeFs.default.mkdtempSync(_nodePath.default.join(_nodeOs.default.tmpdir(), 'typedocs-'));
224
- try {
225
- const entryPoints = writeDocEntries(ts, srcPath, _nodePath.default.join(workDir, 'entries'));
226
- // The entry files live outside the project, so the tsconfig which is used for the documentation extends the
227
- // one of the project and adds the entries to the files it includes.
228
- const projectConfig = gulpConfig.get('docs.tsconfig') || gulpConfig.get('typescript.config');
229
- const tsconfig = _nodePath.default.join(workDir, 'tsconfig.json');
230
- _nodeFs.default.writeFileSync(tsconfig, JSON.stringify({
231
- ...(projectConfig ? {
232
- extends: _nodePath.default.resolve(projectConfig)
233
- } : {}),
234
- include: [_nodePath.default.join(workDir, 'entries', '**', '*.ts').split(_nodePath.default.sep).join('/'), _nodePath.default.resolve(srcPath).split(_nodePath.default.sep).join('/') + '/**/*.ts'],
235
- exclude: [_nodePath.default.resolve(srcPath).split(_nodePath.default.sep).join('/') + '/**/*.test.*']
236
- }));
237
- const indexFile = gulpConfig.get('docs.index');
238
- const gitRevision = gulpConfig.get('docs.gitRevision');
239
- await (0, _removeDirectory.removeDirectory)(outPath);
240
- const app = await Application.bootstrap({
241
- entryPoints,
242
- tsconfig,
243
- name: gulpConfig.get('docs.title') || projectName(),
244
- readme: indexFile && _nodeFs.default.existsSync(indexFile) ? indexFile : 'none',
245
- logLevel: gulpConfig.get('docs.logLevel') || 'Warn',
246
- skipErrorChecking: true,
247
- // Left out, TypeDoc links each declaration to its source at the current commit, so every commit changes
248
- // every page; a branch name keeps the pages the same until the documentation itself changes.
249
- ...(gitRevision ? {
250
- gitRevision
251
- } : {})
252
- });
253
- const project = await app.convert();
254
- if (!project) {
255
- throw new Error('TypeDoc could not read the TypeScript source, see the errors above.');
256
- }
257
- await app.generateDocs(project, outPath);
258
- } finally {
259
- await (0, _removeDirectory.removeDirectory)(workDir);
260
- }
261
- };
262
- return typeof done === 'function' ? generate().then(() => done(), done) : generate();
263
- };
264
- };
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.writeDocEntries = exports.typeDocsFor = exports.loadTypeDoc = exports.describeFolder = exports.describeFile = exports.describeExports = void 0;
8
+ require("core-js/modules/es.array.includes.js");
9
+ require("core-js/modules/es.json.stringify.js");
10
+ require("core-js/modules/esnext.iterator.constructor.js");
11
+ require("core-js/modules/esnext.iterator.filter.js");
12
+ require("core-js/modules/esnext.iterator.find.js");
13
+ require("core-js/modules/esnext.iterator.flat-map.js");
14
+ require("core-js/modules/esnext.iterator.for-each.js");
15
+ require("core-js/modules/esnext.iterator.map.js");
16
+ require("core-js/modules/esnext.iterator.some.js");
17
+ var _nodeFs = _interopRequireDefault(require("node:fs"));
18
+ var _nodeOs = _interopRequireDefault(require("node:os"));
19
+ var _nodePath = _interopRequireDefault(require("node:path"));
20
+ var gulpConfig = _interopRequireWildcard(require("../../gulp.config.js"));
21
+ var _loadPeer = require("./loadPeer.js");
22
+ var _tsFor = require("./tsFor.js");
23
+ var _removeDirectory = require("./removeDirectory.js");
24
+ var cache;
25
+ 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; }
26
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
27
+ const installHint = 'Install it in your project with: npm install --save-dev typedoc';
28
+
29
+ /**
30
+ * Find the TypeDoc of the project being built (an optional peer dependency, only needed when the docs task is
31
+ * enabled) and load it, so projects which do not document TypeScript never need it installed.
32
+ * @memberOf module:partials
33
+ * @param {string} [projectPath=process.cwd()] The folder of the project (which has the package.json) being built.
34
+ * @returns {Promise<Object>} The TypeDoc module.
35
+ * @throws {Error} With install instructions when typedoc is not installed.
36
+ */
37
+ const loadTypeDoc = (projectPath = process.cwd()) => (0, _loadPeer.importPeer)('typedoc', {
38
+ task: 'docs',
39
+ installHint,
40
+ projectPath
41
+ });
42
+ exports.loadTypeDoc = loadTypeDoc;
43
+ const isSource = fileName => /\.(ts|tsx|mts|cts)$/.test(fileName) && !/\.d\.[cm]?ts$/.test(fileName) && !/\.(test|spec)\./.test(fileName);
44
+ const listSources = dirPath => _nodeFs.default.readdirSync(dirPath, {
45
+ withFileTypes: true
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}/`)];
59
+ });
60
+ const toIdentifier = fileName => fileName.replace(/[^\w$]+(\w)?/g, (match, letter) => (letter || '').toUpperCase()).replace(/^(\d)/, '_$1');
61
+ const toModulePath = filePath => filePath.replace(/\.[cm]?tsx?$/, '').split(_nodePath.default.sep).join('/');
62
+
63
+ /**
64
+ * Describe what a source file exports: whether it has a default export, and whether it has any named exports.
65
+ * @memberOf module:partials
66
+ * @param {Object} ts - The TypeScript compiler API.
67
+ * @param {string} filePath
68
+ * @returns {{hasDefault: boolean, hasNamed: boolean}}
69
+ */
70
+ const describeExports = (ts, filePath) => {
71
+ const source = ts.createSourceFile(filePath, _nodeFs.default.readFileSync(filePath, 'utf8'), ts.ScriptTarget.Latest);
72
+ let hasDefault = false;
73
+ let hasNamed = false;
74
+ source.statements.forEach(statement => {
75
+ if (ts.isExportAssignment(statement)) {
76
+ hasDefault = hasDefault || !statement.isExportEquals;
77
+ return;
78
+ }
79
+ if (ts.isExportDeclaration(statement)) {
80
+ const names = statement.exportClause && ts.isNamedExports(statement.exportClause) ? statement.exportClause.elements : null;
81
+ if (names && names.some(element => element.name.text === 'default')) {
82
+ hasDefault = true;
83
+ }
84
+ if (!names || names.some(element => element.name.text !== 'default')) {
85
+ hasNamed = true;
86
+ }
87
+ return;
88
+ }
89
+ const modifiers = ts.canHaveModifiers(statement) ? ts.getModifiers(statement) || [] : [];
90
+ if (modifiers.some(modifier => modifier.kind === ts.SyntaxKind.ExportKeyword)) {
91
+ if (modifiers.some(modifier => modifier.kind === ts.SyntaxKind.DefaultKeyword)) {
92
+ hasDefault = true;
93
+ } else {
94
+ hasNamed = true;
95
+ }
96
+ }
97
+ });
98
+ return {
99
+ hasDefault,
100
+ hasNamed
101
+ };
102
+ };
103
+
104
+ /**
105
+ * The description of a folder for its module: the first doc comment of the folder's index file, without its tags
106
+ * (@module, @file, ...), or an empty string when there is none.
107
+ * @memberOf module:partials
108
+ * @param {string} folderPath
109
+ * @returns {string}
110
+ */
111
+ exports.describeExports = describeExports;
112
+ const describeFolder = folderPath => {
113
+ const indexFile = ['index.ts', 'index.tsx', 'index.mts', 'index.cts'].map(name => _nodePath.default.join(folderPath, name)).find(file => _nodeFs.default.existsSync(file));
114
+ return indexFile ? describeFile(indexFile) : '';
115
+ };
116
+
117
+ /**
118
+ * The description of a source file for its module: its first doc comment without the tags (@module, @file, ...), when
119
+ * that comment is a header (it is followed by an import or export, so it does not document a declaration itself), or
120
+ * an empty string.
121
+ * @memberOf module:partials
122
+ * @param {string} filePath
123
+ * @returns {string}
124
+ */
125
+ exports.describeFolder = describeFolder;
126
+ const describeFile = filePath => {
127
+ const comment = _nodeFs.default.readFileSync(filePath, 'utf8').match(/^\s*\/\*\*([\s\S]*?)\*\/\s*(import\b|export\s+(\*|\{[^}]*\}\s+from)|$)/);
128
+ if (!comment) {
129
+ return '';
130
+ }
131
+ const lines = comment[1].split('\n').map(line => line.replace(/^\s*\* ?/, '').trimEnd());
132
+ const tagAt = lines.findIndex(line => /^@\w+/.test(line));
133
+ return (tagAt === -1 ? lines : lines.slice(0, tagAt)).join('\n').trim();
134
+ };
135
+
136
+ /**
137
+ * Write one entry file per folder of the source directory into the entry directory. TypeDoc makes a module of every
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
140
+ * re-exported under the name of the file (the source files hold one function each), and anything else a file exports
141
+ * is re-exported as it is (that is where the types.ts files go). Index files (the barrels), tests and declaration
142
+ * files are left out, but the first doc comment of a folder's index file becomes the description of its module.
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
144
+ * comment. A source directory with no folders gets a single entry called index.
145
+ * @memberOf module:partials
146
+ * @param {Object} ts - The TypeScript compiler API.
147
+ * @param {string} srcDir - The directory holding the TypeScript source.
148
+ * @param {string} entryDir - The directory to write the entry files into.
149
+ * @returns {Array<string>} The paths of the entry files.
150
+ */
151
+ exports.describeFile = describeFile;
152
+ const writeDocEntries = (ts, srcDir, entryDir) => {
153
+ const absoluteSrc = _nodePath.default.resolve(srcDir);
154
+ _nodeFs.default.mkdirSync(entryDir, {
155
+ recursive: true
156
+ });
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.
161
+ const groups = folders.length ? [...folders, ...rootFiles.map(file => ({
162
+ name: toIdentifier(_nodePath.default.basename(file).replace(/\.[cm]?tsx?$/, '')),
163
+ files: [file],
164
+ description: describeFile(file)
165
+ })).filter(group => !folders.some(folder => folder.name === group.name))] : [{
166
+ name: 'index',
167
+ path: absoluteSrc,
168
+ files: rootFiles
169
+ }];
170
+ return groups.map(group => {
171
+ const lines = group.files.filter(file => !/^index\./.test(_nodePath.default.basename(file))).sort().flatMap(file => {
172
+ const modulePath = toModulePath(file);
173
+ const {
174
+ hasDefault,
175
+ hasNamed
176
+ } = describeExports(ts, file);
177
+ const fileName = _nodePath.default.basename(file).replace(/\.[cm]?tsx?$/, '');
178
+ return [...(hasDefault ? [`export { default as ${toIdentifier(fileName)} } from '${modulePath}'`] : []), ...(hasNamed ? [`export * from '${modulePath}'`] : [])];
179
+ });
180
+ const description = group.description ?? (group.path ? describeFolder(group.path) : '');
181
+ // TypeDoc takes the first comment of an entry file which has the @module tag as the description of the module
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` : '';
185
+ const entryPath = _nodePath.default.join(entryDir, `${group.name}.ts`);
186
+ _nodeFs.default.mkdirSync(_nodePath.default.dirname(entryPath), {
187
+ recursive: true
188
+ });
189
+ _nodeFs.default.writeFileSync(entryPath, moduleComment + lines.join('\n') + '\n');
190
+ return entryPath;
191
+ });
192
+ };
193
+ exports.writeDocEntries = writeDocEntries;
194
+ const projectName = () => {
195
+ try {
196
+ return JSON.parse(_nodeFs.default.readFileSync(_nodePath.default.join(process.cwd(), 'package.json'), 'utf8')).name;
197
+ } catch (error) {
198
+ return _nodePath.default.basename(process.cwd());
199
+ }
200
+ };
201
+
202
+ /**
203
+ * Generate the HTML documentation of a TypeScript project with TypeDoc, straight from the TypeScript source, so the
204
+ * types (and the comments on them) are documented from where they are defined. The modules mirror the folders of the
205
+ * source, see {@link writeDocEntries}. Configure this with 'docs.from', 'docs.to', 'docs.index', 'docs.title',
206
+ * 'docs.tsconfig' and 'docs.logLevel'.
207
+ * @memberOf module:partials
208
+ * @param {string} [srcPath=gulpConfig.get('docs.from')] - The directory holding the TypeScript source.
209
+ * @param {string} [outPath=gulpConfig.get('docs.to')] - The directory the documentation is generated into (cleared first).
210
+ * @param {function(string): Promise<Object>} [loadDocs] - Resolves the TypeDoc module, tests can inject a stand-in.
211
+ * @returns {Function} A gulp task, it accepts an optional callback and returns a promise.
212
+ */
213
+ const typeDocsFor = (srcPath = gulpConfig.get('docs.from'), outPath = gulpConfig.get('docs.to'), loadDocs = loadTypeDoc) => {
214
+ if (gulpConfig.get('docs.enabled') === false) {
215
+ return () => {};
216
+ }
217
+ return done => {
218
+ const generate = async () => {
219
+ const ts = (0, _tsFor.loadTypescript)();
220
+ const {
221
+ Application
222
+ } = await loadDocs();
223
+ const workDir = _nodeFs.default.mkdtempSync(_nodePath.default.join(_nodeOs.default.tmpdir(), 'typedocs-'));
224
+ try {
225
+ const entryPoints = writeDocEntries(ts, srcPath, _nodePath.default.join(workDir, 'entries'));
226
+ // The entry files live outside the project, so the tsconfig which is used for the documentation extends the
227
+ // one of the project and adds the entries to the files it includes.
228
+ const projectConfig = gulpConfig.get('docs.tsconfig') || gulpConfig.get('typescript.config');
229
+ const tsconfig = _nodePath.default.join(workDir, 'tsconfig.json');
230
+ _nodeFs.default.writeFileSync(tsconfig, JSON.stringify({
231
+ ...(projectConfig ? {
232
+ extends: _nodePath.default.resolve(projectConfig)
233
+ } : {}),
234
+ include: [_nodePath.default.join(workDir, 'entries', '**', '*.ts').split(_nodePath.default.sep).join('/'), _nodePath.default.resolve(srcPath).split(_nodePath.default.sep).join('/') + '/**/*.ts'],
235
+ exclude: [_nodePath.default.resolve(srcPath).split(_nodePath.default.sep).join('/') + '/**/*.test.*']
236
+ }));
237
+ const indexFile = gulpConfig.get('docs.index');
238
+ const gitRevision = gulpConfig.get('docs.gitRevision');
239
+ await (0, _removeDirectory.removeDirectory)(outPath);
240
+ const app = await Application.bootstrap({
241
+ entryPoints,
242
+ tsconfig,
243
+ name: gulpConfig.get('docs.title') || projectName(),
244
+ readme: indexFile && _nodeFs.default.existsSync(indexFile) ? indexFile : 'none',
245
+ logLevel: gulpConfig.get('docs.logLevel') || 'Warn',
246
+ skipErrorChecking: true,
247
+ // Left out, TypeDoc links each declaration to its source at the current commit, so every commit changes
248
+ // every page; a branch name keeps the pages the same until the documentation itself changes.
249
+ ...(gitRevision ? {
250
+ gitRevision
251
+ } : {})
252
+ });
253
+ const project = await app.convert();
254
+ if (!project) {
255
+ throw new Error('TypeDoc could not read the TypeScript source, see the errors above.');
256
+ }
257
+ await app.generateDocs(project, outPath);
258
+ } finally {
259
+ await (0, _removeDirectory.removeDirectory)(workDir);
260
+ }
261
+ };
262
+ return typeof done === 'function' ? generate().then(() => done(), done) : generate();
263
+ };
264
+ };
265
265
  exports.typeDocsFor = typeDocsFor;