executable-stories-react 0.14.0 → 0.16.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/index.cjs +142 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +131 -52
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +518 -361
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +4 -0
- package/dist/interactive.d.ts +4 -0
- package/dist/interactive.js +471 -314
- package/dist/interactive.js.map +1 -1
- package/dist/report-island.global.js +53 -51
- package/dist/ssr.cjs +110 -26
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.d.cts +4 -0
- package/dist/ssr.d.ts +4 -0
- package/dist/ssr.js +97 -13
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +3 -3
package/dist/ssr.cjs
CHANGED
|
@@ -23,7 +23,7 @@ __export(ssr_entry_exports, {
|
|
|
23
23
|
renderReportToHtml: () => renderReportToHtml
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(ssr_entry_exports);
|
|
26
|
-
var
|
|
26
|
+
var import_react12 = require("react");
|
|
27
27
|
var import_server = require("react-dom/server");
|
|
28
28
|
|
|
29
29
|
// src/result.ts
|
|
@@ -544,12 +544,29 @@ function DocVideo({ entry }) {
|
|
|
544
544
|
}
|
|
545
545
|
|
|
546
546
|
// src/components/doc/DocHtml.tsx
|
|
547
|
+
var import_react5 = require("react");
|
|
547
548
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
549
|
+
var MEASURE_SCRIPT = "<script>(function(){if(parent===window)return;var last=0,queued=false;var measure=function(){var kids=document.body.children,h=0;for(var i=0;i<kids.length;i++)h=Math.max(h,kids[i].getBoundingClientRect().bottom);return Math.ceil(h||document.body.getBoundingClientRect().bottom)};var post=function(){queued=false;var h=measure();if(h===last)return;last=h;parent.postMessage({__esHtmlHeight:h},'*')};var schedule=function(){if(queued)return;queued=true;requestAnimationFrame(post)};var start=function(){new ResizeObserver(schedule).observe(document.body);new MutationObserver(schedule).observe(document.body,{subtree:true,childList:true,attributes:true,characterData:true});addEventListener('load',schedule);post()};if(document.body)start();else addEventListener('DOMContentLoaded',start)})();</script>";
|
|
550
|
+
var MAX_MEASURED_HEIGHT = 5e3;
|
|
548
551
|
function DocHtml({ entry }) {
|
|
549
|
-
const
|
|
552
|
+
const declaredHeight = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
|
|
550
553
|
const title = entry.title ?? "Embedded HTML";
|
|
551
554
|
const safeHref = (0, import_url.safeUrl)(entry.url ?? entry.path);
|
|
552
|
-
const
|
|
555
|
+
const frameRef = (0, import_react5.useRef)(null);
|
|
556
|
+
const [measuredHeight, setMeasuredHeight] = (0, import_react5.useState)();
|
|
557
|
+
(0, import_react5.useEffect)(() => {
|
|
558
|
+
if (entry.content === void 0) return;
|
|
559
|
+
const onMessage = (event) => {
|
|
560
|
+
if (event.source !== frameRef.current?.contentWindow) return;
|
|
561
|
+
const reported = event.data?.__esHtmlHeight;
|
|
562
|
+
if (typeof reported !== "number" || !Number.isFinite(reported) || reported <= 0) return;
|
|
563
|
+
setMeasuredHeight(Math.min(reported, MAX_MEASURED_HEIGHT));
|
|
564
|
+
};
|
|
565
|
+
window.addEventListener("message", onMessage);
|
|
566
|
+
return () => window.removeEventListener("message", onMessage);
|
|
567
|
+
}, [entry.content]);
|
|
568
|
+
const height = measuredHeight === void 0 ? declaredHeight : `${measuredHeight}px`;
|
|
569
|
+
const frameProps = entry.content !== void 0 ? { srcDoc: entry.content + MEASURE_SCRIPT } : { src: safeHref ?? "" };
|
|
553
570
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
|
|
554
571
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("figcaption", { className: "flex items-center justify-between border-b border-border bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground", children: [
|
|
555
572
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: entry.title ?? "HTML" }),
|
|
@@ -569,6 +586,7 @@ function DocHtml({ entry }) {
|
|
|
569
586
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
570
587
|
"iframe",
|
|
571
588
|
{
|
|
589
|
+
ref: frameRef,
|
|
572
590
|
...frameProps,
|
|
573
591
|
sandbox: "allow-scripts",
|
|
574
592
|
loading: "lazy",
|
|
@@ -1022,11 +1040,11 @@ function ReportTrace({ spans }) {
|
|
|
1022
1040
|
}
|
|
1023
1041
|
|
|
1024
1042
|
// src/interactive/scenario-history-context.ts
|
|
1025
|
-
var
|
|
1026
|
-
var ScenarioHistoryContext = (0,
|
|
1043
|
+
var import_react6 = require("react");
|
|
1044
|
+
var ScenarioHistoryContext = (0, import_react6.createContext)(null);
|
|
1027
1045
|
var ScenarioHistoryProvider = ScenarioHistoryContext.Provider;
|
|
1028
1046
|
function useScenarioHistory() {
|
|
1029
|
-
return (0,
|
|
1047
|
+
return (0, import_react6.useContext)(ScenarioHistoryContext);
|
|
1030
1048
|
}
|
|
1031
1049
|
|
|
1032
1050
|
// src/lib/run-history.ts
|
|
@@ -1117,7 +1135,7 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
1117
1135
|
}
|
|
1118
1136
|
|
|
1119
1137
|
// src/components/ScenarioStaleness.tsx
|
|
1120
|
-
var
|
|
1138
|
+
var import_react8 = require("react");
|
|
1121
1139
|
|
|
1122
1140
|
// src/lib/provenance.ts
|
|
1123
1141
|
function formatRelativeAge(thenMs, nowMs) {
|
|
@@ -1164,11 +1182,11 @@ function prUrl(ci) {
|
|
|
1164
1182
|
}
|
|
1165
1183
|
|
|
1166
1184
|
// src/interactive/scenario-freshness-context.tsx
|
|
1167
|
-
var
|
|
1168
|
-
var ScenarioFreshnessContext = (0,
|
|
1185
|
+
var import_react7 = require("react");
|
|
1186
|
+
var ScenarioFreshnessContext = (0, import_react7.createContext)(null);
|
|
1169
1187
|
var ScenarioFreshnessProvider = ScenarioFreshnessContext.Provider;
|
|
1170
1188
|
function useScenarioFreshness() {
|
|
1171
|
-
return (0,
|
|
1189
|
+
return (0, import_react7.useContext)(ScenarioFreshnessContext);
|
|
1172
1190
|
}
|
|
1173
1191
|
|
|
1174
1192
|
// src/components/ScenarioStaleness.tsx
|
|
@@ -1176,8 +1194,8 @@ var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
|
1176
1194
|
function ScenarioStaleness({ scenario }) {
|
|
1177
1195
|
const freshness = useScenarioFreshness();
|
|
1178
1196
|
const fixedNow = freshness?.nowMs;
|
|
1179
|
-
const [now, setNow] = (0,
|
|
1180
|
-
(0,
|
|
1197
|
+
const [now, setNow] = (0, import_react8.useState)(fixedNow);
|
|
1198
|
+
(0, import_react8.useEffect)(() => {
|
|
1181
1199
|
if (fixedNow === void 0) setNow(Date.now());
|
|
1182
1200
|
}, [fixedNow]);
|
|
1183
1201
|
if (!freshness || now === void 0) return null;
|
|
@@ -1191,20 +1209,20 @@ function ScenarioStaleness({ scenario }) {
|
|
|
1191
1209
|
}
|
|
1192
1210
|
|
|
1193
1211
|
// src/interactive/collapse-context.ts
|
|
1194
|
-
var
|
|
1195
|
-
var CollapseContext = (0,
|
|
1212
|
+
var import_react9 = require("react");
|
|
1213
|
+
var CollapseContext = (0, import_react9.createContext)(null);
|
|
1196
1214
|
var CollapseProvider = CollapseContext.Provider;
|
|
1197
1215
|
function useCollapse() {
|
|
1198
|
-
return (0,
|
|
1216
|
+
return (0, import_react9.useContext)(CollapseContext);
|
|
1199
1217
|
}
|
|
1200
1218
|
|
|
1201
1219
|
// src/interactive/scenario-actions.tsx
|
|
1202
|
-
var
|
|
1220
|
+
var import_react10 = require("react");
|
|
1203
1221
|
var import_scenario_markdown = require("executable-stories-core/utils/scenario-markdown");
|
|
1204
|
-
var ScenarioActionsContext = (0,
|
|
1222
|
+
var ScenarioActionsContext = (0, import_react10.createContext)(null);
|
|
1205
1223
|
var ScenarioActionsProvider = ScenarioActionsContext.Provider;
|
|
1206
1224
|
function useScenarioActions() {
|
|
1207
|
-
return (0,
|
|
1225
|
+
return (0, import_react10.useContext)(ScenarioActionsContext);
|
|
1208
1226
|
}
|
|
1209
1227
|
|
|
1210
1228
|
// src/components/ui/card.tsx
|
|
@@ -1765,23 +1783,85 @@ function ReportErrorShell({
|
|
|
1765
1783
|
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportSchemaError, { error }) });
|
|
1766
1784
|
}
|
|
1767
1785
|
|
|
1768
|
-
// src/components/
|
|
1786
|
+
// src/components/ReportSpanGraph.tsx
|
|
1787
|
+
var import_span_graph = require("executable-stories-core/span-graph");
|
|
1788
|
+
var import_react11 = require("react");
|
|
1769
1789
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
1790
|
+
var LANE_LABEL = {
|
|
1791
|
+
edge: "Edge",
|
|
1792
|
+
service: "Service",
|
|
1793
|
+
queue: "Queue",
|
|
1794
|
+
datastore: "Data"
|
|
1795
|
+
};
|
|
1796
|
+
var MARK_LABEL = {
|
|
1797
|
+
failing: "Failing",
|
|
1798
|
+
added: "New",
|
|
1799
|
+
changed: "Changed"
|
|
1800
|
+
};
|
|
1801
|
+
var MARK_CLASS = {
|
|
1802
|
+
failing: "text-fail",
|
|
1803
|
+
added: "text-pass",
|
|
1804
|
+
changed: "text-pend"
|
|
1805
|
+
};
|
|
1806
|
+
function MarkBadge({ node }) {
|
|
1807
|
+
const mark = (0, import_span_graph.spanGraphNodeMark)(node);
|
|
1808
|
+
if (!mark) return null;
|
|
1809
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: cn("ml-2 text-xs font-medium", MARK_CLASS[mark]), children: MARK_LABEL[mark] });
|
|
1810
|
+
}
|
|
1811
|
+
function ReportSpanGraph() {
|
|
1812
|
+
const report = useReport();
|
|
1813
|
+
const { code, graph, titleById } = (0, import_react11.useMemo)(() => {
|
|
1814
|
+
const scenarios = report.features.flatMap((feature) => feature.scenarios);
|
|
1815
|
+
const derived = (0, import_span_graph.deriveSpanGraph)(scenarios);
|
|
1816
|
+
return {
|
|
1817
|
+
graph: derived,
|
|
1818
|
+
code: (0, import_span_graph.spanGraphToMermaid)(derived),
|
|
1819
|
+
titleById: new Map(scenarios.map((scenario) => [scenario.id, scenario.title]))
|
|
1820
|
+
};
|
|
1821
|
+
}, [report]);
|
|
1822
|
+
if (code === "") return null;
|
|
1823
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("section", { className: "es-span-graph mt-6", "aria-labelledby": "es-span-graph-heading", children: [
|
|
1824
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("h2", { id: "es-span-graph-heading", className: "text-base font-semibold text-foreground", children: "Architecture, as it ran" }),
|
|
1825
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: "Derived from this run\u2019s traces. Every component was named by a span while a scenario ran, so nothing here is inferred from the code. Instrumented, exercised paths only: a component no scenario reaches does not appear." }),
|
|
1826
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(DocMermaid, { entry: { kind: "mermaid", phase: "static", code } }),
|
|
1827
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("table", { className: "mt-2 w-full text-left text-sm", children: [
|
|
1828
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("caption", { className: "sr-only", children: "Each component and the scenarios that exercised it" }),
|
|
1829
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("tr", { className: "text-xs text-muted-foreground", children: [
|
|
1830
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("th", { scope: "col", className: "py-1 pr-4 font-medium", children: "Component" }),
|
|
1831
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("th", { scope: "col", className: "py-1 pr-4 font-medium", children: "Lane" }),
|
|
1832
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("th", { scope: "col", className: "py-1 font-medium", children: "Covered by" })
|
|
1833
|
+
] }) }),
|
|
1834
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("tbody", { children: graph.nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("tr", { className: "border-t border-border align-top", children: [
|
|
1835
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("th", { scope: "row", className: "py-1.5 pr-4 font-mono text-xs font-normal", children: [
|
|
1836
|
+
node.id,
|
|
1837
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(MarkBadge, { node })
|
|
1838
|
+
] }),
|
|
1839
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("td", { className: "py-1.5 pr-4 text-xs text-muted-foreground", children: LANE_LABEL[node.kind] }),
|
|
1840
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("td", { className: "py-1.5", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("ul", { className: "flex flex-col gap-0.5", children: node.scenarioIds.map((id) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("a", { href: `#${id}`, className: "text-xs underline underline-offset-2", children: titleById.get(id) ?? id }) }, id)) }) })
|
|
1841
|
+
] }, node.id)) })
|
|
1842
|
+
] })
|
|
1843
|
+
] });
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
// src/components/Report.tsx
|
|
1847
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
1770
1848
|
function Report(props) {
|
|
1771
1849
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1772
1850
|
const result = unwrapReport(report);
|
|
1773
1851
|
if (!result.ok) {
|
|
1774
|
-
return /* @__PURE__ */ (0,
|
|
1852
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1775
1853
|
}
|
|
1776
1854
|
const data = result.data;
|
|
1777
1855
|
const hasContent = data.features.length > 0;
|
|
1778
|
-
return /* @__PURE__ */ (0,
|
|
1779
|
-
/* @__PURE__ */ (0,
|
|
1780
|
-
|
|
1856
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
|
|
1857
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ReportTitleBlock, { title }) }),
|
|
1858
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ReportSpanGraph, {}),
|
|
1859
|
+
hasContent ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ReportEmpty, {})
|
|
1781
1860
|
] }) });
|
|
1782
1861
|
}
|
|
1783
1862
|
|
|
1784
1863
|
// src/ssr-entry.ts
|
|
1864
|
+
var import_report_favicon = require("executable-stories-core/utils/report-favicon");
|
|
1785
1865
|
var ROOT_ID = "es-report-root";
|
|
1786
1866
|
var DATA_ID = "es-report-data";
|
|
1787
1867
|
var HISTORY_ID = "es-report-history";
|
|
@@ -1835,10 +1915,12 @@ function renderReportToHtml(report, options = {}) {
|
|
|
1835
1915
|
mermaid = true,
|
|
1836
1916
|
islandScript = "",
|
|
1837
1917
|
staleAfterDays = 7,
|
|
1838
|
-
scenarioHistory
|
|
1918
|
+
scenarioHistory,
|
|
1919
|
+
share = false,
|
|
1920
|
+
shareCommand = ""
|
|
1839
1921
|
} = options;
|
|
1840
1922
|
const markup = (0, import_server.renderToStaticMarkup)(
|
|
1841
|
-
(0,
|
|
1923
|
+
(0, import_react12.createElement)(Report, { report, title })
|
|
1842
1924
|
);
|
|
1843
1925
|
const cdn = cdnAssets(syntaxHighlighting, mermaid);
|
|
1844
1926
|
const parsed = unwrapReport(report);
|
|
@@ -1848,7 +1930,8 @@ function renderReportToHtml(report, options = {}) {
|
|
|
1848
1930
|
const historyScript = interactive && scenarioHistory && Object.keys(scenarioHistory).length > 0 ? `<script type="application/json" id="${HISTORY_ID}">${escapeJsonForScript(JSON.stringify(scenarioHistory))}</script>` : "";
|
|
1849
1931
|
const islandTag = interactive ? `<script>${islandScript}</script>` : "";
|
|
1850
1932
|
const cdnBody = interactive ? "" : cdn.body;
|
|
1851
|
-
const
|
|
1933
|
+
const shareAttrs = share ? ` data-es-share="true"${shareCommand ? ` data-es-share-cmd="${escapeHtml(shareCommand)}"` : ""}` : "";
|
|
1934
|
+
const islandConfigAttrs = interactive ? ` data-es-syntax="${syntaxHighlighting ? "true" : "false"}" data-es-mermaid="${mermaid ? "true" : "false"}" data-es-stale-days="${Number.isFinite(staleAfterDays) && staleAfterDays >= 0 ? staleAfterDays : 7}"${shareAttrs}` : "";
|
|
1852
1935
|
const rootAttrs = interactive ? ` id="${ROOT_ID}" data-title="${escapeHtml(title)}"${islandConfigAttrs}` : "";
|
|
1853
1936
|
return `<!DOCTYPE html>
|
|
1854
1937
|
<html lang="${escapeHtml(lang)}" data-theme="${theme === "dark" ? "dark" : "light"}">
|
|
@@ -1856,6 +1939,7 @@ function renderReportToHtml(report, options = {}) {
|
|
|
1856
1939
|
<meta charset="UTF-8">
|
|
1857
1940
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1858
1941
|
<meta name="color-scheme" content="light dark">
|
|
1942
|
+
${import_report_favicon.REPORT_FAVICON_LINK}
|
|
1859
1943
|
<title>${escapeHtml(title)}</title>
|
|
1860
1944
|
${cdn.head}
|
|
1861
1945
|
${headExtra}
|