@vscode/vsce 2.30.0 → 2.30.1-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.
- package/out/main.js +2 -1
- package/out/package.js +29 -25
- package/out/util.js +153 -42
- package/package.json +1 -1
package/out/main.js
CHANGED
|
@@ -77,6 +77,7 @@ module.exports = function (argv) {
|
|
|
77
77
|
commander_1.default
|
|
78
78
|
.command('ls')
|
|
79
79
|
.description('Lists all the files that will be published/packaged')
|
|
80
|
+
.option('--tree', 'Prints the files in a tree format', false)
|
|
80
81
|
.option('--yarn', 'Use yarn instead of npm (default inferred from presence of yarn.lock or .yarnrc)')
|
|
81
82
|
.option('--no-yarn', 'Use npm instead of yarn (default inferred from absence of yarn.lock or .yarnrc)')
|
|
82
83
|
.option('--packagedDependencies <path>', 'Select packages that should be published only (includes dependencies)', (val, all) => (all ? all.concat(val) : [val]), undefined)
|
|
@@ -84,7 +85,7 @@ module.exports = function (argv) {
|
|
|
84
85
|
// default must remain undefined for dependencies or we will fail to load defaults from package.json
|
|
85
86
|
.option('--dependencies', 'Enable dependency detection via npm or yarn', undefined)
|
|
86
87
|
.option('--no-dependencies', 'Disable dependency detection via npm or yarn', undefined)
|
|
87
|
-
.action(({ yarn, packagedDependencies, ignoreFile, dependencies }) => main((0, package_1.ls)({ useYarn: yarn, packagedDependencies, ignoreFile, dependencies })));
|
|
88
|
+
.action(({ tree, yarn, packagedDependencies, ignoreFile, dependencies }) => main((0, package_1.ls)({ tree, useYarn: yarn, packagedDependencies, ignoreFile, dependencies })));
|
|
88
89
|
commander_1.default
|
|
89
90
|
.command('package [version]')
|
|
90
91
|
.alias('pack')
|
package/out/package.js
CHANGED
|
@@ -1346,7 +1346,7 @@ async function pack(options = {}) {
|
|
|
1346
1346
|
const cwd = options.cwd || process.cwd();
|
|
1347
1347
|
const manifest = await readManifest(cwd);
|
|
1348
1348
|
const files = await collect(manifest, options);
|
|
1349
|
-
printPackagedFiles(files, cwd, manifest, options);
|
|
1349
|
+
await printPackagedFiles(files, cwd, manifest, options);
|
|
1350
1350
|
if (options.version && !(options.updatePackageJson ?? true)) {
|
|
1351
1351
|
manifest.version = options.version;
|
|
1352
1352
|
}
|
|
@@ -1393,17 +1393,8 @@ async function packageCommand(options = {}) {
|
|
|
1393
1393
|
await signPackage(packagePath, options.signTool);
|
|
1394
1394
|
}
|
|
1395
1395
|
const stats = await fs.promises.stat(packagePath);
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
if (stats.size > 1048576) {
|
|
1399
|
-
size = Math.round(stats.size / 10485.76) / 100;
|
|
1400
|
-
unit = 'MB';
|
|
1401
|
-
}
|
|
1402
|
-
else {
|
|
1403
|
-
size = Math.round(stats.size / 10.24) / 100;
|
|
1404
|
-
unit = 'KB';
|
|
1405
|
-
}
|
|
1406
|
-
util.log.done(`Packaged: ${packagePath} (${files.length} files, ${size}${unit})`);
|
|
1396
|
+
const packageSize = util.bytesToString(stats.size);
|
|
1397
|
+
util.log.done(`Packaged: ${packagePath} ` + chalk_1.default.bold(`(${files.length} files, ${packageSize})`));
|
|
1407
1398
|
}
|
|
1408
1399
|
exports.packageCommand = packageCommand;
|
|
1409
1400
|
/**
|
|
@@ -1411,7 +1402,7 @@ exports.packageCommand = packageCommand;
|
|
|
1411
1402
|
*/
|
|
1412
1403
|
async function listFiles(options = {}) {
|
|
1413
1404
|
const cwd = options.cwd ?? process.cwd();
|
|
1414
|
-
const manifest = await readManifest(cwd);
|
|
1405
|
+
const manifest = options.manifest ?? await readManifest(cwd);
|
|
1415
1406
|
if (options.prepublish) {
|
|
1416
1407
|
await prepublish(cwd, manifest, options.useYarn);
|
|
1417
1408
|
}
|
|
@@ -1419,27 +1410,33 @@ async function listFiles(options = {}) {
|
|
|
1419
1410
|
}
|
|
1420
1411
|
exports.listFiles = listFiles;
|
|
1421
1412
|
/**
|
|
1422
|
-
* Lists the files included in the extension's package.
|
|
1413
|
+
* Lists the files included in the extension's package.
|
|
1423
1414
|
*/
|
|
1424
1415
|
async function ls(options = {}) {
|
|
1425
|
-
const
|
|
1426
|
-
|
|
1427
|
-
|
|
1416
|
+
const cwd = process.cwd();
|
|
1417
|
+
const manifest = await readManifest(cwd);
|
|
1418
|
+
const files = await listFiles({ ...options, cwd, manifest });
|
|
1419
|
+
if (options.tree) {
|
|
1420
|
+
const printableFileStructure = await util.generateFileStructureTree(getDefaultPackageName(manifest, options), files.map(f => ({ origin: f, tree: f })));
|
|
1421
|
+
console.log(printableFileStructure.join('\n'));
|
|
1422
|
+
}
|
|
1423
|
+
else {
|
|
1424
|
+
console.log(files.join('\n'));
|
|
1428
1425
|
}
|
|
1429
1426
|
}
|
|
1430
1427
|
exports.ls = ls;
|
|
1431
1428
|
/**
|
|
1432
1429
|
* Prints the packaged files of an extension.
|
|
1433
1430
|
*/
|
|
1434
|
-
function printPackagedFiles(files, cwd, manifest, options) {
|
|
1431
|
+
async function printPackagedFiles(files, cwd, manifest, options) {
|
|
1435
1432
|
// Warn if the extension contains a lot of files
|
|
1436
1433
|
const jsFiles = files.filter(f => /\.js$/i.test(f.path));
|
|
1437
1434
|
if (files.length > 5000 || jsFiles.length > 100) {
|
|
1438
|
-
let message = '
|
|
1435
|
+
let message = '';
|
|
1439
1436
|
message += `This extension consists of ${chalk_1.default.bold(String(files.length))} files, out of which ${chalk_1.default.bold(String(jsFiles.length))} are JavaScript files. `;
|
|
1440
1437
|
message += `For performance reasons, you should bundle your extension: ${chalk_1.default.underline('https://aka.ms/vscode-bundle-extension')}. `;
|
|
1441
1438
|
message += `You should also exclude unnecessary files by adding them to your .vscodeignore: ${chalk_1.default.underline('https://aka.ms/vscode-vscodeignore')}.\n`;
|
|
1442
|
-
|
|
1439
|
+
util.log.warn(message);
|
|
1443
1440
|
}
|
|
1444
1441
|
// Warn if the extension does not have a .vscodeignore file or a files property in package.json
|
|
1445
1442
|
if (!options.ignoreFile && !manifest.files) {
|
|
@@ -1447,20 +1444,27 @@ function printPackagedFiles(files, cwd, manifest, options) {
|
|
|
1447
1444
|
if (!hasDeaultIgnore) {
|
|
1448
1445
|
let message = '';
|
|
1449
1446
|
message += `Neither a ${chalk_1.default.bold('.vscodeignore')} file nor a ${chalk_1.default.bold('"files"')} property in package.json was found. `;
|
|
1450
|
-
message += `To ensure only necessary files are included in your extension
|
|
1451
|
-
message += `add a .vscodeignore file or specify the "files" property in package.json. More info: ${chalk_1.default.underline('https://aka.ms/vscode-vscodeignore')}`;
|
|
1447
|
+
message += `To ensure only necessary files are included in your extension, `;
|
|
1448
|
+
message += `add a .vscodeignore file or specify the "files" property in package.json. More info: ${chalk_1.default.underline('https://aka.ms/vscode-vscodeignore')}\n`;
|
|
1452
1449
|
util.log.warn(message);
|
|
1453
1450
|
}
|
|
1454
1451
|
}
|
|
1455
1452
|
// Print the files included in the package
|
|
1456
|
-
const printableFileStructure = util.generateFileStructureTree(getDefaultPackageName(manifest, options), files.map(f =>
|
|
1453
|
+
const printableFileStructure = await util.generateFileStructureTree(getDefaultPackageName(manifest, options), files.map(f => ({
|
|
1454
|
+
// File path relative to the extension root
|
|
1455
|
+
origin: f.path.startsWith('extension/') ? f.path.substring(10) : f.path,
|
|
1456
|
+
// File path in the VSIX
|
|
1457
|
+
tree: f.path
|
|
1458
|
+
})), 35 // Print up to 35 files/folders
|
|
1459
|
+
);
|
|
1457
1460
|
let message = '';
|
|
1458
1461
|
message += chalk_1.default.bold.blue(`Files included in the VSIX:\n`);
|
|
1459
1462
|
message += printableFileStructure.join('\n');
|
|
1463
|
+
// If not all files have been printed, mention how all files can be printed
|
|
1460
1464
|
if (files.length + 1 > printableFileStructure.length) {
|
|
1461
|
-
|
|
1462
|
-
message += `\n\n=> Run ${chalk_1.default.bold('vsce ls')} to see a list of all included files.\n`;
|
|
1465
|
+
message += `\n\n=> Run ${chalk_1.default.bold('vsce ls --tree')} to see all included files.`;
|
|
1463
1466
|
}
|
|
1467
|
+
message += '\n';
|
|
1464
1468
|
util.log.info(message);
|
|
1465
1469
|
}
|
|
1466
1470
|
exports.printPackagedFiles = printPackagedFiles;
|
package/out/util.js
CHANGED
|
@@ -1,10 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
5
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.generateFileStructureTree = exports.patchOptionsWithManifest = exports.log = exports.sequence = exports.CancellationToken = exports.isCancelledError = exports.nonnull = exports.flatten = exports.chain = exports.normalize = exports.getPublicGalleryAPI = exports.getSecurityRolesAPI = exports.getGalleryAPI = exports.getHubUrl = exports.getMarketplaceUrl = exports.getPublishedUrl = exports.read = void 0;
|
|
29
|
+
exports.generateFileStructureTree = exports.bytesToString = exports.patchOptionsWithManifest = exports.log = exports.sequence = exports.CancellationToken = exports.isCancelledError = exports.nonnull = exports.flatten = exports.chain = exports.normalize = exports.getPublicGalleryAPI = exports.getSecurityRolesAPI = exports.getGalleryAPI = exports.getHubUrl = exports.getMarketplaceUrl = exports.getPublishedUrl = exports.read = void 0;
|
|
7
30
|
const util_1 = require("util");
|
|
31
|
+
const fs = __importStar(require("fs"));
|
|
8
32
|
const read_1 = __importDefault(require("read"));
|
|
9
33
|
const WebApi_1 = require("azure-devops-node-api/WebApi");
|
|
10
34
|
const GalleryApi_1 = require("azure-devops-node-api/GalleryApi");
|
|
@@ -166,82 +190,169 @@ function patchOptionsWithManifest(options, manifest) {
|
|
|
166
190
|
}
|
|
167
191
|
}
|
|
168
192
|
exports.patchOptionsWithManifest = patchOptionsWithManifest;
|
|
169
|
-
function
|
|
193
|
+
function bytesToString(bytes) {
|
|
194
|
+
let size = 0;
|
|
195
|
+
let unit = '';
|
|
196
|
+
if (bytes > 1048576) {
|
|
197
|
+
size = Math.round(bytes / 10485.76) / 100;
|
|
198
|
+
unit = 'MB';
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
size = Math.round(bytes / 10.24) / 100;
|
|
202
|
+
unit = 'KB';
|
|
203
|
+
}
|
|
204
|
+
return `${size} ${unit}`;
|
|
205
|
+
}
|
|
206
|
+
exports.bytesToString = bytesToString;
|
|
207
|
+
const FOLDER_SIZE_KEY = "/__FOlDER_SIZE__\\";
|
|
208
|
+
const FOLDER_FILES_TOTAL_KEY = "/__FOLDER_CHILDREN__\\";
|
|
209
|
+
const FILE_SIZE_WARNING_THRESHOLD = 0.85;
|
|
210
|
+
const FILE_SIZE_LARGE_THRESHOLD = 0.2;
|
|
211
|
+
async function generateFileStructureTree(rootFolder, filePaths, printLinesLimit = Number.MAX_VALUE) {
|
|
170
212
|
const folderTree = {};
|
|
171
213
|
const depthCounts = [];
|
|
172
214
|
// Build a tree structure from the file paths
|
|
173
|
-
|
|
174
|
-
|
|
215
|
+
// Store the file size in the leaf node and the folder size in the folder node
|
|
216
|
+
// Store the number of children in the folder node
|
|
217
|
+
for (const filePath of filePaths) {
|
|
218
|
+
const parts = filePath.tree.split('/');
|
|
175
219
|
let currentLevel = folderTree;
|
|
176
220
|
parts.forEach((part, depth) => {
|
|
221
|
+
const isFile = depth === parts.length - 1;
|
|
222
|
+
// Create the node if it doesn't exist
|
|
177
223
|
if (!currentLevel[part]) {
|
|
178
|
-
|
|
224
|
+
if (isFile) {
|
|
225
|
+
// The file size is stored in the leaf node,
|
|
226
|
+
currentLevel[part] = 0;
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
// The folder size is stored in the folder node
|
|
230
|
+
currentLevel[part] = {};
|
|
231
|
+
currentLevel[part][FOLDER_SIZE_KEY] = 0;
|
|
232
|
+
currentLevel[part][FOLDER_FILES_TOTAL_KEY] = 0;
|
|
233
|
+
}
|
|
234
|
+
// Count the number of items at each depth
|
|
179
235
|
if (depthCounts.length <= depth) {
|
|
180
236
|
depthCounts.push(0);
|
|
181
237
|
}
|
|
182
238
|
depthCounts[depth]++;
|
|
183
239
|
}
|
|
184
240
|
currentLevel = currentLevel[part];
|
|
241
|
+
// Count the total number of children in the nested folders
|
|
242
|
+
if (!isFile) {
|
|
243
|
+
currentLevel[FOLDER_FILES_TOTAL_KEY]++;
|
|
244
|
+
}
|
|
185
245
|
});
|
|
186
|
-
}
|
|
187
|
-
|
|
246
|
+
}
|
|
247
|
+
;
|
|
248
|
+
// Get max depth depending on the maximum number of lines allowed to print
|
|
188
249
|
let currentDepth = 0;
|
|
189
|
-
let countUpToCurrentDepth = depthCounts[0]
|
|
250
|
+
let countUpToCurrentDepth = depthCounts[0] + 1 /* root folder */;
|
|
190
251
|
for (let i = 1; i < depthCounts.length; i++) {
|
|
191
|
-
if (countUpToCurrentDepth + depthCounts[i] >
|
|
252
|
+
if (countUpToCurrentDepth + depthCounts[i] > printLinesLimit) {
|
|
192
253
|
break;
|
|
193
254
|
}
|
|
194
255
|
currentDepth++;
|
|
195
256
|
countUpToCurrentDepth += depthCounts[i];
|
|
196
257
|
}
|
|
197
258
|
const maxDepth = currentDepth;
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
259
|
+
// Get all file sizes
|
|
260
|
+
const fileSizes = await Promise.all(filePaths.map(async (filePath) => {
|
|
261
|
+
try {
|
|
262
|
+
const stats = await fs.promises.stat(filePath.origin);
|
|
263
|
+
return [stats.size, filePath.tree];
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
return [0, filePath.origin];
|
|
267
|
+
}
|
|
268
|
+
}));
|
|
269
|
+
// Store all file sizes in the tree
|
|
270
|
+
let totalFileSizes = 0;
|
|
271
|
+
fileSizes.forEach(([size, filePath]) => {
|
|
272
|
+
totalFileSizes += size;
|
|
273
|
+
const parts = filePath.split('/');
|
|
274
|
+
let currentLevel = folderTree;
|
|
275
|
+
parts.forEach(part => {
|
|
276
|
+
if (typeof currentLevel[part] === 'number') {
|
|
277
|
+
currentLevel[part] = size;
|
|
278
|
+
}
|
|
279
|
+
else if (currentLevel[part]) {
|
|
280
|
+
currentLevel[part][FOLDER_SIZE_KEY] += size;
|
|
281
|
+
}
|
|
282
|
+
currentLevel = currentLevel[part];
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
let output = [];
|
|
286
|
+
output.push(chalk_1.default.bold(rootFolder));
|
|
287
|
+
output.push(...createTreeOutput(folderTree, maxDepth, totalFileSizes));
|
|
288
|
+
for (const [size, filePath] of fileSizes) {
|
|
289
|
+
if (size > FILE_SIZE_WARNING_THRESHOLD * totalFileSizes) {
|
|
290
|
+
output.push(`\nThe file ${filePath} is ${chalk_1.default.red('large')} (${bytesToString(size)})`);
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return output;
|
|
295
|
+
}
|
|
296
|
+
exports.generateFileStructureTree = generateFileStructureTree;
|
|
297
|
+
function createTreeOutput(fileSystem, maxDepth, totalFileSizes) {
|
|
298
|
+
const getColorFromSize = (size) => {
|
|
299
|
+
if (size > FILE_SIZE_WARNING_THRESHOLD * totalFileSizes) {
|
|
300
|
+
return chalk_1.default.red;
|
|
301
|
+
}
|
|
302
|
+
else if (size > FILE_SIZE_LARGE_THRESHOLD * totalFileSizes) {
|
|
303
|
+
return chalk_1.default.yellow;
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
return chalk_1.default.grey;
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
const createFileOutput = (prefix, fileName, fileSize) => {
|
|
310
|
+
let fileSizeColored = '';
|
|
311
|
+
if (fileSize > 0) {
|
|
312
|
+
const fileSizeString = `[${bytesToString(fileSize)}]`;
|
|
313
|
+
fileSizeColored = getColorFromSize(fileSize)(fileSizeString);
|
|
314
|
+
}
|
|
315
|
+
return `${prefix}${fileName} ${fileSizeColored}`;
|
|
316
|
+
};
|
|
317
|
+
const createFolderOutput = (prefix, filesCount, folderSize, folderName, depth) => {
|
|
318
|
+
if (depth < maxDepth) {
|
|
319
|
+
// Max depth is not reached, print only the folder
|
|
320
|
+
// as children will be printed
|
|
321
|
+
return prefix + chalk_1.default.bold(`${folderName}/`);
|
|
322
|
+
}
|
|
323
|
+
// Max depth is reached, print the folder name and additional metadata
|
|
324
|
+
// as children will not be printed
|
|
325
|
+
const folderSizeString = bytesToString(folderSize);
|
|
326
|
+
const folder = chalk_1.default.bold(`${folderName}/`);
|
|
327
|
+
const numFilesString = chalk_1.default.green(`(${filesCount} ${filesCount === 1 ? 'file' : 'files'})`);
|
|
328
|
+
const folderSizeColored = getColorFromSize(folderSize)(`[${folderSizeString}]`);
|
|
329
|
+
return `${prefix}${folder} ${numFilesString} ${folderSizeColored}`;
|
|
330
|
+
};
|
|
331
|
+
const createTreeLayerOutput = (tree, depth, prefix, path) => {
|
|
201
332
|
// Print all files before folders
|
|
202
|
-
const sortedFolderKeys = Object.keys(tree).filter(key => tree[key] !==
|
|
203
|
-
const sortedFileKeys = Object.keys(tree).filter(key => tree[key] ===
|
|
204
|
-
const sortedKeys = [...sortedFileKeys, ...sortedFolderKeys];
|
|
333
|
+
const sortedFolderKeys = Object.keys(tree).filter(key => typeof tree[key] !== 'number').sort();
|
|
334
|
+
const sortedFileKeys = Object.keys(tree).filter(key => typeof tree[key] === 'number').sort();
|
|
335
|
+
const sortedKeys = [...sortedFileKeys, ...sortedFolderKeys].filter(key => key !== FOLDER_SIZE_KEY && key !== FOLDER_FILES_TOTAL_KEY);
|
|
336
|
+
const output = [];
|
|
205
337
|
for (let i = 0; i < sortedKeys.length; i++) {
|
|
206
338
|
const key = sortedKeys[i];
|
|
207
339
|
const isLast = i === sortedKeys.length - 1;
|
|
208
340
|
const localPrefix = prefix + (isLast ? '└─ ' : '├─ ');
|
|
209
341
|
const childPrefix = prefix + (isLast ? ' ' : '│ ');
|
|
210
|
-
if (tree[key] ===
|
|
342
|
+
if (typeof tree[key] === 'number') {
|
|
211
343
|
// It's a file
|
|
212
|
-
|
|
344
|
+
output.push(createFileOutput(localPrefix, key, tree[key]));
|
|
213
345
|
}
|
|
214
346
|
else {
|
|
215
347
|
// It's a folder
|
|
348
|
+
output.push(createFolderOutput(localPrefix, tree[key][FOLDER_FILES_TOTAL_KEY], tree[key][FOLDER_SIZE_KEY], key, depth));
|
|
216
349
|
if (depth < maxDepth) {
|
|
217
|
-
|
|
218
|
-
message.push(localPrefix + chalk_1.default.bold(`${key}/`));
|
|
219
|
-
printTree(tree[key], depth + 1, childPrefix);
|
|
350
|
+
output.push(...createTreeLayerOutput(tree[key], depth + 1, childPrefix, path + key + '/'));
|
|
220
351
|
}
|
|
221
|
-
else {
|
|
222
|
-
// max depth is reached, print the folder but not its children
|
|
223
|
-
const filesCount = countFiles(tree[key]);
|
|
224
|
-
message.push(localPrefix + chalk_1.default.bold(`${key}/`) + chalk_1.default.green(` (${filesCount} ${filesCount === 1 ? 'file' : 'files'})`));
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
// Helper function to count the number of files in a tree
|
|
230
|
-
const countFiles = (tree) => {
|
|
231
|
-
let filesCount = 0;
|
|
232
|
-
for (const key in tree) {
|
|
233
|
-
if (tree[key] === null) {
|
|
234
|
-
filesCount++;
|
|
235
|
-
}
|
|
236
|
-
else {
|
|
237
|
-
filesCount += countFiles(tree[key]);
|
|
238
352
|
}
|
|
239
353
|
}
|
|
240
|
-
return
|
|
354
|
+
return output;
|
|
241
355
|
};
|
|
242
|
-
|
|
243
|
-
printTree(folderTree, 0, '');
|
|
244
|
-
return message;
|
|
356
|
+
return createTreeLayerOutput(fileSystem, 0, '', '');
|
|
245
357
|
}
|
|
246
|
-
exports.generateFileStructureTree = generateFileStructureTree;
|
|
247
358
|
//# sourceMappingURL=util.js.map
|