executable-stories-formatters 0.13.0 → 0.14.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/dist/cli.js +426 -103
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +43 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +43 -52
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1237,7 +1237,7 @@ var CucumberJsonFormatter = class {
|
|
|
1237
1237
|
/**
|
|
1238
1238
|
* Build a single step.
|
|
1239
1239
|
*/
|
|
1240
|
-
buildStep(step, result,
|
|
1240
|
+
buildStep(step, result, line2, index, attachments, isLastStep, hasFailedStep) {
|
|
1241
1241
|
const keyword = this.options.keywordSpacing ? `${step.keyword} ` : step.keyword;
|
|
1242
1242
|
const stepResult = this.buildStepResult(result);
|
|
1243
1243
|
const embeddings = this.buildEmbeddings(attachments, result, isLastStep, hasFailedStep);
|
|
@@ -1245,7 +1245,7 @@ var CucumberJsonFormatter = class {
|
|
|
1245
1245
|
embeddings.push(...screenshotEmbeddings);
|
|
1246
1246
|
const jsonStep = {
|
|
1247
1247
|
keyword,
|
|
1248
|
-
line,
|
|
1248
|
+
line: line2,
|
|
1249
1249
|
name: step.text,
|
|
1250
1250
|
result: stepResult
|
|
1251
1251
|
};
|
|
@@ -15792,8 +15792,8 @@ var JUnitFormatter = class {
|
|
|
15792
15792
|
case "section": {
|
|
15793
15793
|
const lines = [];
|
|
15794
15794
|
lines.push(`${indent}${entry.title}:`);
|
|
15795
|
-
for (const
|
|
15796
|
-
lines.push(`${indent} ${
|
|
15795
|
+
for (const line2 of entry.markdown.split("\n")) {
|
|
15796
|
+
lines.push(`${indent} ${line2}`);
|
|
15797
15797
|
}
|
|
15798
15798
|
return lines.join("\n");
|
|
15799
15799
|
}
|
|
@@ -15802,8 +15802,8 @@ var JUnitFormatter = class {
|
|
|
15802
15802
|
if (entry.title) {
|
|
15803
15803
|
lines.push(`${indent}${entry.title}:`);
|
|
15804
15804
|
}
|
|
15805
|
-
for (const
|
|
15806
|
-
lines.push(`${indent} ${
|
|
15805
|
+
for (const line2 of entry.code.split("\n")) {
|
|
15806
|
+
lines.push(`${indent} ${line2}`);
|
|
15807
15807
|
}
|
|
15808
15808
|
return lines.join("\n");
|
|
15809
15809
|
}
|
|
@@ -15815,8 +15815,8 @@ var JUnitFormatter = class {
|
|
|
15815
15815
|
const dataStr = JSON.stringify(entry.data, null, 2);
|
|
15816
15816
|
const lines = [];
|
|
15817
15817
|
lines.push(`${indent}[${entry.type}]:`);
|
|
15818
|
-
for (const
|
|
15819
|
-
lines.push(`${indent} ${
|
|
15818
|
+
for (const line2 of dataStr.split("\n")) {
|
|
15819
|
+
lines.push(`${indent} ${line2}`);
|
|
15820
15820
|
}
|
|
15821
15821
|
return lines.join("\n");
|
|
15822
15822
|
}
|
|
@@ -15862,7 +15862,9 @@ var MarkdownFormatter = class {
|
|
|
15862
15862
|
ticketUrlTemplate: options.ticketUrlTemplate,
|
|
15863
15863
|
traceUrlTemplate: options.traceUrlTemplate,
|
|
15864
15864
|
includeSourceLinks: options.includeSourceLinks ?? true,
|
|
15865
|
-
customRenderers: options.customRenderers
|
|
15865
|
+
customRenderers: options.customRenderers,
|
|
15866
|
+
scenarioAnchor: options.scenarioAnchor,
|
|
15867
|
+
scenarioBadge: options.scenarioBadge
|
|
15866
15868
|
};
|
|
15867
15869
|
}
|
|
15868
15870
|
/**
|
|
@@ -16049,6 +16051,11 @@ var MarkdownFormatter = class {
|
|
|
16049
16051
|
* Render a single scenario.
|
|
16050
16052
|
*/
|
|
16051
16053
|
renderScenario(lines, tc) {
|
|
16054
|
+
const anchorId = this.options.scenarioAnchor?.(tc);
|
|
16055
|
+
if (anchorId) {
|
|
16056
|
+
lines.push(`<a id="${anchorId}"></a>`);
|
|
16057
|
+
lines.push("");
|
|
16058
|
+
}
|
|
16052
16059
|
if (this.options.customRenderers?.renderScenarioHeader) {
|
|
16053
16060
|
const custom = this.options.customRenderers.renderScenarioHeader(tc);
|
|
16054
16061
|
if (custom !== null) {
|
|
@@ -16064,6 +16071,10 @@ var MarkdownFormatter = class {
|
|
|
16064
16071
|
icon = this.getStatusIcon(tc.status) + " ";
|
|
16065
16072
|
}
|
|
16066
16073
|
lines.push(`${headingPrefix} ${icon}${tc.story.scenario}`);
|
|
16074
|
+
const badge2 = this.options.scenarioBadge?.(tc);
|
|
16075
|
+
if (badge2) {
|
|
16076
|
+
lines.push(badge2);
|
|
16077
|
+
}
|
|
16067
16078
|
if (this.options.includeSourceLinks && this.options.permalinkBaseUrl && tc.sourceFile !== "unknown") {
|
|
16068
16079
|
const permalink = this.buildPermalink(tc);
|
|
16069
16080
|
lines.push(`Source: [${tc.sourceFile}](${permalink})`);
|
|
@@ -16138,8 +16149,8 @@ var MarkdownFormatter = class {
|
|
|
16138
16149
|
buildPermalink(tc) {
|
|
16139
16150
|
const base = this.options.permalinkBaseUrl.replace(/\/$/, "");
|
|
16140
16151
|
const file = tc.sourceFile;
|
|
16141
|
-
const
|
|
16142
|
-
return `${base}/${file}${
|
|
16152
|
+
const line2 = tc.sourceLine > 0 ? `#L${tc.sourceLine}` : "";
|
|
16153
|
+
return `${base}/${file}${line2}`;
|
|
16143
16154
|
}
|
|
16144
16155
|
/**
|
|
16145
16156
|
* Render a step.
|
|
@@ -16207,8 +16218,8 @@ var MarkdownFormatter = class {
|
|
|
16207
16218
|
lines.push(`${indent}`);
|
|
16208
16219
|
}
|
|
16209
16220
|
lines.push(`${indent}\`\`\`${entry.lang ?? ""}`);
|
|
16210
|
-
for (const
|
|
16211
|
-
lines.push(`${indent}${
|
|
16221
|
+
for (const line2 of (entry.content ?? "").split("\n")) {
|
|
16222
|
+
lines.push(`${indent}${line2}`);
|
|
16212
16223
|
}
|
|
16213
16224
|
lines.push(`${indent}\`\`\``);
|
|
16214
16225
|
lines.push(`${indent}`);
|
|
@@ -16231,8 +16242,8 @@ var MarkdownFormatter = class {
|
|
|
16231
16242
|
case "section":
|
|
16232
16243
|
lines.push(`${indent}**${entry.title}**`);
|
|
16233
16244
|
lines.push(`${indent}`);
|
|
16234
|
-
for (const
|
|
16235
|
-
lines.push(`${indent}${
|
|
16245
|
+
for (const line2 of (entry.markdown ?? "").split("\n")) {
|
|
16246
|
+
lines.push(`${indent}${line2}`);
|
|
16236
16247
|
}
|
|
16237
16248
|
lines.push(`${indent}`);
|
|
16238
16249
|
break;
|
|
@@ -16241,8 +16252,8 @@ var MarkdownFormatter = class {
|
|
|
16241
16252
|
lines.push(`${indent}**${entry.title}**`);
|
|
16242
16253
|
}
|
|
16243
16254
|
lines.push(`${indent}\`\`\`mermaid`);
|
|
16244
|
-
for (const
|
|
16245
|
-
lines.push(`${indent}${
|
|
16255
|
+
for (const line2 of (entry.code ?? "").split("\n")) {
|
|
16256
|
+
lines.push(`${indent}${line2}`);
|
|
16246
16257
|
}
|
|
16247
16258
|
lines.push(`${indent}\`\`\``);
|
|
16248
16259
|
break;
|
|
@@ -16272,8 +16283,8 @@ var MarkdownFormatter = class {
|
|
|
16272
16283
|
lines.push(`${indent}<summary>${htmlLabel}</summary>`);
|
|
16273
16284
|
lines.push(`${indent}`);
|
|
16274
16285
|
lines.push(`${indent}\`\`\`html`);
|
|
16275
|
-
for (const
|
|
16276
|
-
lines.push(`${indent}${
|
|
16286
|
+
for (const line2 of (entry.content ?? "").split("\n")) {
|
|
16287
|
+
lines.push(`${indent}${line2}`);
|
|
16277
16288
|
}
|
|
16278
16289
|
lines.push(`${indent}\`\`\``);
|
|
16279
16290
|
lines.push(`${indent}`);
|
|
@@ -16295,8 +16306,8 @@ var MarkdownFormatter = class {
|
|
|
16295
16306
|
lines.push(`${indent}**[${entry.type}]**`);
|
|
16296
16307
|
lines.push(`${indent}`);
|
|
16297
16308
|
lines.push(`${indent}\`\`\`json`);
|
|
16298
|
-
for (const
|
|
16299
|
-
lines.push(`${indent}${
|
|
16309
|
+
for (const line2 of JSON.stringify(entry.data ?? null, null, 2).split("\n")) {
|
|
16310
|
+
lines.push(`${indent}${line2}`);
|
|
16300
16311
|
}
|
|
16301
16312
|
lines.push(`${indent}\`\`\``);
|
|
16302
16313
|
lines.push(`${indent}`);
|
|
@@ -16807,60 +16818,60 @@ function buildStepArguments(step, stepLine) {
|
|
|
16807
16818
|
}
|
|
16808
16819
|
return {};
|
|
16809
16820
|
}
|
|
16810
|
-
function docEntryToDocString(doc,
|
|
16821
|
+
function docEntryToDocString(doc, line2) {
|
|
16811
16822
|
switch (doc.kind) {
|
|
16812
16823
|
case "code":
|
|
16813
16824
|
return {
|
|
16814
|
-
location: { line },
|
|
16825
|
+
location: { line: line2 },
|
|
16815
16826
|
mediaType: doc.lang,
|
|
16816
16827
|
content: doc.content,
|
|
16817
16828
|
delimiter: '"""'
|
|
16818
16829
|
};
|
|
16819
16830
|
case "note":
|
|
16820
16831
|
return {
|
|
16821
|
-
location: { line },
|
|
16832
|
+
location: { line: line2 },
|
|
16822
16833
|
mediaType: "text/plain",
|
|
16823
16834
|
content: doc.text,
|
|
16824
16835
|
delimiter: '"""'
|
|
16825
16836
|
};
|
|
16826
16837
|
case "section":
|
|
16827
16838
|
return {
|
|
16828
|
-
location: { line },
|
|
16839
|
+
location: { line: line2 },
|
|
16829
16840
|
mediaType: "text/markdown",
|
|
16830
16841
|
content: doc.markdown,
|
|
16831
16842
|
delimiter: '"""'
|
|
16832
16843
|
};
|
|
16833
16844
|
case "mermaid":
|
|
16834
16845
|
return {
|
|
16835
|
-
location: { line },
|
|
16846
|
+
location: { line: line2 },
|
|
16836
16847
|
mediaType: "text/x-mermaid",
|
|
16837
16848
|
content: doc.code,
|
|
16838
16849
|
delimiter: '"""'
|
|
16839
16850
|
};
|
|
16840
16851
|
case "kv":
|
|
16841
16852
|
return {
|
|
16842
|
-
location: { line },
|
|
16853
|
+
location: { line: line2 },
|
|
16843
16854
|
mediaType: "text/plain",
|
|
16844
16855
|
content: `${doc.label}: ${typeof doc.value === "string" ? doc.value : JSON.stringify(doc.value)}`,
|
|
16845
16856
|
delimiter: '"""'
|
|
16846
16857
|
};
|
|
16847
16858
|
case "link":
|
|
16848
16859
|
return {
|
|
16849
|
-
location: { line },
|
|
16860
|
+
location: { line: line2 },
|
|
16850
16861
|
mediaType: "text/markdown",
|
|
16851
16862
|
content: `[${doc.label}](${doc.url})`,
|
|
16852
16863
|
delimiter: '"""'
|
|
16853
16864
|
};
|
|
16854
16865
|
case "custom":
|
|
16855
16866
|
return {
|
|
16856
|
-
location: { line },
|
|
16867
|
+
location: { line: line2 },
|
|
16857
16868
|
mediaType: "application/json",
|
|
16858
16869
|
content: JSON.stringify(doc.data, null, 2),
|
|
16859
16870
|
delimiter: '"""'
|
|
16860
16871
|
};
|
|
16861
16872
|
case "tag":
|
|
16862
16873
|
return {
|
|
16863
|
-
location: { line },
|
|
16874
|
+
location: { line: line2 },
|
|
16864
16875
|
mediaType: "text/plain",
|
|
16865
16876
|
content: doc.names.map((n) => `@${n}`).join(" "),
|
|
16866
16877
|
delimiter: '"""'
|
|
@@ -16870,18 +16881,18 @@ function docEntryToDocString(doc, line) {
|
|
|
16870
16881
|
return void 0;
|
|
16871
16882
|
}
|
|
16872
16883
|
}
|
|
16873
|
-
function buildDataTable(table2,
|
|
16884
|
+
function buildDataTable(table2, line2) {
|
|
16874
16885
|
const rows = [];
|
|
16875
16886
|
rows.push({
|
|
16876
|
-
location: { line },
|
|
16887
|
+
location: { line: line2 },
|
|
16877
16888
|
cells: table2.columns.map((col) => ({
|
|
16878
|
-
location: { line },
|
|
16889
|
+
location: { line: line2 },
|
|
16879
16890
|
value: col
|
|
16880
16891
|
})),
|
|
16881
16892
|
id: ""
|
|
16882
16893
|
});
|
|
16883
16894
|
for (let r = 0; r < table2.rows.length; r++) {
|
|
16884
|
-
const rowLine =
|
|
16895
|
+
const rowLine = line2 + 1 + r;
|
|
16885
16896
|
rows.push({
|
|
16886
16897
|
location: { line: rowLine },
|
|
16887
16898
|
cells: table2.rows[r].map((cell) => ({
|
|
@@ -16892,7 +16903,7 @@ function buildDataTable(table2, line) {
|
|
|
16892
16903
|
});
|
|
16893
16904
|
}
|
|
16894
16905
|
return {
|
|
16895
|
-
location: { line },
|
|
16906
|
+
location: { line: line2 },
|
|
16896
16907
|
rows
|
|
16897
16908
|
};
|
|
16898
16909
|
}
|
|
@@ -18444,17 +18455,17 @@ ${body}`;
|
|
|
18444
18455
|
return humanizeSourceFile([...sourceFiles][0]) || this.title;
|
|
18445
18456
|
}
|
|
18446
18457
|
buildFrontmatter(run) {
|
|
18447
|
-
const
|
|
18458
|
+
const badge2 = _AstroFormatter.computeBadge(run.testCases);
|
|
18448
18459
|
const count2 = run.testCases.length;
|
|
18449
|
-
const description = `${count2} scenario${count2 !== 1 ? "s" : ""} \u2014 ${
|
|
18460
|
+
const description = `${count2} scenario${count2 !== 1 ? "s" : ""} \u2014 ${badge2.text.toLowerCase()}`;
|
|
18450
18461
|
const lines = [
|
|
18451
18462
|
"---",
|
|
18452
18463
|
`title: ${yamlScalar(this.deriveTitle(run))}`,
|
|
18453
18464
|
`description: ${description}`,
|
|
18454
18465
|
"sidebar:",
|
|
18455
18466
|
" badge:",
|
|
18456
|
-
` text: ${
|
|
18457
|
-
` variant: ${
|
|
18467
|
+
` text: ${badge2.text}`,
|
|
18468
|
+
` variant: ${badge2.variant}`,
|
|
18458
18469
|
"---"
|
|
18459
18470
|
];
|
|
18460
18471
|
return lines.join("\n");
|
|
@@ -18910,12 +18921,16 @@ function groupBy7(items, keyFn) {
|
|
|
18910
18921
|
import * as fs5 from "fs";
|
|
18911
18922
|
import * as path6 from "path";
|
|
18912
18923
|
var SKIP_PREFIXES = ["http://", "https://", "data:", "#"];
|
|
18913
|
-
function
|
|
18924
|
+
function isRemoteRef(src) {
|
|
18914
18925
|
const trimmed = src.trim();
|
|
18915
|
-
|
|
18916
|
-
|
|
18917
|
-
|
|
18918
|
-
|
|
18926
|
+
return SKIP_PREFIXES.some((prefix) => trimmed.startsWith(prefix));
|
|
18927
|
+
}
|
|
18928
|
+
function isAbsoluteRef(src) {
|
|
18929
|
+
const trimmed = src.trim();
|
|
18930
|
+
return path6.posix.isAbsolute(trimmed) || path6.win32.isAbsolute(trimmed);
|
|
18931
|
+
}
|
|
18932
|
+
function isRelativeLocalPath(src) {
|
|
18933
|
+
return !isRemoteRef(src) && !isAbsoluteRef(src);
|
|
18919
18934
|
}
|
|
18920
18935
|
function stripCodeContent(markdown) {
|
|
18921
18936
|
let result = markdown.replace(/^[ \t]*(`{3,}|~{3,})[^\n]*\n[\s\S]*?^[ \t]*\1\s*$/gm, "");
|
|
@@ -18931,21 +18946,21 @@ function scanMarkdownAssets(markdown) {
|
|
|
18931
18946
|
let match;
|
|
18932
18947
|
while ((match = mdImageRe.exec(stripped)) !== null) {
|
|
18933
18948
|
const src = match[1].trim();
|
|
18934
|
-
if (
|
|
18949
|
+
if (!isRemoteRef(src)) {
|
|
18935
18950
|
found.add(src);
|
|
18936
18951
|
}
|
|
18937
18952
|
}
|
|
18938
18953
|
const htmlSrcRe = /<(?:img|source|video)[^>]+\bsrc=["']([^"']+)["'][^>]*>/gi;
|
|
18939
18954
|
while ((match = htmlSrcRe.exec(stripped)) !== null) {
|
|
18940
18955
|
const src = match[1].trim();
|
|
18941
|
-
if (
|
|
18956
|
+
if (!isRemoteRef(src)) {
|
|
18942
18957
|
found.add(src);
|
|
18943
18958
|
}
|
|
18944
18959
|
}
|
|
18945
18960
|
const posterRe = /<video[^>]+\bposter=["']([^"']+)["'][^>]*>/gi;
|
|
18946
18961
|
while ((match = posterRe.exec(stripped)) !== null) {
|
|
18947
18962
|
const src = match[1].trim();
|
|
18948
|
-
if (
|
|
18963
|
+
if (!isRemoteRef(src)) {
|
|
18949
18964
|
found.add(src);
|
|
18950
18965
|
}
|
|
18951
18966
|
}
|
|
@@ -18971,48 +18986,21 @@ function isCode(segment) {
|
|
|
18971
18986
|
const trimmed = segment.trimStart();
|
|
18972
18987
|
return trimmed.startsWith("`") || trimmed.startsWith("~") || trimmed.startsWith("<pre") || trimmed.startsWith("<code");
|
|
18973
18988
|
}
|
|
18989
|
+
function resolveRewrite(trimmed, assetsBaseUrl, pathMap) {
|
|
18990
|
+
if (isRemoteRef(trimmed)) return null;
|
|
18991
|
+
if (pathMap) {
|
|
18992
|
+
const mapped = pathMap.get(trimmed);
|
|
18993
|
+
return mapped === void 0 ? null : `${assetsBaseUrl}/${mapped}`;
|
|
18994
|
+
}
|
|
18995
|
+
if (!isRelativeLocalPath(trimmed)) return null;
|
|
18996
|
+
return `${assetsBaseUrl}/${trimmed}`;
|
|
18997
|
+
}
|
|
18974
18998
|
function rewriteProseSegment(prose, assetsBaseUrl, pathMap) {
|
|
18975
|
-
|
|
18976
|
-
|
|
18977
|
-
|
|
18978
|
-
|
|
18979
|
-
|
|
18980
|
-
if (!isLocalPath(trimmed)) return full;
|
|
18981
|
-
if (pathMap) {
|
|
18982
|
-
const mapped = pathMap.get(trimmed);
|
|
18983
|
-
if (mapped === void 0) return full;
|
|
18984
|
-
return `${pre}${assetsBaseUrl}/${mapped}${post}`;
|
|
18985
|
-
}
|
|
18986
|
-
return `${pre}${assetsBaseUrl}/${trimmed}${post}`;
|
|
18987
|
-
}
|
|
18988
|
-
);
|
|
18989
|
-
result = result.replace(
|
|
18990
|
-
/(<(?:img|source|video)[^>]+\bsrc=["'])([^"']+)(["'][^>]*>)/gi,
|
|
18991
|
-
(full, pre, src, post) => {
|
|
18992
|
-
const trimmed = src.trim();
|
|
18993
|
-
if (!isLocalPath(trimmed)) return full;
|
|
18994
|
-
if (pathMap) {
|
|
18995
|
-
const mapped = pathMap.get(trimmed);
|
|
18996
|
-
if (mapped === void 0) return full;
|
|
18997
|
-
return `${pre}${assetsBaseUrl}/${mapped}${post}`;
|
|
18998
|
-
}
|
|
18999
|
-
return `${pre}${assetsBaseUrl}/${trimmed}${post}`;
|
|
19000
|
-
}
|
|
19001
|
-
);
|
|
19002
|
-
result = result.replace(
|
|
19003
|
-
/(<video[^>]+\bposter=["'])([^"']+)(["'][^>]*>)/gi,
|
|
19004
|
-
(full, pre, src, post) => {
|
|
19005
|
-
const trimmed = src.trim();
|
|
19006
|
-
if (!isLocalPath(trimmed)) return full;
|
|
19007
|
-
if (pathMap) {
|
|
19008
|
-
const mapped = pathMap.get(trimmed);
|
|
19009
|
-
if (mapped === void 0) return full;
|
|
19010
|
-
return `${pre}${assetsBaseUrl}/${mapped}${post}`;
|
|
19011
|
-
}
|
|
19012
|
-
return `${pre}${assetsBaseUrl}/${trimmed}${post}`;
|
|
19013
|
-
}
|
|
19014
|
-
);
|
|
19015
|
-
return result;
|
|
18999
|
+
const rewrite = (full, pre, src, post) => {
|
|
19000
|
+
const target = resolveRewrite(src.trim(), assetsBaseUrl, pathMap);
|
|
19001
|
+
return target === null ? full : `${pre}${target}${post}`;
|
|
19002
|
+
};
|
|
19003
|
+
return prose.replace(/(!\[[^\]]*\]\()([^)"'\s]+)((?:\s+["'][^"']*["'])?\s*\))/g, rewrite).replace(/(<(?:img|source|video)[^>]+\bsrc=["'])([^"']+)(["'][^>]*>)/gi, rewrite).replace(/(<video[^>]+\bposter=["'])([^"']+)(["'][^>]*>)/gi, rewrite);
|
|
19016
19004
|
}
|
|
19017
19005
|
function rewriteAssetPaths(markdown, assetsBaseUrl, pathMap) {
|
|
19018
19006
|
return splitByCode(markdown).map((seg) => isCode(seg) ? seg : rewriteProseSegment(seg, assetsBaseUrl, pathMap)).join("");
|
|
@@ -19029,8 +19017,9 @@ function copyMarkdownAssets(options) {
|
|
|
19029
19017
|
const pathMap = /* @__PURE__ */ new Map();
|
|
19030
19018
|
const missing = [];
|
|
19031
19019
|
for (const ref of refs) {
|
|
19032
|
-
const absPath = path6.resolve(markdownDir, ref);
|
|
19020
|
+
const absPath = isAbsoluteRef(ref) ? ref : path6.resolve(markdownDir, ref);
|
|
19033
19021
|
if (!fs5.existsSync(absPath)) {
|
|
19022
|
+
if (isAbsoluteRef(ref)) continue;
|
|
19034
19023
|
if (!allowMissing) {
|
|
19035
19024
|
throw new Error(`Asset not found: ${absPath}`);
|
|
19036
19025
|
}
|
|
@@ -19112,6 +19101,47 @@ function startWatch(options, deps = {}) {
|
|
|
19112
19101
|
};
|
|
19113
19102
|
}
|
|
19114
19103
|
|
|
19104
|
+
// src/behavior-diff.ts
|
|
19105
|
+
function classifyStatusChange(baseline, current) {
|
|
19106
|
+
if (baseline === void 0) return "added";
|
|
19107
|
+
if (current === void 0) return "removed";
|
|
19108
|
+
if (baseline === current) return "unchanged";
|
|
19109
|
+
if (baseline === "passed" && current === "failed") return "regressed";
|
|
19110
|
+
if (baseline === "failed" && current === "passed") return "fixed";
|
|
19111
|
+
return "changed";
|
|
19112
|
+
}
|
|
19113
|
+
function scenarioMap(report) {
|
|
19114
|
+
const map = /* @__PURE__ */ new Map();
|
|
19115
|
+
for (const feature of report.features) {
|
|
19116
|
+
for (const scenario of feature.scenarios) {
|
|
19117
|
+
map.set(scenario.id, { scenario, sourceFile: feature.sourceFile });
|
|
19118
|
+
}
|
|
19119
|
+
}
|
|
19120
|
+
return map;
|
|
19121
|
+
}
|
|
19122
|
+
function diffStoryReports(baseline, current) {
|
|
19123
|
+
const base = scenarioMap(baseline);
|
|
19124
|
+
const curr = scenarioMap(current);
|
|
19125
|
+
const ids = [.../* @__PURE__ */ new Set([...base.keys(), ...curr.keys()])];
|
|
19126
|
+
const scenarios = ids.map((id) => {
|
|
19127
|
+
const b = base.get(id);
|
|
19128
|
+
const c = curr.get(id);
|
|
19129
|
+
const kind = classifyStatusChange(b?.scenario.status, c?.scenario.status);
|
|
19130
|
+
const meta = c ?? b;
|
|
19131
|
+
return {
|
|
19132
|
+
id,
|
|
19133
|
+
title: meta.scenario.title,
|
|
19134
|
+
sourceFile: meta.sourceFile,
|
|
19135
|
+
kind,
|
|
19136
|
+
baselineStatus: b?.scenario.status,
|
|
19137
|
+
currentStatus: c?.scenario.status
|
|
19138
|
+
};
|
|
19139
|
+
});
|
|
19140
|
+
const summary = { added: 0, removed: 0, regressed: 0, fixed: 0, changed: 0, unchanged: 0 };
|
|
19141
|
+
for (const s of scenarios) summary[s.kind] += 1;
|
|
19142
|
+
return { schemaVersion: "1.0", summary, scenarios };
|
|
19143
|
+
}
|
|
19144
|
+
|
|
19115
19145
|
// src/publishers/confluence.ts
|
|
19116
19146
|
function parseAdf(adf) {
|
|
19117
19147
|
let parsed;
|
|
@@ -19344,7 +19374,7 @@ async function updateDescription(issueKey, base, adf, headers, fetchFn) {
|
|
|
19344
19374
|
// src/converters/ndjson-parser.ts
|
|
19345
19375
|
function parseNdjson(ndjson) {
|
|
19346
19376
|
const lines = ndjson.trim().split("\n").filter(Boolean);
|
|
19347
|
-
const envelopes = lines.map((
|
|
19377
|
+
const envelopes = lines.map((line2) => JSON.parse(line2));
|
|
19348
19378
|
return parseEnvelopes(envelopes);
|
|
19349
19379
|
}
|
|
19350
19380
|
function parseEnvelopes(envelopes) {
|
|
@@ -21695,7 +21725,9 @@ var ReportGenerator = class {
|
|
|
21695
21725
|
permalinkBaseUrl: options.astro?.markdown?.permalinkBaseUrl,
|
|
21696
21726
|
ticketUrlTemplate: options.astro?.markdown?.ticketUrlTemplate,
|
|
21697
21727
|
traceUrlTemplate: options.astro?.markdown?.traceUrlTemplate,
|
|
21698
|
-
customRenderers: options.astro?.markdown?.customRenderers
|
|
21728
|
+
customRenderers: options.astro?.markdown?.customRenderers,
|
|
21729
|
+
scenarioAnchor: options.astro?.markdown?.scenarioAnchor,
|
|
21730
|
+
scenarioBadge: options.astro?.markdown?.scenarioBadge
|
|
21699
21731
|
}
|
|
21700
21732
|
},
|
|
21701
21733
|
assetMode: options.assetMode ?? "none",
|
|
@@ -22558,6 +22590,189 @@ async function importOpenApi(options) {
|
|
|
22558
22590
|
// src/build-docs.ts
|
|
22559
22591
|
import * as fs13 from "fs";
|
|
22560
22592
|
import * as path14 from "path";
|
|
22593
|
+
|
|
22594
|
+
// src/scenario-links.ts
|
|
22595
|
+
function scenarioAnchor(title) {
|
|
22596
|
+
return `scenario-${slugify(title)}`;
|
|
22597
|
+
}
|
|
22598
|
+
function buildScenarioLinks(report, options = {}) {
|
|
22599
|
+
const audienceSplit = options.audienceSplit ?? false;
|
|
22600
|
+
const baseUrl = (options.baseUrl ?? "/stories").replace(/\/$/, "");
|
|
22601
|
+
const scenarios = {};
|
|
22602
|
+
for (const feature of report.features) {
|
|
22603
|
+
const stem = slugify(cleanTestStem(feature.sourceFile));
|
|
22604
|
+
for (const scenario of feature.scenarios) {
|
|
22605
|
+
const audience = deriveAudience(feature.sourceFile, scenario.tags);
|
|
22606
|
+
const url = audienceSplit ? `${baseUrl}/${audience}/${stem}/` : `${baseUrl}/${stem}/`;
|
|
22607
|
+
const anchor = scenarioAnchor(scenario.title);
|
|
22608
|
+
scenarios[scenario.id] = {
|
|
22609
|
+
id: scenario.id,
|
|
22610
|
+
title: scenario.title,
|
|
22611
|
+
audience,
|
|
22612
|
+
status: scenario.status,
|
|
22613
|
+
sourceFile: feature.sourceFile,
|
|
22614
|
+
url,
|
|
22615
|
+
anchor,
|
|
22616
|
+
deepLink: `${url}#${anchor}`
|
|
22617
|
+
};
|
|
22618
|
+
}
|
|
22619
|
+
}
|
|
22620
|
+
return { schemaVersion: "1.0", runId: report.runId, baseUrl, scenarios };
|
|
22621
|
+
}
|
|
22622
|
+
|
|
22623
|
+
// src/changes-page.ts
|
|
22624
|
+
var GROUPS = [
|
|
22625
|
+
{ kind: "regressed", heading: "Regressed", icon: "\u26A0\uFE0F" },
|
|
22626
|
+
{ kind: "removed", heading: "Removed", icon: "\u{1F5D1}\uFE0F" },
|
|
22627
|
+
{ kind: "added", heading: "Added", icon: "\u2728" },
|
|
22628
|
+
{ kind: "fixed", heading: "Fixed", icon: "\u2705" },
|
|
22629
|
+
{ kind: "changed", heading: "Changed", icon: "\u{1F501}" }
|
|
22630
|
+
];
|
|
22631
|
+
function yamlScalar2(value) {
|
|
22632
|
+
if (/[:#[\]{}&*!|>'"%@`]|^[\s-]|\s$/.test(value)) {
|
|
22633
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
22634
|
+
}
|
|
22635
|
+
return value;
|
|
22636
|
+
}
|
|
22637
|
+
function badge(summary) {
|
|
22638
|
+
if (summary.regressed > 0 || summary.removed > 0) return { text: "Regressed", variant: "danger" };
|
|
22639
|
+
if (summary.added > 0 || summary.fixed > 0 || summary.changed > 0)
|
|
22640
|
+
return { text: "Updated", variant: "tip" };
|
|
22641
|
+
return { text: "No changes", variant: "note" };
|
|
22642
|
+
}
|
|
22643
|
+
function line(entry, links) {
|
|
22644
|
+
const link2 = links.scenarios[entry.id];
|
|
22645
|
+
const label = link2 ? `[${entry.title}](${link2.deepLink})` : entry.title;
|
|
22646
|
+
const transition = entry.baselineStatus && entry.currentStatus && entry.baselineStatus !== entry.currentStatus ? ` \u2014 \`${entry.baselineStatus}\` \u2192 \`${entry.currentStatus}\`` : "";
|
|
22647
|
+
return `- ${label} \`${entry.sourceFile}\`${transition}`;
|
|
22648
|
+
}
|
|
22649
|
+
function renderChangesPage(diff, links) {
|
|
22650
|
+
const b = badge(diff.summary);
|
|
22651
|
+
const { added, removed, regressed, fixed, changed } = diff.summary;
|
|
22652
|
+
const totalChanged = added + removed + regressed + fixed + changed;
|
|
22653
|
+
const frontmatter = [
|
|
22654
|
+
"---",
|
|
22655
|
+
"title: What's changed",
|
|
22656
|
+
`description: ${yamlScalar2(
|
|
22657
|
+
totalChanged === 0 ? "No behavioural changes since the baseline" : `${totalChanged} scenario${totalChanged !== 1 ? "s" : ""} changed since the baseline`
|
|
22658
|
+
)}`,
|
|
22659
|
+
"sidebar:",
|
|
22660
|
+
" order: 0",
|
|
22661
|
+
" badge:",
|
|
22662
|
+
` text: ${b.text}`,
|
|
22663
|
+
` variant: ${b.variant}`,
|
|
22664
|
+
"---"
|
|
22665
|
+
].join("\n");
|
|
22666
|
+
const body = [];
|
|
22667
|
+
if (totalChanged === 0) {
|
|
22668
|
+
body.push("No behavioural changes since the baseline run. \u2705");
|
|
22669
|
+
} else {
|
|
22670
|
+
body.push(
|
|
22671
|
+
`**${regressed}** regressed \xB7 **${removed}** removed \xB7 **${added}** added \xB7 **${fixed}** fixed \xB7 **${changed}** changed`,
|
|
22672
|
+
""
|
|
22673
|
+
);
|
|
22674
|
+
for (const group of GROUPS) {
|
|
22675
|
+
const entries = diff.scenarios.filter((s) => s.kind === group.kind);
|
|
22676
|
+
if (entries.length === 0) continue;
|
|
22677
|
+
body.push(`## ${group.icon} ${group.heading} (${entries.length})`, "");
|
|
22678
|
+
for (const entry of entries) body.push(line(entry, links));
|
|
22679
|
+
body.push("");
|
|
22680
|
+
}
|
|
22681
|
+
}
|
|
22682
|
+
return `${frontmatter}
|
|
22683
|
+
|
|
22684
|
+
${body.join("\n")}
|
|
22685
|
+
`;
|
|
22686
|
+
}
|
|
22687
|
+
|
|
22688
|
+
// src/overview-page.ts
|
|
22689
|
+
var AUDIENCE_CARDS = [
|
|
22690
|
+
{
|
|
22691
|
+
key: "engineer",
|
|
22692
|
+
label: "Engineer",
|
|
22693
|
+
icon: "\u{1F527}",
|
|
22694
|
+
blurb: "Unit & integration behaviour \u2014 how the system works under the hood."
|
|
22695
|
+
},
|
|
22696
|
+
{
|
|
22697
|
+
key: "stakeholder",
|
|
22698
|
+
label: "Stakeholder",
|
|
22699
|
+
icon: "\u{1F3AC}",
|
|
22700
|
+
blurb: "End-to-end journeys \u2014 what the product does, with video and traces."
|
|
22701
|
+
}
|
|
22702
|
+
];
|
|
22703
|
+
var STATUS_ICON = {
|
|
22704
|
+
passed: "\u2705",
|
|
22705
|
+
failed: "\u274C",
|
|
22706
|
+
skipped: "\u23ED\uFE0F",
|
|
22707
|
+
pending: "\u{1F6A7}"
|
|
22708
|
+
};
|
|
22709
|
+
function yamlScalar3(value) {
|
|
22710
|
+
if (/[:#[\]{}&*!|>'"%@`]|^[\s-]|\s$/.test(value)) {
|
|
22711
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
22712
|
+
}
|
|
22713
|
+
return value;
|
|
22714
|
+
}
|
|
22715
|
+
function renderOverviewPage(links) {
|
|
22716
|
+
const all = Object.values(links.scenarios);
|
|
22717
|
+
const total = all.length;
|
|
22718
|
+
const passed = all.filter((s) => s.status === "passed").length;
|
|
22719
|
+
const failed = all.filter((s) => s.status === "failed").length;
|
|
22720
|
+
const frontmatter = [
|
|
22721
|
+
"---",
|
|
22722
|
+
"title: Stories",
|
|
22723
|
+
`description: ${yamlScalar3(
|
|
22724
|
+
`${total} scenario${total !== 1 ? "s" : ""} \u2014 ${passed} passed, ${failed} failed`
|
|
22725
|
+
)}`,
|
|
22726
|
+
"sidebar:",
|
|
22727
|
+
" order: 1",
|
|
22728
|
+
"---"
|
|
22729
|
+
].join("\n");
|
|
22730
|
+
const body = [
|
|
22731
|
+
`**${total}** scenarios \xB7 **${passed}** passed \xB7 **${failed}** failed`,
|
|
22732
|
+
""
|
|
22733
|
+
];
|
|
22734
|
+
for (const card of AUDIENCE_CARDS) {
|
|
22735
|
+
const scenarios = all.filter((s) => s.audience === card.key);
|
|
22736
|
+
if (scenarios.length === 0) continue;
|
|
22737
|
+
const cardPassed = scenarios.filter((s) => s.status === "passed").length;
|
|
22738
|
+
const cardFailed = scenarios.filter((s) => s.status === "failed").length;
|
|
22739
|
+
const counts = cardFailed > 0 ? `${cardPassed} passed, ${cardFailed} failed` : `${cardPassed} passed`;
|
|
22740
|
+
body.push(`## ${card.icon} ${card.label} (${scenarios.length} \u2014 ${counts})`, "");
|
|
22741
|
+
body.push(`${card.blurb}`, "");
|
|
22742
|
+
for (const s of scenariosSorted(scenarios)) {
|
|
22743
|
+
body.push(`- ${STATUS_ICON[s.status] ?? "\u2022"} [${s.title}](${s.deepLink})`);
|
|
22744
|
+
}
|
|
22745
|
+
body.push("");
|
|
22746
|
+
}
|
|
22747
|
+
return `${frontmatter}
|
|
22748
|
+
|
|
22749
|
+
${body.join("\n")}
|
|
22750
|
+
`;
|
|
22751
|
+
}
|
|
22752
|
+
function scenariosSorted(scenarios) {
|
|
22753
|
+
return [...scenarios].sort((a, b) => {
|
|
22754
|
+
const aFail = a.status === "failed" ? 0 : 1;
|
|
22755
|
+
const bFail = b.status === "failed" ? 0 : 1;
|
|
22756
|
+
if (aFail !== bFail) return aFail - bFail;
|
|
22757
|
+
return a.title.localeCompare(b.title);
|
|
22758
|
+
});
|
|
22759
|
+
}
|
|
22760
|
+
|
|
22761
|
+
// src/build-docs.ts
|
|
22762
|
+
var AUDIENCES = ["engineer", "stakeholder"];
|
|
22763
|
+
function partitionByAudience(run) {
|
|
22764
|
+
const buckets = {
|
|
22765
|
+
engineer: [],
|
|
22766
|
+
stakeholder: []
|
|
22767
|
+
};
|
|
22768
|
+
for (const tc of run.testCases) {
|
|
22769
|
+
buckets[deriveAudience(tc.sourceFile, tc.tags)].push(tc);
|
|
22770
|
+
}
|
|
22771
|
+
return {
|
|
22772
|
+
engineer: { ...run, testCases: buckets.engineer },
|
|
22773
|
+
stakeholder: { ...run, testCases: buckets.stakeholder }
|
|
22774
|
+
};
|
|
22775
|
+
}
|
|
22561
22776
|
var BuildDocsError = class extends Error {
|
|
22562
22777
|
constructor(message, kind) {
|
|
22563
22778
|
super(message);
|
|
@@ -22599,6 +22814,40 @@ function bundleExplorerAssets(reportPath, assetsDir, baseUrl = "/stories/assets"
|
|
|
22599
22814
|
}
|
|
22600
22815
|
return copied;
|
|
22601
22816
|
}
|
|
22817
|
+
var CHANGE_BADGE = {
|
|
22818
|
+
added: "\u{1F195} **New** _since last run_",
|
|
22819
|
+
fixed: "\u2705 **Fixed** _since last run_",
|
|
22820
|
+
regressed: "\u26A0\uFE0F **Regressed** _since last run_"
|
|
22821
|
+
};
|
|
22822
|
+
function changeBadgeLookup(diff) {
|
|
22823
|
+
if (!diff) return void 0;
|
|
22824
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
22825
|
+
for (const s of diff.scenarios) {
|
|
22826
|
+
const badge2 = CHANGE_BADGE[s.kind];
|
|
22827
|
+
if (badge2) byKey.set(`${s.sourceFile}\0${s.title}`, badge2);
|
|
22828
|
+
}
|
|
22829
|
+
if (byKey.size === 0) return void 0;
|
|
22830
|
+
return (tc) => byKey.get(`${tc.sourceFile}\0${tc.story.scenario}`);
|
|
22831
|
+
}
|
|
22832
|
+
function readStoryReport(reportPath) {
|
|
22833
|
+
if (!fs13.existsSync(reportPath)) return null;
|
|
22834
|
+
try {
|
|
22835
|
+
return JSON.parse(fs13.readFileSync(reportPath, "utf8"));
|
|
22836
|
+
} catch {
|
|
22837
|
+
return null;
|
|
22838
|
+
}
|
|
22839
|
+
}
|
|
22840
|
+
function writeScenarioLinks(reportPath, outDir, options = {}) {
|
|
22841
|
+
const report = readStoryReport(reportPath);
|
|
22842
|
+
if (!report) return null;
|
|
22843
|
+
const index = buildScenarioLinks(report, { audienceSplit: options.audienceSplit });
|
|
22844
|
+
fs13.writeFileSync(
|
|
22845
|
+
path14.join(outDir, "scenario-links.json"),
|
|
22846
|
+
JSON.stringify(index, null, 2),
|
|
22847
|
+
"utf8"
|
|
22848
|
+
);
|
|
22849
|
+
return index;
|
|
22850
|
+
}
|
|
22602
22851
|
function clearGeneratedPages(dir) {
|
|
22603
22852
|
if (!fs13.existsSync(dir)) return;
|
|
22604
22853
|
for (const entry of fs13.readdirSync(dir, { withFileTypes: true })) {
|
|
@@ -22649,16 +22898,72 @@ async function buildDocs(options) {
|
|
|
22649
22898
|
outputDir: storiesPublicDir,
|
|
22650
22899
|
outputName: "story-report"
|
|
22651
22900
|
}).generate(canonical);
|
|
22901
|
+
let diff;
|
|
22902
|
+
if (options.baselinePath) {
|
|
22903
|
+
const baselineResolved = path14.resolve(options.baselinePath);
|
|
22904
|
+
const baseline = readStoryReport(baselineResolved);
|
|
22905
|
+
if (!baseline) {
|
|
22906
|
+
throw new BuildDocsError(
|
|
22907
|
+
`Baseline story-report not found or unreadable: ${baselineResolved}`,
|
|
22908
|
+
"input"
|
|
22909
|
+
);
|
|
22910
|
+
}
|
|
22911
|
+
const current = readStoryReport(reportPath);
|
|
22912
|
+
if (current) diff = diffStoryReports(baseline, current);
|
|
22913
|
+
}
|
|
22914
|
+
const scenarioBadge = changeBadgeLookup(diff);
|
|
22652
22915
|
clearGeneratedPages(storyPagesDir);
|
|
22653
|
-
|
|
22916
|
+
const genPages = (run, outDir) => new ReportGenerator({
|
|
22654
22917
|
formats: ["astro"],
|
|
22655
|
-
outputDir:
|
|
22918
|
+
outputDir: outDir,
|
|
22656
22919
|
outputName: "index",
|
|
22657
22920
|
output: { mode: "colocated", colocatedStyle: "flat" },
|
|
22658
22921
|
assetMode: "copy",
|
|
22659
|
-
astro: {
|
|
22660
|
-
|
|
22922
|
+
astro: {
|
|
22923
|
+
assetsDir,
|
|
22924
|
+
assetsBaseUrl: "/stories/assets",
|
|
22925
|
+
markdown: {
|
|
22926
|
+
// Emit the same anchor scenario-links.json points at, so fragments resolve.
|
|
22927
|
+
scenarioAnchor: (tc) => scenarioAnchor(tc.story.scenario),
|
|
22928
|
+
scenarioBadge
|
|
22929
|
+
}
|
|
22930
|
+
}
|
|
22931
|
+
}).generate(run);
|
|
22932
|
+
const audiences = { engineer: 0, stakeholder: 0 };
|
|
22933
|
+
if (options.audienceSplit ?? false) {
|
|
22934
|
+
const partitioned = partitionByAudience(canonical);
|
|
22935
|
+
for (const audience of AUDIENCES) {
|
|
22936
|
+
const sub = partitioned[audience];
|
|
22937
|
+
audiences[audience] = sub.testCases.length;
|
|
22938
|
+
if (sub.testCases.length === 0) continue;
|
|
22939
|
+
await genPages(sub, path14.join(storyPagesDir, audience));
|
|
22940
|
+
}
|
|
22941
|
+
} else {
|
|
22942
|
+
await genPages(canonical, storyPagesDir);
|
|
22943
|
+
}
|
|
22661
22944
|
const bundledAssets = bundleExplorerAssets(reportPath, assetsDir);
|
|
22945
|
+
const linksIndex = writeScenarioLinks(reportPath, storiesPublicDir, {
|
|
22946
|
+
audienceSplit: options.audienceSplit ?? false
|
|
22947
|
+
});
|
|
22948
|
+
const scenarioLinks = linksIndex ? Object.keys(linksIndex.scenarios).length : 0;
|
|
22949
|
+
if (linksIndex) {
|
|
22950
|
+
fs13.writeFileSync(
|
|
22951
|
+
path14.join(storyPagesDir, "index.md"),
|
|
22952
|
+
renderOverviewPage(linksIndex),
|
|
22953
|
+
"utf8"
|
|
22954
|
+
);
|
|
22955
|
+
}
|
|
22956
|
+
const changesJsonPath = path14.join(storiesPublicDir, "changes.json");
|
|
22957
|
+
const changesMdPath = path14.join(storyPagesDir, "changes.md");
|
|
22958
|
+
let changes;
|
|
22959
|
+
if (diff && linksIndex) {
|
|
22960
|
+
fs13.writeFileSync(changesJsonPath, JSON.stringify(diff, null, 2), "utf8");
|
|
22961
|
+
fs13.writeFileSync(changesMdPath, renderChangesPage(diff, linksIndex), "utf8");
|
|
22962
|
+
changes = diff.summary;
|
|
22963
|
+
} else {
|
|
22964
|
+
fs13.rmSync(changesJsonPath, { force: true });
|
|
22965
|
+
fs13.rmSync(changesMdPath, { force: true });
|
|
22966
|
+
}
|
|
22662
22967
|
let apiPages = 0;
|
|
22663
22968
|
if (options.openapiPath) {
|
|
22664
22969
|
const res = await importOpenApi({
|
|
@@ -22669,7 +22974,7 @@ async function buildDocs(options) {
|
|
|
22669
22974
|
});
|
|
22670
22975
|
apiPages = res.pageCount;
|
|
22671
22976
|
}
|
|
22672
|
-
return { siteDir, bundledAssets, apiPages };
|
|
22977
|
+
return { siteDir, bundledAssets, apiPages, audiences, scenarioLinks, changes };
|
|
22673
22978
|
} catch (err) {
|
|
22674
22979
|
if (err instanceof BuildDocsError) throw err;
|
|
22675
22980
|
throw new BuildDocsError(`Generation failed: ${err.message}`, "generation");
|
|
@@ -24008,9 +24313,9 @@ function mapStatus(status) {
|
|
|
24008
24313
|
function parseNameStatus(text2) {
|
|
24009
24314
|
const files = [];
|
|
24010
24315
|
for (const raw of text2.split("\n")) {
|
|
24011
|
-
const
|
|
24012
|
-
if (!
|
|
24013
|
-
const cols =
|
|
24316
|
+
const line2 = raw.trim();
|
|
24317
|
+
if (!line2) continue;
|
|
24318
|
+
const cols = line2.includes(" ") ? line2.split(" ") : line2.split(/\s+/);
|
|
24014
24319
|
const status = cols[0];
|
|
24015
24320
|
if (!status) continue;
|
|
24016
24321
|
const filePath = /^[RC]/i.test(status) && cols.length >= 3 ? cols[cols.length - 1] : cols[1];
|
|
@@ -24517,7 +24822,9 @@ async function runBuildDocs(rawArgs) {
|
|
|
24517
24822
|
options: {
|
|
24518
24823
|
"site-dir": { type: "string" },
|
|
24519
24824
|
openapi: { type: "string" },
|
|
24520
|
-
"no-synthesize-stories": { type: "boolean", default: false }
|
|
24825
|
+
"no-synthesize-stories": { type: "boolean", default: false },
|
|
24826
|
+
"audience-split": { type: "boolean", default: false },
|
|
24827
|
+
baseline: { type: "string" }
|
|
24521
24828
|
},
|
|
24522
24829
|
allowPositionals: true,
|
|
24523
24830
|
strict: true
|
|
@@ -24525,26 +24832,42 @@ async function runBuildDocs(rawArgs) {
|
|
|
24525
24832
|
const rawRunPath = positionals[0];
|
|
24526
24833
|
if (!rawRunPath) {
|
|
24527
24834
|
console.error(
|
|
24528
|
-
`Usage: executable-stories build-docs <raw-run.json> [--site-dir <dir>] [--openapi <spec>]`
|
|
24835
|
+
`Usage: executable-stories build-docs <raw-run.json> [--site-dir <dir>] [--openapi <spec>] [--baseline <prev-story-report.json>] [--audience-split]`
|
|
24529
24836
|
);
|
|
24530
24837
|
return EXIT_USAGE;
|
|
24531
24838
|
}
|
|
24839
|
+
const audienceSplit = values["audience-split"];
|
|
24532
24840
|
try {
|
|
24533
24841
|
const result = await buildDocs({
|
|
24534
24842
|
rawRunPath,
|
|
24535
24843
|
siteDir: values["site-dir"] ?? ".",
|
|
24536
24844
|
openapiPath: values.openapi,
|
|
24537
|
-
synthesizeStories: !values["no-synthesize-stories"]
|
|
24845
|
+
synthesizeStories: !values["no-synthesize-stories"],
|
|
24846
|
+
audienceSplit,
|
|
24847
|
+
baselinePath: values.baseline
|
|
24538
24848
|
});
|
|
24539
24849
|
console.log(`\u2713 Living docs generated in ${result.siteDir}`);
|
|
24540
24850
|
console.log(` \u2022 Explorer data \u2192 public/stories/story-report.json`);
|
|
24541
|
-
console.log(` \u2022
|
|
24851
|
+
console.log(` \u2022 Deep links \u2192 public/stories/scenario-links.json (${result.scenarioLinks})`);
|
|
24852
|
+
if (audienceSplit) {
|
|
24853
|
+
console.log(
|
|
24854
|
+
` \u2022 Story pages \u2192 src/content/docs/stories/{engineer,stakeholder} (engineer: ${result.audiences.engineer}, stakeholder: ${result.audiences.stakeholder})`
|
|
24855
|
+
);
|
|
24856
|
+
} else {
|
|
24857
|
+
console.log(` \u2022 Story pages \u2192 src/content/docs/stories`);
|
|
24858
|
+
}
|
|
24542
24859
|
if (result.bundledAssets > 0) {
|
|
24543
24860
|
console.log(` \u2022 Bundled assets \u2192 public/stories/assets (${result.bundledAssets})`);
|
|
24544
24861
|
}
|
|
24545
24862
|
if (result.apiPages > 0) {
|
|
24546
24863
|
console.log(` \u2022 API pages \u2192 src/content/docs/api (${result.apiPages})`);
|
|
24547
24864
|
}
|
|
24865
|
+
if (result.changes) {
|
|
24866
|
+
const c = result.changes;
|
|
24867
|
+
console.log(
|
|
24868
|
+
` \u2022 What's changed \u2192 src/content/docs/stories/changes.md (+${c.added} added, ${c.regressed} regressed, ${c.fixed} fixed, ${c.removed} removed)`
|
|
24869
|
+
);
|
|
24870
|
+
}
|
|
24548
24871
|
const rel = path15.relative(process.cwd(), result.siteDir) || ".";
|
|
24549
24872
|
console.log(`
|
|
24550
24873
|
Preview: cd ${rel} && npm run dev`);
|