@metricinsights/pp-dev 0.4.0 → 0.6.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/README.md +113 -4
- package/dist/cjs/cli.js +649 -40
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/{index-0adc09ce.js → index-09809c31.js} +39 -30
- package/dist/cjs/index-09809c31.js.map +1 -0
- package/dist/cjs/index.js +8 -9
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/package.json +13 -1
- package/dist/cjs/{plugin-ab0651c4.js → plugin-2105b1ac.js} +242 -30
- package/dist/cjs/plugin-2105b1ac.js.map +1 -0
- package/dist/cjs/plugin.js +7 -2
- package/dist/cjs/plugin.js.map +1 -1
- package/dist/esm/cli.js +635 -29
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/{index-1a1d27e5.js → index-bc9325e9.js} +38 -28
- package/dist/esm/index-bc9325e9.js.map +1 -0
- package/dist/esm/index.js +8 -8
- package/dist/esm/package.json +13 -1
- package/dist/esm/{plugin-7db34718.js → plugin-63f01789.js} +239 -30
- package/dist/esm/plugin-63f01789.js.map +1 -0
- package/dist/esm/plugin.js +3 -1
- package/dist/esm/plugin.js.map +1 -1
- package/dist/types/index.d.ts +9 -3
- package/dist/types/plugin.d.ts +67 -2
- package/package.json +13 -1
- package/dist/cjs/index-0adc09ce.js.map +0 -1
- package/dist/cjs/plugin-ab0651c4.js.map +0 -1
- package/dist/esm/index-1a1d27e5.js.map +0 -1
- package/dist/esm/plugin-7db34718.js.map +0 -1
package/dist/cjs/cli.js
CHANGED
|
@@ -4,22 +4,27 @@ var path = require('path');
|
|
|
4
4
|
var fs = require('fs');
|
|
5
5
|
var node_perf_hooks = require('node:perf_hooks');
|
|
6
6
|
var cac = require('cac');
|
|
7
|
-
var
|
|
8
|
-
var
|
|
7
|
+
var index = require('./index-09809c31.js');
|
|
8
|
+
var plugin = require('./plugin-2105b1ac.js');
|
|
9
9
|
var vite = require('vite');
|
|
10
10
|
var url = require('url');
|
|
11
|
-
var plugin = require('./plugin-ab0651c4.js');
|
|
12
11
|
var express = require('express');
|
|
13
12
|
var winston = require('winston');
|
|
14
|
-
require('
|
|
15
|
-
require('
|
|
13
|
+
var dirCompare = require('dir-compare');
|
|
14
|
+
var DiffMatchPatch = require('diff-match-patch');
|
|
15
|
+
var isbinaryfile = require('isbinaryfile');
|
|
16
|
+
var os = require('os');
|
|
17
|
+
var crypto = require('crypto');
|
|
18
|
+
var extractZip = require('extract-zip');
|
|
19
|
+
var svgToFont = require('svgtofont');
|
|
16
20
|
require('ejs');
|
|
21
|
+
require('esbuild');
|
|
17
22
|
require('http-proxy-middleware');
|
|
23
|
+
require('picocolors');
|
|
18
24
|
require('axios');
|
|
19
25
|
require('jsdom');
|
|
20
26
|
require('https');
|
|
21
27
|
require('memory-cache');
|
|
22
|
-
require('crypto');
|
|
23
28
|
require('process');
|
|
24
29
|
require('child_process');
|
|
25
30
|
require('console');
|
|
@@ -46,8 +51,10 @@ var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
|
46
51
|
var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
|
|
47
52
|
var express__namespace = /*#__PURE__*/_interopNamespaceDefault(express);
|
|
48
53
|
var winston__namespace = /*#__PURE__*/_interopNamespaceDefault(winston);
|
|
54
|
+
var dirCompare__namespace = /*#__PURE__*/_interopNamespaceDefault(dirCompare);
|
|
55
|
+
var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os);
|
|
56
|
+
var crypto__namespace = /*#__PURE__*/_interopNamespaceDefault(crypto);
|
|
49
57
|
|
|
50
|
-
const colors$2 = picocolors.createColors();
|
|
51
58
|
function isDefined(value) {
|
|
52
59
|
return value != null;
|
|
53
60
|
}
|
|
@@ -56,8 +63,9 @@ function bindShortcuts(server, opts) {
|
|
|
56
63
|
return;
|
|
57
64
|
}
|
|
58
65
|
server._shortcutsOptions = opts;
|
|
66
|
+
const logger = plugin.createLogger();
|
|
59
67
|
if (opts.print) {
|
|
60
|
-
|
|
68
|
+
logger.info(plugin.colors.dim(plugin.colors.green(' ➜')) + plugin.colors.dim(' press ') + plugin.colors.bold('h') + plugin.colors.dim(' to show help'));
|
|
61
69
|
}
|
|
62
70
|
const shortcuts = (opts.customShortcuts ?? []).filter(isDefined).concat(BASE_SHORTCUTS);
|
|
63
71
|
let actionRunning = false;
|
|
@@ -71,10 +79,10 @@ function bindShortcuts(server, opts) {
|
|
|
71
79
|
return;
|
|
72
80
|
}
|
|
73
81
|
if (input === 'h') {
|
|
74
|
-
|
|
82
|
+
logger.info([
|
|
75
83
|
'',
|
|
76
|
-
colors
|
|
77
|
-
...shortcuts.map((shortcut) => colors
|
|
84
|
+
plugin.colors.bold(' Shortcuts'),
|
|
85
|
+
...shortcuts.map((shortcut) => plugin.colors.dim(' press ') + plugin.colors.bold(shortcut.key) + plugin.colors.dim(` to ${shortcut.description}`)),
|
|
78
86
|
].join('\n'));
|
|
79
87
|
}
|
|
80
88
|
const shortcut = shortcuts.find((shortcut) => shortcut.key === input);
|
|
@@ -140,7 +148,6 @@ const BASE_SHORTCUTS = [
|
|
|
140
148
|
},
|
|
141
149
|
];
|
|
142
150
|
|
|
143
|
-
const colors$1 = picocolors.createColors();
|
|
144
151
|
function createDevServer(logLevel = 'info') {
|
|
145
152
|
const server = express__namespace.default();
|
|
146
153
|
const logger = winston__namespace.createLogger({
|
|
@@ -160,24 +167,516 @@ function createDevServer(logLevel = 'info') {
|
|
|
160
167
|
if (!listener) {
|
|
161
168
|
throw new Error('Server is not listening');
|
|
162
169
|
}
|
|
163
|
-
const colorUrl = (url) => colors
|
|
170
|
+
const colorUrl = (url) => plugin.colors.cyan(url.replace(/:(\d+)\//, (_, port) => `:${plugin.colors.bold(port)}/`));
|
|
164
171
|
const address = listener.address();
|
|
165
172
|
if (address && typeof address === 'object') {
|
|
166
173
|
if (address.address === '::') {
|
|
167
174
|
const url$1 = new url.URL(base || '', `http://localhost:${address.port}`);
|
|
168
|
-
logger.info(` ${colors
|
|
175
|
+
logger.info(` ${plugin.colors.green('➜')} ${plugin.colors.bold('Local')}: ${colorUrl(url$1.toString())}`);
|
|
169
176
|
}
|
|
170
177
|
else {
|
|
171
178
|
const url$1 = new url.URL(base || '', `http://[${address.address}]:${address.port}`);
|
|
172
|
-
logger.info(` ${colors
|
|
179
|
+
logger.info(` ${plugin.colors.green('➜')} ${plugin.colors.bold('Local')}: ${colorUrl(url$1.toString())}`);
|
|
173
180
|
}
|
|
174
181
|
}
|
|
175
182
|
};
|
|
176
183
|
return server;
|
|
177
184
|
}
|
|
178
185
|
|
|
186
|
+
const changelogTemplate = /* HTML */ `<!DOCTYPE html>
|
|
187
|
+
<html lang="en">
|
|
188
|
+
<head>
|
|
189
|
+
<meta charset="UTF-8" />
|
|
190
|
+
<title>Changelog Diff</title>
|
|
191
|
+
<style>
|
|
192
|
+
tr,
|
|
193
|
+
td {
|
|
194
|
+
padding: 0;
|
|
195
|
+
}
|
|
196
|
+
.diff-file {
|
|
197
|
+
margin-top: 20px;
|
|
198
|
+
border: 1px solid #e1e4e8;
|
|
199
|
+
border-radius: 6px;
|
|
200
|
+
}
|
|
201
|
+
.diff-file-title {
|
|
202
|
+
padding: 10px 20px;
|
|
203
|
+
background-color: #f6f8fa;
|
|
204
|
+
border-bottom: 1px solid #e1e4e8;
|
|
205
|
+
border-radius: 6px 6px 0 0;
|
|
206
|
+
font-weight: bold;
|
|
207
|
+
}
|
|
208
|
+
.diff-file-title .renamed {
|
|
209
|
+
font-weight: normal;
|
|
210
|
+
}
|
|
211
|
+
.diff-file-title .renamed .from {
|
|
212
|
+
color: #cb2431;
|
|
213
|
+
}
|
|
214
|
+
.diff-file-title .renamed .to {
|
|
215
|
+
color: #22863a;
|
|
216
|
+
}
|
|
217
|
+
.diff-file-title .added {
|
|
218
|
+
color: #22863a;
|
|
219
|
+
}
|
|
220
|
+
.diff-file-title .deleted {
|
|
221
|
+
color: #cb2431;
|
|
222
|
+
}
|
|
223
|
+
.diff-file-content {
|
|
224
|
+
}
|
|
225
|
+
.diff-table {
|
|
226
|
+
tab-size: 8;
|
|
227
|
+
width: 100%;
|
|
228
|
+
border-collapse: separate;
|
|
229
|
+
border-spacing: 0;
|
|
230
|
+
}
|
|
231
|
+
.blob-num {
|
|
232
|
+
position: relative;
|
|
233
|
+
color: #1f2328;
|
|
234
|
+
width: 1%;
|
|
235
|
+
min-width: 50px;
|
|
236
|
+
padding: 0 10px;
|
|
237
|
+
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
|
|
238
|
+
font-size: 12px;
|
|
239
|
+
line-height: 20px;
|
|
240
|
+
text-align: right;
|
|
241
|
+
white-space: nowrap;
|
|
242
|
+
vertical-align: top;
|
|
243
|
+
cursor: pointer;
|
|
244
|
+
-webkit-user-select: none;
|
|
245
|
+
user-select: none;
|
|
246
|
+
}
|
|
247
|
+
.blob-num.addition {
|
|
248
|
+
background-color: #ccffd8;
|
|
249
|
+
border-color: #1f883e;
|
|
250
|
+
}
|
|
251
|
+
.blob-num.deletion {
|
|
252
|
+
background-color: #ffd7d5;
|
|
253
|
+
border-color: #cf222e;
|
|
254
|
+
}
|
|
255
|
+
.blob-num::before {
|
|
256
|
+
content: attr(data-line-number);
|
|
257
|
+
}
|
|
258
|
+
.blob-code {
|
|
259
|
+
position: relative;
|
|
260
|
+
padding: 0 10px 0 22px;
|
|
261
|
+
vertical-align: top;
|
|
262
|
+
color: #1f2329;
|
|
263
|
+
}
|
|
264
|
+
.blob-code.code-addition {
|
|
265
|
+
background-color: #e6ffec;
|
|
266
|
+
}
|
|
267
|
+
.blob-code.code-deletion {
|
|
268
|
+
background-color: #ffebe9;
|
|
269
|
+
}
|
|
270
|
+
.blob-code.skip,
|
|
271
|
+
.blob-code.message {
|
|
272
|
+
text-align: center;
|
|
273
|
+
}
|
|
274
|
+
.blob-code.skip .blob-code-inner,
|
|
275
|
+
.blob-code.message .blob-code-inner {
|
|
276
|
+
font-weight: bold;
|
|
277
|
+
color: #6a737d;
|
|
278
|
+
padding: 10px 0;
|
|
279
|
+
}
|
|
280
|
+
.blob-code-inner {
|
|
281
|
+
display: table-cell;
|
|
282
|
+
overflow: visible;
|
|
283
|
+
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
|
|
284
|
+
font-size: 12px;
|
|
285
|
+
word-wrap: anywhere;
|
|
286
|
+
white-space: pre-wrap;
|
|
287
|
+
}
|
|
288
|
+
.blob-code-inner::before {
|
|
289
|
+
content: attr(data-code-prefix);
|
|
290
|
+
position: absolute;
|
|
291
|
+
top: 1px;
|
|
292
|
+
left: 8px;
|
|
293
|
+
padding-right: 8px;
|
|
294
|
+
}
|
|
295
|
+
</style>
|
|
296
|
+
</head>
|
|
297
|
+
<body>
|
|
298
|
+
<h1>Changelog Diff</h1>
|
|
299
|
+
|
|
300
|
+
%FILES%
|
|
301
|
+
</body>
|
|
302
|
+
</html>`;
|
|
303
|
+
const LINE_ADDED = 1;
|
|
304
|
+
const LINE_REMOVED = -1;
|
|
305
|
+
const LINE_CONTEXT = 0;
|
|
306
|
+
/**
|
|
307
|
+
* Escape HTML sequence
|
|
308
|
+
* @param str
|
|
309
|
+
*/
|
|
310
|
+
function escapeHTMLSequence(str) {
|
|
311
|
+
return str.replace(/[\u00A0-\u9999<>&]/g, (i) => '&#' + i.charCodeAt(0) + ';');
|
|
312
|
+
}
|
|
313
|
+
const fileNameWithHashRegEx = /(.+)(-[a-f0-9]{6,20})(\.[a-z0-9]+)$/i;
|
|
314
|
+
/**
|
|
315
|
+
* Changelog generator class
|
|
316
|
+
* @class
|
|
317
|
+
* @classdesc
|
|
318
|
+
* Generates a changelog file based on the differences between two asset folders or zip files
|
|
319
|
+
* @example
|
|
320
|
+
* const changelogGenerator = new ChangelogGenerator({
|
|
321
|
+
* previousAssetsPath: './dist-zip/previous',
|
|
322
|
+
* currentAssetsPath: './dist-zip/current',
|
|
323
|
+
* destinationPath: './dist-zip',
|
|
324
|
+
* changelogFilename: 'CHANGELOG.html',
|
|
325
|
+
* });
|
|
326
|
+
* changelogGenerator.generateChangelog();
|
|
327
|
+
*/
|
|
328
|
+
class ChangelogGenerator {
|
|
329
|
+
oldAssetsPath;
|
|
330
|
+
newAssetsPath;
|
|
331
|
+
destinationPath;
|
|
332
|
+
changelogFilename;
|
|
333
|
+
changelogTemplate = changelogTemplate;
|
|
334
|
+
diffFileTemplateHandler;
|
|
335
|
+
diffLineTemplateHandler;
|
|
336
|
+
contextLines = 3;
|
|
337
|
+
logger;
|
|
338
|
+
/**
|
|
339
|
+
* Changelog generator class constructor
|
|
340
|
+
* @param opts
|
|
341
|
+
*/
|
|
342
|
+
constructor(opts) {
|
|
343
|
+
const { oldAssetsPath, newAssetsPath, destinationPath, changelogTemplate, diffFileTemplateHandler, diffLineTemplateHandler, changelogFilename, contextLines, } = opts;
|
|
344
|
+
this.logger = plugin.createLogger();
|
|
345
|
+
if (!oldAssetsPath || !newAssetsPath || !destinationPath) {
|
|
346
|
+
throw new Error('Previous assets path, current assets path and destination path are required');
|
|
347
|
+
}
|
|
348
|
+
if (oldAssetsPath === newAssetsPath) {
|
|
349
|
+
throw new Error('Previous and current assets paths must be different');
|
|
350
|
+
}
|
|
351
|
+
if (!this.isExists(oldAssetsPath)) {
|
|
352
|
+
throw new Error(`Previous assets path ${oldAssetsPath} does not exist`);
|
|
353
|
+
}
|
|
354
|
+
if (!this.isExists(newAssetsPath)) {
|
|
355
|
+
throw new Error(`Current assets path ${newAssetsPath} does not exist`);
|
|
356
|
+
}
|
|
357
|
+
if (this.isZipFile(oldAssetsPath)) {
|
|
358
|
+
const unzipDestinationPath = path__namespace.resolve(os__namespace.tmpdir(), crypto__namespace.createHash('md5').update(oldAssetsPath).digest('hex'));
|
|
359
|
+
this.oldAssetsPath = this.unzipFile(oldAssetsPath, unzipDestinationPath)
|
|
360
|
+
.then(() => {
|
|
361
|
+
return this.normalizeAssetFolderPath(unzipDestinationPath);
|
|
362
|
+
})
|
|
363
|
+
.then((path) => {
|
|
364
|
+
if (this.isEmptyFolder(path)) {
|
|
365
|
+
throw new Error(`Previous assets path ${path} is empty`);
|
|
366
|
+
}
|
|
367
|
+
return path;
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
else if (this.isFolder(oldAssetsPath)) {
|
|
371
|
+
const path = this.normalizeAssetFolderPath(oldAssetsPath);
|
|
372
|
+
if (this.isEmptyFolder(path)) {
|
|
373
|
+
throw new Error(`Previous assets path ${path} is empty`);
|
|
374
|
+
}
|
|
375
|
+
this.oldAssetsPath = Promise.resolve(path);
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
throw new Error(`Invalid previous assets path ${oldAssetsPath}. It must be a folder or a zip file`);
|
|
379
|
+
}
|
|
380
|
+
if (this.isZipFile(newAssetsPath)) {
|
|
381
|
+
const unzipDestinationPath = path__namespace.resolve(os__namespace.tmpdir(), crypto__namespace.createHash('md5').update(newAssetsPath).digest('hex'));
|
|
382
|
+
this.newAssetsPath = this.unzipFile(newAssetsPath, unzipDestinationPath)
|
|
383
|
+
.then(() => {
|
|
384
|
+
return this.normalizeAssetFolderPath(unzipDestinationPath);
|
|
385
|
+
})
|
|
386
|
+
.then((path) => {
|
|
387
|
+
if (this.isEmptyFolder(path)) {
|
|
388
|
+
throw new Error(`Current assets path ${path} is empty`);
|
|
389
|
+
}
|
|
390
|
+
return path;
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
else if (this.isFolder(newAssetsPath)) {
|
|
394
|
+
const path = this.normalizeAssetFolderPath(newAssetsPath);
|
|
395
|
+
if (this.isEmptyFolder(path)) {
|
|
396
|
+
throw new Error(`Current assets path ${newAssetsPath} is empty`);
|
|
397
|
+
}
|
|
398
|
+
this.newAssetsPath = Promise.resolve(path);
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
throw new Error(`Invalid current assets path ${newAssetsPath}. It must be a folder or a zip file`);
|
|
402
|
+
}
|
|
403
|
+
this.destinationPath = destinationPath;
|
|
404
|
+
this.mkdirpSync(this.destinationPath);
|
|
405
|
+
if (changelogFilename) {
|
|
406
|
+
this.changelogFilename = changelogFilename;
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
this.changelogFilename = 'CHANGELOG.html';
|
|
410
|
+
}
|
|
411
|
+
if (changelogTemplate) {
|
|
412
|
+
if (this.templateIsValid(changelogTemplate)) {
|
|
413
|
+
this.changelogTemplate = changelogTemplate;
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
this.logger.warn(plugin.colors.yellow('Invalid changelog template, using default'));
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
if (typeof diffFileTemplateHandler === 'function') {
|
|
420
|
+
this.diffFileTemplateHandler = diffFileTemplateHandler;
|
|
421
|
+
}
|
|
422
|
+
if (typeof diffLineTemplateHandler === 'function') {
|
|
423
|
+
this.diffLineTemplateHandler = diffLineTemplateHandler;
|
|
424
|
+
}
|
|
425
|
+
if (contextLines) {
|
|
426
|
+
this.contextLines = contextLines;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
templateIsValid(template) {
|
|
430
|
+
return template.includes('%FILES%');
|
|
431
|
+
}
|
|
432
|
+
isExists(assetPath) {
|
|
433
|
+
return fs__namespace.existsSync(assetPath);
|
|
434
|
+
}
|
|
435
|
+
isZipFile(assetPath) {
|
|
436
|
+
return assetPath.endsWith('.zip');
|
|
437
|
+
}
|
|
438
|
+
isFolder(assetPath) {
|
|
439
|
+
return fs__namespace.lstatSync(assetPath).isDirectory();
|
|
440
|
+
}
|
|
441
|
+
isEmptyFolder(assetPath) {
|
|
442
|
+
return fs__namespace.readdirSync(assetPath, { withFileTypes: true }).length === 0;
|
|
443
|
+
}
|
|
444
|
+
mkdirpSync(dir) {
|
|
445
|
+
if (!fs__namespace.existsSync(dir)) {
|
|
446
|
+
fs__namespace.mkdirSync(dir, { recursive: true });
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
async unzipFile(assetPath, destinationPath) {
|
|
450
|
+
fs__namespace.rmSync(destinationPath, { force: true, recursive: true });
|
|
451
|
+
return extractZip(assetPath, { dir: destinationPath });
|
|
452
|
+
}
|
|
453
|
+
normalizeAssetFolderPath(assetPath) {
|
|
454
|
+
const folderContent = fs__namespace.readdirSync(assetPath);
|
|
455
|
+
if (folderContent.length === 1 && fs__namespace.lstatSync(path__namespace.join(assetPath, folderContent[0])).isDirectory()) {
|
|
456
|
+
return this.normalizeAssetFolderPath(path__namespace.join(assetPath, folderContent[0]));
|
|
457
|
+
}
|
|
458
|
+
return assetPath;
|
|
459
|
+
}
|
|
460
|
+
pathToPosix(path) {
|
|
461
|
+
return path.replace(/\\/g, '/');
|
|
462
|
+
}
|
|
463
|
+
diffTableTemplate(diffLinesHTML) {
|
|
464
|
+
return /* HTML */ `<table class="diff-table">
|
|
465
|
+
<tbody>
|
|
466
|
+
${diffLinesHTML}
|
|
467
|
+
</tbody>
|
|
468
|
+
</table>`;
|
|
469
|
+
}
|
|
470
|
+
getDiffTableHTML(diffLines) {
|
|
471
|
+
const diffLinesHTML = diffLines
|
|
472
|
+
.filter((value, index, array) => {
|
|
473
|
+
if (value.lineType === LINE_CONTEXT) {
|
|
474
|
+
return ((index >= 0 && index < this.contextLines) ||
|
|
475
|
+
(index > array.length - (this.contextLines + 1) && index <= array.length - 1) ||
|
|
476
|
+
array
|
|
477
|
+
.slice(index - this.contextLines, index + this.contextLines + 1)
|
|
478
|
+
.some((line) => line.lineType !== LINE_CONTEXT));
|
|
479
|
+
}
|
|
480
|
+
return true;
|
|
481
|
+
})
|
|
482
|
+
.map((line, index, array) => {
|
|
483
|
+
if (index > 0) {
|
|
484
|
+
const prevLine = array[index - 1];
|
|
485
|
+
if (line.lineNumber - prevLine.lineNumber > 1) {
|
|
486
|
+
return [{ lineNumber: -1, lineContent: '', lineType: LINE_CONTEXT }, line];
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return [line];
|
|
490
|
+
})
|
|
491
|
+
.flat()
|
|
492
|
+
.map((line) => this.diffLineHTML(line))
|
|
493
|
+
.join('');
|
|
494
|
+
return this.diffTableTemplate(diffLinesHTML);
|
|
495
|
+
}
|
|
496
|
+
diffLineMessageTemplate(message) {
|
|
497
|
+
return /* HTML */ `<tr>
|
|
498
|
+
<td class="blob-num"></td>
|
|
499
|
+
<td class="blob-num"></td>
|
|
500
|
+
<td class="blob-code message">
|
|
501
|
+
<span class="blob-code-inner">${message}</span>
|
|
502
|
+
</td>
|
|
503
|
+
</tr>`;
|
|
504
|
+
}
|
|
505
|
+
diffLineSkipTemplate() {
|
|
506
|
+
return /* HTML */ `<tr>
|
|
507
|
+
<td class="blob-num"></td>
|
|
508
|
+
<td class="blob-num"></td>
|
|
509
|
+
<td class="blob-code skip">
|
|
510
|
+
<span class="blob-code-inner">Skip</span>
|
|
511
|
+
</td>
|
|
512
|
+
</tr>`;
|
|
513
|
+
}
|
|
514
|
+
diffLineTemplate(diffLine) {
|
|
515
|
+
const { lineNumber, lineContent, lineType } = diffLine;
|
|
516
|
+
const numClass = lineType === LINE_ADDED ? 'addition' : lineType === LINE_REMOVED ? 'deletion' : '';
|
|
517
|
+
const codeClass = lineType === LINE_ADDED ? 'code-addition' : lineType === LINE_REMOVED ? 'code-deletion' : '';
|
|
518
|
+
const prefix = lineType === LINE_ADDED ? '+' : lineType === LINE_REMOVED ? '-' : ' ';
|
|
519
|
+
return /* HTML */ `<tr>
|
|
520
|
+
<td
|
|
521
|
+
class="blob-num ${numClass}${numClass === 'addition' ? ' empty' : ''}"
|
|
522
|
+
${numClass !== 'addition' ? ` data-line-number="${lineNumber}"` : ''}
|
|
523
|
+
></td>
|
|
524
|
+
<td
|
|
525
|
+
class="blob-num ${numClass}${numClass === 'deletion' ? ' empty' : ''}"
|
|
526
|
+
${numClass !== 'deletion' ? ` data-line-number="${lineNumber}"` : ''}
|
|
527
|
+
></td>
|
|
528
|
+
<td class="blob-code ${codeClass}">
|
|
529
|
+
<span class="blob-code-inner" data-code-prefix="${prefix}">${escapeHTMLSequence(lineContent ?? '')}</span>
|
|
530
|
+
</td>
|
|
531
|
+
</tr>`;
|
|
532
|
+
}
|
|
533
|
+
diffLineHTML(diffLine) {
|
|
534
|
+
if (this.diffLineTemplateHandler) {
|
|
535
|
+
return this.diffLineTemplateHandler(diffLine);
|
|
536
|
+
}
|
|
537
|
+
const { lineNumber } = diffLine;
|
|
538
|
+
if (lineNumber === -1) {
|
|
539
|
+
return this.diffLineSkipTemplate();
|
|
540
|
+
}
|
|
541
|
+
return this.diffLineTemplate(diffLine);
|
|
542
|
+
}
|
|
543
|
+
diffFileTemplate(filename, htmlDiff) {
|
|
544
|
+
if (this.diffFileTemplateHandler) {
|
|
545
|
+
return this.diffFileTemplateHandler(filename, htmlDiff);
|
|
546
|
+
}
|
|
547
|
+
return /* HTML */ `<div class="diff-file">
|
|
548
|
+
<div class="diff-file-title">${filename}</div>
|
|
549
|
+
<div class="diff-file-content">${htmlDiff}</div>
|
|
550
|
+
</div>`;
|
|
551
|
+
}
|
|
552
|
+
async generateAssetFoldersDiff() {
|
|
553
|
+
this.logger.info(plugin.colors.blue(`Comparing asset folders ${await this.oldAssetsPath} and ${await this.newAssetsPath}`));
|
|
554
|
+
const dirDiff = await dirCompare__namespace.compare(await this.oldAssetsPath, await this.newAssetsPath, {
|
|
555
|
+
compareContent: true,
|
|
556
|
+
skipSymlinks: true,
|
|
557
|
+
compareSize: true,
|
|
558
|
+
compareDate: false,
|
|
559
|
+
compareNameHandler: (name1, name2) => {
|
|
560
|
+
if (fileNameWithHashRegEx.test(name1)) {
|
|
561
|
+
name1 = name1.replace(fileNameWithHashRegEx, '$1$3');
|
|
562
|
+
}
|
|
563
|
+
if (fileNameWithHashRegEx.test(name2)) {
|
|
564
|
+
name2 = name2.replace(fileNameWithHashRegEx, '$1$3');
|
|
565
|
+
}
|
|
566
|
+
if (name1.localeCompare(name2) === 0) {
|
|
567
|
+
return 0;
|
|
568
|
+
}
|
|
569
|
+
return name1.localeCompare(name2) > 0 ? 1 : -1;
|
|
570
|
+
},
|
|
571
|
+
});
|
|
572
|
+
return dirDiff.diffSet?.filter((d) => d.state !== 'equal' || d.name1 !== d.name2) || [];
|
|
573
|
+
}
|
|
574
|
+
async generateAssetFilesDiff(oldFileString, newFileString) {
|
|
575
|
+
const dmp = new DiffMatchPatch();
|
|
576
|
+
const linesChars = dmp.diff_linesToChars_(oldFileString, newFileString);
|
|
577
|
+
const linesDiff = dmp.diff_main(linesChars.chars1, linesChars.chars2, false);
|
|
578
|
+
dmp.diff_charsToLines_(linesDiff, linesChars.lineArray);
|
|
579
|
+
let lineNumber = 0;
|
|
580
|
+
return linesDiff
|
|
581
|
+
.map((diffLine) => {
|
|
582
|
+
const [lineType, lineContent] = diffLine;
|
|
583
|
+
const linesCount = lineContent.endsWith('\n')
|
|
584
|
+
? lineContent.split('\n').length - 1
|
|
585
|
+
: lineContent.split('\n').length;
|
|
586
|
+
const lines = lineContent
|
|
587
|
+
.split('\n')
|
|
588
|
+
.map((line, index) => {
|
|
589
|
+
return { lineContent: line, lineNumber: lineNumber + index + 1, lineType };
|
|
590
|
+
})
|
|
591
|
+
.slice(0, linesCount);
|
|
592
|
+
if (lineType !== LINE_REMOVED) {
|
|
593
|
+
lineNumber += linesCount;
|
|
594
|
+
}
|
|
595
|
+
return lines;
|
|
596
|
+
})
|
|
597
|
+
.flat();
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Generate diff for a file
|
|
601
|
+
* @param difference
|
|
602
|
+
* @private
|
|
603
|
+
*/
|
|
604
|
+
async generateFilesDiff(difference) {
|
|
605
|
+
if (difference.state === 'equal') {
|
|
606
|
+
const filepath1 = this.pathToPosix(path__namespace.join('.', difference.relativePath, difference.name1 ?? ''));
|
|
607
|
+
const filepath2 = this.pathToPosix(path__namespace.join('.', difference.relativePath, difference.name2 ?? ''));
|
|
608
|
+
return this.diffFileTemplate(
|
|
609
|
+
/* HTML */ `<span class="renamed"
|
|
610
|
+
>Renamed <span class="from">${filepath1}</span> -> <span class="to">${filepath2}</span></span
|
|
611
|
+
>`, this.diffTableTemplate(this.diffLineMessageTemplate('No changes')));
|
|
612
|
+
}
|
|
613
|
+
const assetFile1Path = difference.path1 && difference.name1 ? path__namespace.join(difference.path1, difference.name1) : null;
|
|
614
|
+
const assetFile2Path = difference.path2 && difference.name2 ? path__namespace.join(difference.path2, difference.name2) : null;
|
|
615
|
+
const filepath = this.pathToPosix(path__namespace.join('.', difference.relativePath, (difference.name1 || difference.name2) ?? ''));
|
|
616
|
+
if (difference.state === 'left' && assetFile1Path) {
|
|
617
|
+
return this.diffFileTemplate(
|
|
618
|
+
/* HTML */ `<span class="removed">Removed ${filepath}</span>`, this.diffTableTemplate(this.diffLineMessageTemplate('File removed')));
|
|
619
|
+
}
|
|
620
|
+
if (difference.state === 'right' && assetFile2Path) {
|
|
621
|
+
return this.diffFileTemplate(
|
|
622
|
+
/* HTML */ `<span class="added">Added ${filepath}</span>`, this.diffTableTemplate(this.diffLineMessageTemplate('File added')));
|
|
623
|
+
}
|
|
624
|
+
if (difference.state === 'distinct' && assetFile1Path && assetFile2Path) {
|
|
625
|
+
const filepath1 = this.pathToPosix(path__namespace.join('.', difference.relativePath, difference.name1 ?? ''));
|
|
626
|
+
const filepath2 = this.pathToPosix(path__namespace.join('.', difference.relativePath, difference.name2 ?? ''));
|
|
627
|
+
const filenameTitle = difference.name1 !== difference.name2
|
|
628
|
+
? /* HTML */ `<span class="renamed"
|
|
629
|
+
>Renamed <span class="from">${filepath1}</span> -> <span class="to">${filepath2}</span></span
|
|
630
|
+
>`
|
|
631
|
+
: filepath;
|
|
632
|
+
return this.diffFileTemplate(filenameTitle, (await isbinaryfile.isBinaryFile(assetFile1Path)) || (await isbinaryfile.isBinaryFile(assetFile2Path))
|
|
633
|
+
? this.diffTableTemplate(this.diffLineMessageTemplate('Binary file'))
|
|
634
|
+
: this.getDiffTableHTML(await this.generateAssetFilesDiff(fs__namespace.readFileSync(assetFile1Path, 'utf-8'), fs__namespace.readFileSync(assetFile2Path, 'utf-8'))));
|
|
635
|
+
}
|
|
636
|
+
return '';
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Generate changelog file based on the differences between two asset folders or zip files
|
|
640
|
+
* and write it to the destination folder
|
|
641
|
+
*/
|
|
642
|
+
async generateChangelog() {
|
|
643
|
+
this.logger.info(plugin.colors.green('Generating changelog'));
|
|
644
|
+
const diffSet = await this.generateAssetFoldersDiff();
|
|
645
|
+
const htmlDiff = (await Promise.all(diffSet.map((difference) => this.generateFilesDiff(difference)))).join('');
|
|
646
|
+
this.logger.info(plugin.colors.green('Writing changelog file'));
|
|
647
|
+
const templateArray = this.changelogTemplate.split('%FILES%');
|
|
648
|
+
templateArray.splice(1, 0, htmlDiff);
|
|
649
|
+
const changelogHTML = templateArray.join('');
|
|
650
|
+
fs__namespace.writeFileSync(path__namespace.join(this.destinationPath, this.changelogFilename), changelogHTML);
|
|
651
|
+
this.logger.info(plugin.colors.green(`Changelog file written to ${path__namespace.join(this.destinationPath, this.changelogFilename)}`));
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
class IconFontGenerator {
|
|
656
|
+
sourceDir;
|
|
657
|
+
outputDir;
|
|
658
|
+
fontName;
|
|
659
|
+
constructor(options) {
|
|
660
|
+
this.sourceDir = options.sourceDir;
|
|
661
|
+
this.outputDir = options.outputDir;
|
|
662
|
+
this.fontName = options.fontName;
|
|
663
|
+
}
|
|
664
|
+
async generate() {
|
|
665
|
+
await svgToFont({
|
|
666
|
+
src: this.sourceDir,
|
|
667
|
+
dist: this.outputDir,
|
|
668
|
+
fontName: this.fontName,
|
|
669
|
+
css: true,
|
|
670
|
+
typescript: true,
|
|
671
|
+
startUnicode: 0xea01,
|
|
672
|
+
svgicons2svgfont: {
|
|
673
|
+
fontHeight: 1024,
|
|
674
|
+
},
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
179
679
|
const cli = cac.cac('pp-dev');
|
|
180
|
-
const colors = picocolors.createColors();
|
|
181
680
|
let profileSession = global.__pp_dev_profile_session;
|
|
182
681
|
let profileCount = 0;
|
|
183
682
|
const stopProfiler = (log) => {
|
|
@@ -190,7 +689,7 @@ const stopProfiler = (log) => {
|
|
|
190
689
|
if (!err) {
|
|
191
690
|
const outPath = path__namespace.resolve(`./pp-dev-profile-${profileCount++}.cpuprofile`);
|
|
192
691
|
fs__namespace.writeFileSync(outPath, JSON.stringify(profile));
|
|
193
|
-
log(colors.yellow(`CPU profile written to ${colors.white(colors.dim(outPath))}`));
|
|
692
|
+
log(plugin.colors.yellow(`CPU profile written to ${plugin.colors.white(plugin.colors.dim(outPath))}`));
|
|
194
693
|
profileSession = undefined;
|
|
195
694
|
res();
|
|
196
695
|
}
|
|
@@ -268,19 +767,21 @@ cli
|
|
|
268
767
|
clearScreen: options.clearScreen,
|
|
269
768
|
optimizeDeps: { force: options.force },
|
|
270
769
|
server: cleanOptions(options),
|
|
770
|
+
customLogger: plugin.createLogger(options.logLevel),
|
|
271
771
|
}, true));
|
|
772
|
+
if (!server.config.base || server.config.base === '/') {
|
|
773
|
+
throw new Error('base cannot be equal to "/" or empty string');
|
|
774
|
+
}
|
|
272
775
|
if (!server.httpServer) {
|
|
273
776
|
throw new Error('HTTP server not available');
|
|
274
777
|
}
|
|
275
778
|
await server.listen();
|
|
276
|
-
const
|
|
779
|
+
const logger = plugin.createLogger(options.logLevel);
|
|
277
780
|
const ppDevStartTime = global.__pp_dev_start_time ?? false;
|
|
278
781
|
const startupDurationString = ppDevStartTime
|
|
279
|
-
? colors.dim(`ready in ${colors.reset(colors.bold(Math.ceil(node_perf_hooks.performance.now() - ppDevStartTime)))} ms`)
|
|
782
|
+
? plugin.colors.dim(`ready in ${plugin.colors.reset(plugin.colors.bold(Math.ceil(node_perf_hooks.performance.now() - ppDevStartTime)))} ms`)
|
|
280
783
|
: '';
|
|
281
|
-
info(`\n ${colors.green(`${colors.bold('PP-DEV')} v${index.VERSION}`)} ${startupDurationString}\n
|
|
282
|
-
clear: !server.config.logger.hasWarned,
|
|
283
|
-
});
|
|
784
|
+
logger.info(`\n ${plugin.colors.green(`${plugin.colors.bold('PP-DEV')} v${index.VERSION}`)} ${startupDurationString}\n`);
|
|
284
785
|
server.printUrls();
|
|
285
786
|
bindShortcuts(server, {
|
|
286
787
|
print: true,
|
|
@@ -290,7 +791,7 @@ cli
|
|
|
290
791
|
description: 'start/stop the profiler',
|
|
291
792
|
async action(server) {
|
|
292
793
|
if (profileSession) {
|
|
293
|
-
await stopProfiler(
|
|
794
|
+
await stopProfiler(logger.info);
|
|
294
795
|
}
|
|
295
796
|
else {
|
|
296
797
|
const inspector = await import('node:inspector').then((r) => r.default);
|
|
@@ -299,7 +800,7 @@ cli
|
|
|
299
800
|
profileSession.connect();
|
|
300
801
|
profileSession.post('Profiler.enable', () => {
|
|
301
802
|
profileSession?.post('Profiler.start', () => {
|
|
302
|
-
|
|
803
|
+
logger.info('Profiler started');
|
|
303
804
|
res();
|
|
304
805
|
});
|
|
305
806
|
});
|
|
@@ -322,8 +823,8 @@ cli
|
|
|
322
823
|
});
|
|
323
824
|
}
|
|
324
825
|
catch (e) {
|
|
325
|
-
const logger =
|
|
326
|
-
logger.error(colors.red(`error when starting dev server:\n${e.stack}`), {
|
|
826
|
+
const logger = plugin.createLogger(options.logLevel);
|
|
827
|
+
logger.error(plugin.colors.red(`error when starting dev server:\n${e.stack}`), {
|
|
327
828
|
error: e,
|
|
328
829
|
});
|
|
329
830
|
stopProfiler(logger.info);
|
|
@@ -345,16 +846,20 @@ cli
|
|
|
345
846
|
.action(async (root, options) => {
|
|
346
847
|
filterDuplicateOptions(options);
|
|
347
848
|
const { default: next } = await import('next');
|
|
849
|
+
const logger = plugin.createLogger();
|
|
348
850
|
const server = createDevServer(options.logLevel);
|
|
349
851
|
const opts = cleanOptions(options);
|
|
350
852
|
const app = next({ dev: true, hostname: opts.host, port: opts.port });
|
|
351
|
-
const handle = app.getRequestHandler();
|
|
352
853
|
await app.prepare();
|
|
353
854
|
const nextServer = (await app.getServer());
|
|
354
855
|
let base = nextServer.nextConfig.basePath;
|
|
856
|
+
const { assetPrefix } = nextServer.nextConfig;
|
|
355
857
|
if (!base.endsWith('/')) {
|
|
356
858
|
base += '/';
|
|
357
859
|
}
|
|
860
|
+
if (base === '/') {
|
|
861
|
+
throw new Error('basePath cannot be equal to "/" or empty string');
|
|
862
|
+
}
|
|
358
863
|
const baseWithoutTrailingSlash = base.substring(0, base.lastIndexOf('/'));
|
|
359
864
|
const templateName = nextServer.nextConfig.serverRuntimeConfig.templateName;
|
|
360
865
|
const ppDevConfig = nextServer.nextConfig.serverRuntimeConfig.ppDevConfig;
|
|
@@ -379,10 +884,14 @@ cli
|
|
|
379
884
|
}
|
|
380
885
|
server.use(plugin.initProxyCache({ devServer: server, ttl }));
|
|
381
886
|
}
|
|
887
|
+
const proxyIgnore = ['/@vite', '/@metricinsights', '/@', baseWithoutTrailingSlash];
|
|
888
|
+
if (assetPrefix) {
|
|
889
|
+
proxyIgnore.push(assetPrefix);
|
|
890
|
+
}
|
|
382
891
|
server.use(plugin.initProxy({
|
|
383
892
|
devServer: server,
|
|
384
893
|
baseURL: backendBaseURL,
|
|
385
|
-
proxyIgnore
|
|
894
|
+
proxyIgnore,
|
|
386
895
|
disableSSLValidation,
|
|
387
896
|
}));
|
|
388
897
|
const isIndexRegExp = new RegExp(`^((${base})|/)$`);
|
|
@@ -394,7 +903,12 @@ cli
|
|
|
394
903
|
return Buffer.from(plugin.urlReplacer(baseUrlHost, req.headers.host ?? '', mi.buildPage(response, miHudLess)));
|
|
395
904
|
}));
|
|
396
905
|
}
|
|
906
|
+
const handle = app.getRequestHandler();
|
|
397
907
|
server.all('*', (req, res) => {
|
|
908
|
+
if (req.url.startsWith(assetPrefix) && assetPrefix !== baseWithoutTrailingSlash) {
|
|
909
|
+
const parsedUrl = url.parse(req.url.replace(assetPrefix, baseWithoutTrailingSlash), true);
|
|
910
|
+
return handle(req, res, parsedUrl);
|
|
911
|
+
}
|
|
398
912
|
const parsedUrl = url.parse(req.url, true);
|
|
399
913
|
handle(req, res, parsedUrl);
|
|
400
914
|
});
|
|
@@ -411,12 +925,11 @@ cli
|
|
|
411
925
|
}));
|
|
412
926
|
}
|
|
413
927
|
});
|
|
414
|
-
const info = server.config.logger.info;
|
|
415
928
|
const ppDevStartTime = global.__pp_dev_start_time ?? false;
|
|
416
929
|
const startupDurationString = ppDevStartTime
|
|
417
|
-
? colors.dim(`ready in ${colors.reset(colors.bold(Math.ceil(node_perf_hooks.performance.now() - ppDevStartTime)))} ms`)
|
|
930
|
+
? plugin.colors.dim(`ready in ${plugin.colors.reset(plugin.colors.bold(Math.ceil(node_perf_hooks.performance.now() - ppDevStartTime)))} ms`)
|
|
418
931
|
: '';
|
|
419
|
-
info(`\n ${colors.green(`${colors.bold('PP-DEV')} v${index.VERSION}`)} ${startupDurationString}\n`, {
|
|
932
|
+
logger.info(`\n ${plugin.colors.green(`${plugin.colors.bold('PP-DEV')} v${index.VERSION}`)} ${startupDurationString}\n`, {
|
|
420
933
|
clear: true,
|
|
421
934
|
});
|
|
422
935
|
server.printUrls(base);
|
|
@@ -459,8 +972,8 @@ cli
|
|
|
459
972
|
// });
|
|
460
973
|
}
|
|
461
974
|
catch (e) {
|
|
462
|
-
const logger =
|
|
463
|
-
logger.error(colors.red(`error when starting dev server:\n${e.stack}`), {
|
|
975
|
+
const logger = plugin.createLogger(options.logLevel);
|
|
976
|
+
logger.error(plugin.colors.red(`error when starting dev server:\n${e.stack}`), {
|
|
464
977
|
error: e,
|
|
465
978
|
});
|
|
466
979
|
stopProfiler(logger.info);
|
|
@@ -482,6 +995,7 @@ cli
|
|
|
482
995
|
.option('--force', `[boolean] force the optimizer to ignore the cache and re-bundle (experimental)`)
|
|
483
996
|
.option('--emptyOutDir', `[boolean] force empty outDir when it's outside of root`)
|
|
484
997
|
.option('-w, --watch', `[boolean] rebuilds when modules have changed on disk`)
|
|
998
|
+
.option('--changelog [assetsFile]', `[boolean | string] generate changelog between assetsFile and current build (default: false)`)
|
|
485
999
|
.action(async (root, options) => {
|
|
486
1000
|
filterDuplicateOptions(options);
|
|
487
1001
|
const buildOptions = cleanOptions(options);
|
|
@@ -492,7 +1006,7 @@ cli
|
|
|
492
1006
|
const { plugins, ...fileConfig } = configFromFile.config;
|
|
493
1007
|
config = vite.mergeConfig(config, fileConfig);
|
|
494
1008
|
}
|
|
495
|
-
|
|
1009
|
+
const buildConfig = vite.mergeConfig(config, {
|
|
496
1010
|
root,
|
|
497
1011
|
base: options.base,
|
|
498
1012
|
mode: options.mode,
|
|
@@ -501,15 +1015,110 @@ cli
|
|
|
501
1015
|
clearScreen: options.clearScreen,
|
|
502
1016
|
optimizeDeps: { force: options.force },
|
|
503
1017
|
build: buildOptions,
|
|
504
|
-
}, true)
|
|
1018
|
+
}, true);
|
|
1019
|
+
await vite.build(buildConfig);
|
|
1020
|
+
if (buildOptions.changelog) {
|
|
1021
|
+
const executionRoot = root || process.cwd();
|
|
1022
|
+
const outDir = buildConfig.build?.outDir || 'dist';
|
|
1023
|
+
let oldAssetsPath = '';
|
|
1024
|
+
if (typeof buildOptions.changelog === 'string') {
|
|
1025
|
+
oldAssetsPath = path__namespace.resolve(executionRoot, buildOptions.changelog);
|
|
1026
|
+
}
|
|
1027
|
+
else {
|
|
1028
|
+
const backupsDirPath = path__namespace.resolve(executionRoot, buildConfig.ppDevConfig?.syncBackupsDir || 'backups');
|
|
1029
|
+
if (!fs__namespace.existsSync(backupsDirPath)) {
|
|
1030
|
+
plugin.createLogger(options.logLevel).warn(plugin.colors.yellow(`backups directory not found, skipping changelog generation`));
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
const backups = fs__namespace.readdirSync(backupsDirPath, { withFileTypes: true });
|
|
1034
|
+
if (!backups.length) {
|
|
1035
|
+
plugin.createLogger(options.logLevel).warn(plugin.colors.yellow(`no backups found, skipping changelog generation`));
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
const latestBackup = backups
|
|
1039
|
+
.filter((value) => {
|
|
1040
|
+
return value.isFile() && value.name.endsWith('.zip');
|
|
1041
|
+
})
|
|
1042
|
+
.reduce((latest, current) => {
|
|
1043
|
+
const latestTime = fs__namespace.statSync(path__namespace.resolve(backupsDirPath, latest.name)).mtimeMs;
|
|
1044
|
+
const currentTime = fs__namespace.statSync(path__namespace.resolve(backupsDirPath, current.name)).mtimeMs;
|
|
1045
|
+
return latestTime > currentTime ? latest : current;
|
|
1046
|
+
}, backups[0]).name;
|
|
1047
|
+
oldAssetsPath = path__namespace.resolve(backupsDirPath, latestBackup);
|
|
1048
|
+
}
|
|
1049
|
+
const currentAssetFilePath = path__namespace.resolve(executionRoot, outDir);
|
|
1050
|
+
let changelogDestination = 'dist-zip';
|
|
1051
|
+
if (buildConfig.ppDevConfig) {
|
|
1052
|
+
if (buildConfig.ppDevConfig.distZip === false) {
|
|
1053
|
+
changelogDestination = buildConfig.build?.outDir || 'dist';
|
|
1054
|
+
}
|
|
1055
|
+
else if (typeof buildConfig.ppDevConfig.distZip === 'object' &&
|
|
1056
|
+
typeof buildConfig.ppDevConfig.distZip.outDir === 'string') {
|
|
1057
|
+
changelogDestination = buildConfig.ppDevConfig.distZip.outDir;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
const changelogGenerator = new ChangelogGenerator({
|
|
1061
|
+
oldAssetsPath,
|
|
1062
|
+
newAssetsPath: currentAssetFilePath,
|
|
1063
|
+
destinationPath: path__namespace.resolve(executionRoot, changelogDestination),
|
|
1064
|
+
});
|
|
1065
|
+
await changelogGenerator.generateChangelog();
|
|
1066
|
+
}
|
|
505
1067
|
}
|
|
506
1068
|
catch (e) {
|
|
507
|
-
|
|
1069
|
+
plugin.createLogger(options.logLevel).error(plugin.colors.red(`error during build:\n${e.stack}`), { error: e });
|
|
508
1070
|
process.exit(1);
|
|
509
1071
|
}
|
|
510
1072
|
finally {
|
|
511
|
-
stopProfiler((message) =>
|
|
1073
|
+
stopProfiler((message) => plugin.createLogger(options.logLevel).info(message));
|
|
1074
|
+
}
|
|
1075
|
+
});
|
|
1076
|
+
// changelog
|
|
1077
|
+
cli
|
|
1078
|
+
.command('changelog [oldAssetPath] [newAssetPath]', 'generate changelog between two assets files/folders')
|
|
1079
|
+
.option('--oldAssetsPath <oldAssetsPath>', `[string] path to the old assets zip file or folder`)
|
|
1080
|
+
.option('--newAssetsPath <newAssetsPath>', `[string] path to the new assets zip file or folder`)
|
|
1081
|
+
.option('--destination <destination>', `[string] destination folder for the changelog (default: .)`)
|
|
1082
|
+
.option('--filename <filename>', `[string] filename for the changelog (default: CHANGELOG.html)`)
|
|
1083
|
+
.action(async (oldAssetPath, newAssetPath, options) => {
|
|
1084
|
+
filterDuplicateOptions(options);
|
|
1085
|
+
const { oldAssetsPath: oldPath = oldAssetPath, newAssetsPath: newPath = newAssetPath, destination = '.', filename = 'CHANGELOG.html', logLevel, } = options;
|
|
1086
|
+
const root = process.cwd();
|
|
1087
|
+
if (!oldPath || !newPath) {
|
|
1088
|
+
plugin.createLogger(logLevel).error(plugin.colors.red(`error during changelog generation: oldAssetPath and newAssetPath are required`));
|
|
1089
|
+
process.exit(1);
|
|
512
1090
|
}
|
|
1091
|
+
const fullOldPath = path__namespace.resolve(root, oldPath);
|
|
1092
|
+
const fullNewPath = path__namespace.resolve(root, newPath);
|
|
1093
|
+
const fullDestination = path__namespace.resolve(root, destination);
|
|
1094
|
+
const changelogGenerator = new ChangelogGenerator({
|
|
1095
|
+
oldAssetsPath: fullOldPath,
|
|
1096
|
+
newAssetsPath: fullNewPath,
|
|
1097
|
+
destinationPath: fullDestination,
|
|
1098
|
+
changelogFilename: filename,
|
|
1099
|
+
});
|
|
1100
|
+
await changelogGenerator.generateChangelog();
|
|
1101
|
+
});
|
|
1102
|
+
cli
|
|
1103
|
+
.command('generate-icon-font [source] [destination]', 'generate icon font from SVG files')
|
|
1104
|
+
.option('--source <source>', `[string] path to the source directory with SVG files`)
|
|
1105
|
+
.option('--destination <destination>', `[string] path to the destination directory to save the generated font files`)
|
|
1106
|
+
.option('--font-name, -n <fontName>', `[string] name of the font to generate (default: 'icon-font')`)
|
|
1107
|
+
.action(async (source, destination, options) => {
|
|
1108
|
+
filterDuplicateOptions(options);
|
|
1109
|
+
const { source: sourceDir = source, destination: destDir = destination, fontName = 'icon-font' } = options;
|
|
1110
|
+
const root = process.cwd();
|
|
1111
|
+
const fullSourceDir = path__namespace.resolve(root, sourceDir);
|
|
1112
|
+
const fullDestDir = path__namespace.resolve(root, destDir);
|
|
1113
|
+
const iconFontGenerator = new IconFontGenerator({
|
|
1114
|
+
sourceDir: fullSourceDir,
|
|
1115
|
+
outputDir: fullDestDir,
|
|
1116
|
+
fontName,
|
|
1117
|
+
});
|
|
1118
|
+
const logger = plugin.createLogger(options.logLevel);
|
|
1119
|
+
logger.info(`Generating icon font from SVG files in ${plugin.colors.dim(fullSourceDir)}`);
|
|
1120
|
+
await iconFontGenerator.generate();
|
|
1121
|
+
logger.info(`Icon font generated and saved to ${plugin.colors.dim(fullDestDir)}`);
|
|
513
1122
|
});
|
|
514
1123
|
// optimize
|
|
515
1124
|
cli
|
|
@@ -534,7 +1143,7 @@ cli
|
|
|
534
1143
|
await vite.optimizeDeps(optimizeConfig, options.force, true);
|
|
535
1144
|
}
|
|
536
1145
|
catch (e) {
|
|
537
|
-
|
|
1146
|
+
plugin.createLogger(options.logLevel).error(plugin.colors.red(`error when optimizing deps:\n${e.stack}`), { error: e });
|
|
538
1147
|
process.exit(1);
|
|
539
1148
|
}
|
|
540
1149
|
});
|
|
@@ -575,13 +1184,13 @@ cli
|
|
|
575
1184
|
server.printUrls();
|
|
576
1185
|
}
|
|
577
1186
|
catch (e) {
|
|
578
|
-
|
|
1187
|
+
plugin.createLogger(options.logLevel).error(plugin.colors.red(`error when starting preview server:\n${e.stack}`), {
|
|
579
1188
|
error: e,
|
|
580
1189
|
});
|
|
581
1190
|
process.exit(1);
|
|
582
1191
|
}
|
|
583
1192
|
finally {
|
|
584
|
-
stopProfiler((message) =>
|
|
1193
|
+
stopProfiler((message) => plugin.createLogger(options.logLevel).info(message));
|
|
585
1194
|
}
|
|
586
1195
|
});
|
|
587
1196
|
cli.help();
|