qfai 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/cli/index.cjs +166 -32
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.mjs +166 -32
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.cjs +103 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.mjs +103 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/cli/index.mjs
CHANGED
|
@@ -16,6 +16,7 @@ var DEFAULT_IGNORE_DIRS = /* @__PURE__ */ new Set([
|
|
|
16
16
|
"tmp",
|
|
17
17
|
".mcp-tools"
|
|
18
18
|
]);
|
|
19
|
+
var DEFAULT_GLOB_FILE_LIMIT = 2e4;
|
|
19
20
|
async function collectFiles(root, options = {}) {
|
|
20
21
|
const entries = [];
|
|
21
22
|
if (!await exists(root)) {
|
|
@@ -30,16 +31,29 @@ async function collectFiles(root, options = {}) {
|
|
|
30
31
|
return entries;
|
|
31
32
|
}
|
|
32
33
|
async function collectFilesByGlobs(root, options) {
|
|
34
|
+
const limit = normalizeLimit(options.limit);
|
|
33
35
|
if (options.globs.length === 0) {
|
|
34
|
-
return [];
|
|
36
|
+
return { files: [], truncated: false, matchedFileCount: 0, limit };
|
|
35
37
|
}
|
|
36
|
-
|
|
38
|
+
const stream = fg.stream(options.globs, {
|
|
37
39
|
cwd: root,
|
|
38
40
|
ignore: options.ignore ?? [],
|
|
39
41
|
onlyFiles: true,
|
|
40
42
|
absolute: true,
|
|
41
43
|
unique: true
|
|
42
44
|
});
|
|
45
|
+
const files = [];
|
|
46
|
+
let truncated = false;
|
|
47
|
+
for await (const entry of stream) {
|
|
48
|
+
if (files.length >= limit) {
|
|
49
|
+
truncated = true;
|
|
50
|
+
destroyStream(stream);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
files.push(String(entry));
|
|
54
|
+
}
|
|
55
|
+
const matchedFileCount = files.length;
|
|
56
|
+
return { files, truncated, matchedFileCount, limit };
|
|
43
57
|
}
|
|
44
58
|
async function walk(base, current, ignoreDirs, extensions, out) {
|
|
45
59
|
const items = await readdir(current, { withFileTypes: true });
|
|
@@ -71,6 +85,25 @@ async function exists(target) {
|
|
|
71
85
|
return false;
|
|
72
86
|
}
|
|
73
87
|
}
|
|
88
|
+
function normalizeLimit(value) {
|
|
89
|
+
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
90
|
+
return DEFAULT_GLOB_FILE_LIMIT;
|
|
91
|
+
}
|
|
92
|
+
const flooredValue = Math.floor(value);
|
|
93
|
+
if (flooredValue <= 0) {
|
|
94
|
+
return DEFAULT_GLOB_FILE_LIMIT;
|
|
95
|
+
}
|
|
96
|
+
return flooredValue;
|
|
97
|
+
}
|
|
98
|
+
function destroyStream(stream) {
|
|
99
|
+
if (!stream || typeof stream !== "object") {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const record2 = stream;
|
|
103
|
+
if (typeof record2.destroy === "function") {
|
|
104
|
+
record2.destroy();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
74
107
|
|
|
75
108
|
// src/cli/commands/analyze.ts
|
|
76
109
|
async function runAnalyze(options) {
|
|
@@ -890,15 +923,18 @@ async function collectScTestReferences(root, globs, excludeGlobs) {
|
|
|
890
923
|
scan: {
|
|
891
924
|
globs: normalizedGlobs,
|
|
892
925
|
excludeGlobs: mergedExcludeGlobs,
|
|
893
|
-
matchedFileCount: 0
|
|
926
|
+
matchedFileCount: 0,
|
|
927
|
+
truncated: false,
|
|
928
|
+
limit: DEFAULT_GLOB_FILE_LIMIT
|
|
894
929
|
}
|
|
895
930
|
};
|
|
896
931
|
}
|
|
897
|
-
let
|
|
932
|
+
let scanResult;
|
|
898
933
|
try {
|
|
899
|
-
|
|
934
|
+
scanResult = await collectFilesByGlobs(root, {
|
|
900
935
|
globs: normalizedGlobs,
|
|
901
|
-
ignore: mergedExcludeGlobs
|
|
936
|
+
ignore: mergedExcludeGlobs,
|
|
937
|
+
limit: DEFAULT_GLOB_FILE_LIMIT
|
|
902
938
|
});
|
|
903
939
|
} catch (error2) {
|
|
904
940
|
return {
|
|
@@ -906,13 +942,15 @@ async function collectScTestReferences(root, globs, excludeGlobs) {
|
|
|
906
942
|
scan: {
|
|
907
943
|
globs: normalizedGlobs,
|
|
908
944
|
excludeGlobs: mergedExcludeGlobs,
|
|
909
|
-
matchedFileCount: 0
|
|
945
|
+
matchedFileCount: 0,
|
|
946
|
+
truncated: false,
|
|
947
|
+
limit: DEFAULT_GLOB_FILE_LIMIT
|
|
910
948
|
},
|
|
911
949
|
error: formatError3(error2)
|
|
912
950
|
};
|
|
913
951
|
}
|
|
914
952
|
const normalizedFiles = Array.from(
|
|
915
|
-
new Set(files.map((file) => path6.normalize(file)))
|
|
953
|
+
new Set(scanResult.files.map((file) => path6.normalize(file)))
|
|
916
954
|
);
|
|
917
955
|
for (const file of normalizedFiles) {
|
|
918
956
|
const text = await readFile3(file, "utf-8");
|
|
@@ -931,7 +969,9 @@ async function collectScTestReferences(root, globs, excludeGlobs) {
|
|
|
931
969
|
scan: {
|
|
932
970
|
globs: normalizedGlobs,
|
|
933
971
|
excludeGlobs: mergedExcludeGlobs,
|
|
934
|
-
matchedFileCount:
|
|
972
|
+
matchedFileCount: scanResult.matchedFileCount,
|
|
973
|
+
truncated: scanResult.truncated,
|
|
974
|
+
limit: scanResult.limit
|
|
935
975
|
}
|
|
936
976
|
};
|
|
937
977
|
}
|
|
@@ -1101,8 +1141,8 @@ import { readFile as readFile5 } from "fs/promises";
|
|
|
1101
1141
|
import path9 from "path";
|
|
1102
1142
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1103
1143
|
async function resolveToolVersion() {
|
|
1104
|
-
if ("1.0.
|
|
1105
|
-
return "1.0.
|
|
1144
|
+
if ("1.0.1".length > 0) {
|
|
1145
|
+
return "1.0.1";
|
|
1106
1146
|
}
|
|
1107
1147
|
try {
|
|
1108
1148
|
const packagePath = resolvePackageJsonPath();
|
|
@@ -1313,19 +1353,27 @@ async function createDoctorData(options) {
|
|
|
1313
1353
|
...config.validation.traceability.testFileExcludeGlobs
|
|
1314
1354
|
]);
|
|
1315
1355
|
try {
|
|
1316
|
-
const
|
|
1317
|
-
|
|
1318
|
-
|
|
1356
|
+
const scanResult = globs.length === 0 ? {
|
|
1357
|
+
files: [],
|
|
1358
|
+
truncated: false,
|
|
1359
|
+
matchedFileCount: 0,
|
|
1360
|
+
limit: DEFAULT_GLOB_FILE_LIMIT
|
|
1361
|
+
} : await collectFilesByGlobs(root, { globs, ignore: exclude });
|
|
1362
|
+
const matchedCount = scanResult.matchedFileCount;
|
|
1363
|
+
const truncated = scanResult.truncated;
|
|
1364
|
+
const severity = globs.length === 0 ? "warning" : truncated ? "warning" : scenarioFiles.length > 0 && config.validation.traceability.scMustHaveTest && matchedCount === 0 ? "warning" : "ok";
|
|
1319
1365
|
addCheck(checks, {
|
|
1320
1366
|
id: "traceability.testGlobs",
|
|
1321
1367
|
severity,
|
|
1322
1368
|
title: "Test file globs",
|
|
1323
|
-
message: globs.length === 0 ? "testFileGlobs is empty (SC\u2192Test cannot be verified)" : `
|
|
1369
|
+
message: globs.length === 0 ? "testFileGlobs is empty (SC\u2192Test cannot be verified)" : truncated ? `fileCount=${matchedCount} (truncated, limit=${scanResult.limit})` : `fileCount=${matchedCount}`,
|
|
1324
1370
|
details: {
|
|
1325
1371
|
globs,
|
|
1326
1372
|
excludeGlobs: exclude,
|
|
1327
1373
|
scenarioFiles: scenarioFiles.length,
|
|
1328
|
-
scMustHaveTest: config.validation.traceability.scMustHaveTest
|
|
1374
|
+
scMustHaveTest: config.validation.traceability.scMustHaveTest,
|
|
1375
|
+
truncated,
|
|
1376
|
+
limit: scanResult.limit
|
|
1329
1377
|
}
|
|
1330
1378
|
});
|
|
1331
1379
|
} catch (error2) {
|
|
@@ -1334,7 +1382,12 @@ async function createDoctorData(options) {
|
|
|
1334
1382
|
severity: "error",
|
|
1335
1383
|
title: "Test file globs",
|
|
1336
1384
|
message: "Glob scan failed (invalid pattern or filesystem error)",
|
|
1337
|
-
details: {
|
|
1385
|
+
details: {
|
|
1386
|
+
globs,
|
|
1387
|
+
excludeGlobs: exclude,
|
|
1388
|
+
limit: DEFAULT_GLOB_FILE_LIMIT,
|
|
1389
|
+
error: String(error2)
|
|
1390
|
+
}
|
|
1338
1391
|
});
|
|
1339
1392
|
}
|
|
1340
1393
|
return {
|
|
@@ -1368,8 +1421,10 @@ async function buildOutDirCollisionCheck(root) {
|
|
|
1368
1421
|
(collisionRoot) => toRelativePath(result.monorepoRoot, collisionRoot)
|
|
1369
1422
|
).sort((a, b) => a.localeCompare(b))
|
|
1370
1423
|
})).sort((a, b) => a.outDir.localeCompare(b.outDir));
|
|
1371
|
-
const
|
|
1372
|
-
const
|
|
1424
|
+
const truncated = result.scan.truncated;
|
|
1425
|
+
const severity = collisions.length > 0 || truncated ? "warning" : "ok";
|
|
1426
|
+
const messageBase = collisions.length > 0 ? `outDir collision detected (count=${collisions.length})` : `outDir collision not detected (configs=${configRoots.length})`;
|
|
1427
|
+
const message = truncated ? `${messageBase}; scan truncated (collected=${result.scan.matchedFileCount}, limit=${result.scan.limit})` : messageBase;
|
|
1373
1428
|
return {
|
|
1374
1429
|
id: "output.outDirCollision",
|
|
1375
1430
|
severity,
|
|
@@ -1378,7 +1433,8 @@ async function buildOutDirCollisionCheck(root) {
|
|
|
1378
1433
|
details: {
|
|
1379
1434
|
monorepoRoot: relativeRoot,
|
|
1380
1435
|
configRoots,
|
|
1381
|
-
collisions
|
|
1436
|
+
collisions,
|
|
1437
|
+
scan: result.scan
|
|
1382
1438
|
}
|
|
1383
1439
|
};
|
|
1384
1440
|
} catch (error2) {
|
|
@@ -1393,10 +1449,11 @@ async function buildOutDirCollisionCheck(root) {
|
|
|
1393
1449
|
}
|
|
1394
1450
|
async function detectOutDirCollisions(root) {
|
|
1395
1451
|
const monorepoRoot = await findMonorepoRoot(root);
|
|
1396
|
-
const
|
|
1452
|
+
const configScan = await collectFilesByGlobs(monorepoRoot, {
|
|
1397
1453
|
globs: ["**/qfai.config.yaml"],
|
|
1398
1454
|
ignore: DEFAULT_CONFIG_SEARCH_IGNORE_GLOBS
|
|
1399
1455
|
});
|
|
1456
|
+
const configPaths = configScan.files;
|
|
1400
1457
|
const configRoots = Array.from(
|
|
1401
1458
|
new Set(configPaths.map((configPath) => path10.dirname(configPath)))
|
|
1402
1459
|
).sort((a, b) => a.localeCompare(b));
|
|
@@ -1417,7 +1474,16 @@ async function detectOutDirCollisions(root) {
|
|
|
1417
1474
|
});
|
|
1418
1475
|
}
|
|
1419
1476
|
}
|
|
1420
|
-
return {
|
|
1477
|
+
return {
|
|
1478
|
+
monorepoRoot,
|
|
1479
|
+
configRoots,
|
|
1480
|
+
collisions,
|
|
1481
|
+
scan: {
|
|
1482
|
+
truncated: configScan.truncated,
|
|
1483
|
+
matchedFileCount: configScan.matchedFileCount,
|
|
1484
|
+
limit: configScan.limit
|
|
1485
|
+
}
|
|
1486
|
+
};
|
|
1421
1487
|
}
|
|
1422
1488
|
async function findMonorepoRoot(startDir) {
|
|
1423
1489
|
let current = path10.resolve(startDir);
|
|
@@ -3524,13 +3590,14 @@ async function createReportData(root, validation, configResult) {
|
|
|
3524
3590
|
issues: normalizedValidation.issues
|
|
3525
3591
|
};
|
|
3526
3592
|
}
|
|
3527
|
-
function formatReportMarkdown(data) {
|
|
3593
|
+
function formatReportMarkdown(data, options = {}) {
|
|
3528
3594
|
const lines = [];
|
|
3595
|
+
const baseUrl = normalizeBaseUrl(options.baseUrl);
|
|
3529
3596
|
lines.push("# QFAI Report");
|
|
3530
3597
|
lines.push("");
|
|
3531
3598
|
lines.push(`- \u751F\u6210\u65E5\u6642: ${data.generatedAt}`);
|
|
3532
|
-
lines.push(`- \u30EB\u30FC\u30C8: ${data.root}`);
|
|
3533
|
-
lines.push(`- \u8A2D\u5B9A: ${data.configPath}`);
|
|
3599
|
+
lines.push(`- \u30EB\u30FC\u30C8: ${formatPathLink(data.root, baseUrl)}`);
|
|
3600
|
+
lines.push(`- \u8A2D\u5B9A: ${formatPathLink(data.configPath, baseUrl)}`);
|
|
3534
3601
|
lines.push(`- \u7248: ${data.version}`);
|
|
3535
3602
|
lines.push("");
|
|
3536
3603
|
const severityOrder = {
|
|
@@ -3669,8 +3736,7 @@ function formatReportMarkdown(data) {
|
|
|
3669
3736
|
`#### ${item.severity.toUpperCase()} [${item.code}] ${item.message}`
|
|
3670
3737
|
);
|
|
3671
3738
|
if (item.file) {
|
|
3672
|
-
|
|
3673
|
-
out.push(`- file: ${item.file}${loc}`);
|
|
3739
|
+
out.push(`- file: ${formatPathWithLine(item.file, item.loc, baseUrl)}`);
|
|
3674
3740
|
}
|
|
3675
3741
|
if (item.rule) {
|
|
3676
3742
|
out.push(`- rule: ${item.rule}`);
|
|
@@ -3796,6 +3862,11 @@ function formatReportMarkdown(data) {
|
|
|
3796
3862
|
lines.push(
|
|
3797
3863
|
`- testFileCount: ${data.traceability.testFiles.matchedFileCount}`
|
|
3798
3864
|
);
|
|
3865
|
+
if (data.traceability.testFiles.truncated) {
|
|
3866
|
+
lines.push(
|
|
3867
|
+
`- testFileTruncated: true (limit=${data.traceability.testFiles.limit})`
|
|
3868
|
+
);
|
|
3869
|
+
}
|
|
3799
3870
|
if (data.traceability.sc.missingIds.length === 0) {
|
|
3800
3871
|
lines.push("- missingIds: (none)");
|
|
3801
3872
|
} else {
|
|
@@ -3805,7 +3876,8 @@ function formatReportMarkdown(data) {
|
|
|
3805
3876
|
if (files.length === 0) {
|
|
3806
3877
|
return id;
|
|
3807
3878
|
}
|
|
3808
|
-
|
|
3879
|
+
const formattedFiles = files.map((file) => formatPathLink(file, baseUrl));
|
|
3880
|
+
return `${id} (${formattedFiles.join(", ")})`;
|
|
3809
3881
|
});
|
|
3810
3882
|
lines.push(`- missingIds: ${missingWithSources.join(", ")}`);
|
|
3811
3883
|
}
|
|
@@ -3822,7 +3894,8 @@ function formatReportMarkdown(data) {
|
|
|
3822
3894
|
if (refs.length === 0) {
|
|
3823
3895
|
lines.push(`- ${scId}: (none)`);
|
|
3824
3896
|
} else {
|
|
3825
|
-
|
|
3897
|
+
const formattedRefs = refs.map((ref) => formatPathLink(ref, baseUrl));
|
|
3898
|
+
lines.push(`- ${scId}: ${formattedRefs.join(", ")}`);
|
|
3826
3899
|
}
|
|
3827
3900
|
}
|
|
3828
3901
|
}
|
|
@@ -3837,8 +3910,9 @@ function formatReportMarkdown(data) {
|
|
|
3837
3910
|
} else {
|
|
3838
3911
|
for (const item of specScIssues) {
|
|
3839
3912
|
const location = item.file ?? "(unknown)";
|
|
3913
|
+
const formattedLocation = location === "(unknown)" ? location : formatPathLink(location, baseUrl);
|
|
3840
3914
|
const refs = item.refs && item.refs.length > 0 ? item.refs.join(", ") : item.message;
|
|
3841
|
-
lines.push(`- ${
|
|
3915
|
+
lines.push(`- ${formattedLocation}: ${refs}`);
|
|
3842
3916
|
}
|
|
3843
3917
|
}
|
|
3844
3918
|
lines.push("");
|
|
@@ -3850,7 +3924,7 @@ function formatReportMarkdown(data) {
|
|
|
3850
3924
|
} else {
|
|
3851
3925
|
for (const spot of hotspots) {
|
|
3852
3926
|
lines.push(
|
|
3853
|
-
`- ${spot.file}: total ${spot.total} (error ${spot.error} / warning ${spot.warning} / info ${spot.info})`
|
|
3927
|
+
`- ${formatPathLink(spot.file, baseUrl)}: total ${spot.total} (error ${spot.error} / warning ${spot.warning} / info ${spot.info})`
|
|
3854
3928
|
);
|
|
3855
3929
|
}
|
|
3856
3930
|
}
|
|
@@ -4007,6 +4081,41 @@ function formatMarkdownTable(headers, rows) {
|
|
|
4007
4081
|
const separator = `| ${widths.map((width) => "-".repeat(width)).join(" | ")} |`;
|
|
4008
4082
|
return [formatRow(headers), separator, ...rows.map(formatRow)];
|
|
4009
4083
|
}
|
|
4084
|
+
function normalizeBaseUrl(value) {
|
|
4085
|
+
if (!value) {
|
|
4086
|
+
return void 0;
|
|
4087
|
+
}
|
|
4088
|
+
const trimmed = value.trim();
|
|
4089
|
+
if (!trimmed) {
|
|
4090
|
+
return void 0;
|
|
4091
|
+
}
|
|
4092
|
+
return trimmed.replace(/\/+$/, "");
|
|
4093
|
+
}
|
|
4094
|
+
function formatPathLink(value, baseUrl) {
|
|
4095
|
+
if (!baseUrl) {
|
|
4096
|
+
return value;
|
|
4097
|
+
}
|
|
4098
|
+
if (value === ".") {
|
|
4099
|
+
return `[${value}](${baseUrl})`;
|
|
4100
|
+
}
|
|
4101
|
+
const encoded = encodePathForUrl(value);
|
|
4102
|
+
if (!encoded) {
|
|
4103
|
+
return value;
|
|
4104
|
+
}
|
|
4105
|
+
return `[${value}](${baseUrl}/${encoded})`;
|
|
4106
|
+
}
|
|
4107
|
+
function formatPathWithLine(value, loc, baseUrl) {
|
|
4108
|
+
const link = formatPathLink(value, baseUrl);
|
|
4109
|
+
const line = loc?.line ? `:${loc.line}` : "";
|
|
4110
|
+
return `${link}${line}`;
|
|
4111
|
+
}
|
|
4112
|
+
function encodePathForUrl(value) {
|
|
4113
|
+
const normalized = value.replace(/\\/g, "/");
|
|
4114
|
+
if (normalized === ".") {
|
|
4115
|
+
return "";
|
|
4116
|
+
}
|
|
4117
|
+
return normalized.split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
4118
|
+
}
|
|
4010
4119
|
function toSortedArray2(values) {
|
|
4011
4120
|
return Array.from(values).sort((a, b) => a.localeCompare(b));
|
|
4012
4121
|
}
|
|
@@ -4060,6 +4169,16 @@ function buildHotspots(issues) {
|
|
|
4060
4169
|
);
|
|
4061
4170
|
}
|
|
4062
4171
|
|
|
4172
|
+
// src/cli/lib/warnings.ts
|
|
4173
|
+
function warnIfTruncated(scan, context) {
|
|
4174
|
+
if (!scan.truncated) {
|
|
4175
|
+
return;
|
|
4176
|
+
}
|
|
4177
|
+
warn(
|
|
4178
|
+
`[warn] ${context}: file scan truncated: collected ${scan.matchedFileCount} files (limit ${scan.limit})`
|
|
4179
|
+
);
|
|
4180
|
+
}
|
|
4181
|
+
|
|
4063
4182
|
// src/cli/commands/report.ts
|
|
4064
4183
|
async function runReport(options) {
|
|
4065
4184
|
const root = path20.resolve(options.root);
|
|
@@ -4103,7 +4222,8 @@ async function runReport(options) {
|
|
|
4103
4222
|
}
|
|
4104
4223
|
}
|
|
4105
4224
|
const data = await createReportData(root, validation, configResult);
|
|
4106
|
-
|
|
4225
|
+
warnIfTruncated(data.traceability.testFiles, "report");
|
|
4226
|
+
const output = options.format === "json" ? formatReportJson(data) : options.baseUrl ? formatReportMarkdown(data, { baseUrl: options.baseUrl }) : formatReportMarkdown(data);
|
|
4107
4227
|
const outRoot = resolvePath(root, configResult.config, "outDir");
|
|
4108
4228
|
const defaultOut = options.format === "json" ? path20.join(outRoot, "report.json") : path20.join(outRoot, "report.md");
|
|
4109
4229
|
const out = options.outPath ?? defaultOut;
|
|
@@ -4200,6 +4320,7 @@ async function runValidate(options) {
|
|
|
4200
4320
|
const configResult = await loadConfig(root);
|
|
4201
4321
|
const result = await validateProject(root, configResult);
|
|
4202
4322
|
const normalized = normalizeValidationResult(root, result);
|
|
4323
|
+
warnIfTruncated(normalized.traceability.testFiles, "validate");
|
|
4203
4324
|
const failOn = resolveFailOn(options, configResult.config.validation.failOn);
|
|
4204
4325
|
const willFail = shouldFail(normalized, failOn);
|
|
4205
4326
|
const format = options.format ?? "text";
|
|
@@ -4458,6 +4579,17 @@ function parseArgs(argv, cwd) {
|
|
|
4458
4579
|
case "--run-validate":
|
|
4459
4580
|
options.reportRunValidate = true;
|
|
4460
4581
|
break;
|
|
4582
|
+
case "--base-url": {
|
|
4583
|
+
const next = readOptionValue(args, i);
|
|
4584
|
+
if (next === null) {
|
|
4585
|
+
invalid = true;
|
|
4586
|
+
options.help = true;
|
|
4587
|
+
break;
|
|
4588
|
+
}
|
|
4589
|
+
options.reportBaseUrl = next;
|
|
4590
|
+
i += 1;
|
|
4591
|
+
break;
|
|
4592
|
+
}
|
|
4461
4593
|
case "--help":
|
|
4462
4594
|
case "-h":
|
|
4463
4595
|
options.help = true;
|
|
@@ -4554,6 +4686,7 @@ async function run(argv, cwd) {
|
|
|
4554
4686
|
format: options.reportFormat,
|
|
4555
4687
|
...options.reportOut !== void 0 ? { outPath: options.reportOut } : {},
|
|
4556
4688
|
...options.reportIn !== void 0 ? { inputPath: options.reportIn } : {},
|
|
4689
|
+
...options.reportBaseUrl !== void 0 ? { baseUrl: options.reportBaseUrl } : {},
|
|
4557
4690
|
...options.reportRunValidate ? { runValidate: true } : {}
|
|
4558
4691
|
});
|
|
4559
4692
|
}
|
|
@@ -4603,6 +4736,7 @@ Options:
|
|
|
4603
4736
|
--out <path> report/doctor: \u51FA\u529B\u5148
|
|
4604
4737
|
--in <path> report: validate.json \u306E\u5165\u529B\u5148\uFF08config\u3088\u308A\u512A\u5148\uFF09
|
|
4605
4738
|
--run-validate report: validate \u3092\u5B9F\u884C\u3057\u3066\u304B\u3089 report \u3092\u751F\u6210
|
|
4739
|
+
--base-url <url> report: \u30D1\u30B9\u3092\u30EA\u30F3\u30AF\u5316\u3059\u308B\u57FA\u6E96URL
|
|
4606
4740
|
-h, --help \u30D8\u30EB\u30D7\u8868\u793A
|
|
4607
4741
|
`;
|
|
4608
4742
|
}
|