executable-stories-formatters 0.11.4 → 0.12.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/adapters.d.cts +1 -1
- package/dist/adapters.d.ts +1 -1
- package/dist/cli.js +247 -5
- package/dist/cli.js.map +1 -1
- package/dist/{index-DF16Xl5i.d.cts → index-mrT6-JSt.d.cts} +9 -0
- package/dist/{index-DF16Xl5i.d.ts → index-mrT6-JSt.d.ts} +9 -0
- package/dist/index.cjs +248 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -5
- package/dist/index.d.ts +50 -5
- package/dist/index.js +247 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schemas/raw-run.schema.json +21 -0
- package/schemas/story-report-v1.json +24 -0
|
@@ -120,6 +120,15 @@ type DocEntry = {
|
|
|
120
120
|
poster?: string;
|
|
121
121
|
phase: DocPhase;
|
|
122
122
|
children?: DocEntry[];
|
|
123
|
+
} | {
|
|
124
|
+
kind: "html";
|
|
125
|
+
path?: string;
|
|
126
|
+
url?: string;
|
|
127
|
+
content?: string;
|
|
128
|
+
title?: string;
|
|
129
|
+
height?: number | string;
|
|
130
|
+
phase: DocPhase;
|
|
131
|
+
children?: DocEntry[];
|
|
123
132
|
} | {
|
|
124
133
|
kind: "custom";
|
|
125
134
|
type: string;
|
|
@@ -120,6 +120,15 @@ type DocEntry = {
|
|
|
120
120
|
poster?: string;
|
|
121
121
|
phase: DocPhase;
|
|
122
122
|
children?: DocEntry[];
|
|
123
|
+
} | {
|
|
124
|
+
kind: "html";
|
|
125
|
+
path?: string;
|
|
126
|
+
url?: string;
|
|
127
|
+
content?: string;
|
|
128
|
+
title?: string;
|
|
129
|
+
height?: number | string;
|
|
130
|
+
phase: DocPhase;
|
|
131
|
+
children?: DocEntry[];
|
|
123
132
|
} | {
|
|
124
133
|
kind: "custom";
|
|
125
134
|
type: string;
|
package/dist/index.cjs
CHANGED
|
@@ -59,6 +59,7 @@ __export(src_exports, {
|
|
|
59
59
|
adaptPlaywrightRun: () => adaptPlaywrightRun,
|
|
60
60
|
adaptVitestRun: () => adaptVitestRun,
|
|
61
61
|
assertValidRun: () => assertValidRun,
|
|
62
|
+
buildHtmlDocEntry: () => buildHtmlDocEntry,
|
|
62
63
|
buildReview: () => buildReview,
|
|
63
64
|
bundleAssets: () => bundleAssets,
|
|
64
65
|
calculateFlakiness: () => calculateFlakiness,
|
|
@@ -630,6 +631,14 @@ var CucumberJsonFormatter = class {
|
|
|
630
631
|
}
|
|
631
632
|
const embeddings = [];
|
|
632
633
|
for (const doc of step.docs) {
|
|
634
|
+
if (doc.kind === "html" && doc.content !== void 0) {
|
|
635
|
+
embeddings.push({
|
|
636
|
+
data: Buffer.from(doc.content, "utf8").toString("base64"),
|
|
637
|
+
mime_type: "text/html",
|
|
638
|
+
name: doc.title
|
|
639
|
+
});
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
633
642
|
if (doc.kind !== "screenshot" || !doc.path.startsWith("data:")) {
|
|
634
643
|
continue;
|
|
635
644
|
}
|
|
@@ -809,6 +818,17 @@ ${doc.markdown}`,
|
|
|
809
818
|
};
|
|
810
819
|
case "screenshot":
|
|
811
820
|
return null;
|
|
821
|
+
case "html":
|
|
822
|
+
if (doc.url !== void 0 || doc.path !== void 0) {
|
|
823
|
+
return {
|
|
824
|
+
doc_string: {
|
|
825
|
+
content: `[${doc.title ?? "Embedded HTML"}](${doc.url ?? doc.path})`,
|
|
826
|
+
content_type: "text/markdown",
|
|
827
|
+
line: 0
|
|
828
|
+
}
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
return null;
|
|
812
832
|
default:
|
|
813
833
|
return null;
|
|
814
834
|
}
|
|
@@ -908,6 +928,17 @@ function copyDocEntry(entry) {
|
|
|
908
928
|
phase: entry.phase,
|
|
909
929
|
...children
|
|
910
930
|
};
|
|
931
|
+
case "html":
|
|
932
|
+
return {
|
|
933
|
+
kind: "html",
|
|
934
|
+
...entry.path !== void 0 ? { path: entry.path } : {},
|
|
935
|
+
...entry.url !== void 0 ? { url: entry.url } : {},
|
|
936
|
+
...entry.content !== void 0 ? { content: entry.content } : {},
|
|
937
|
+
...entry.title !== void 0 ? { title: entry.title } : {},
|
|
938
|
+
...entry.height !== void 0 ? { height: entry.height } : {},
|
|
939
|
+
phase: entry.phase,
|
|
940
|
+
...children
|
|
941
|
+
};
|
|
911
942
|
case "custom":
|
|
912
943
|
return {
|
|
913
944
|
kind: "custom",
|
|
@@ -1296,7 +1327,7 @@ function scenarioHasDocs(scenario) {
|
|
|
1296
1327
|
var fs2 = __toESM(require("fs"), 1);
|
|
1297
1328
|
var path3 = __toESM(require("path"), 1);
|
|
1298
1329
|
|
|
1299
|
-
// src/formatters/html/template.ts
|
|
1330
|
+
// src/formatters/html/template-scripts.ts
|
|
1300
1331
|
var JS_THEME = `
|
|
1301
1332
|
// Theme management
|
|
1302
1333
|
function getSystemTheme() {
|
|
@@ -2098,6 +2129,23 @@ function parseMarkdownSections(marked) {
|
|
|
2098
2129
|
});
|
|
2099
2130
|
}
|
|
2100
2131
|
`;
|
|
2132
|
+
var JS_HTML_EMBED = `
|
|
2133
|
+
// Open srcdoc-embedded HTML (doc-html iframes) in a new tab via a blob URL
|
|
2134
|
+
function initHtmlEmbeds() {
|
|
2135
|
+
document.querySelectorAll('.doc-html-open-srcdoc').forEach((btn) => {
|
|
2136
|
+
btn.addEventListener('click', function() {
|
|
2137
|
+
const container = btn.closest('.doc-html');
|
|
2138
|
+
const iframe = container ? container.querySelector('iframe.doc-html-frame') : null;
|
|
2139
|
+
const html = iframe ? iframe.getAttribute('srcdoc') : null;
|
|
2140
|
+
if (!html) return;
|
|
2141
|
+
const url = URL.createObjectURL(new Blob([html], { type: 'text/html' }));
|
|
2142
|
+
window.open(url, '_blank', 'noopener');
|
|
2143
|
+
});
|
|
2144
|
+
});
|
|
2145
|
+
}
|
|
2146
|
+
`;
|
|
2147
|
+
|
|
2148
|
+
// src/formatters/html/template.ts
|
|
2101
2149
|
function generateScript(options) {
|
|
2102
2150
|
const initCalls = [];
|
|
2103
2151
|
if (options.includeDarkMode) {
|
|
@@ -2115,6 +2163,7 @@ function generateScript(options) {
|
|
|
2115
2163
|
initCalls.push("initHashScroll();");
|
|
2116
2164
|
initCalls.push("initToc();");
|
|
2117
2165
|
initCalls.push("initThemePicker();");
|
|
2166
|
+
initCalls.push("initHtmlEmbeds();");
|
|
2118
2167
|
const initScript = `
|
|
2119
2168
|
// Initialize on load
|
|
2120
2169
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -2123,6 +2172,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
2123
2172
|
`;
|
|
2124
2173
|
let script = options.includeDarkMode ? JS_THEME : "";
|
|
2125
2174
|
script += JS_CORE;
|
|
2175
|
+
script += JS_HTML_EMBED;
|
|
2126
2176
|
if (options.additionalJs) {
|
|
2127
2177
|
script += options.additionalJs;
|
|
2128
2178
|
}
|
|
@@ -3788,6 +3838,82 @@ body {
|
|
|
3788
3838
|
opacity: 0.8;
|
|
3789
3839
|
}
|
|
3790
3840
|
|
|
3841
|
+
/* ============================================================================
|
|
3842
|
+
Documentation Entries - Embedded HTML
|
|
3843
|
+
============================================================================ */
|
|
3844
|
+
.doc-html {
|
|
3845
|
+
margin-bottom: 0.5rem;
|
|
3846
|
+
border: 1px solid var(--border);
|
|
3847
|
+
border-radius: calc(var(--radius) - 2px);
|
|
3848
|
+
overflow: hidden;
|
|
3849
|
+
}
|
|
3850
|
+
|
|
3851
|
+
.doc-html:last-child {
|
|
3852
|
+
margin-bottom: 0;
|
|
3853
|
+
}
|
|
3854
|
+
|
|
3855
|
+
.doc-html-header {
|
|
3856
|
+
display: flex;
|
|
3857
|
+
align-items: center;
|
|
3858
|
+
justify-content: space-between;
|
|
3859
|
+
gap: 0.5rem;
|
|
3860
|
+
padding: 0.375rem 0.75rem;
|
|
3861
|
+
background: var(--muted, transparent);
|
|
3862
|
+
border-bottom: 1px solid var(--border);
|
|
3863
|
+
}
|
|
3864
|
+
|
|
3865
|
+
.doc-html-title {
|
|
3866
|
+
font-size: 0.75rem;
|
|
3867
|
+
font-weight: 600;
|
|
3868
|
+
color: var(--muted-foreground);
|
|
3869
|
+
text-transform: uppercase;
|
|
3870
|
+
letter-spacing: 0.04em;
|
|
3871
|
+
}
|
|
3872
|
+
|
|
3873
|
+
.doc-html-open {
|
|
3874
|
+
font-size: 0.875rem;
|
|
3875
|
+
line-height: 1;
|
|
3876
|
+
padding: 0.125rem 0.375rem;
|
|
3877
|
+
border: 1px solid var(--border);
|
|
3878
|
+
border-radius: calc(var(--radius) - 4px);
|
|
3879
|
+
background: transparent;
|
|
3880
|
+
color: var(--muted-foreground);
|
|
3881
|
+
cursor: pointer;
|
|
3882
|
+
text-decoration: none;
|
|
3883
|
+
}
|
|
3884
|
+
|
|
3885
|
+
.doc-html-open:hover {
|
|
3886
|
+
color: var(--foreground);
|
|
3887
|
+
border-color: var(--foreground);
|
|
3888
|
+
}
|
|
3889
|
+
|
|
3890
|
+
.doc-html-frame {
|
|
3891
|
+
display: block;
|
|
3892
|
+
width: 100%;
|
|
3893
|
+
border: 0;
|
|
3894
|
+
background: #fff;
|
|
3895
|
+
}
|
|
3896
|
+
|
|
3897
|
+
.doc-html-missing {
|
|
3898
|
+
padding: 0.75rem 1rem;
|
|
3899
|
+
border: 1px dashed var(--border);
|
|
3900
|
+
background: var(--muted, transparent);
|
|
3901
|
+
color: var(--muted-foreground);
|
|
3902
|
+
font-size: 0.8125rem;
|
|
3903
|
+
}
|
|
3904
|
+
|
|
3905
|
+
.doc-html-missing-label {
|
|
3906
|
+
font-weight: 600;
|
|
3907
|
+
margin-bottom: 0.25rem;
|
|
3908
|
+
}
|
|
3909
|
+
|
|
3910
|
+
.doc-html-missing-path {
|
|
3911
|
+
font-family: var(--font-mono, ui-monospace, monospace);
|
|
3912
|
+
font-size: 0.75rem;
|
|
3913
|
+
word-break: break-all;
|
|
3914
|
+
opacity: 0.8;
|
|
3915
|
+
}
|
|
3916
|
+
|
|
3791
3917
|
/* ============================================================================
|
|
3792
3918
|
Documentation Entries - Visual Check
|
|
3793
3919
|
============================================================================ */
|
|
@@ -14086,6 +14212,36 @@ function renderDocVideo(entry, deps) {
|
|
|
14086
14212
|
${captionHtml}
|
|
14087
14213
|
</div>`;
|
|
14088
14214
|
}
|
|
14215
|
+
function resolveHtmlSource(entry, deps) {
|
|
14216
|
+
if (entry.url !== void 0) return { mode: "src", value: entry.url };
|
|
14217
|
+
if (entry.content !== void 0) return { mode: "srcdoc", value: entry.content };
|
|
14218
|
+
const filePath = entry.path ?? "";
|
|
14219
|
+
if (/^https?:/i.test(filePath)) return { mode: "src", value: filePath };
|
|
14220
|
+
const inlined = deps.readHtmlFile?.(filePath);
|
|
14221
|
+
if (inlined !== void 0) return { mode: "srcdoc", value: inlined };
|
|
14222
|
+
const isAbsoluteFsPath = /^(?:[/\\]|[A-Za-z]:[/\\])/.test(filePath);
|
|
14223
|
+
if (deps.readHtmlFile && isAbsoluteFsPath) return { mode: "missing", value: filePath };
|
|
14224
|
+
return { mode: "src", value: filePath };
|
|
14225
|
+
}
|
|
14226
|
+
function renderDocHtml(entry, deps) {
|
|
14227
|
+
const source = resolveHtmlSource(entry, deps);
|
|
14228
|
+
if (source.mode === "missing") {
|
|
14229
|
+
return `<div class="doc-html doc-html-missing">
|
|
14230
|
+
<div class="doc-html-missing-label">HTML unavailable</div>
|
|
14231
|
+
<div class="doc-html-missing-path">${deps.escapeHtml(source.value)}</div>
|
|
14232
|
+
</div>`;
|
|
14233
|
+
}
|
|
14234
|
+
const heightCss = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
|
|
14235
|
+
const frame = `<iframe class="doc-html-frame" sandbox="allow-scripts" loading="lazy" style="height: ${deps.escapeHtml(heightCss)};" title="${deps.escapeHtml(entry.title ?? "Embedded HTML")}" ${source.mode}="${deps.escapeHtml(source.value)}"></iframe>`;
|
|
14236
|
+
const openBtn = source.mode === "src" ? `<a class="doc-html-open" href="${deps.escapeHtml(source.value)}" target="_blank" rel="noopener noreferrer" title="Open in new tab" aria-label="Open in new tab">↗</a>` : `<button type="button" class="doc-html-open doc-html-open-srcdoc" title="Open in new tab" aria-label="Open in new tab">↗</button>`;
|
|
14237
|
+
return `<div class="doc-html">
|
|
14238
|
+
<div class="doc-html-header">
|
|
14239
|
+
<span class="doc-html-title">${deps.escapeHtml(entry.title ?? "HTML")}</span>
|
|
14240
|
+
${openBtn}
|
|
14241
|
+
</div>
|
|
14242
|
+
${frame}
|
|
14243
|
+
</div>`;
|
|
14244
|
+
}
|
|
14089
14245
|
function renderDocCustom(entry, deps) {
|
|
14090
14246
|
if (entry.type === "visual" && entry.data && typeof entry.data === "object") {
|
|
14091
14247
|
const data = entry.data;
|
|
@@ -14142,6 +14298,9 @@ function renderDocEntry(entry, deps) {
|
|
|
14142
14298
|
case "video":
|
|
14143
14299
|
html = renderDocVideo(entry, deps);
|
|
14144
14300
|
break;
|
|
14301
|
+
case "html":
|
|
14302
|
+
html = renderDocHtml(entry, deps);
|
|
14303
|
+
break;
|
|
14145
14304
|
case "custom":
|
|
14146
14305
|
html = renderDocCustom(entry, deps);
|
|
14147
14306
|
break;
|
|
@@ -14713,6 +14872,21 @@ function readScreenshotAsDataUri(filePath) {
|
|
|
14713
14872
|
return void 0;
|
|
14714
14873
|
}
|
|
14715
14874
|
}
|
|
14875
|
+
var HTML_INLINE_WARN_BYTES = 1024 * 1024;
|
|
14876
|
+
function readHtmlFileContent(filePath) {
|
|
14877
|
+
try {
|
|
14878
|
+
if (!fs2.existsSync(filePath)) return void 0;
|
|
14879
|
+
const buf = fs2.readFileSync(filePath);
|
|
14880
|
+
if (buf.byteLength > HTML_INLINE_WARN_BYTES) {
|
|
14881
|
+
console.warn(
|
|
14882
|
+
`[executable-stories] Inlining large HTML file (${Math.round(buf.byteLength / 1024)} KiB) into the report: ${filePath}. Consider --asset-mode copy.`
|
|
14883
|
+
);
|
|
14884
|
+
}
|
|
14885
|
+
return buf.toString("utf8");
|
|
14886
|
+
} catch {
|
|
14887
|
+
return void 0;
|
|
14888
|
+
}
|
|
14889
|
+
}
|
|
14716
14890
|
function normalizeOptions(options = {}) {
|
|
14717
14891
|
return {
|
|
14718
14892
|
title: options.title ?? "Test Results",
|
|
@@ -14720,6 +14894,7 @@ function normalizeOptions(options = {}) {
|
|
|
14720
14894
|
searchable: options.searchable ?? true,
|
|
14721
14895
|
startCollapsed: options.startCollapsed ?? false,
|
|
14722
14896
|
embedScreenshots: options.embedScreenshots ?? true,
|
|
14897
|
+
embedHtmlFiles: options.embedHtmlFiles ?? true,
|
|
14723
14898
|
syntaxHighlighting: options.syntaxHighlighting ?? true,
|
|
14724
14899
|
mermaidEnabled: options.mermaidEnabled ?? true,
|
|
14725
14900
|
markdownEnabled: options.markdownEnabled ?? true,
|
|
@@ -14738,7 +14913,10 @@ function createHtmlFormatter(options = {}) {
|
|
|
14738
14913
|
markdownEnabled: opts.markdownEnabled,
|
|
14739
14914
|
mermaidEnabled: opts.mermaidEnabled,
|
|
14740
14915
|
embedScreenshots: opts.embedScreenshots,
|
|
14741
|
-
readScreenshot: (filePath) => readScreenshotAsDataUri(filePath)
|
|
14916
|
+
readScreenshot: (filePath) => readScreenshotAsDataUri(filePath),
|
|
14917
|
+
// When html-file inlining is off (e.g. --asset-mode copy), omit the read
|
|
14918
|
+
// hook so doc-html iframes keep their src path for the asset bundler.
|
|
14919
|
+
...opts.embedHtmlFiles ? { readHtmlFile: (filePath) => readHtmlFileContent(filePath) } : {}
|
|
14742
14920
|
};
|
|
14743
14921
|
const renderDocs = (docs, containerClass) => {
|
|
14744
14922
|
if (!docs || docs.length === 0) return "";
|
|
@@ -15030,6 +15208,8 @@ var JUnitFormatter = class {
|
|
|
15030
15208
|
}
|
|
15031
15209
|
case "screenshot":
|
|
15032
15210
|
return `${indent}Screenshot: ${entry.alt ?? entry.path}`;
|
|
15211
|
+
case "html":
|
|
15212
|
+
return `${indent}HTML: ${entry.title ?? "Embedded HTML"} (${entry.url ?? entry.path ?? "inline"})`;
|
|
15033
15213
|
case "custom": {
|
|
15034
15214
|
const dataStr = JSON.stringify(entry.data, null, 2);
|
|
15035
15215
|
const lines = [];
|
|
@@ -15481,6 +15661,25 @@ var MarkdownFormatter = class {
|
|
|
15481
15661
|
lines.push(`${indent}`);
|
|
15482
15662
|
break;
|
|
15483
15663
|
}
|
|
15664
|
+
case "html": {
|
|
15665
|
+
const htmlLabel = entry.title ?? "Embedded HTML";
|
|
15666
|
+
if (entry.url !== void 0 || entry.path !== void 0) {
|
|
15667
|
+
lines.push(`${indent}[${htmlLabel}](${entry.url ?? entry.path})`);
|
|
15668
|
+
break;
|
|
15669
|
+
}
|
|
15670
|
+
lines.push(`${indent}<details>`);
|
|
15671
|
+
lines.push(`${indent}<summary>${htmlLabel}</summary>`);
|
|
15672
|
+
lines.push(`${indent}`);
|
|
15673
|
+
lines.push(`${indent}\`\`\`html`);
|
|
15674
|
+
for (const line of (entry.content ?? "").split("\n")) {
|
|
15675
|
+
lines.push(`${indent}${line}`);
|
|
15676
|
+
}
|
|
15677
|
+
lines.push(`${indent}\`\`\``);
|
|
15678
|
+
lines.push(`${indent}`);
|
|
15679
|
+
lines.push(`${indent}</details>`);
|
|
15680
|
+
lines.push(`${indent}`);
|
|
15681
|
+
break;
|
|
15682
|
+
}
|
|
15484
15683
|
case "custom":
|
|
15485
15684
|
if (entry.type === "visual" && entry.data && typeof entry.data === "object") {
|
|
15486
15685
|
const data = entry.data;
|
|
@@ -16724,6 +16923,8 @@ function formatDocEntry(doc) {
|
|
|
16724
16923
|
return `${doc.alt ? `${escapeHtml2(doc.alt)}: ` : ""}${escapeHtml2(doc.path)}`;
|
|
16725
16924
|
case "video":
|
|
16726
16925
|
return `${doc.caption ? `${escapeHtml2(doc.caption)}: ` : ""}${escapeHtml2(doc.path)}`;
|
|
16926
|
+
case "html":
|
|
16927
|
+
return `${doc.title ? `${escapeHtml2(doc.title)}: ` : ""}${escapeHtml2(doc.url ?? doc.path ?? "(inline html)")}`;
|
|
16727
16928
|
case "custom":
|
|
16728
16929
|
return `${escapeHtml2(doc.type)}: ${escapeHtml2(JSON.stringify(doc.data))}`;
|
|
16729
16930
|
}
|
|
@@ -17182,6 +17383,8 @@ function formatDocEntry2(doc) {
|
|
|
17182
17383
|
return `${doc.alt ? `${doc.alt}: ` : ""}${doc.path}`;
|
|
17183
17384
|
case "video":
|
|
17184
17385
|
return `${doc.caption ? `${doc.caption}: ` : ""}${doc.path}`;
|
|
17386
|
+
case "html":
|
|
17387
|
+
return `${doc.title ? `${doc.title}: ` : ""}${doc.url ?? doc.path ?? "(inline html)"}`;
|
|
17185
17388
|
case "custom":
|
|
17186
17389
|
return `${doc.type}: ${JSON.stringify(doc.data)}`;
|
|
17187
17390
|
}
|
|
@@ -17331,7 +17534,7 @@ var path5 = __toESM(require("path"), 1);
|
|
|
17331
17534
|
function scanHtmlAssets(html) {
|
|
17332
17535
|
const seen = /* @__PURE__ */ new Set();
|
|
17333
17536
|
const patterns = [
|
|
17334
|
-
/<(?:img|video)\b[^>]*?\bsrc=["']([^"']+)["']/g,
|
|
17537
|
+
/<(?:img|video|iframe)\b[^>]*?\bsrc=["']([^"']+)["']/g,
|
|
17335
17538
|
/<a\b[^>]*?\bclass=["']attachment["'][^>]*?\bhref=["']([^"']+)["']/g,
|
|
17336
17539
|
/<a\b[^>]*?\bhref=["']([^"']+)["'][^>]*?\bclass=["']attachment["']/g
|
|
17337
17540
|
];
|
|
@@ -17410,7 +17613,7 @@ function bundleAssets(htmlPath, options = {}) {
|
|
|
17410
17613
|
function replaceAssetRef(html, original, replacement) {
|
|
17411
17614
|
const escaped = original.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
17412
17615
|
const srcPattern = new RegExp(
|
|
17413
|
-
`(<(?:img|video)\\b[^>]*?\\bsrc=["'])${escaped}(["'])`,
|
|
17616
|
+
`(<(?:img|video|iframe)\\b[^>]*?\\bsrc=["'])${escaped}(["'])`,
|
|
17414
17617
|
"g"
|
|
17415
17618
|
);
|
|
17416
17619
|
html = html.replace(srcPattern, `$1${replacement}$2`);
|
|
@@ -17798,6 +18001,21 @@ ${tc.errorStack}` : "");
|
|
|
17798
18001
|
])
|
|
17799
18002
|
);
|
|
17800
18003
|
break;
|
|
18004
|
+
case "html":
|
|
18005
|
+
if (entry.url !== void 0 || entry.path !== void 0) {
|
|
18006
|
+
const target = entry.url ?? entry.path ?? "";
|
|
18007
|
+
content.push(
|
|
18008
|
+
paragraph([
|
|
18009
|
+
text(entry.title ?? "Embedded HTML", strong()),
|
|
18010
|
+
text(": "),
|
|
18011
|
+
link(target, target)
|
|
18012
|
+
])
|
|
18013
|
+
);
|
|
18014
|
+
break;
|
|
18015
|
+
}
|
|
18016
|
+
content.push(paragraph([text(entry.title ?? "Embedded HTML", strong())]));
|
|
18017
|
+
content.push(codeBlock(entry.content ?? "", "html"));
|
|
18018
|
+
break;
|
|
17801
18019
|
case "custom":
|
|
17802
18020
|
content.push(paragraph([text(`[${entry.type}]`, strong())]));
|
|
17803
18021
|
content.push(codeBlock(JSON.stringify(entry.data ?? null, null, 2), "json"));
|
|
@@ -19515,6 +19733,27 @@ function resolveTraceUrl(template, traceId) {
|
|
|
19515
19733
|
return template.replace(/\{traceId\}/g, traceId);
|
|
19516
19734
|
}
|
|
19517
19735
|
|
|
19736
|
+
// src/utils/doc-builders.ts
|
|
19737
|
+
function buildHtmlDocEntry(options) {
|
|
19738
|
+
const sources = [options.path, options.url, options.content].filter(
|
|
19739
|
+
(v) => v !== void 0
|
|
19740
|
+
);
|
|
19741
|
+
if (sources.length !== 1) {
|
|
19742
|
+
throw new Error(
|
|
19743
|
+
"story.html() requires exactly one of path, url, or content"
|
|
19744
|
+
);
|
|
19745
|
+
}
|
|
19746
|
+
return {
|
|
19747
|
+
kind: "html",
|
|
19748
|
+
path: options.path,
|
|
19749
|
+
url: options.url,
|
|
19750
|
+
content: options.content,
|
|
19751
|
+
title: options.title,
|
|
19752
|
+
height: options.height,
|
|
19753
|
+
phase: "runtime"
|
|
19754
|
+
};
|
|
19755
|
+
}
|
|
19756
|
+
|
|
19518
19757
|
// src/notifiers/slack.ts
|
|
19519
19758
|
function truncate(text2, maxLen) {
|
|
19520
19759
|
if (text2.length <= maxLen) return text2;
|
|
@@ -21324,6 +21563,9 @@ var ReportGenerator = class {
|
|
|
21324
21563
|
searchable: options.html?.searchable ?? true,
|
|
21325
21564
|
startCollapsed: options.html?.startCollapsed ?? false,
|
|
21326
21565
|
embedScreenshots: options.html?.embedScreenshots ?? true,
|
|
21566
|
+
// Under "copy" asset mode local html files become hashed assets with
|
|
21567
|
+
// an iframe src instead of being inlined into the report.
|
|
21568
|
+
embedHtmlFiles: options.html?.embedHtmlFiles ?? (options.assetMode ?? "none") !== "copy",
|
|
21327
21569
|
syntaxHighlighting: options.html?.syntaxHighlighting ?? true,
|
|
21328
21570
|
mermaidEnabled: options.html?.mermaidEnabled ?? true,
|
|
21329
21571
|
markdownEnabled: options.html?.markdownEnabled ?? true,
|
|
@@ -21499,6 +21741,7 @@ var ReportGenerator = class {
|
|
|
21499
21741
|
searchable: this.options.html.searchable,
|
|
21500
21742
|
startCollapsed: this.options.html.startCollapsed,
|
|
21501
21743
|
embedScreenshots: this.options.html.embedScreenshots,
|
|
21744
|
+
embedHtmlFiles: this.options.html.embedHtmlFiles,
|
|
21502
21745
|
syntaxHighlighting: this.options.html.syntaxHighlighting,
|
|
21503
21746
|
mermaidEnabled: this.options.html.mermaidEnabled,
|
|
21504
21747
|
markdownEnabled: this.options.html.markdownEnabled,
|
|
@@ -21670,6 +21913,7 @@ function normalizePlaywrightResults(testResults, adapterOptions, canonicalizeOpt
|
|
|
21670
21913
|
adaptPlaywrightRun,
|
|
21671
21914
|
adaptVitestRun,
|
|
21672
21915
|
assertValidRun,
|
|
21916
|
+
buildHtmlDocEntry,
|
|
21673
21917
|
buildReview,
|
|
21674
21918
|
bundleAssets,
|
|
21675
21919
|
calculateFlakiness,
|