executable-stories-formatters 0.13.0 → 0.15.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 +706 -236
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +49 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +49 -52
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -15269,7 +15269,10 @@ var MarkdownFormatter = class {
|
|
|
15269
15269
|
ticketUrlTemplate: options.ticketUrlTemplate,
|
|
15270
15270
|
traceUrlTemplate: options.traceUrlTemplate,
|
|
15271
15271
|
includeSourceLinks: options.includeSourceLinks ?? true,
|
|
15272
|
-
customRenderers: options.customRenderers
|
|
15272
|
+
customRenderers: options.customRenderers,
|
|
15273
|
+
scenarioAnchor: options.scenarioAnchor,
|
|
15274
|
+
scenarioBadge: options.scenarioBadge,
|
|
15275
|
+
scenarioNoteLink: options.scenarioNoteLink
|
|
15273
15276
|
};
|
|
15274
15277
|
}
|
|
15275
15278
|
/**
|
|
@@ -15456,6 +15459,11 @@ var MarkdownFormatter = class {
|
|
|
15456
15459
|
* Render a single scenario.
|
|
15457
15460
|
*/
|
|
15458
15461
|
renderScenario(lines, tc) {
|
|
15462
|
+
const anchorId = this.options.scenarioAnchor?.(tc);
|
|
15463
|
+
if (anchorId) {
|
|
15464
|
+
lines.push(`<a id="${anchorId}"></a>`);
|
|
15465
|
+
lines.push("");
|
|
15466
|
+
}
|
|
15459
15467
|
if (this.options.customRenderers?.renderScenarioHeader) {
|
|
15460
15468
|
const custom = this.options.customRenderers.renderScenarioHeader(tc);
|
|
15461
15469
|
if (custom !== null) {
|
|
@@ -15471,6 +15479,14 @@ var MarkdownFormatter = class {
|
|
|
15471
15479
|
icon = this.getStatusIcon(tc.status) + " ";
|
|
15472
15480
|
}
|
|
15473
15481
|
lines.push(`${headingPrefix} ${icon}${tc.story.scenario}`);
|
|
15482
|
+
const badge = this.options.scenarioBadge?.(tc);
|
|
15483
|
+
if (badge) {
|
|
15484
|
+
lines.push(badge);
|
|
15485
|
+
}
|
|
15486
|
+
const noteLink = this.options.scenarioNoteLink?.(tc);
|
|
15487
|
+
if (noteLink) {
|
|
15488
|
+
lines.push(noteLink);
|
|
15489
|
+
}
|
|
15474
15490
|
if (this.options.includeSourceLinks && this.options.permalinkBaseUrl && tc.sourceFile !== "unknown") {
|
|
15475
15491
|
const permalink = this.buildPermalink(tc);
|
|
15476
15492
|
lines.push(`Source: [${tc.sourceFile}](${permalink})`);
|
|
@@ -18287,12 +18303,16 @@ function groupBy7(items, keyFn) {
|
|
|
18287
18303
|
var fs5 = __toESM(require("fs"), 1);
|
|
18288
18304
|
var path6 = __toESM(require("path"), 1);
|
|
18289
18305
|
var SKIP_PREFIXES = ["http://", "https://", "data:", "#"];
|
|
18290
|
-
function
|
|
18306
|
+
function isRemoteRef(src) {
|
|
18291
18307
|
const trimmed = src.trim();
|
|
18292
|
-
|
|
18293
|
-
|
|
18294
|
-
|
|
18295
|
-
|
|
18308
|
+
return SKIP_PREFIXES.some((prefix) => trimmed.startsWith(prefix));
|
|
18309
|
+
}
|
|
18310
|
+
function isAbsoluteRef(src) {
|
|
18311
|
+
const trimmed = src.trim();
|
|
18312
|
+
return path6.posix.isAbsolute(trimmed) || path6.win32.isAbsolute(trimmed);
|
|
18313
|
+
}
|
|
18314
|
+
function isRelativeLocalPath(src) {
|
|
18315
|
+
return !isRemoteRef(src) && !isAbsoluteRef(src);
|
|
18296
18316
|
}
|
|
18297
18317
|
function stripCodeContent(markdown) {
|
|
18298
18318
|
let result = markdown.replace(/^[ \t]*(`{3,}|~{3,})[^\n]*\n[\s\S]*?^[ \t]*\1\s*$/gm, "");
|
|
@@ -18308,21 +18328,21 @@ function scanMarkdownAssets(markdown) {
|
|
|
18308
18328
|
let match;
|
|
18309
18329
|
while ((match = mdImageRe.exec(stripped)) !== null) {
|
|
18310
18330
|
const src = match[1].trim();
|
|
18311
|
-
if (
|
|
18331
|
+
if (!isRemoteRef(src)) {
|
|
18312
18332
|
found.add(src);
|
|
18313
18333
|
}
|
|
18314
18334
|
}
|
|
18315
18335
|
const htmlSrcRe = /<(?:img|source|video)[^>]+\bsrc=["']([^"']+)["'][^>]*>/gi;
|
|
18316
18336
|
while ((match = htmlSrcRe.exec(stripped)) !== null) {
|
|
18317
18337
|
const src = match[1].trim();
|
|
18318
|
-
if (
|
|
18338
|
+
if (!isRemoteRef(src)) {
|
|
18319
18339
|
found.add(src);
|
|
18320
18340
|
}
|
|
18321
18341
|
}
|
|
18322
18342
|
const posterRe = /<video[^>]+\bposter=["']([^"']+)["'][^>]*>/gi;
|
|
18323
18343
|
while ((match = posterRe.exec(stripped)) !== null) {
|
|
18324
18344
|
const src = match[1].trim();
|
|
18325
|
-
if (
|
|
18345
|
+
if (!isRemoteRef(src)) {
|
|
18326
18346
|
found.add(src);
|
|
18327
18347
|
}
|
|
18328
18348
|
}
|
|
@@ -18348,48 +18368,21 @@ function isCode(segment) {
|
|
|
18348
18368
|
const trimmed = segment.trimStart();
|
|
18349
18369
|
return trimmed.startsWith("`") || trimmed.startsWith("~") || trimmed.startsWith("<pre") || trimmed.startsWith("<code");
|
|
18350
18370
|
}
|
|
18371
|
+
function resolveRewrite(trimmed, assetsBaseUrl, pathMap) {
|
|
18372
|
+
if (isRemoteRef(trimmed)) return null;
|
|
18373
|
+
if (pathMap) {
|
|
18374
|
+
const mapped = pathMap.get(trimmed);
|
|
18375
|
+
return mapped === void 0 ? null : `${assetsBaseUrl}/${mapped}`;
|
|
18376
|
+
}
|
|
18377
|
+
if (!isRelativeLocalPath(trimmed)) return null;
|
|
18378
|
+
return `${assetsBaseUrl}/${trimmed}`;
|
|
18379
|
+
}
|
|
18351
18380
|
function rewriteProseSegment(prose, assetsBaseUrl, pathMap) {
|
|
18352
|
-
|
|
18353
|
-
|
|
18354
|
-
|
|
18355
|
-
|
|
18356
|
-
|
|
18357
|
-
if (!isLocalPath(trimmed)) return full;
|
|
18358
|
-
if (pathMap) {
|
|
18359
|
-
const mapped = pathMap.get(trimmed);
|
|
18360
|
-
if (mapped === void 0) return full;
|
|
18361
|
-
return `${pre}${assetsBaseUrl}/${mapped}${post}`;
|
|
18362
|
-
}
|
|
18363
|
-
return `${pre}${assetsBaseUrl}/${trimmed}${post}`;
|
|
18364
|
-
}
|
|
18365
|
-
);
|
|
18366
|
-
result = result.replace(
|
|
18367
|
-
/(<(?:img|source|video)[^>]+\bsrc=["'])([^"']+)(["'][^>]*>)/gi,
|
|
18368
|
-
(full, pre, src, post) => {
|
|
18369
|
-
const trimmed = src.trim();
|
|
18370
|
-
if (!isLocalPath(trimmed)) return full;
|
|
18371
|
-
if (pathMap) {
|
|
18372
|
-
const mapped = pathMap.get(trimmed);
|
|
18373
|
-
if (mapped === void 0) return full;
|
|
18374
|
-
return `${pre}${assetsBaseUrl}/${mapped}${post}`;
|
|
18375
|
-
}
|
|
18376
|
-
return `${pre}${assetsBaseUrl}/${trimmed}${post}`;
|
|
18377
|
-
}
|
|
18378
|
-
);
|
|
18379
|
-
result = result.replace(
|
|
18380
|
-
/(<video[^>]+\bposter=["'])([^"']+)(["'][^>]*>)/gi,
|
|
18381
|
-
(full, pre, src, post) => {
|
|
18382
|
-
const trimmed = src.trim();
|
|
18383
|
-
if (!isLocalPath(trimmed)) return full;
|
|
18384
|
-
if (pathMap) {
|
|
18385
|
-
const mapped = pathMap.get(trimmed);
|
|
18386
|
-
if (mapped === void 0) return full;
|
|
18387
|
-
return `${pre}${assetsBaseUrl}/${mapped}${post}`;
|
|
18388
|
-
}
|
|
18389
|
-
return `${pre}${assetsBaseUrl}/${trimmed}${post}`;
|
|
18390
|
-
}
|
|
18391
|
-
);
|
|
18392
|
-
return result;
|
|
18381
|
+
const rewrite = (full, pre, src, post) => {
|
|
18382
|
+
const target = resolveRewrite(src.trim(), assetsBaseUrl, pathMap);
|
|
18383
|
+
return target === null ? full : `${pre}${target}${post}`;
|
|
18384
|
+
};
|
|
18385
|
+
return prose.replace(/(!\[[^\]]*\]\()([^)"'\s]+)((?:\s+["'][^"']*["'])?\s*\))/g, rewrite).replace(/(<(?:img|source|video)[^>]+\bsrc=["'])([^"']+)(["'][^>]*>)/gi, rewrite).replace(/(<video[^>]+\bposter=["'])([^"']+)(["'][^>]*>)/gi, rewrite);
|
|
18393
18386
|
}
|
|
18394
18387
|
function rewriteAssetPaths(markdown, assetsBaseUrl, pathMap) {
|
|
18395
18388
|
return splitByCode(markdown).map((seg) => isCode(seg) ? seg : rewriteProseSegment(seg, assetsBaseUrl, pathMap)).join("");
|
|
@@ -18406,8 +18399,9 @@ function copyMarkdownAssets(options) {
|
|
|
18406
18399
|
const pathMap = /* @__PURE__ */ new Map();
|
|
18407
18400
|
const missing = [];
|
|
18408
18401
|
for (const ref of refs) {
|
|
18409
|
-
const absPath = path6.resolve(markdownDir, ref);
|
|
18402
|
+
const absPath = isAbsoluteRef(ref) ? ref : path6.resolve(markdownDir, ref);
|
|
18410
18403
|
if (!fs5.existsSync(absPath)) {
|
|
18404
|
+
if (isAbsoluteRef(ref)) continue;
|
|
18411
18405
|
if (!allowMissing) {
|
|
18412
18406
|
throw new Error(`Asset not found: ${absPath}`);
|
|
18413
18407
|
}
|
|
@@ -22034,7 +22028,10 @@ var ReportGenerator = class {
|
|
|
22034
22028
|
permalinkBaseUrl: options.astro?.markdown?.permalinkBaseUrl,
|
|
22035
22029
|
ticketUrlTemplate: options.astro?.markdown?.ticketUrlTemplate,
|
|
22036
22030
|
traceUrlTemplate: options.astro?.markdown?.traceUrlTemplate,
|
|
22037
|
-
customRenderers: options.astro?.markdown?.customRenderers
|
|
22031
|
+
customRenderers: options.astro?.markdown?.customRenderers,
|
|
22032
|
+
scenarioAnchor: options.astro?.markdown?.scenarioAnchor,
|
|
22033
|
+
scenarioBadge: options.astro?.markdown?.scenarioBadge,
|
|
22034
|
+
scenarioNoteLink: options.astro?.markdown?.scenarioNoteLink
|
|
22038
22035
|
}
|
|
22039
22036
|
},
|
|
22040
22037
|
assetMode: options.assetMode ?? "none",
|