@fern-api/fern-api-dev 5.65.4 → 5.65.5

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.
Files changed (2) hide show
  1. package/cli.cjs +303 -145
  2. package/package.json +1 -1
package/cli.cjs CHANGED
@@ -450038,6 +450038,13 @@ function parseImagePaths(markdown, metadata, context3) {
450038
450038
  }
450039
450039
  visitFrontmatterImages(data2, ["image", "og:image", "og:logo", "twitter:image"], mapImage);
450040
450040
  replaceFrontmatterImagesforLogo(data2, mapImage);
450041
+ const hasImageIndicators = content5.includes("![") || content5.includes("src=") || content5.includes("icon=");
450042
+ if (!hasImageIndicators) {
450043
+ return {
450044
+ filepaths: [...filepaths],
450045
+ markdown: requoteLeadingZeroValues(import_gray_matter3.default.stringify(content5, data2))
450046
+ };
450047
+ }
450041
450048
  const contentBytes = Buffer.byteLength(content5, "utf8");
450042
450049
  const isLargeFile = contentBytes > getLargeFileBytes();
450043
450050
  let replacedContent;
@@ -450237,142 +450244,208 @@ function replaceImagePathsAndUrls(markdown, fileIdsMap, markdownFilesToPathName,
450237
450244
  }
450238
450245
  visitFrontmatterImages(data2, ["image", "og:image", "og:logo", "twitter:image"], mapImage);
450239
450246
  replaceFrontmatterImagesforLogo(data2, mapImage);
