{"version":3,"sources":["../../../src/lib/metadata/is-metadata-route.ts"],"sourcesContent":["import type { PageExtensions } from '../../build/page-extensions-type'\nimport { normalizePathSep } from '../../shared/lib/page-path/normalize-path-sep'\nimport { normalizeAppPath } from '../../shared/lib/router/utils/app-paths'\nimport { isAppRouteRoute } from '../is-app-route-route'\n\nexport const STATIC_METADATA_IMAGES = {\n  icon: {\n    filename: 'icon',\n    extensions: ['ico', 'jpg', 'jpeg', 'png', 'svg'],\n  },\n  apple: {\n    filename: 'apple-icon',\n    extensions: ['jpg', 'jpeg', 'png'],\n  },\n  favicon: {\n    filename: 'favicon',\n    extensions: ['ico'],\n  },\n  openGraph: {\n    filename: 'opengraph-image',\n    extensions: ['jpg', 'jpeg', 'png', 'gif'],\n  },\n  twitter: {\n    filename: 'twitter-image',\n    extensions: ['jpg', 'jpeg', 'png', 'gif'],\n  },\n} as const\n\n// Match routes that are metadata routes, e.g. /sitemap.xml, /favicon.<ext>, /<icon>.<ext>, etc.\n// TODO-METADATA: support more metadata routes with more extensions\nexport const DEFAULT_METADATA_ROUTE_EXTENSIONS = ['js', 'jsx', 'ts', 'tsx']\n\n// Match the file extension with the dynamic multi-routes extensions\n// e.g. ([xml, js], null) -> can match `/sitemap.xml/route`, `sitemap.js/route`\n// e.g. ([png], [ts]) -> can match `/opengrapg-image.png`, `/opengraph-image.ts`\nexport const getExtensionRegexString = (\n  staticExtensions: readonly string[],\n  dynamicExtensions: readonly string[] | null\n) => {\n  // If there's no possible multi dynamic routes, will not match any <name>[].<ext> files\n  if (!dynamicExtensions || dynamicExtensions.length === 0) {\n    return `(\\\\.(?:${staticExtensions.join('|')}))`\n  }\n  return `(?:\\\\.(${staticExtensions.join('|')})|(\\\\.(${dynamicExtensions.join('|')})))`\n}\n\n/**\n * Determine if the file is a metadata route file entry\n * @param appDirRelativePath the relative file path to app/\n * @param pageExtensions the js extensions, such as ['js', 'jsx', 'ts', 'tsx']\n * @param strictlyMatchExtensions if it's true, match the file with page extension, otherwise match the file with default corresponding extension\n * @returns if the file is a metadata route file\n */\nexport function isMetadataRouteFile(\n  appDirRelativePath: string,\n  pageExtensions: PageExtensions,\n  strictlyMatchExtensions: boolean\n) {\n  // End with the extension or optional to have the extension\n  // When strictlyMatchExtensions is true, it's used for match file path;\n  // When strictlyMatchExtensions, the dynamic extension is skipped but\n  // static extension is kept, which is usually used for matching route path.\n  const trailingMatcher = (strictlyMatchExtensions ? '' : '?') + '$'\n  // Match the optional variants like /opengraph-image2, /icon-a102f4.png, etc.\n  const variantsMatcher = '\\\\d?'\n  // The -\\w{6} is the suffix that normalized from group routes;\n  const groupSuffix = strictlyMatchExtensions ? '' : '(-\\\\w{6})?'\n\n  const suffixMatcher = `${variantsMatcher}${groupSuffix}`\n\n  const metadataRouteFilesRegex = [\n    new RegExp(\n      `^[\\\\\\\\/]robots${getExtensionRegexString(\n        pageExtensions.concat('txt'),\n        null\n      )}${trailingMatcher}`\n    ),\n    new RegExp(\n      `^[\\\\\\\\/]manifest${getExtensionRegexString(\n        pageExtensions.concat('webmanifest', 'json'),\n        null\n      )}${trailingMatcher}`\n    ),\n    new RegExp(`^[\\\\\\\\/]favicon\\\\.ico$`),\n    new RegExp(\n      `[\\\\\\\\/]sitemap${getExtensionRegexString(['xml'], pageExtensions)}${trailingMatcher}`\n    ),\n    new RegExp(\n      `[\\\\\\\\/]${STATIC_METADATA_IMAGES.icon.filename}${suffixMatcher}${getExtensionRegexString(\n        STATIC_METADATA_IMAGES.icon.extensions,\n        pageExtensions\n      )}${trailingMatcher}`\n    ),\n    new RegExp(\n      `[\\\\\\\\/]${STATIC_METADATA_IMAGES.apple.filename}${suffixMatcher}${getExtensionRegexString(\n        STATIC_METADATA_IMAGES.apple.extensions,\n        pageExtensions\n      )}${trailingMatcher}`\n    ),\n    new RegExp(\n      `[\\\\\\\\/]${STATIC_METADATA_IMAGES.openGraph.filename}${suffixMatcher}${getExtensionRegexString(\n        STATIC_METADATA_IMAGES.openGraph.extensions,\n        pageExtensions\n      )}${trailingMatcher}`\n    ),\n    new RegExp(\n      `[\\\\\\\\/]${STATIC_METADATA_IMAGES.twitter.filename}${suffixMatcher}${getExtensionRegexString(\n        STATIC_METADATA_IMAGES.twitter.extensions,\n        pageExtensions\n      )}${trailingMatcher}`\n    ),\n  ]\n\n  const normalizedAppDirRelativePath = normalizePathSep(appDirRelativePath)\n  const matched = metadataRouteFilesRegex.some((r) =>\n    r.test(normalizedAppDirRelativePath)\n  )\n\n  return matched\n}\n\n// Check if the route is a static metadata route, with /route suffix\n// e.g. /favicon.ico/route, /icon.png/route, etc.\n// But skip the text routes like robots.txt since they might also be dynamic.\n// Checking route path is not enough to determine if text routes is dynamic.\nexport function isStaticMetadataRoute(route: string) {\n  // extract ext with regex\n  const pathname = route.replace(/\\/route$/, '')\n\n  const matched =\n    isAppRouteRoute(route) &&\n    isMetadataRouteFile(pathname, [], true) &&\n    // These routes can either be built by static or dynamic entrypoints,\n    // so we assume they're dynamic\n    pathname !== '/robots.txt' &&\n    pathname !== '/manifest.webmanifest' &&\n    !pathname.endsWith('/sitemap.xml')\n\n  return matched\n}\n\n/**\n * Determine if a page or pathname is a metadata page.\n *\n * The input is a page or pathname, which can be with or without page suffix /foo/page or /foo.\n * But it will not contain the /route suffix.\n *\n * .e.g\n * /robots -> true\n * /sitemap -> true\n * /foo -> false\n */\nexport function isMetadataPage(page: string) {\n  const matched = !isAppRouteRoute(page) && isMetadataRouteFile(page, [], false)\n\n  return matched\n}\n\n/*\n * Determine if a Next.js route is a metadata route.\n * `route` will has a route suffix.\n *\n * e.g.\n * /app/robots/route -> true\n * /robots/route -> true\n * /sitemap/[__metadata_id__]/route -> true\n * /app/sitemap/page -> false\n * /icon-a102f4/route -> true\n */\nexport function isMetadataRoute(route: string): boolean {\n  let page = normalizeAppPath(route)\n    .replace(/^\\/?app\\//, '')\n    // Remove the dynamic route id\n    .replace('/[__metadata_id__]', '')\n    // Remove the /route suffix\n    .replace(/\\/route$/, '')\n\n  if (page[0] !== '/') page = '/' + page\n\n  const matched = isAppRouteRoute(route) && isMetadataRouteFile(page, [], false)\n\n  return matched\n}\n"],"names":["normalizePathSep","normalizeAppPath","isAppRouteRoute","STATIC_METADATA_IMAGES","icon","filename","extensions","apple","favicon","openGraph","twitter","DEFAULT_METADATA_ROUTE_EXTENSIONS","getExtensionRegexString","staticExtensions","dynamicExtensions","length","join","isMetadataRouteFile","appDirRelativePath","pageExtensions","strictlyMatchExtensions","trailingMatcher","variantsMatcher","groupSuffix","suffixMatcher","metadataRouteFilesRegex","RegExp","concat","normalizedAppDirRelativePath","matched","some","r","test","isStaticMetadataRoute","route","pathname","replace","endsWith","isMetadataPage","page","isMetadataRoute"],"mappings":"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","ignoreList":[0]}