{"version":3,"sources":["../../../../src/shared/lib/segment-cache/output-export-prefetch-encoding.ts"],"sourcesContent":["// In output: export mode, the build id is added to the start of the HTML\n// document, directly after the doctype declaration. During a prefetch, the\n// client performs a range request to get the build id, so it can check whether\n// the target page belongs to the same build.\n//\n// The first 64 bytes of the document are requested. The exact number isn't\n// too important; it must be larger than the build id + doctype + closing and\n// ending comment markers, but it doesn't need to match the end of the\n// comment exactly.\n//\n// Build ids are 21 bytes long in the default implementation, though this\n// can be overridden in the Next.js config. For the purposes of this check,\n// it's OK to only match the start of the id, so we'll truncate it if exceeds\n// a certain length.\n\nconst DOCTYPE_PREFIX = '<!DOCTYPE html>' // 15 bytes\nconst MAX_BUILD_ID_LENGTH = 24\n\n// Request the first 64 bytes. The Range header is inclusive of the end value.\nexport const DOC_PREFETCH_RANGE_HEADER_VALUE = 'bytes=0-63'\n\nfunction escapeBuildId(buildId: string) {\n  // If the build id is longer than the given limit, it's OK for our purposes\n  // to only match the beginning.\n  const truncated = buildId.slice(0, MAX_BUILD_ID_LENGTH)\n  // Replace hyphens with underscores so it doesn't break the HTML comment.\n  // (Unlikely, but if this did happen it would break the whole document.)\n  return truncated.replace(/-/g, '_')\n}\n\nexport function insertBuildIdComment(originalHtml: string, buildId: string) {\n  if (\n    // Skip if the build id contains a closing comment marker.\n    buildId.includes('-->') ||\n    // React always inserts a doctype at the start of the document. Skip if it\n    // isn't present. Shouldn't happen; suggests an issue elsewhere.\n    !originalHtml.startsWith(DOCTYPE_PREFIX)\n  ) {\n    // Return the original HTML unchanged. This means the document will not\n    // be prefetched.\n    // TODO: The build id comment is currently only used during prefetches, but\n    // if we eventually use this mechanism for regular navigations, we may need\n    // to error during build if we fail to insert it for some reason.\n    return originalHtml\n  }\n  // The comment must be inserted after the doctype.\n  return originalHtml.replace(\n    DOCTYPE_PREFIX,\n    DOCTYPE_PREFIX + '<!--' + escapeBuildId(buildId) + '-->'\n  )\n}\n\nexport function doesExportedHtmlMatchBuildId(\n  partialHtmlDocument: string,\n  buildId: string\n) {\n  // Check whether the document starts with the expected buildId.\n  return partialHtmlDocument.startsWith(\n    DOCTYPE_PREFIX + '<!--' + escapeBuildId(buildId) + '-->'\n  )\n}\n"],"names":["DOCTYPE_PREFIX","MAX_BUILD_ID_LENGTH","DOC_PREFETCH_RANGE_HEADER_VALUE","escapeBuildId","buildId","truncated","slice","replace","insertBuildIdComment","originalHtml","includes","startsWith","doesExportedHtmlMatchBuildId","partialHtmlDocument"],"mappings":"AAAA,yEAAyE;AACzE,2EAA2E;AAC3E,+EAA+E;AAC/E,6CAA6C;AAC7C,EAAE;AACF,2EAA2E;AAC3E,6EAA6E;AAC7E,sEAAsE;AACtE,mBAAmB;AACnB,EAAE;AACF,yEAAyE;AACzE,2EAA2E;AAC3E,6EAA6E;AAC7E,oBAAoB;AAEpB,MAAMA,iBAAiB,kBAAkB,WAAW;;AACpD,MAAMC,sBAAsB;AAE5B,8EAA8E;AAC9E,OAAO,MAAMC,kCAAkC,aAAY;AAE3D,SAASC,cAAcC,OAAe;IACpC,2EAA2E;IAC3E,+BAA+B;IAC/B,MAAMC,YAAYD,QAAQE,KAAK,CAAC,GAAGL;IACnC,yEAAyE;IACzE,wEAAwE;IACxE,OAAOI,UAAUE,OAAO,CAAC,MAAM;AACjC;AAEA,OAAO,SAASC,qBAAqBC,YAAoB,EAAEL,OAAe;IACxE,IACE,0DAA0D;IAC1DA,QAAQM,QAAQ,CAAC,UACjB,0EAA0E;IAC1E,gEAAgE;IAChE,CAACD,aAAaE,UAAU,CAACX,iBACzB;QACA,uEAAuE;QACvE,iBAAiB;QACjB,2EAA2E;QAC3E,2EAA2E;QAC3E,iEAAiE;QACjE,OAAOS;IACT;IACA,kDAAkD;IAClD,OAAOA,aAAaF,OAAO,CACzBP,gBACAA,iBAAiB,SAASG,cAAcC,WAAW;AAEvD;AAEA,OAAO,SAASQ,6BACdC,mBAA2B,EAC3BT,OAAe;IAEf,+DAA+D;IAC/D,OAAOS,oBAAoBF,UAAU,CACnCX,iBAAiB,SAASG,cAAcC,WAAW;AAEvD","ignoreList":[0]}