executable-stories-formatters 0.7.6 → 0.7.8

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 CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
+ AstroFormatter: () => AstroFormatter,
33
34
  CucumberHtmlFormatter: () => CucumberHtmlFormatter,
34
35
  CucumberJsonFormatter: () => CucumberJsonFormatter,
35
36
  CucumberMessagesFormatter: () => CucumberMessagesFormatter,
@@ -53,6 +54,7 @@ __export(src_exports, {
53
54
  canonicalizeRun: () => canonicalizeRun,
54
55
  clearVersionCache: () => clearVersionCache,
55
56
  computeTestMetrics: () => computeTestMetrics,
57
+ copyMarkdownAssets: () => copyMarkdownAssets,
56
58
  createPrCommentSummary: () => createPrCommentSummary,
57
59
  createReportGenerator: () => createReportGenerator,
58
60
  deriveStepResults: () => deriveStepResults,
@@ -85,6 +87,7 @@ __export(src_exports, {
85
87
  resolveAttachments: () => resolveAttachments,
86
88
  resolveTheme: () => resolveTheme,
87
89
  resolveTraceUrl: () => resolveTraceUrl,
90
+ rewriteAssetPaths: () => rewriteAssetPaths,
88
91
  saveHistory: () => saveHistory,
89
92
  sendNotifications: () => sendNotifications,
90
93
  sendSlackNotification: () => sendSlackNotification,
@@ -100,8 +103,8 @@ __export(src_exports, {
100
103
  validateCanonicalRun: () => validateCanonicalRun
101
104
  });
102
105
  module.exports = __toCommonJS(src_exports);
103
- var fs6 = require("fs");
104
- var path6 = __toESM(require("path"), 1);
106
+ var fs7 = require("fs");
107
+ var path7 = __toESM(require("path"), 1);
105
108
  var fsPromises = __toESM(require("fs/promises"), 1);
106
109
 
107
110
  // src/converters/acl/status.ts
@@ -15103,8 +15106,8 @@ function extractDocAttachments(step) {
15103
15106
  }
15104
15107
  return attachments;
15105
15108
  }
15106
- function guessMediaType(path7) {
15107
- const lower = path7.toLowerCase();
15109
+ function guessMediaType(path8) {
15110
+ const lower = path8.toLowerCase();
15108
15111
  if (lower.endsWith(".png")) return "image/png";
15109
15112
  if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
15110
15113
  if (lower.endsWith(".gif")) return "image/gif";
@@ -15245,11 +15248,11 @@ var CucumberHtmlFormatter = class {
15245
15248
  for (const envelope of envelopes) {
15246
15249
  const accepted = htmlStream.write(envelope);
15247
15250
  if (!accepted) {
15248
- await new Promise((resolve5) => htmlStream.once("drain", resolve5));
15251
+ await new Promise((resolve7) => htmlStream.once("drain", resolve7));
15249
15252
  }
15250
15253
  }
15251
- await new Promise((resolve5, reject) => {
15252
- collector.on("finish", resolve5);
15254
+ await new Promise((resolve7, reject) => {
15255
+ collector.on("finish", resolve7);
15253
15256
  collector.on("error", reject);
15254
15257
  htmlStream.end();
15255
15258
  });
@@ -16251,6 +16254,177 @@ function replaceAssetRef(html, original, replacement) {
16251
16254
  return html;
16252
16255
  }
16253
16256
 
16257
+ // src/formatters/astro.ts
16258
+ var AstroFormatter = class _AstroFormatter {
16259
+ markdownFormatter;
16260
+ title;
16261
+ constructor(options = {}) {
16262
+ this.title = options.markdown?.title ?? "User Stories";
16263
+ this.markdownFormatter = new MarkdownFormatter({
16264
+ ...options.markdown,
16265
+ title: this.title,
16266
+ stepStyle: "gherkin",
16267
+ includeFrontMatter: false,
16268
+ includeSummaryTable: false,
16269
+ includeMetadata: false
16270
+ });
16271
+ }
16272
+ format(run) {
16273
+ const markdown = this.markdownFormatter.format(run);
16274
+ const body = markdown.replace(/^# .+\n\n?/, "");
16275
+ const frontmatter = this.buildFrontmatter(run);
16276
+ return `${frontmatter}
16277
+ ${body}`;
16278
+ }
16279
+ buildFrontmatter(run) {
16280
+ const badge = _AstroFormatter.computeBadge(run.testCases);
16281
+ const count = run.testCases.length;
16282
+ const description = `${count} scenario${count !== 1 ? "s" : ""} \u2014 ${badge.text.toLowerCase()}`;
16283
+ const lines = [
16284
+ "---",
16285
+ `title: ${this.title}`,
16286
+ `description: ${description}`,
16287
+ "sidebar:",
16288
+ " badge:",
16289
+ ` text: ${badge.text}`,
16290
+ ` variant: ${badge.variant}`,
16291
+ "---"
16292
+ ];
16293
+ return lines.join("\n");
16294
+ }
16295
+ static computeBadge(testCases) {
16296
+ const statuses = new Set(testCases.map((tc) => tc.status));
16297
+ if (statuses.has("failed")) return { text: "Failed", variant: "danger" };
16298
+ if (statuses.has("pending")) return { text: "Pending", variant: "caution" };
16299
+ if (statuses.has("skipped") && !statuses.has("passed")) return { text: "Skipped", variant: "caution" };
16300
+ return { text: "Passed", variant: "success" };
16301
+ }
16302
+ };
16303
+
16304
+ // src/formatters/astro-assets.ts
16305
+ var fs4 = __toESM(require("fs"), 1);
16306
+ var path4 = __toESM(require("path"), 1);
16307
+ var SKIP_PREFIXES = ["http://", "https://", "data:", "#"];
16308
+ function isLocalPath(src) {
16309
+ const trimmed = src.trim();
16310
+ if (SKIP_PREFIXES.some((prefix) => trimmed.startsWith(prefix))) {
16311
+ return false;
16312
+ }
16313
+ return !path4.posix.isAbsolute(trimmed) && !path4.win32.isAbsolute(trimmed);
16314
+ }
16315
+ function stripCodeContent(markdown) {
16316
+ let result = markdown.replace(/^[ \t]*(`{3,}|~{3,})[^\n]*\n[\s\S]*?^[ \t]*\1\s*$/gm, "");
16317
+ result = result.replace(/(`+)(?:(?!\1).)+\1/g, "");
16318
+ result = result.replace(/<pre\b[^>]*>[\s\S]*?<\/pre>/gi, "");
16319
+ result = result.replace(/<code\b[^>]*>[\s\S]*?<\/code>/gi, "");
16320
+ return result;
16321
+ }
16322
+ function scanMarkdownAssets(markdown) {
16323
+ const found = /* @__PURE__ */ new Set();
16324
+ const stripped = stripCodeContent(markdown);
16325
+ const mdImageRe = /!\[[^\]]*\]\(([^)"'\s]+)(?:\s+["'][^"']*["'])?\s*\)/g;
16326
+ let match;
16327
+ while ((match = mdImageRe.exec(stripped)) !== null) {
16328
+ const src = match[1].trim();
16329
+ if (isLocalPath(src)) {
16330
+ found.add(src);
16331
+ }
16332
+ }
16333
+ const htmlSrcRe = /<(?:img|source|video)[^>]+\bsrc=["']([^"']+)["'][^>]*>/gi;
16334
+ while ((match = htmlSrcRe.exec(stripped)) !== null) {
16335
+ const src = match[1].trim();
16336
+ if (isLocalPath(src)) {
16337
+ found.add(src);
16338
+ }
16339
+ }
16340
+ return Array.from(found);
16341
+ }
16342
+ function splitByCode(markdown) {
16343
+ const codeRe = /^[ \t]*(`{3,}|~{3,})[^\n]*\n[\s\S]*?^[ \t]*\1\s*$|<pre\b[^>]*>[\s\S]*?<\/pre>|<code\b[^>]*>[\s\S]*?<\/code>|(`+)(?:(?!\2).)+\2/gim;
16344
+ const segments = [];
16345
+ let lastIndex = 0;
16346
+ for (const match of markdown.matchAll(codeRe)) {
16347
+ if (match.index > lastIndex) {
16348
+ segments.push(markdown.slice(lastIndex, match.index));
16349
+ }
16350
+ segments.push(match[0]);
16351
+ lastIndex = match.index + match[0].length;
16352
+ }
16353
+ if (lastIndex < markdown.length) {
16354
+ segments.push(markdown.slice(lastIndex));
16355
+ }
16356
+ return segments;
16357
+ }
16358
+ function isCode(segment) {
16359
+ const trimmed = segment.trimStart();
16360
+ return trimmed.startsWith("`") || trimmed.startsWith("~") || trimmed.startsWith("<pre") || trimmed.startsWith("<code");
16361
+ }
16362
+ function rewriteProseSegment(prose, assetsBaseUrl, pathMap) {
16363
+ let result = prose;
16364
+ result = result.replace(
16365
+ /(!\[[^\]]*\]\()([^)"'\s]+)((?:\s+["'][^"']*["'])?\s*\))/g,
16366
+ (full, pre, src, post) => {
16367
+ const trimmed = src.trim();
16368
+ if (!isLocalPath(trimmed)) return full;
16369
+ if (pathMap) {
16370
+ const mapped = pathMap.get(trimmed);
16371
+ if (mapped === void 0) return full;
16372
+ return `${pre}${assetsBaseUrl}/${mapped}${post}`;
16373
+ }
16374
+ return `${pre}${assetsBaseUrl}/${trimmed}${post}`;
16375
+ }
16376
+ );
16377
+ result = result.replace(
16378
+ /(<(?:img|source|video)[^>]+\bsrc=["'])([^"']+)(["'][^>]*>)/gi,
16379
+ (full, pre, src, post) => {
16380
+ const trimmed = src.trim();
16381
+ if (!isLocalPath(trimmed)) return full;
16382
+ if (pathMap) {
16383
+ const mapped = pathMap.get(trimmed);
16384
+ if (mapped === void 0) return full;
16385
+ return `${pre}${assetsBaseUrl}/${mapped}${post}`;
16386
+ }
16387
+ return `${pre}${assetsBaseUrl}/${trimmed}${post}`;
16388
+ }
16389
+ );
16390
+ return result;
16391
+ }
16392
+ function rewriteAssetPaths(markdown, assetsBaseUrl, pathMap) {
16393
+ return splitByCode(markdown).map((seg) => isCode(seg) ? seg : rewriteProseSegment(seg, assetsBaseUrl, pathMap)).join("");
16394
+ }
16395
+ function copyMarkdownAssets(options) {
16396
+ const {
16397
+ markdown,
16398
+ markdownDir,
16399
+ assetsDir,
16400
+ assetsBaseUrl,
16401
+ allowMissing = false
16402
+ } = options;
16403
+ const refs = scanMarkdownAssets(markdown);
16404
+ const pathMap = /* @__PURE__ */ new Map();
16405
+ const missing = [];
16406
+ for (const ref of refs) {
16407
+ const absPath = path4.resolve(markdownDir, ref);
16408
+ if (!fs4.existsSync(absPath)) {
16409
+ if (!allowMissing) {
16410
+ throw new Error(`Asset not found: ${absPath}`);
16411
+ }
16412
+ missing.push(ref);
16413
+ continue;
16414
+ }
16415
+ const relativeCopied = copyAsset(absPath, assetsDir);
16416
+ const fileName = relativeCopied.replace(/^assets\//, "");
16417
+ pathMap.set(ref, fileName);
16418
+ }
16419
+ const rewritten = rewriteAssetPaths(markdown, assetsBaseUrl, pathMap);
16420
+ return {
16421
+ markdown: rewritten,
16422
+ copiedCount: pathMap.size,
16423
+ missingCount: missing.length,
16424
+ missing
16425
+ };
16426
+ }
16427
+
16254
16428
  // src/converters/adapters/jest.ts
16255
16429
  function mapJestStatus(status) {
16256
16430
  switch (status) {
@@ -17018,27 +17192,27 @@ function pickleStepArgumentToDocs(ps) {
17018
17192
  }
17019
17193
 
17020
17194
  // src/utils/git-info.ts
17021
- var fs4 = __toESM(require("fs"), 1);
17022
- var path4 = __toESM(require("path"), 1);
17195
+ var fs5 = __toESM(require("fs"), 1);
17196
+ var path5 = __toESM(require("path"), 1);
17023
17197
  function readGitSha(cwd = process.cwd()) {
17024
17198
  const envSha = process.env.GITHUB_SHA || process.env.GIT_COMMIT || process.env.CI_COMMIT_SHA;
17025
17199
  if (envSha) return envSha;
17026
17200
  const gitDir = findGitDir(cwd);
17027
17201
  if (!gitDir) return void 0;
17028
17202
  try {
17029
- const headPath = path4.join(gitDir, "HEAD");
17030
- const head = fs4.readFileSync(headPath, "utf8").trim();
17203
+ const headPath = path5.join(gitDir, "HEAD");
17204
+ const head = fs5.readFileSync(headPath, "utf8").trim();
17031
17205
  if (!head.startsWith("ref:")) {
17032
17206
  return head;
17033
17207
  }
17034
17208
  const refPath = head.replace("ref:", "").trim();
17035
- const refFile = path4.join(gitDir, refPath);
17036
- if (fs4.existsSync(refFile)) {
17037
- return fs4.readFileSync(refFile, "utf8").trim();
17209
+ const refFile = path5.join(gitDir, refPath);
17210
+ if (fs5.existsSync(refFile)) {
17211
+ return fs5.readFileSync(refFile, "utf8").trim();
17038
17212
  }
17039
- const packedRefs = path4.join(gitDir, "packed-refs");
17040
- if (fs4.existsSync(packedRefs)) {
17041
- const content = fs4.readFileSync(packedRefs, "utf8");
17213
+ const packedRefs = path5.join(gitDir, "packed-refs");
17214
+ if (fs5.existsSync(packedRefs)) {
17215
+ const content = fs5.readFileSync(packedRefs, "utf8");
17042
17216
  for (const line of content.split("\n")) {
17043
17217
  if (!line || line.startsWith("#") || line.startsWith("^")) continue;
17044
17218
  const [sha, ref] = line.split(" ");
@@ -17053,19 +17227,19 @@ function readGitSha(cwd = process.cwd()) {
17053
17227
  function findGitDir(start) {
17054
17228
  let current = start;
17055
17229
  while (true) {
17056
- const candidate = path4.join(current, ".git");
17057
- if (fs4.existsSync(candidate)) {
17058
- const stat = fs4.statSync(candidate);
17230
+ const candidate = path5.join(current, ".git");
17231
+ if (fs5.existsSync(candidate)) {
17232
+ const stat = fs5.statSync(candidate);
17059
17233
  if (stat.isFile()) {
17060
- const content = fs4.readFileSync(candidate, "utf8").trim();
17234
+ const content = fs5.readFileSync(candidate, "utf8").trim();
17061
17235
  const match = content.match(/^gitdir: (.+)$/);
17062
17236
  if (match) {
17063
- return path4.resolve(current, match[1]);
17237
+ return path5.resolve(current, match[1]);
17064
17238
  }
17065
17239
  }
17066
17240
  return candidate;
17067
17241
  }
17068
- const parent = path4.dirname(current);
17242
+ const parent = path5.dirname(current);
17069
17243
  if (parent === current) return void 0;
17070
17244
  current = parent;
17071
17245
  }
@@ -17076,8 +17250,8 @@ function readBranchName(cwd = process.cwd()) {
17076
17250
  const gitDir = findGitDir(cwd);
17077
17251
  if (!gitDir) return void 0;
17078
17252
  try {
17079
- const headPath = path4.join(gitDir, "HEAD");
17080
- const head = fs4.readFileSync(headPath, "utf8").trim();
17253
+ const headPath = path5.join(gitDir, "HEAD");
17254
+ const head = fs5.readFileSync(headPath, "utf8").trim();
17081
17255
  if (head.startsWith("ref:")) {
17082
17256
  const refPath = head.replace("ref:", "").trim();
17083
17257
  const match = refPath.match(/^refs\/heads\/(.+)$/);
@@ -17114,8 +17288,8 @@ function nanosecondsToMs(ns) {
17114
17288
  }
17115
17289
 
17116
17290
  // src/utils/metadata.ts
17117
- var fs5 = __toESM(require("fs"), 1);
17118
- var path5 = __toESM(require("path"), 1);
17291
+ var fs6 = __toESM(require("fs"), 1);
17292
+ var path6 = __toESM(require("path"), 1);
17119
17293
  var versionCache = /* @__PURE__ */ new Map();
17120
17294
  function readPackageVersion(root) {
17121
17295
  if (versionCache.has(root)) {
@@ -17126,18 +17300,18 @@ function readPackageVersion(root) {
17126
17300
  return version;
17127
17301
  }
17128
17302
  function findPackageVersion(startDir) {
17129
- let current = path5.resolve(startDir);
17303
+ let current = path6.resolve(startDir);
17130
17304
  while (true) {
17131
- const pkgPath = path5.join(current, "package.json");
17305
+ const pkgPath = path6.join(current, "package.json");
17132
17306
  try {
17133
- if (fs5.existsSync(pkgPath)) {
17134
- const raw = fs5.readFileSync(pkgPath, "utf8");
17307
+ if (fs6.existsSync(pkgPath)) {
17308
+ const raw = fs6.readFileSync(pkgPath, "utf8");
17135
17309
  const parsed = JSON.parse(raw);
17136
17310
  return parsed.version;
17137
17311
  }
17138
17312
  } catch {
17139
17313
  }
17140
- const parent = path5.dirname(current);
17314
+ const parent = path6.dirname(current);
17141
17315
  if (parent === current) {
17142
17316
  return void 0;
17143
17317
  }
@@ -18022,6 +18196,37 @@ function listScenarios(args, _deps) {
18022
18196
  }));
18023
18197
  return JSON.stringify(items, null, 2);
18024
18198
  }
18199
+ if (format === "csv") {
18200
+ const header = "id,scenario,status,sourceFile,sourceLine,tags";
18201
+ const rows = testCases.map((tc) => {
18202
+ const fields = [
18203
+ tc.id,
18204
+ tc.story.scenario,
18205
+ tc.status,
18206
+ tc.sourceFile,
18207
+ String(tc.sourceLine),
18208
+ tc.tags.join(" ")
18209
+ ];
18210
+ return fields.map((f) => {
18211
+ if (f.includes(",") || f.includes('"') || f.includes("\n")) {
18212
+ return `"${f.replace(/"/g, '""')}"`;
18213
+ }
18214
+ return f;
18215
+ }).join(",");
18216
+ });
18217
+ return [header, ...rows].join("\n");
18218
+ }
18219
+ if (format === "markdown-table") {
18220
+ const header = "| Status | Scenario | Location | Tags |";
18221
+ const divider = "|--------|----------|----------|------|";
18222
+ const rows = testCases.map((tc) => {
18223
+ const icon = STATUS_ICONS[tc.status] ?? "?";
18224
+ const location = `${tc.sourceFile}:${tc.sourceLine}`;
18225
+ const tags = tc.tags.map((t) => `@${t}`).join(" ");
18226
+ return `| ${icon} | ${tc.story.scenario} | ${location} | ${tags} |`;
18227
+ });
18228
+ return [header, divider, ...rows].join("\n");
18229
+ }
18025
18230
  if (testCases.length === 0) {
18026
18231
  return "No scenarios found.";
18027
18232
  }
@@ -18063,6 +18268,7 @@ function listScenarios(args, _deps) {
18063
18268
 
18064
18269
  // src/index.ts
18065
18270
  var FORMAT_EXTENSIONS = {
18271
+ astro: ".md",
18066
18272
  markdown: ".md",
18067
18273
  html: ".html",
18068
18274
  "cucumber-html": ".cucumber.html",
@@ -18095,11 +18301,11 @@ function computeOutputPath(sourceFile, format, mode, colocatedStyle, baseOutputD
18095
18301
  const ext = FORMAT_EXTENSIONS[format];
18096
18302
  const effectiveName = outputName + (outputNameSuffix ?? "");
18097
18303
  if (mode === "aggregated") {
18098
- return toPosix(path6.join(baseOutputDir, `${effectiveName}${ext}`));
18304
+ return toPosix(path7.join(baseOutputDir, `${effectiveName}${ext}`));
18099
18305
  }
18100
18306
  const normalizedSource = toPosix(sourceFile);
18101
- const dirOfSource = path6.posix.dirname(normalizedSource);
18102
- let baseName = path6.posix.basename(normalizedSource);
18307
+ const dirOfSource = path7.posix.dirname(normalizedSource);
18308
+ let baseName = path7.posix.basename(normalizedSource);
18103
18309
  for (const testExt of TEST_EXTENSIONS) {
18104
18310
  if (baseName.endsWith(testExt)) {
18105
18311
  baseName = baseName.slice(0, -testExt.length);
@@ -18108,9 +18314,9 @@ function computeOutputPath(sourceFile, format, mode, colocatedStyle, baseOutputD
18108
18314
  }
18109
18315
  const fileName = `${baseName}.${effectiveName}${ext}`;
18110
18316
  if (colocatedStyle === "adjacent") {
18111
- return toPosix(path6.posix.join(dirOfSource, fileName));
18317
+ return toPosix(path7.posix.join(dirOfSource, fileName));
18112
18318
  }
18113
- return toPosix(path6.posix.join(baseOutputDir, dirOfSource, fileName));
18319
+ return toPosix(path7.posix.join(baseOutputDir, dirOfSource, fileName));
18114
18320
  }
18115
18321
  function groupTestCasesByOutput(testCases, format, options, logger, outputNameSuffix) {
18116
18322
  const groups = /* @__PURE__ */ new Map();
@@ -18236,6 +18442,24 @@ var ReportGenerator = class {
18236
18442
  includeSourceLinks: options.markdown?.includeSourceLinks ?? true,
18237
18443
  customRenderers: options.markdown?.customRenderers
18238
18444
  },
18445
+ astro: {
18446
+ assetsDir: options.astro?.assetsDir ?? "public/stories/assets",
18447
+ assetsBaseUrl: options.astro?.assetsBaseUrl ?? "/stories/assets",
18448
+ markdown: {
18449
+ title: options.astro?.markdown?.title ?? "User Stories",
18450
+ includeStatusIcons: options.astro?.markdown?.includeStatusIcons ?? true,
18451
+ includeErrors: options.astro?.markdown?.includeErrors ?? true,
18452
+ scenarioHeadingLevel: options.astro?.markdown?.scenarioHeadingLevel ?? 3,
18453
+ groupBy: options.astro?.markdown?.groupBy ?? "file",
18454
+ sortScenarios: options.astro?.markdown?.sortScenarios ?? "source",
18455
+ suiteSeparator: options.astro?.markdown?.suiteSeparator ?? " - ",
18456
+ includeSourceLinks: options.astro?.markdown?.includeSourceLinks ?? true,
18457
+ permalinkBaseUrl: options.astro?.markdown?.permalinkBaseUrl,
18458
+ ticketUrlTemplate: options.astro?.markdown?.ticketUrlTemplate,
18459
+ traceUrlTemplate: options.astro?.markdown?.traceUrlTemplate,
18460
+ customRenderers: options.astro?.markdown?.customRenderers
18461
+ }
18462
+ },
18239
18463
  assetMode: options.assetMode ?? "none",
18240
18464
  allowMissingAssets: options.allowMissingAssets ?? false
18241
18465
  };
@@ -18273,6 +18497,24 @@ var ReportGenerator = class {
18273
18497
  });
18274
18498
  }
18275
18499
  }
18500
+ const astroPaths = results.get("astro");
18501
+ if (astroPaths) {
18502
+ for (const mdPath of astroPaths) {
18503
+ const content = await fsPromises.readFile(mdPath, "utf8");
18504
+ const mdDir = path7.dirname(mdPath);
18505
+ const assetsDir = path7.resolve(this.options.astro.assetsDir);
18506
+ const result = copyMarkdownAssets({
18507
+ markdown: content,
18508
+ markdownDir: mdDir,
18509
+ assetsDir,
18510
+ assetsBaseUrl: this.options.astro.assetsBaseUrl,
18511
+ allowMissing: this.options.allowMissingAssets
18512
+ });
18513
+ if (result.copiedCount > 0 || result.missingCount > 0) {
18514
+ await this.deps.writeFile(mdPath, result.markdown);
18515
+ }
18516
+ }
18517
+ }
18276
18518
  }
18277
18519
  return results;
18278
18520
  }
@@ -18291,9 +18533,9 @@ var ReportGenerator = class {
18291
18533
  if (groups.size === 0 && this.options.output.mode === "aggregated") {
18292
18534
  const ext = FORMAT_EXTENSIONS[format];
18293
18535
  const effectiveName = this.options.outputName + (outputNameSuffix ?? "");
18294
- const outputPath = toPosix(path6.join(this.options.outputDir, `${effectiveName}${ext}`));
18536
+ const outputPath = toPosix(path7.join(this.options.outputDir, `${effectiveName}${ext}`));
18295
18537
  const content = await this.formatContent(run, format);
18296
- const dir = path6.dirname(outputPath);
18538
+ const dir = path7.dirname(outputPath);
18297
18539
  await fsPromises.mkdir(dir, { recursive: true });
18298
18540
  await this.deps.writeFile(outputPath, content);
18299
18541
  return [outputPath];
@@ -18305,7 +18547,7 @@ var ReportGenerator = class {
18305
18547
  testCases
18306
18548
  };
18307
18549
  const content = await this.formatContent(groupRun, format);
18308
- const dir = path6.dirname(outputPath);
18550
+ const dir = path7.dirname(outputPath);
18309
18551
  await fsPromises.mkdir(dir, { recursive: true });
18310
18552
  await this.deps.writeFile(outputPath, content);
18311
18553
  writtenPaths.push(outputPath);
@@ -18368,6 +18610,13 @@ var ReportGenerator = class {
18368
18610
  });
18369
18611
  return formatter.formatToString(run);
18370
18612
  }
18613
+ case "astro": {
18614
+ const formatter = new AstroFormatter({
18615
+ assetsBaseUrl: this.options.astro.assetsBaseUrl,
18616
+ markdown: this.options.astro.markdown
18617
+ });
18618
+ return formatter.format(run);
18619
+ }
18371
18620
  case "markdown": {
18372
18621
  const formatter = new MarkdownFormatter({
18373
18622
  title: this.options.markdown.title,
@@ -18405,7 +18654,7 @@ async function generateRunComparison(args) {
18405
18654
  await fsPromises.mkdir(outputDir, { recursive: true });
18406
18655
  for (const format of args.formats) {
18407
18656
  const ext = format === "html" ? ".html" : ".md";
18408
- const outputPath = toPosix(path6.join(outputDir, `${outputName}${ext}`));
18657
+ const outputPath = toPosix(path7.join(outputDir, `${outputName}${ext}`));
18409
18658
  const content = format === "html" ? new RunDiffHtmlFormatter({ title: args.title }).format(diff) : new RunDiffMarkdownFormatter({ title: args.title }).format(diff);
18410
18659
  await fsPromises.writeFile(outputPath, content, "utf8");
18411
18660
  files.push(outputPath);
@@ -18426,6 +18675,7 @@ function normalizePlaywrightResults(testResults, adapterOptions, canonicalizeOpt
18426
18675
  }
18427
18676
  // Annotate the CommonJS export names for ESM import in node:
18428
18677
  0 && (module.exports = {
18678
+ AstroFormatter,
18429
18679
  CucumberHtmlFormatter,
18430
18680
  CucumberJsonFormatter,
18431
18681
  CucumberMessagesFormatter,
@@ -18449,6 +18699,7 @@ function normalizePlaywrightResults(testResults, adapterOptions, canonicalizeOpt
18449
18699
  canonicalizeRun,
18450
18700
  clearVersionCache,
18451
18701
  computeTestMetrics,
18702
+ copyMarkdownAssets,
18452
18703
  createPrCommentSummary,
18453
18704
  createReportGenerator,
18454
18705
  deriveStepResults,
@@ -18481,6 +18732,7 @@ function normalizePlaywrightResults(testResults, adapterOptions, canonicalizeOpt
18481
18732
  resolveAttachments,
18482
18733
  resolveTheme,
18483
18734
  resolveTraceUrl,
18735
+ rewriteAssetPaths,
18484
18736
  saveHistory,
18485
18737
  sendNotifications,
18486
18738
  sendSlackNotification,