450240
- const contentBytes = Buffer.byteLength(content5, "utf8");
450241
- const isLargeFile = contentBytes > getLargeFileBytes();
450242
- let replacedContent;
450243
- if (isLargeFile) {
450244
- context3.logger.debug(`Using streaming parser for large file replacement: ${metadata.absolutePathToMarkdownFile} (${(contentBytes / 1024 / 1024).toFixed(2)} MB)`);
450245
- const streamingStart = performance.now();
450246
- const edits = [];
450247
- let i5 = 0;
450248
- const len = content5.length;
450249
- while (i5 < len) {
450250
- if (content5[i5] === "!" && content5[i5 + 1] === "[") {
450251
- const result = parseMarkdownImage(content5, i5, metadata);
450252
- if (result) {
450253
- const imageSrc = mapImage(result.src);
450254
- if (imageSrc) {
450255
- edits.push({
450256
- start: result.edit.start,
450257
- end: result.edit.end,
450258
- replacement: result.originalUrl.replace(result.rawSrc, imageSrc)
450259
- });
450260
- }
450261
- i5 = result.nextIndex;
450262
- continue;
450247
+ const edits = [];
450248
+ let hasUnhandledExpressions = false;
450249
+ let i5 = 0;
450250
+ const len = content5.length;
450251
+ while (i5 < len) {
450252
+ if (content5[i5] === "!" && content5[i5 + 1] === "[") {
450253
+ const result = parseMarkdownImage(content5, i5, metadata);
450254
+ if (result) {
450255
+ const imageSrc = mapImage(result.src);
450256
+ if (imageSrc) {
450257
+ edits.push({
450258
+ start: result.edit.start,
450259
+ end: result.edit.end,
450260
+ replacement: result.originalUrl.replace(result.rawSrc, imageSrc)
450261
+ });
450263
450262
  }
450264
- } else if (content5[i5] === "[" && content5[i5 - 1] !== "!") {
450265
- const linkStart = i5;
450266
- let j5 = i5 + 1;
450267
- while (j5 < len && content5[j5] !== "]") {
450263
+ i5 = result.nextIndex;
450264
+ continue;
450265
+ }
450266
+ } else if (content5[i5] === "[" && content5[i5 - 1] !== "!") {
450267
+ let j5 = i5 + 1;
450268
+ while (j5 < len && content5[j5] !== "]") {
450269
+ if (content5[j5] === "\\") {
450270
+ j5 += 2;
450271
+ } else {
450272
+ j5++;
450273
+ }
450274
+ }
450275
+ if (j5 < len && content5[j5] === "]" && content5[j5 + 1] === "(") {
450276
+ j5 += 2;
450277
+ const urlStart = j5;
450278
+ let parenDepth = 1;
450279
+ while (j5 < len && parenDepth > 0) {
450268
450280
  if (content5[j5] === "\\") {
450269
450281
  j5 += 2;
450282
+ } else if (content5[j5] === "(") {
450283
+ parenDepth++;
450284
+ j5++;
450285
+ } else if (content5[j5] === ")") {
450286
+ parenDepth--;
450287
+ j5++;
450270
450288
  } else {
450271
450289
  j5++;
450272
450290
  }
450273
450291
  }
450274
- if (j5 < len && content5[j5] === "]" && content5[j5 + 1] === "(") {
450275
- j5 += 2;
450276
- const urlStart = j5;
450277
- let parenDepth = 1;
450278
- while (j5 < len && parenDepth > 0) {
450279
- if (content5[j5] === "\\") {
450280
- j5 += 2;
450281
- } else if (content5[j5] === "(") {
450282
- parenDepth++;
450283
- j5++;
450284
- } else if (content5[j5] === ")") {
450285
- parenDepth--;
450286
- j5++;
450287
- } else {
450292
+ const urlEnd = j5 - 1;
450293
+ const href = content5.slice(urlStart, urlEnd).trim();
450294
+ const trimmedHref = trimAnchor(href) ?? href;
450295
+ const hrefAnchor = trimmedHref !== href ? href.slice(trimmedHref.length) : "";
450296
+ const replacedHref = getReplacedHref({
450297
+ href: trimmedHref,
450298
+ markdownFilesToPathName,
450299
+ metadata
450300
+ });
450301
+ if (replacedHref && replacedHref.type === "replace") {
450302
+ edits.push({
450303
+ start: urlStart,
450304
+ end: urlEnd,
450305
+ replacement: replacedHref.slug + hrefAnchor
450306
+ });
450307
+ }
450308
+ i5 = j5;
450309
+ continue;
450310
+ }
450311
+ } else if (content5[i5] === "<") {
450312
+ let j5 = i5 + 1;
450313
+ while (j5 < len && content5[j5] !== ">" && content5[j5] !== " " && content5[j5] !== "\n") {
450314
+ j5++;
450315
+ }
450316
+ while (j5 < len && content5[j5] !== ">") {
450317
+ while (j5 < len && (content5[j5] === " " || content5[j5] === "\n")) {
450318
+ j5++;
450319
+ }
450320
+ const attrStart = j5;
450321
+ while (j5 < len && content5[j5] !== "=" && content5[j5] !== ">" && content5[j5] !== " " && content5[j5] !== "\n") {
450322
+ j5++;
450323
+ }
450324
+ const attrName = content5.slice(attrStart, j5).trim();
450325
+ if (attrName.startsWith("{")) {
450326
+ hasUnhandledExpressions = true;
450327
+ let braceDepth = 0;
450328
+ j5 = attrStart;
450329
+ while (j5 < len) {
450330
+ if (content5[j5] === "{") {
450331
+ braceDepth++;
450332
+ } else if (content5[j5] === "}") {
450333
+ braceDepth--;
450334
+ if (braceDepth === 0) {
450335
+ j5++;
450336
+ break;
450337
+ }
450338
+ } else if (content5[j5] === '"' || content5[j5] === "'") {
450339
+ const q5 = content5[j5];
450288
450340
  j5++;
450341
+ while (j5 < len && content5[j5] !== q5) {
450342
+ if (content5[j5] === "\\") {
450343
+ j5++;
450344
+ }
450345
+ j5++;
450346
+ }
450289
450347
  }
450348
+ j5++;
450290
450349
  }
450291
- const urlEnd = j5 - 1;
450292
- const href = content5.slice(urlStart, urlEnd).trim();
450293
- const replacedHref = getReplacedHref({ href, markdownFilesToPathName, metadata });
450294
- if (replacedHref && replacedHref.type === "replace") {
450295
- edits.push({ start: urlStart, end: urlEnd, replacement: replacedHref.slug });
450296
- }
450297
- i5 = j5;
450298
450350
  continue;
450299
450351
  }
450300
- } else if (content5[i5] === "<") {
450301
- let j5 = i5 + 1;
450302
- while (j5 < len && content5[j5] !== ">" && content5[j5] !== " " && content5[j5] !== "\n") {
450352
+ if (content5[j5] === "=") {
450303
450353
  j5++;
450304
- }
450305
- while (j5 < len && content5[j5] !== ">") {
450306
450354
  while (j5 < len && (content5[j5] === " " || content5[j5] === "\n")) {
450307
450355
  j5++;
450308
450356
  }
450309
- const attrStart = j5;
450310
- while (j5 < len && content5[j5] !== "=" && content5[j5] !== ">" && content5[j5] !== " " && content5[j5] !== "\n") {
450311
- j5++;
450312
- }
450313
- const attrName = content5.slice(attrStart, j5).trim();
450314
- if (content5[j5] === "=") {
450357
+ const isCurlyWrapped = content5[j5] === "{";
450358
+ if (isCurlyWrapped) {
450315
450359
  j5++;
450316
450360
  while (j5 < len && (content5[j5] === " " || content5[j5] === "\n")) {
450317
450361
  j5++;
450318
450362
  }
450319
- if (content5[j5] === '"' || content5[j5] === "'") {
450320
- const quote2 = content5[j5];
450321
- j5++;
450322
- const valueStart = j5;
450323
- while (j5 < len && content5[j5] !== quote2) {
450324
- if (content5[j5] === "\\") {
450325
- j5 += 2;
450326
- } else {
450327
- j5++;
450328
- }
450363
+ }
450364
+ if (content5[j5] === '"' || content5[j5] === "'") {
450365
+ const quote2 = content5[j5];
450366
+ j5++;
450367
+ const valueStart = j5;
450368
+ while (j5 < len && content5[j5] !== quote2) {
450369
+ if (content5[j5] === "\\") {
450370
+ j5 += 2;
450371
+ } else {
450372
+ j5++;
450329
450373
  }
450330
- const value2 = content5.slice(valueStart, j5);
450331
- j5++;
450332
- if (attrName === "src" || attrName === "icon" && isLocalIconReference(value2)) {
450333
- const imageSrc = mapImage(value2);
450334
- if (imageSrc) {
450335
- edits.push({
450336
- start: valueStart,
450337
- end: valueStart + value2.length,
450338
- replacement: imageSrc
450339
- });
450340
- }
450341
- } else if (attrName === "href") {
450342
- const replacedHref = getReplacedHref({
450343
- href: value2,
450344
- markdownFilesToPathName,
450345
- metadata
450374
+ }
450375
+ const value2 = content5.slice(valueStart, j5);
450376
+ j5++;
450377
+ if (isCurlyWrapped) {
450378
+ while (j5 < len && (content5[j5] === " " || content5[j5] === "\n")) {
450379
+ j5++;
450380
+ }
450381
+ if (j5 < len && content5[j5] === "}") {
450382
+ j5++;
450383
+ }
450384
+ }
450385
+ if (attrName === "src" || attrName === "icon" && isLocalIconReference(value2)) {
450386
+ const trimmedValue = trimAnchor(value2);
450387
+ const anchor = trimmedValue && value2 !== trimmedValue ? value2.slice(trimmedValue.length) : "";
450388
+ const imageSrc = mapImage(trimmedValue ?? value2);
450389
+ if (imageSrc) {
450390
+ edits.push({
450391
+ start: valueStart,
450392
+ end: valueStart + value2.length,
450393
+ replacement: imageSrc + anchor
450346
450394
  });
450347
- if (replacedHref && replacedHref.type === "replace") {
450348
- edits.push({
450349
- start: valueStart,
450350
- end: valueStart + value2.length,
450351
- replacement: replacedHref.slug
450352
- });
450395
+ }
450396
+ } else if (attrName === "href") {
450397
+ const trimmedHrefValue = trimAnchor(value2) ?? value2;
450398
+ const hrefAnchorSuffix = trimmedHrefValue !== value2 ? value2.slice(trimmedHrefValue.length) : "";
450399
+ const replacedHref = getReplacedHref({
450400
+ href: trimmedHrefValue,
450401
+ markdownFilesToPathName,
450402
+ metadata
450403
+ });
450404
+ if (replacedHref && replacedHref.type === "replace") {
450405
+ edits.push({
450406
+ start: valueStart,
450407
+ end: valueStart + value2.length,
450408
+ replacement: replacedHref.slug + hrefAnchorSuffix
450409
+ });
450410
+ }
450411
+ }
450412
+ } else if (isCurlyWrapped && (attrName === "src" || attrName === "icon" || attrName === "href")) {
450413
+ hasUnhandledExpressions = true;
450414
+ let braceDepth = 1;
450415
+ while (j5 < len && braceDepth > 0) {
450416
+ if (content5[j5] === "{") {
450417
+ braceDepth++;
450418
+ } else if (content5[j5] === "}") {
450419
+ braceDepth--;
450420
+ } else if (content5[j5] === '"' || content5[j5] === "'") {
450421
+ const q5 = content5[j5];
450422
+ j5++;
450423
+ while (j5 < len && content5[j5] !== q5) {
450424
+ if (content5[j5] === "\\") {
450425
+ j5++;
450426
+ }
450427
+ j5++;
450353
450428
  }
450354
450429
  }
450430
+ j5++;
450355
450431
  }
450356
450432
  }
450357
450433
  }
450358
- if (j5 < len && content5[j5] === ">") {
450359
- j5++;
450360
- }
450361
- i5 = j5;
450362
- continue;
450363
450434
  }
450364
- i5++;
450435
+ if (j5 < len && content5[j5] === ">") {
450436
+ j5++;
450437
+ }
450438
+ i5 = j5;
450439
+ continue;
450365
450440
  }
450366
- replacedContent = applyEdits(content5, edits);
450367
- const streamingTime = performance.now() - streamingStart;
450368
- context3.logger.debug(`Streaming replacement completed in ${streamingTime.toFixed(0)}ms: ${edits.length} edits applied`);
450369
- } else {
450441
+ i5++;
450442
+ }
450443
+ if (hasUnhandledExpressions) {
450370
450444
  const tree = parseMarkdownToTree(content5);
450371
450445
  const lineStarts = precomputeLineStarts(content5);
450372
- const edits = [];
450373
450446
  const nodeTypeFilter = (node4) => {
450374
450447
  const n2 = node4;
450375
- return n2.type === "image" || n2.type === "link" || n2.type === "mdxJsxFlowElement" || n2.type === "mdxJsxTextElement" || n2.type === "mdxFlowExpression" || n2.type === "mdxTextExpression";
450448
+ return n2.type === "mdxJsxFlowElement" || n2.type === "mdxJsxTextElement" || n2.type === "mdxFlowExpression" || n2.type === "mdxTextExpression";
450376
450449
  };
450377
450450
  visit3(tree, nodeTypeFilter, (node4) => {
450378
450451
  if (node4.position == null) {
@@ -450405,25 +450478,12 @@ function replaceImagePathsAndUrls(markdown, fileIdsMap, markdownFilesToPathName,
450405
450478
  href: (attr) => replaceHref(trimAnchor(extractSingleLiteral(attr.value)))
450406
450479
  });
450407
450480
  }
450408
- if (node4.type === "image") {
450409
- const src = trimAnchor(node4.url);
450410
- replaceSrc(trimAnchor(src));
450411
- }
450412
- if (node4.type === "link") {
450413
- replaceHref(trimAnchor(node4.url));
450414
- }
450415
450481
  if (isMdxJsxElement(node4)) {
450416
- const srcAttr = node4.attributes.filter(isMdxJsxAttribute).find((attr) => attr.name === "src");
450417
- replaceSrc(trimAnchor(extractAttributeValueLiteral(srcAttr?.value)));
450418
- const iconAttr = node4.attributes.filter(isMdxJsxAttribute).find((attr) => attr.name === "icon");
450419
- const iconValue = trimAnchor(extractAttributeValueLiteral(iconAttr?.value));
450420
- if (isLocalIconReference(iconValue)) {
450421
- replaceSrc(iconValue);
450422
- }
450423
- const hrefAttr = node4.attributes.find((attr) => attr.type === "mdxJsxAttribute" && attr.name === "href");
450424
- replaceHref(trimAnchor(extractAttributeValueLiteral(hrefAttr?.value)));
450425
450482
  node4.attributes.forEach((attr) => {
450426
450483
  if (isMdxJsxAttribute(attr) && typeof attr.value !== "string" && attr.value != null && attr.value.data?.estree) {
450484
+ if (extractSingleLiteral(attr.value.data.estree) != null) {
450485
+ return;
450486
+ }
450427
450487
  walkEstreeForSrcAndHref(attr.value.data.estree);
450428
450488
  } else if (isMdxJsxExpressionAttribute(attr) && attr.data?.estree) {
450429
450489
  walkEstreeForSrcAndHref(attr.data.estree);
@@ -450438,8 +450498,8 @@ function replaceImagePathsAndUrls(markdown, fileIdsMap, markdownFilesToPathName,
450438
450498
  }
450439
450499
  return CONTINUE;
450440
450500
  });
450441
- replacedContent = applyEdits(content5, edits);
450442
450501
  }
450502
+ const replacedContent = applyEdits(content5, edits);
450443
450503
  return requoteLeadingZeroValues(import_gray_matter3.default.stringify(replacedContent, data2));
450444
450504
  }
450445
450505
  function trimAnchor(text9) {
@@ -450570,18 +450630,56 @@ function extractLines(content5, linesParam) {
450570
450630
  const extractedLines = sortedIndices.filter((idx) => idx >= 0 && idx < allLines.length).map((idx) => allLines[idx] ?? "");
450571
450631
  return extractedLines.join("\n");
450572
450632
  }
450633
+ function collectCodeSrcUrls(markdown) {
450634
+ if (!markdown.includes("<Code")) {
450635
+ return [];
450636
+ }
450637
+ const urls = [];
450638
+ const regex6 = new RegExp(CODE_TAG_REGEX.source, CODE_TAG_REGEX.flags);
450639
+ let match3;
450640
+ while ((match3 = regex6.exec(markdown)) != null) {
450641
+ const src = match3[2];
450642
+ if (src && isUrl(src)) {
450643
+ urls.push(src);
450644
+ }
450645
+ }
450646
+ return urls;
450647
+ }
450648
+ async function prefetchCodeSrcUrls(urls, context3) {
450649
+ const cache2 = /* @__PURE__ */ new Map();
450650
+ const unique = [...new Set(urls)];
450651
+ if (unique.length === 0) {
450652
+ return cache2;
450653
+ }
450654
+ const results = await Promise.allSettled(unique.map(async (url3) => {
450655
+ const response = await fetch(url3);
450656
+ if (!response.ok) {
450657
+ context3.logger.warn(`Failed to prefetch code from URL "${url3}" (status ${response.status})`);
450658
+ return { url: url3, content: void 0 };
450659
+ }
450660
+ const content5 = await response.text();
450661
+ return { url: url3, content: content5 };
450662
+ }));
450663
+ for (const result of results) {
450664
+ if (result.status === "fulfilled" && result.value.content !== void 0) {
450665
+ cache2.set(result.value.url, result.value.content);
450666
+ }
450667
+ }
450668
+ return cache2;
450669
+ }
450573
450670
  async function replaceReferencedCode({
450574
450671
  markdown,
450575
450672
  absolutePathToFernFolder,
450576
450673
  absolutePathToMarkdownFile,
450577
450674
  context: context3,
450578
450675
  // allow for custom markdown loader for testing
450579
- fileLoader = defaultFileLoader
450676
+ fileLoader = defaultFileLoader,
450677
+ urlCache
450580
450678
  }) {
450581
450679
  if (!markdown.includes("<Code")) {
450582
450680
  return markdown;
450583
450681
  }
450584
- const regex6 = /([ \t]*)<Code(?:\s+[^>]*?)?\s+src={?['"]([^'"]+)['"](?! \+)}?((?:\s+[^>]*)?)\/>/g;
450682
+ const regex6 = new RegExp(CODE_TAG_REGEX.source, CODE_TAG_REGEX.flags);
450585
450683
  let newMarkdown = markdown;
450586
450684
  let match3;
450587
450685
  while ((match3 = regex6.exec(markdown)) != null) {
@@ -450596,21 +450694,26 @@ async function replaceReferencedCode({
450596
450694
  let language;
450597
450695
  let title2;
450598
450696
  if (isUrl(src)) {
450599
- try {
450600
- const response = await fetch(src);
450601
- if (!response.ok) {
450602
- context3.logger.warn(`Failed to fetch code from URL "${src}" (status ${response.status}) referenced in ${absolutePathToMarkdownFile}`);
450697
+ const cached2 = urlCache?.get(src);
450698
+ if (cached2 !== void 0) {
450699
+ replacement = cached2;
450700
+ } else {
450701
+ try {
450702
+ const response = await fetch(src);
450703
+ if (!response.ok) {
450704
+ context3.logger.warn(`Failed to fetch code from URL "${src}" (status ${response.status}) referenced in ${absolutePathToMarkdownFile}`);
450705
+ break;
450706
+ }
450707
+ replacement = await response.text();
450708
+ } catch (e2) {
450709
+ context3.logger.warn(`Failed to fetch code from URL "${src}" referenced in ${absolutePathToMarkdownFile}: ${e2}`);
450603
450710
  break;
450604
450711
  }
450605
- replacement = await response.text();
450606
- const url3 = new URL(src);
450607
- const pathname = url3.pathname;
450608
- language = pathname.split(".").pop();
450609
- title2 = pathname.split("/").pop();
450610
- } catch (e2) {
450611
- context3.logger.warn(`Failed to fetch code from URL "${src}" referenced in ${absolutePathToMarkdownFile}: ${e2}`);
450612
- break;
450613
450712
  }
450713
+ const url3 = new URL(src);
450714
+ const pathname = url3.pathname;
450715
+ language = pathname.split(".").pop();
450716
+ title2 = pathname.split("/").pop();
450614
450717
  } else {
450615
450718
  const filepath = resolve6(src.startsWith("/") ? absolutePathToFernFolder : dirname6(absolutePathToMarkdownFile), RelativeFilePath2.of(src.replace(/^\//, "")));
450616
450719
  replacement = await fileLoader(filepath);
@@ -450693,12 +450796,13 @@ ${replacement}
450693
450796
  }
450694
450797
  return newMarkdown;
450695
450798
  }
450696
- var import_promises68;
450799
+ var import_promises68, CODE_TAG_REGEX;
450697
450800
  var init_replaceReferencedCode = __esm({
450698
450801
  "../docs-markdown-utils/lib/replaceReferencedCode.js"() {
450699
450802
  "use strict";
450700
450803
  init_lib8();
450701
450804
  import_promises68 = require("fs/promises");
450805
+ CODE_TAG_REGEX = /([ \t]*)<Code(?:\s+[^>]*?)?\s+src={?['"]([^'"]+)['"](?! \+)}?((?:\s+[^>]*)?)\/>/g;
450702
450806
  }
450703
450807
  });
450704
450808
 
@@ -450916,6 +451020,7 @@ var init_transformAtPrefixImports = __esm({
450916
451020
  // ../docs-markdown-utils/lib/index.js
450917
451021
  var lib_exports10 = {};
450918
451022
  __export(lib_exports10, {
451023
+ collectCodeSrcUrls: () => collectCodeSrcUrls,
450919
451024
  extractAttributeValueLiteral: () => extractAttributeValueLiteral,
450920
451025
  extractSingleLiteral: () => extractSingleLiteral,
450921
451026
  getMarkdownFormat: () => getMarkdownFormat,
@@ -450927,6 +451032,7 @@ __export(lib_exports10, {
450927
451032
  isValidRelativeSlug: () => isValidRelativeSlug,
450928
451033
  parseImagePaths: () => parseImagePaths,
450929
451034
  parseMarkdownToTree: () => parseMarkdownToTree,
451035
+ prefetchCodeSrcUrls: () => prefetchCodeSrcUrls,
450930
451036
  replaceImagePathsAndUrls: () => replaceImagePathsAndUrls,
450931
451037
  replaceReferencedCode: () => replaceReferencedCode,
450932
451038
  replaceReferencedMarkdown: () => replaceReferencedMarkdown,
@@ -460601,7 +460707,18 @@ var init_DocsDefinitionResolver = __esm({
460601
460707
  this.taskContext.logger.debug("Replacing referenced markdown and code files...");
460602
460708
  const refStart = performance.now();
460603
460709
  const seenReferencedFiles = /* @__PURE__ */ new Set();
460604
- for (const [relativePath, markdown] of Object.entries(this.parsedDocsConfig.pages)) {
460710
+ const pageEntries = Object.entries(this.parsedDocsConfig.pages);
460711
+ const allCodeSrcUrls = [];
460712
+ for (const [, markdown] of pageEntries) {
460713
+ allCodeSrcUrls.push(...collectCodeSrcUrls(markdown));
460714
+ }
460715
+ const prefetchStart = Date.now();
460716
+ const urlCache = await prefetchCodeSrcUrls(allCodeSrcUrls, this.taskContext);
460717
+ if (urlCache.size > 0) {
460718
+ const uniqueCount = new Set(allCodeSrcUrls).size;
460719
+ this.taskContext.logger.info(`Prefetched ${uniqueCount} external code URLs in ${Date.now() - prefetchStart}ms`);
460720
+ }
460721
+ for (const [relativePath, markdown] of pageEntries) {
460605
460722
  const result = await replaceReferencedMarkdown({
460606
460723
  markdown,
460607
460724
  absolutePathToFernFolder: this.docsWorkspace.absoluteFilePath,
@@ -460618,7 +460735,8 @@ var init_DocsDefinitionResolver = __esm({
460618
460735
  markdown: result.markdown,
460619
460736
  absolutePathToFernFolder: this.docsWorkspace.absoluteFilePath,
460620
460737
  absolutePathToMarkdownFile: this.resolveFilepath(relativePath),
460621
- context: this.taskContext
460738
+ context: this.taskContext,
460739
+ urlCache
460622
460740
  });
460623
460741
  const newMarkdown = transformAtPrefixImports({
460624
460742
  markdown: codeReplacedMarkdown,
@@ -582008,7 +582126,9 @@ var require_ReplayStep = __commonJS({
582008
582126
  "use strict";
582009
582127
  Object.defineProperty(exports2, "__esModule", { value: true });
582010
582128
  exports2.ReplayStep = void 0;
582129
+ var child_process_1 = require("child_process");
582011
582130
  var replay_run_1 = require_replay_run();
582131
+ var constants_1 = require_constants8();
582012
582132
  var BaseStep_1 = require_BaseStep();
582013
582133
  var ReplayStep = class extends BaseStep_1.BaseStep {
582014
582134
  config;
@@ -582050,17 +582170,21 @@ var require_ReplayStep = __commonJS({
582050
582170
  patchesWithConflicts: 0
582051
582171
  };
582052
582172
  }
582173
+ const stageOnly = this.config.stageOnly ?? false;
582053
582174
  const result = prepared != null ? await (0, replay_run_1.replayApply)(prepared, {
582054
- stageOnly: this.config.stageOnly ?? false,
582175
+ stageOnly,
582055
582176
  logger: this.logger
582056
582177
  }) : await (0, replay_run_1.replayRun)({
582057
582178
  outputDir: this.outputDir,
582058
582179
  cliVersion: this.cliVersion,
582059
582180
  generatorVersions: this.generatorVersions,
582060
- stageOnly: this.config.stageOnly ?? false,
582181
+ stageOnly,
582061
582182
  skipApplication: this.config.skipApplication,
582062
582183
  logger: this.logger
582063
582184
  });
582185
+ if (!stageOnly) {
582186
+ this.commitLockfileIfUncommitted();
582187
+ }
582064
582188
  if (result.failureReason != null) {
582065
582189
  return {
582066
582190
  executed: true,
@@ -582124,6 +582248,40 @@ var require_ReplayStep = __commonJS({
582124
582248
  warnings: report.warnings
582125
582249
  };
582126
582250
  }
582251
+ /**
582252
+ * Commits `.fern/replay.lock` when replay saved the lockfile to disk but
582253
+ * didn't create a `[fern-replay]` commit (e.g. no-patches flow with zero
582254
+ * new patches). Without this, `skipCommit = true` in GithubStep drops the
582255
+ * lockfile advance, freezing `previousGenerationSha` across runs.
582256
+ */
582257
+ commitLockfileIfUncommitted() {
582258
+ try {
582259
+ const status = (0, child_process_1.execFileSync)("git", ["status", "--porcelain", "--", ".fern/replay.lock"], {
582260
+ cwd: this.outputDir,
582261
+ encoding: "utf-8",
582262
+ stdio: ["pipe", "pipe", "pipe"]
582263
+ }).trim();
582264
+ if (status.length === 0) {
582265
+ return;
582266
+ }
582267
+ (0, child_process_1.execFileSync)("git", ["add", "--", ".fern/replay.lock"], {
582268
+ cwd: this.outputDir,
582269
+ stdio: "pipe"
582270
+ });
582271
+ (0, child_process_1.execFileSync)("git", [
582272
+ "-c",
582273
+ `user.name=${constants_1.FERN_BOT_NAME}`,
582274
+ "-c",
582275
+ `user.email=${constants_1.FERN_BOT_EMAIL}`,
582276
+ "commit",
582277
+ "-m",
582278
+ "[fern-replay] advance lockfile"
582279
+ ], { cwd: this.outputDir, stdio: "pipe" });
582280
+ this.logger.debug("ReplayStep: committed uncommitted lockfile advance.");
582281
+ } catch (error50) {
582282
+ this.logger.debug("ReplayStep: failed to commit lockfile advance: " + String(error50));
582283
+ }
582284
+ }
582127
582285
  };
582128
582286
  exports2.ReplayStep = ReplayStep;
582129
582287
  }
@@ -688438,7 +688596,7 @@ var AccessTokenPosthogManager = class {
688438
688596
  properties: {
688439
688597
  ...event,
688440
688598
  ...event.properties,
688441
- version: "5.65.4",
688599
+ version: "5.65.5",
688442
688600
  usingAccessToken: true,
688443
688601
  ...getRunIdProperties()
688444
688602
  }
@@ -688504,7 +688662,7 @@ var UserPosthogManager = class {
688504
688662
  distinctId: this.userId ?? await this.getPersistedDistinctId(),
688505
688663
  event: "CLI",
688506
688664
  properties: {
688507
- version: "5.65.4",
688665
+ version: "5.65.5",
688508
688666
  ...event,
688509
688667
  ...event.properties,
688510
688668
  usingAccessToken: false,
@@ -869600,7 +869758,7 @@ var LOCAL_STORAGE_FOLDER4 = ".fern-dev";
869600
869758
  var LOGS_FOLDER_NAME = "logs";
869601
869759
  var MAX_LOGS_DIR_SIZE_BYTES = 100 * 1024 * 1024;
869602
869760
  function getCliSource() {
869603
- const version7 = "5.65.4";
869761
+ const version7 = "5.65.5";
869604
869762
  return `cli@${version7}`;
869605
869763
  }
869606
869764
  var DebugLogger = class {
@@ -902162,7 +902320,7 @@ var LegacyDocsPublisher = class {
902162
902320
  previewId,
902163
902321
  disableTemplates: void 0,
902164
902322
  skipUpload,
902165
- cliVersion: "5.65.4",
902323
+ cliVersion: "5.65.5",
902166
902324
  loginCommand: "fern auth login"
902167
902325
  });
902168
902326
  if (taskContext.getResult() === TaskResult.Failure) {
@@ -968472,7 +968630,7 @@ function getAutomationContextFromEnv() {
968472
968630
  config_branch: process.env.FERN_CONFIG_BRANCH,
968473
968631
  config_pr_number: process.env.FERN_CONFIG_PR_NUMBER,
968474
968632
  trigger: process.env.GITHUB_EVENT_NAME,
968475
- cli_version: "5.65.4"
968633
+ cli_version: "5.65.5"
968476
968634
  };
968477
968635
  }
968478
968636
  function isAutomationMode() {
@@ -969304,7 +969462,7 @@ var CliContext = class _CliContext {
969304
969462
  if (false) {
969305
969463
  this.logger.error("CLI_VERSION is not defined");
969306
969464
  }
969307
- return "5.65.4";
969465
+ return "5.65.5";
969308
969466
  }
969309
969467
  getCliName() {
969310
969468
  if (false) {
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.65.4",
2
+ "version": "5.65.5",
3
3
  "repository": {
4
4
  "type": "git",
5
5
  "url": "git+https://github.com/fern-api/fern.git",