@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/esm/cli.js
CHANGED
|
@@ -2,28 +2,32 @@ import * as path from 'path';
|
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import { performance } from 'node:perf_hooks';
|
|
4
4
|
import { cac } from 'cac';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { loadConfigFromFile, mergeConfig,
|
|
5
|
+
import { g as getViteConfig, V as VERSION } from './index-bc9325e9.js';
|
|
6
|
+
import { c as createLogger, a as colors, i as initPPRedirect, M as MiAPI, b as initProxyCache, d as initProxy, e as initLoadPPData, f as initRewriteResponse, u as urlReplacer, g as cutUrlParams } from './plugin-63f01789.js';
|
|
7
|
+
import { loadConfigFromFile, mergeConfig, build, resolveConfig, optimizeDeps, preview } from 'vite';
|
|
8
8
|
import { URL as URL$1, parse } from 'url';
|
|
9
|
-
import { i as initPPRedirect, M as MiAPI, a as initProxyCache, b as initProxy, c as initLoadPPData, d as initRewriteResponse, u as urlReplacer, e as cutUrlParams } from './plugin-7db34718.js';
|
|
10
9
|
import * as express from 'express';
|
|
11
10
|
import * as winston from 'winston';
|
|
12
|
-
import '
|
|
13
|
-
import '
|
|
11
|
+
import * as dirCompare from 'dir-compare';
|
|
12
|
+
import DiffMatchPatch from 'diff-match-patch';
|
|
13
|
+
import { isBinaryFile } from 'isbinaryfile';
|
|
14
|
+
import * as os from 'os';
|
|
15
|
+
import * as crypto from 'crypto';
|
|
16
|
+
import extractZip from 'extract-zip';
|
|
17
|
+
import svgToFont from 'svgtofont';
|
|
14
18
|
import 'ejs';
|
|
19
|
+
import 'esbuild';
|
|
15
20
|
import 'http-proxy-middleware';
|
|
21
|
+
import 'picocolors';
|
|
16
22
|
import 'axios';
|
|
17
23
|
import 'jsdom';
|
|
18
24
|
import 'https';
|
|
19
25
|
import 'memory-cache';
|
|
20
|
-
import 'crypto';
|
|
21
26
|
import 'process';
|
|
22
27
|
import 'child_process';
|
|
23
28
|
import 'console';
|
|
24
29
|
import 'zlib';
|
|
25
30
|
|
|
26
|
-
const colors$2 = createColors();
|
|
27
31
|
function isDefined(value) {
|
|
28
32
|
return value != null;
|
|
29
33
|
}
|
|
@@ -32,8 +36,9 @@ function bindShortcuts(server, opts) {
|
|
|
32
36
|
return;
|
|
33
37
|
}
|
|
34
38
|
server._shortcutsOptions = opts;
|
|
39
|
+
const logger = createLogger();
|
|
35
40
|
if (opts.print) {
|
|
36
|
-
|
|
41
|
+
logger.info(colors.dim(colors.green(' ➜')) + colors.dim(' press ') + colors.bold('h') + colors.dim(' to show help'));
|
|
37
42
|
}
|
|
38
43
|
const shortcuts = (opts.customShortcuts ?? []).filter(isDefined).concat(BASE_SHORTCUTS);
|
|
39
44
|
let actionRunning = false;
|
|
@@ -47,10 +52,10 @@ function bindShortcuts(server, opts) {
|
|
|
47
52
|
return;
|
|
48
53
|
}
|
|
49
54
|
if (input === 'h') {
|
|
50
|
-
|
|
55
|
+
logger.info([
|
|
51
56
|
'',
|
|
52
|
-
colors
|
|
53
|
-
...shortcuts.map((shortcut) => colors
|
|
57
|
+
colors.bold(' Shortcuts'),
|
|
58
|
+
...shortcuts.map((shortcut) => colors.dim(' press ') + colors.bold(shortcut.key) + colors.dim(` to ${shortcut.description}`)),
|
|
54
59
|
].join('\n'));
|
|
55
60
|
}
|
|
56
61
|
const shortcut = shortcuts.find((shortcut) => shortcut.key === input);
|
|
@@ -116,7 +121,6 @@ const BASE_SHORTCUTS = [
|
|
|
116
121
|
},
|
|
117
122
|
];
|
|
118
123
|
|
|
119
|
-
const colors$1 = createColors();
|
|
120
124
|
function createDevServer(logLevel = 'info') {
|
|
121
125
|
const server = express.default();
|
|
122
126
|
const logger = winston.createLogger({
|
|
@@ -136,24 +140,516 @@ function createDevServer(logLevel = 'info') {
|
|
|
136
140
|
if (!listener) {
|
|
137
141
|
throw new Error('Server is not listening');
|
|
138
142
|
}
|
|
139
|
-
const colorUrl = (url) => colors
|
|
143
|
+
const colorUrl = (url) => colors.cyan(url.replace(/:(\d+)\//, (_, port) => `:${colors.bold(port)}/`));
|
|
140
144
|
const address = listener.address();
|
|
141
145
|
if (address && typeof address === 'object') {
|
|
142
146
|
if (address.address === '::') {
|
|
143
147
|
const url = new URL$1(base || '', `http://localhost:${address.port}`);
|
|
144
|
-
logger.info(` ${colors
|
|
148
|
+
logger.info(` ${colors.green('➜')} ${colors.bold('Local')}: ${colorUrl(url.toString())}`);
|
|
145
149
|
}
|
|
146
150
|
else {
|
|
147
151
|
const url = new URL$1(base || '', `http://[${address.address}]:${address.port}`);
|
|
148
|
-
logger.info(` ${colors
|
|
152
|
+
logger.info(` ${colors.green('➜')} ${colors.bold('Local')}: ${colorUrl(url.toString())}`);
|
|
149
153
|
}
|
|
150
154
|
}
|
|
151
155
|
};
|
|
152
156
|
return server;
|
|
153
157
|
}
|
|
154
158
|
|
|
159
|
+
const changelogTemplate = /* HTML */ `<!DOCTYPE html>
|
|
160
|
+
<html lang="en">
|
|
161
|
+
<head>
|
|
162
|
+
<meta charset="UTF-8" />
|
|
163
|
+
<title>Changelog Diff</title>
|
|
164
|
+
<style>
|
|
165
|
+
tr,
|
|
166
|
+
td {
|
|
167
|
+
padding: 0;
|
|
168
|
+
}
|
|
169
|
+
.diff-file {
|
|
170
|
+
margin-top: 20px;
|
|
171
|
+
border: 1px solid #e1e4e8;
|
|
172
|
+
border-radius: 6px;
|
|
173
|
+
}
|
|
174
|
+
.diff-file-title {
|
|
175
|
+
padding: 10px 20px;
|
|
176
|
+
background-color: #f6f8fa;
|
|
177
|
+
border-bottom: 1px solid #e1e4e8;
|
|
178
|
+
border-radius: 6px 6px 0 0;
|
|
179
|
+
font-weight: bold;
|
|
180
|
+
}
|
|
181
|
+
.diff-file-title .renamed {
|
|
182
|
+
font-weight: normal;
|
|
183
|
+
}
|
|
184
|
+
.diff-file-title .renamed .from {
|
|
185
|
+
color: #cb2431;
|
|
186
|
+
}
|
|
187
|
+
.diff-file-title .renamed .to {
|
|
188
|
+
color: #22863a;
|
|
189
|
+
}
|
|
190
|
+
.diff-file-title .added {
|
|
191
|
+
color: #22863a;
|
|
192
|
+
}
|
|
193
|
+
.diff-file-title .deleted {
|
|
194
|
+
color: #cb2431;
|
|
195
|
+
}
|
|
196
|
+
.diff-file-content {
|
|
197
|
+
}
|
|
198
|
+
.diff-table {
|
|
199
|
+
tab-size: 8;
|
|
200
|
+
width: 100%;
|
|
201
|
+
border-collapse: separate;
|
|
202
|
+
border-spacing: 0;
|
|
203
|
+
}
|
|
204
|
+
.blob-num {
|
|
205
|
+
position: relative;
|
|
206
|
+
color: #1f2328;
|
|
207
|
+
width: 1%;
|
|
208
|
+
min-width: 50px;
|
|
209
|
+
padding: 0 10px;
|
|
210
|
+
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
|
|
211
|
+
font-size: 12px;
|
|
212
|
+
line-height: 20px;
|
|
213
|
+
text-align: right;
|
|
214
|
+
white-space: nowrap;
|
|
215
|
+
vertical-align: top;
|
|
216
|
+
cursor: pointer;
|
|
217
|
+
-webkit-user-select: none;
|
|
218
|
+
user-select: none;
|
|
219
|
+
}
|
|
220
|
+
.blob-num.addition {
|
|
221
|
+
background-color: #ccffd8;
|
|
222
|
+
border-color: #1f883e;
|
|
223
|
+
}
|
|
224
|
+
.blob-num.deletion {
|
|
225
|
+
background-color: #ffd7d5;
|
|
226
|
+
border-color: #cf222e;
|
|
227
|
+
}
|
|
228
|
+
.blob-num::before {
|
|
229
|
+
content: attr(data-line-number);
|
|
230
|
+
}
|
|
231
|
+
.blob-code {
|
|
232
|
+
position: relative;
|
|
233
|
+
padding: 0 10px 0 22px;
|
|
234
|
+
vertical-align: top;
|
|
235
|
+
color: #1f2329;
|
|
236
|
+
}
|
|
237
|
+
.blob-code.code-addition {
|
|
238
|
+
background-color: #e6ffec;
|
|
239
|
+
}
|
|
240
|
+
.blob-code.code-deletion {
|
|
241
|
+
background-color: #ffebe9;
|
|
242
|
+
}
|
|
243
|
+
.blob-code.skip,
|
|
244
|
+
.blob-code.message {
|
|
245
|
+
text-align: center;
|
|
246
|
+
}
|
|
247
|
+
.blob-code.skip .blob-code-inner,
|
|
248
|
+
.blob-code.message .blob-code-inner {
|
|
249
|
+
font-weight: bold;
|
|
250
|
+
color: #6a737d;
|
|
251
|
+
padding: 10px 0;
|
|
252
|
+
}
|
|
253
|
+
.blob-code-inner {
|
|
254
|
+
display: table-cell;
|
|
255
|
+
overflow: visible;
|
|
256
|
+
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
|
|
257
|
+
font-size: 12px;
|
|
258
|
+
word-wrap: anywhere;
|
|
259
|
+
white-space: pre-wrap;
|
|
260
|
+
}
|
|
261
|
+
.blob-code-inner::before {
|
|
262
|
+
content: attr(data-code-prefix);
|
|
263
|
+
position: absolute;
|
|
264
|
+
top: 1px;
|
|
265
|
+
left: 8px;
|
|
266
|
+
padding-right: 8px;
|
|
267
|
+
}
|
|
268
|
+
</style>
|
|
269
|
+
</head>
|
|
270
|
+
<body>
|
|
271
|
+
<h1>Changelog Diff</h1>
|
|
272
|
+
|
|
273
|
+
%FILES%
|
|
274
|
+
</body>
|
|
275
|
+
</html>`;
|
|
276
|
+
const LINE_ADDED = 1;
|
|
277
|
+
const LINE_REMOVED = -1;
|
|
278
|
+
const LINE_CONTEXT = 0;
|
|
279
|
+
/**
|
|
280
|
+
* Escape HTML sequence
|
|
281
|
+
* @param str
|
|
282
|
+
*/
|
|
283
|
+
function escapeHTMLSequence(str) {
|
|
284
|
+
return str.replace(/[\u00A0-\u9999<>&]/g, (i) => '&#' + i.charCodeAt(0) + ';');
|
|
285
|
+
}
|
|
286
|
+
const fileNameWithHashRegEx = /(.+)(-[a-f0-9]{6,20})(\.[a-z0-9]+)$/i;
|
|
287
|
+
/**
|
|
288
|
+
* Changelog generator class
|
|
289
|
+
* @class
|
|
290
|
+
* @classdesc
|
|
291
|
+
* Generates a changelog file based on the differences between two asset folders or zip files
|
|
292
|
+
* @example
|
|
293
|
+
* const changelogGenerator = new ChangelogGenerator({
|
|
294
|
+
* previousAssetsPath: './dist-zip/previous',
|
|
295
|
+
* currentAssetsPath: './dist-zip/current',
|
|
296
|
+
* destinationPath: './dist-zip',
|
|
297
|
+
* changelogFilename: 'CHANGELOG.html',
|
|
298
|
+
* });
|
|
299
|
+
* changelogGenerator.generateChangelog();
|
|
300
|
+
*/
|
|
301
|
+
class ChangelogGenerator {
|
|
302
|
+
oldAssetsPath;
|
|
303
|
+
newAssetsPath;
|
|
304
|
+
destinationPath;
|
|
305
|
+
changelogFilename;
|
|
306
|
+
changelogTemplate = changelogTemplate;
|
|
307
|
+
diffFileTemplateHandler;
|
|
308
|
+
diffLineTemplateHandler;
|
|
309
|
+
contextLines = 3;
|
|
310
|
+
logger;
|
|
311
|
+
/**
|
|
312
|
+
* Changelog generator class constructor
|
|
313
|
+
* @param opts
|
|
314
|
+
*/
|
|
315
|
+
constructor(opts) {
|
|
316
|
+
const { oldAssetsPath, newAssetsPath, destinationPath, changelogTemplate, diffFileTemplateHandler, diffLineTemplateHandler, changelogFilename, contextLines, } = opts;
|
|
317
|
+
this.logger = createLogger();
|
|
318
|
+
if (!oldAssetsPath || !newAssetsPath || !destinationPath) {
|
|
319
|
+
throw new Error('Previous assets path, current assets path and destination path are required');
|
|
320
|
+
}
|
|
321
|
+
if (oldAssetsPath === newAssetsPath) {
|
|
322
|
+
throw new Error('Previous and current assets paths must be different');
|
|
323
|
+
}
|
|
324
|
+
if (!this.isExists(oldAssetsPath)) {
|
|
325
|
+
throw new Error(`Previous assets path ${oldAssetsPath} does not exist`);
|
|
326
|
+
}
|
|
327
|
+
if (!this.isExists(newAssetsPath)) {
|
|
328
|
+
throw new Error(`Current assets path ${newAssetsPath} does not exist`);
|
|
329
|
+
}
|
|
330
|
+
if (this.isZipFile(oldAssetsPath)) {
|
|
331
|
+
const unzipDestinationPath = path.resolve(os.tmpdir(), crypto.createHash('md5').update(oldAssetsPath).digest('hex'));
|
|
332
|
+
this.oldAssetsPath = this.unzipFile(oldAssetsPath, unzipDestinationPath)
|
|
333
|
+
.then(() => {
|
|
334
|
+
return this.normalizeAssetFolderPath(unzipDestinationPath);
|
|
335
|
+
})
|
|
336
|
+
.then((path) => {
|
|
337
|
+
if (this.isEmptyFolder(path)) {
|
|
338
|
+
throw new Error(`Previous assets path ${path} is empty`);
|
|
339
|
+
}
|
|
340
|
+
return path;
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
else if (this.isFolder(oldAssetsPath)) {
|
|
344
|
+
const path = this.normalizeAssetFolderPath(oldAssetsPath);
|
|
345
|
+
if (this.isEmptyFolder(path)) {
|
|
346
|
+
throw new Error(`Previous assets path ${path} is empty`);
|
|
347
|
+
}
|
|
348
|
+
this.oldAssetsPath = Promise.resolve(path);
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
throw new Error(`Invalid previous assets path ${oldAssetsPath}. It must be a folder or a zip file`);
|
|
352
|
+
}
|
|
353
|
+
if (this.isZipFile(newAssetsPath)) {
|
|
354
|
+
const unzipDestinationPath = path.resolve(os.tmpdir(), crypto.createHash('md5').update(newAssetsPath).digest('hex'));
|
|
355
|
+
this.newAssetsPath = this.unzipFile(newAssetsPath, unzipDestinationPath)
|
|
356
|
+
.then(() => {
|
|
357
|
+
return this.normalizeAssetFolderPath(unzipDestinationPath);
|
|
358
|
+
})
|
|
359
|
+
.then((path) => {
|
|
360
|
+
if (this.isEmptyFolder(path)) {
|
|
361
|
+
throw new Error(`Current assets path ${path} is empty`);
|
|
362
|
+
}
|
|
363
|
+
return path;
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
else if (this.isFolder(newAssetsPath)) {
|
|
367
|
+
const path = this.normalizeAssetFolderPath(newAssetsPath);
|
|
368
|
+
if (this.isEmptyFolder(path)) {
|
|
369
|
+
throw new Error(`Current assets path ${newAssetsPath} is empty`);
|
|
370
|
+
}
|
|
371
|
+
this.newAssetsPath = Promise.resolve(path);
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
throw new Error(`Invalid current assets path ${newAssetsPath}. It must be a folder or a zip file`);
|
|
375
|
+
}
|
|
376
|
+
this.destinationPath = destinationPath;
|
|
377
|
+
this.mkdirpSync(this.destinationPath);
|
|
378
|
+
if (changelogFilename) {
|
|
379
|
+
this.changelogFilename = changelogFilename;
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
this.changelogFilename = 'CHANGELOG.html';
|
|
383
|
+
}
|
|
384
|
+
if (changelogTemplate) {
|
|
385
|
+
if (this.templateIsValid(changelogTemplate)) {
|
|
386
|
+
this.changelogTemplate = changelogTemplate;
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
this.logger.warn(colors.yellow('Invalid changelog template, using default'));
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (typeof diffFileTemplateHandler === 'function') {
|
|
393
|
+
this.diffFileTemplateHandler = diffFileTemplateHandler;
|
|
394
|
+
}
|
|
395
|
+
if (typeof diffLineTemplateHandler === 'function') {
|
|
396
|
+
this.diffLineTemplateHandler = diffLineTemplateHandler;
|
|
397
|
+
}
|
|
398
|
+
if (contextLines) {
|
|
399
|
+
this.contextLines = contextLines;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
templateIsValid(template) {
|
|
403
|
+
return template.includes('%FILES%');
|
|
404
|
+
}
|
|
405
|
+
isExists(assetPath) {
|
|
406
|
+
return fs.existsSync(assetPath);
|
|
407
|
+
}
|
|
408
|
+
isZipFile(assetPath) {
|
|
409
|
+
return assetPath.endsWith('.zip');
|
|
410
|
+
}
|
|
411
|
+
isFolder(assetPath) {
|
|
412
|
+
return fs.lstatSync(assetPath).isDirectory();
|
|
413
|
+
}
|
|
414
|
+
isEmptyFolder(assetPath) {
|
|
415
|
+
return fs.readdirSync(assetPath, { withFileTypes: true }).length === 0;
|
|
416
|
+
}
|
|
417
|
+
mkdirpSync(dir) {
|
|
418
|
+
if (!fs.existsSync(dir)) {
|
|
419
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
async unzipFile(assetPath, destinationPath) {
|
|
423
|
+
fs.rmSync(destinationPath, { force: true, recursive: true });
|
|
424
|
+
return extractZip(assetPath, { dir: destinationPath });
|
|
425
|
+
}
|
|
426
|
+
normalizeAssetFolderPath(assetPath) {
|
|
427
|
+
const folderContent = fs.readdirSync(assetPath);
|
|
428
|
+
if (folderContent.length === 1 && fs.lstatSync(path.join(assetPath, folderContent[0])).isDirectory()) {
|
|
429
|
+
return this.normalizeAssetFolderPath(path.join(assetPath, folderContent[0]));
|
|
430
|
+
}
|
|
431
|
+
return assetPath;
|
|
432
|
+
}
|
|
433
|
+
pathToPosix(path) {
|
|
434
|
+
return path.replace(/\\/g, '/');
|
|
435
|
+
}
|
|
436
|
+
diffTableTemplate(diffLinesHTML) {
|
|
437
|
+
return /* HTML */ `<table class="diff-table">
|
|
438
|
+
<tbody>
|
|
439
|
+
${diffLinesHTML}
|
|
440
|
+
</tbody>
|
|
441
|
+
</table>`;
|
|
442
|
+
}
|
|
443
|
+
getDiffTableHTML(diffLines) {
|
|
444
|
+
const diffLinesHTML = diffLines
|
|
445
|
+
.filter((value, index, array) => {
|
|
446
|
+
if (value.lineType === LINE_CONTEXT) {
|
|
447
|
+
return ((index >= 0 && index < this.contextLines) ||
|
|
448
|
+
(index > array.length - (this.contextLines + 1) && index <= array.length - 1) ||
|
|
449
|
+
array
|
|
450
|
+
.slice(index - this.contextLines, index + this.contextLines + 1)
|
|
451
|
+
.some((line) => line.lineType !== LINE_CONTEXT));
|
|
452
|
+
}
|
|
453
|
+
return true;
|
|
454
|
+
})
|
|
455
|
+
.map((line, index, array) => {
|
|
456
|
+
if (index > 0) {
|
|
457
|
+
const prevLine = array[index - 1];
|
|
458
|
+
if (line.lineNumber - prevLine.lineNumber > 1) {
|
|
459
|
+
return [{ lineNumber: -1, lineContent: '', lineType: LINE_CONTEXT }, line];
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return [line];
|
|
463
|
+
})
|
|
464
|
+
.flat()
|
|
465
|
+
.map((line) => this.diffLineHTML(line))
|
|
466
|
+
.join('');
|
|
467
|
+
return this.diffTableTemplate(diffLinesHTML);
|
|
468
|
+
}
|
|
469
|
+
diffLineMessageTemplate(message) {
|
|
470
|
+
return /* HTML */ `<tr>
|
|
471
|
+
<td class="blob-num"></td>
|
|
472
|
+
<td class="blob-num"></td>
|
|
473
|
+
<td class="blob-code message">
|
|
474
|
+
<span class="blob-code-inner">${message}</span>
|
|
475
|
+
</td>
|
|
476
|
+
</tr>`;
|
|
477
|
+
}
|
|
478
|
+
diffLineSkipTemplate() {
|
|
479
|
+
return /* HTML */ `<tr>
|
|
480
|
+
<td class="blob-num"></td>
|
|
481
|
+
<td class="blob-num"></td>
|
|
482
|
+
<td class="blob-code skip">
|
|
483
|
+
<span class="blob-code-inner">Skip</span>
|
|
484
|
+
</td>
|
|
485
|
+
</tr>`;
|
|
486
|
+
}
|
|
487
|
+
diffLineTemplate(diffLine) {
|
|
488
|
+
const { lineNumber, lineContent, lineType } = diffLine;
|
|
489
|
+
const numClass = lineType === LINE_ADDED ? 'addition' : lineType === LINE_REMOVED ? 'deletion' : '';
|
|
490
|
+
const codeClass = lineType === LINE_ADDED ? 'code-addition' : lineType === LINE_REMOVED ? 'code-deletion' : '';
|
|
491
|
+
const prefix = lineType === LINE_ADDED ? '+' : lineType === LINE_REMOVED ? '-' : ' ';
|
|
492
|
+
return /* HTML */ `<tr>
|
|
493
|
+
<td
|
|
494
|
+
class="blob-num ${numClass}${numClass === 'addition' ? ' empty' : ''}"
|
|
495
|
+
${numClass !== 'addition' ? ` data-line-number="${lineNumber}"` : ''}
|
|
496
|
+
></td>
|
|
497
|
+
<td
|
|
498
|
+
class="blob-num ${numClass}${numClass === 'deletion' ? ' empty' : ''}"
|
|
499
|
+
${numClass !== 'deletion' ? ` data-line-number="${lineNumber}"` : ''}
|
|
500
|
+
></td>
|
|
501
|
+
<td class="blob-code ${codeClass}">
|
|
502
|
+
<span class="blob-code-inner" data-code-prefix="${prefix}">${escapeHTMLSequence(lineContent ?? '')}</span>
|
|
503
|
+
</td>
|
|
504
|
+
</tr>`;
|
|
505
|
+
}
|
|
506
|
+
diffLineHTML(diffLine) {
|
|
507
|
+
if (this.diffLineTemplateHandler) {
|
|
508
|
+
return this.diffLineTemplateHandler(diffLine);
|
|
509
|
+
}
|
|
510
|
+
const { lineNumber } = diffLine;
|
|
511
|
+
if (lineNumber === -1) {
|
|
512
|
+
return this.diffLineSkipTemplate();
|
|
513
|
+
}
|
|
514
|
+
return this.diffLineTemplate(diffLine);
|
|
515
|
+
}
|
|
516
|
+
diffFileTemplate(filename, htmlDiff) {
|
|
517
|
+
if (this.diffFileTemplateHandler) {
|
|
518
|
+
return this.diffFileTemplateHandler(filename, htmlDiff);
|
|
519
|
+
}
|
|
520
|
+
return /* HTML */ `<div class="diff-file">
|
|
521
|
+
<div class="diff-file-title">${filename}</div>
|
|
522
|
+
<div class="diff-file-content">${htmlDiff}</div>
|
|
523
|
+
</div>`;
|
|
524
|
+
}
|
|
525
|
+
async generateAssetFoldersDiff() {
|
|
526
|
+
this.logger.info(colors.blue(`Comparing asset folders ${await this.oldAssetsPath} and ${await this.newAssetsPath}`));
|
|
527
|
+
const dirDiff = await dirCompare.compare(await this.oldAssetsPath, await this.newAssetsPath, {
|
|
528
|
+
compareContent: true,
|
|
529
|
+
skipSymlinks: true,
|
|
530
|
+
compareSize: true,
|
|
531
|
+
compareDate: false,
|
|
532
|
+
compareNameHandler: (name1, name2) => {
|
|
533
|
+
if (fileNameWithHashRegEx.test(name1)) {
|
|
534
|
+
name1 = name1.replace(fileNameWithHashRegEx, '$1$3');
|
|
535
|
+
}
|
|
536
|
+
if (fileNameWithHashRegEx.test(name2)) {
|
|
537
|
+
name2 = name2.replace(fileNameWithHashRegEx, '$1$3');
|
|
538
|
+
}
|
|
539
|
+
if (name1.localeCompare(name2) === 0) {
|
|
540
|
+
return 0;
|
|
541
|
+
}
|
|
542
|
+
return name1.localeCompare(name2) > 0 ? 1 : -1;
|
|
543
|
+
},
|
|
544
|
+
});
|
|
545
|
+
return dirDiff.diffSet?.filter((d) => d.state !== 'equal' || d.name1 !== d.name2) || [];
|
|
546
|
+
}
|
|
547
|
+
async generateAssetFilesDiff(oldFileString, newFileString) {
|
|
548
|
+
const dmp = new DiffMatchPatch();
|
|
549
|
+
const linesChars = dmp.diff_linesToChars_(oldFileString, newFileString);
|
|
550
|
+
const linesDiff = dmp.diff_main(linesChars.chars1, linesChars.chars2, false);
|
|
551
|
+
dmp.diff_charsToLines_(linesDiff, linesChars.lineArray);
|
|
552
|
+
let lineNumber = 0;
|
|
553
|
+
return linesDiff
|
|
554
|
+
.map((diffLine) => {
|
|
555
|
+
const [lineType, lineContent] = diffLine;
|
|
556
|
+
const linesCount = lineContent.endsWith('\n')
|
|
557
|
+
? lineContent.split('\n').length - 1
|
|
558
|
+
: lineContent.split('\n').length;
|
|
559
|
+
const lines = lineContent
|
|
560
|
+
.split('\n')
|
|
561
|
+
.map((line, index) => {
|
|
562
|
+
return { lineContent: line, lineNumber: lineNumber + index + 1, lineType };
|
|
563
|
+
})
|
|
564
|
+
.slice(0, linesCount);
|
|
565
|
+
if (lineType !== LINE_REMOVED) {
|
|
566
|
+
lineNumber += linesCount;
|
|
567
|
+
}
|
|
568
|
+
return lines;
|
|
569
|
+
})
|
|
570
|
+
.flat();
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Generate diff for a file
|
|
574
|
+
* @param difference
|
|
575
|
+
* @private
|
|
576
|
+
*/
|
|
577
|
+
async generateFilesDiff(difference) {
|
|
578
|
+
if (difference.state === 'equal') {
|
|
579
|
+
const filepath1 = this.pathToPosix(path.join('.', difference.relativePath, difference.name1 ?? ''));
|
|
580
|
+
const filepath2 = this.pathToPosix(path.join('.', difference.relativePath, difference.name2 ?? ''));
|
|
581
|
+
return this.diffFileTemplate(
|
|
582
|
+
/* HTML */ `<span class="renamed"
|
|
583
|
+
>Renamed <span class="from">${filepath1}</span> -> <span class="to">${filepath2}</span></span
|
|
584
|
+
>`, this.diffTableTemplate(this.diffLineMessageTemplate('No changes')));
|
|
585
|
+
}
|
|
586
|
+
const assetFile1Path = difference.path1 && difference.name1 ? path.join(difference.path1, difference.name1) : null;
|
|
587
|
+
const assetFile2Path = difference.path2 && difference.name2 ? path.join(difference.path2, difference.name2) : null;
|
|
588
|
+
const filepath = this.pathToPosix(path.join('.', difference.relativePath, (difference.name1 || difference.name2) ?? ''));
|
|
589
|
+
if (difference.state === 'left' && assetFile1Path) {
|
|
590
|
+
return this.diffFileTemplate(
|
|
591
|
+
/* HTML */ `<span class="removed">Removed ${filepath}</span>`, this.diffTableTemplate(this.diffLineMessageTemplate('File removed')));
|
|
592
|
+
}
|
|
593
|
+
if (difference.state === 'right' && assetFile2Path) {
|
|
594
|
+
return this.diffFileTemplate(
|
|
595
|
+
/* HTML */ `<span class="added">Added ${filepath}</span>`, this.diffTableTemplate(this.diffLineMessageTemplate('File added')));
|
|
596
|
+
}
|
|
597
|
+
if (difference.state === 'distinct' && assetFile1Path && assetFile2Path) {
|
|
598
|
+
const filepath1 = this.pathToPosix(path.join('.', difference.relativePath, difference.name1 ?? ''));
|
|
599
|
+
const filepath2 = this.pathToPosix(path.join('.', difference.relativePath, difference.name2 ?? ''));
|
|
600
|
+
const filenameTitle = difference.name1 !== difference.name2
|
|
601
|
+
? /* HTML */ `<span class="renamed"
|
|
602
|
+
>Renamed <span class="from">${filepath1}</span> -> <span class="to">${filepath2}</span></span
|
|
603
|
+
>`
|
|
604
|
+
: filepath;
|
|
605
|
+
return this.diffFileTemplate(filenameTitle, (await isBinaryFile(assetFile1Path)) || (await isBinaryFile(assetFile2Path))
|
|
606
|
+
? this.diffTableTemplate(this.diffLineMessageTemplate('Binary file'))
|
|
607
|
+
: this.getDiffTableHTML(await this.generateAssetFilesDiff(fs.readFileSync(assetFile1Path, 'utf-8'), fs.readFileSync(assetFile2Path, 'utf-8'))));
|
|
608
|
+
}
|
|
609
|
+
return '';
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Generate changelog file based on the differences between two asset folders or zip files
|
|
613
|
+
* and write it to the destination folder
|
|
614
|
+
*/
|
|
615
|
+
async generateChangelog() {
|
|
616
|
+
this.logger.info(colors.green('Generating changelog'));
|
|
617
|
+
const diffSet = await this.generateAssetFoldersDiff();
|
|
618
|
+
const htmlDiff = (await Promise.all(diffSet.map((difference) => this.generateFilesDiff(difference)))).join('');
|
|
619
|
+
this.logger.info(colors.green('Writing changelog file'));
|
|
620
|
+
const templateArray = this.changelogTemplate.split('%FILES%');
|
|
621
|
+
templateArray.splice(1, 0, htmlDiff);
|
|
622
|
+
const changelogHTML = templateArray.join('');
|
|
623
|
+
fs.writeFileSync(path.join(this.destinationPath, this.changelogFilename), changelogHTML);
|
|
624
|
+
this.logger.info(colors.green(`Changelog file written to ${path.join(this.destinationPath, this.changelogFilename)}`));
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
class IconFontGenerator {
|
|
629
|
+
sourceDir;
|
|
630
|
+
outputDir;
|
|
631
|
+
fontName;
|
|
632
|
+
constructor(options) {
|
|
633
|
+
this.sourceDir = options.sourceDir;
|
|
634
|
+
this.outputDir = options.outputDir;
|
|
635
|
+
this.fontName = options.fontName;
|
|
636
|
+
}
|
|
637
|
+
async generate() {
|
|
638
|
+
await svgToFont({
|
|
639
|
+
src: this.sourceDir,
|
|
640
|
+
dist: this.outputDir,
|
|
641
|
+
fontName: this.fontName,
|
|
642
|
+
css: true,
|
|
643
|
+
typescript: true,
|
|
644
|
+
startUnicode: 0xea01,
|
|
645
|
+
svgicons2svgfont: {
|
|
646
|
+
fontHeight: 1024,
|
|
647
|
+
},
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
155
652
|
const cli = cac('pp-dev');
|
|
156
|
-
const colors = createColors();
|
|
157
653
|
let profileSession = global.__pp_dev_profile_session;
|
|
158
654
|
let profileCount = 0;
|
|
159
655
|
const stopProfiler = (log) => {
|
|
@@ -244,19 +740,21 @@ cli
|
|
|
244
740
|
clearScreen: options.clearScreen,
|
|
245
741
|
optimizeDeps: { force: options.force },
|
|
246
742
|
server: cleanOptions(options),
|
|
743
|
+
customLogger: createLogger(options.logLevel),
|
|
247
744
|
}, true));
|
|
745
|
+
if (!server.config.base || server.config.base === '/') {
|
|
746
|
+
throw new Error('base cannot be equal to "/" or empty string');
|
|
747
|
+
}
|
|
248
748
|
if (!server.httpServer) {
|
|
249
749
|
throw new Error('HTTP server not available');
|
|
250
750
|
}
|
|
251
751
|
await server.listen();
|
|
252
|
-
const
|
|
752
|
+
const logger = createLogger(options.logLevel);
|
|
253
753
|
const ppDevStartTime = global.__pp_dev_start_time ?? false;
|
|
254
754
|
const startupDurationString = ppDevStartTime
|
|
255
755
|
? colors.dim(`ready in ${colors.reset(colors.bold(Math.ceil(performance.now() - ppDevStartTime)))} ms`)
|
|
256
756
|
: '';
|
|
257
|
-
info(`\n ${colors.green(`${colors.bold('PP-DEV')} v${VERSION}`)} ${startupDurationString}\n
|
|
258
|
-
clear: !server.config.logger.hasWarned,
|
|
259
|
-
});
|
|
757
|
+
logger.info(`\n ${colors.green(`${colors.bold('PP-DEV')} v${VERSION}`)} ${startupDurationString}\n`);
|
|
260
758
|
server.printUrls();
|
|
261
759
|
bindShortcuts(server, {
|
|
262
760
|
print: true,
|
|
@@ -266,7 +764,7 @@ cli
|
|
|
266
764
|
description: 'start/stop the profiler',
|
|
267
765
|
async action(server) {
|
|
268
766
|
if (profileSession) {
|
|
269
|
-
await stopProfiler(
|
|
767
|
+
await stopProfiler(logger.info);
|
|
270
768
|
}
|
|
271
769
|
else {
|
|
272
770
|
const inspector = await import('node:inspector').then((r) => r.default);
|
|
@@ -275,7 +773,7 @@ cli
|
|
|
275
773
|
profileSession.connect();
|
|
276
774
|
profileSession.post('Profiler.enable', () => {
|
|
277
775
|
profileSession?.post('Profiler.start', () => {
|
|
278
|
-
|
|
776
|
+
logger.info('Profiler started');
|
|
279
777
|
res();
|
|
280
778
|
});
|
|
281
779
|
});
|
|
@@ -321,16 +819,20 @@ cli
|
|
|
321
819
|
.action(async (root, options) => {
|
|
322
820
|
filterDuplicateOptions(options);
|
|
323
821
|
const { default: next } = await import('next');
|
|
822
|
+
const logger = createLogger();
|
|
324
823
|
const server = createDevServer(options.logLevel);
|
|
325
824
|
const opts = cleanOptions(options);
|
|
326
825
|
const app = next({ dev: true, hostname: opts.host, port: opts.port });
|
|
327
|
-
const handle = app.getRequestHandler();
|
|
328
826
|
await app.prepare();
|
|
329
827
|
const nextServer = (await app.getServer());
|
|
330
828
|
let base = nextServer.nextConfig.basePath;
|
|
829
|
+
const { assetPrefix } = nextServer.nextConfig;
|
|
331
830
|
if (!base.endsWith('/')) {
|
|
332
831
|
base += '/';
|
|
333
832
|
}
|
|
833
|
+
if (base === '/') {
|
|
834
|
+
throw new Error('basePath cannot be equal to "/" or empty string');
|
|
835
|
+
}
|
|
334
836
|
const baseWithoutTrailingSlash = base.substring(0, base.lastIndexOf('/'));
|
|
335
837
|
const templateName = nextServer.nextConfig.serverRuntimeConfig.templateName;
|
|
336
838
|
const ppDevConfig = nextServer.nextConfig.serverRuntimeConfig.ppDevConfig;
|
|
@@ -355,10 +857,14 @@ cli
|
|
|
355
857
|
}
|
|
356
858
|
server.use(initProxyCache({ devServer: server, ttl }));
|
|
357
859
|
}
|
|
860
|
+
const proxyIgnore = ['/@vite', '/@metricinsights', '/@', baseWithoutTrailingSlash];
|
|
861
|
+
if (assetPrefix) {
|
|
862
|
+
proxyIgnore.push(assetPrefix);
|
|
863
|
+
}
|
|
358
864
|
server.use(initProxy({
|
|
359
865
|
devServer: server,
|
|
360
866
|
baseURL: backendBaseURL,
|
|
361
|
-
proxyIgnore
|
|
867
|
+
proxyIgnore,
|
|
362
868
|
disableSSLValidation,
|
|
363
869
|
}));
|
|
364
870
|
const isIndexRegExp = new RegExp(`^((${base})|/)$`);
|
|
@@ -370,7 +876,12 @@ cli
|
|
|
370
876
|
return Buffer.from(urlReplacer(baseUrlHost, req.headers.host ?? '', mi.buildPage(response, miHudLess)));
|
|
371
877
|
}));
|
|
372
878
|
}
|
|
879
|
+
const handle = app.getRequestHandler();
|
|
373
880
|
server.all('*', (req, res) => {
|
|
881
|
+
if (req.url.startsWith(assetPrefix) && assetPrefix !== baseWithoutTrailingSlash) {
|
|
882
|
+
const parsedUrl = parse(req.url.replace(assetPrefix, baseWithoutTrailingSlash), true);
|
|
883
|
+
return handle(req, res, parsedUrl);
|
|
884
|
+
}
|
|
374
885
|
const parsedUrl = parse(req.url, true);
|
|
375
886
|
handle(req, res, parsedUrl);
|
|
376
887
|
});
|
|
@@ -387,12 +898,11 @@ cli
|
|
|
387
898
|
}));
|
|
388
899
|
}
|
|
389
900
|
});
|
|
390
|
-
const info = server.config.logger.info;
|
|
391
901
|
const ppDevStartTime = global.__pp_dev_start_time ?? false;
|
|
392
902
|
const startupDurationString = ppDevStartTime
|
|
393
903
|
? colors.dim(`ready in ${colors.reset(colors.bold(Math.ceil(performance.now() - ppDevStartTime)))} ms`)
|
|
394
904
|
: '';
|
|
395
|
-
info(`\n ${colors.green(`${colors.bold('PP-DEV')} v${VERSION}`)} ${startupDurationString}\n`, {
|
|
905
|
+
logger.info(`\n ${colors.green(`${colors.bold('PP-DEV')} v${VERSION}`)} ${startupDurationString}\n`, {
|
|
396
906
|
clear: true,
|
|
397
907
|
});
|
|
398
908
|
server.printUrls(base);
|
|
@@ -458,6 +968,7 @@ cli
|
|
|
458
968
|
.option('--force', `[boolean] force the optimizer to ignore the cache and re-bundle (experimental)`)
|
|
459
969
|
.option('--emptyOutDir', `[boolean] force empty outDir when it's outside of root`)
|
|
460
970
|
.option('-w, --watch', `[boolean] rebuilds when modules have changed on disk`)
|
|
971
|
+
.option('--changelog [assetsFile]', `[boolean | string] generate changelog between assetsFile and current build (default: false)`)
|
|
461
972
|
.action(async (root, options) => {
|
|
462
973
|
filterDuplicateOptions(options);
|
|
463
974
|
const buildOptions = cleanOptions(options);
|
|
@@ -468,7 +979,7 @@ cli
|
|
|
468
979
|
const { plugins, ...fileConfig } = configFromFile.config;
|
|
469
980
|
config = mergeConfig(config, fileConfig);
|
|
470
981
|
}
|
|
471
|
-
|
|
982
|
+
const buildConfig = mergeConfig(config, {
|
|
472
983
|
root,
|
|
473
984
|
base: options.base,
|
|
474
985
|
mode: options.mode,
|
|
@@ -477,7 +988,55 @@ cli
|
|
|
477
988
|
clearScreen: options.clearScreen,
|
|
478
989
|
optimizeDeps: { force: options.force },
|
|
479
990
|
build: buildOptions,
|
|
480
|
-
}, true)
|
|
991
|
+
}, true);
|
|
992
|
+
await build(buildConfig);
|
|
993
|
+
if (buildOptions.changelog) {
|
|
994
|
+
const executionRoot = root || process.cwd();
|
|
995
|
+
const outDir = buildConfig.build?.outDir || 'dist';
|
|
996
|
+
let oldAssetsPath = '';
|
|
997
|
+
if (typeof buildOptions.changelog === 'string') {
|
|
998
|
+
oldAssetsPath = path.resolve(executionRoot, buildOptions.changelog);
|
|
999
|
+
}
|
|
1000
|
+
else {
|
|
1001
|
+
const backupsDirPath = path.resolve(executionRoot, buildConfig.ppDevConfig?.syncBackupsDir || 'backups');
|
|
1002
|
+
if (!fs.existsSync(backupsDirPath)) {
|
|
1003
|
+
createLogger(options.logLevel).warn(colors.yellow(`backups directory not found, skipping changelog generation`));
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
1006
|
+
const backups = fs.readdirSync(backupsDirPath, { withFileTypes: true });
|
|
1007
|
+
if (!backups.length) {
|
|
1008
|
+
createLogger(options.logLevel).warn(colors.yellow(`no backups found, skipping changelog generation`));
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
1011
|
+
const latestBackup = backups
|
|
1012
|
+
.filter((value) => {
|
|
1013
|
+
return value.isFile() && value.name.endsWith('.zip');
|
|
1014
|
+
})
|
|
1015
|
+
.reduce((latest, current) => {
|
|
1016
|
+
const latestTime = fs.statSync(path.resolve(backupsDirPath, latest.name)).mtimeMs;
|
|
1017
|
+
const currentTime = fs.statSync(path.resolve(backupsDirPath, current.name)).mtimeMs;
|
|
1018
|
+
return latestTime > currentTime ? latest : current;
|
|
1019
|
+
}, backups[0]).name;
|
|
1020
|
+
oldAssetsPath = path.resolve(backupsDirPath, latestBackup);
|
|
1021
|
+
}
|
|
1022
|
+
const currentAssetFilePath = path.resolve(executionRoot, outDir);
|
|
1023
|
+
let changelogDestination = 'dist-zip';
|
|
1024
|
+
if (buildConfig.ppDevConfig) {
|
|
1025
|
+
if (buildConfig.ppDevConfig.distZip === false) {
|
|
1026
|
+
changelogDestination = buildConfig.build?.outDir || 'dist';
|
|
1027
|
+
}
|
|
1028
|
+
else if (typeof buildConfig.ppDevConfig.distZip === 'object' &&
|
|
1029
|
+
typeof buildConfig.ppDevConfig.distZip.outDir === 'string') {
|
|
1030
|
+
changelogDestination = buildConfig.ppDevConfig.distZip.outDir;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
const changelogGenerator = new ChangelogGenerator({
|
|
1034
|
+
oldAssetsPath,
|
|
1035
|
+
newAssetsPath: currentAssetFilePath,
|
|
1036
|
+
destinationPath: path.resolve(executionRoot, changelogDestination),
|
|
1037
|
+
});
|
|
1038
|
+
await changelogGenerator.generateChangelog();
|
|
1039
|
+
}
|
|
481
1040
|
}
|
|
482
1041
|
catch (e) {
|
|
483
1042
|
createLogger(options.logLevel).error(colors.red(`error during build:\n${e.stack}`), { error: e });
|
|
@@ -487,6 +1046,53 @@ cli
|
|
|
487
1046
|
stopProfiler((message) => createLogger(options.logLevel).info(message));
|
|
488
1047
|
}
|
|
489
1048
|
});
|
|
1049
|
+
// changelog
|
|
1050
|
+
cli
|
|
1051
|
+
.command('changelog [oldAssetPath] [newAssetPath]', 'generate changelog between two assets files/folders')
|
|
1052
|
+
.option('--oldAssetsPath <oldAssetsPath>', `[string] path to the old assets zip file or folder`)
|
|
1053
|
+
.option('--newAssetsPath <newAssetsPath>', `[string] path to the new assets zip file or folder`)
|
|
1054
|
+
.option('--destination <destination>', `[string] destination folder for the changelog (default: .)`)
|
|
1055
|
+
.option('--filename <filename>', `[string] filename for the changelog (default: CHANGELOG.html)`)
|
|
1056
|
+
.action(async (oldAssetPath, newAssetPath, options) => {
|
|
1057
|
+
filterDuplicateOptions(options);
|
|
1058
|
+
const { oldAssetsPath: oldPath = oldAssetPath, newAssetsPath: newPath = newAssetPath, destination = '.', filename = 'CHANGELOG.html', logLevel, } = options;
|
|
1059
|
+
const root = process.cwd();
|
|
1060
|
+
if (!oldPath || !newPath) {
|
|
1061
|
+
createLogger(logLevel).error(colors.red(`error during changelog generation: oldAssetPath and newAssetPath are required`));
|
|
1062
|
+
process.exit(1);
|
|
1063
|
+
}
|
|
1064
|
+
const fullOldPath = path.resolve(root, oldPath);
|
|
1065
|
+
const fullNewPath = path.resolve(root, newPath);
|
|
1066
|
+
const fullDestination = path.resolve(root, destination);
|
|
1067
|
+
const changelogGenerator = new ChangelogGenerator({
|
|
1068
|
+
oldAssetsPath: fullOldPath,
|
|
1069
|
+
newAssetsPath: fullNewPath,
|
|
1070
|
+
destinationPath: fullDestination,
|
|
1071
|
+
changelogFilename: filename,
|
|
1072
|
+
});
|
|
1073
|
+
await changelogGenerator.generateChangelog();
|
|
1074
|
+
});
|
|
1075
|
+
cli
|
|
1076
|
+
.command('generate-icon-font [source] [destination]', 'generate icon font from SVG files')
|
|
1077
|
+
.option('--source <source>', `[string] path to the source directory with SVG files`)
|
|
1078
|
+
.option('--destination <destination>', `[string] path to the destination directory to save the generated font files`)
|
|
1079
|
+
.option('--font-name, -n <fontName>', `[string] name of the font to generate (default: 'icon-font')`)
|
|
1080
|
+
.action(async (source, destination, options) => {
|
|
1081
|
+
filterDuplicateOptions(options);
|
|
1082
|
+
const { source: sourceDir = source, destination: destDir = destination, fontName = 'icon-font' } = options;
|
|
1083
|
+
const root = process.cwd();
|
|
1084
|
+
const fullSourceDir = path.resolve(root, sourceDir);
|
|
1085
|
+
const fullDestDir = path.resolve(root, destDir);
|
|
1086
|
+
const iconFontGenerator = new IconFontGenerator({
|
|
1087
|
+
sourceDir: fullSourceDir,
|
|
1088
|
+
outputDir: fullDestDir,
|
|
1089
|
+
fontName,
|
|
1090
|
+
});
|
|
1091
|
+
const logger = createLogger(options.logLevel);
|
|
1092
|
+
logger.info(`Generating icon font from SVG files in ${colors.dim(fullSourceDir)}`);
|
|
1093
|
+
await iconFontGenerator.generate();
|
|
1094
|
+
logger.info(`Icon font generated and saved to ${colors.dim(fullDestDir)}`);
|
|
1095
|
+
});
|
|
490
1096
|
// optimize
|
|
491
1097
|
cli
|
|
492
1098
|
.command('optimize [root]', 'pre-bundle dependencies')
|