{"version":3,"sources":["../../../../src/build/webpack/loaders/next-metadata-image-loader.ts"],"sourcesContent":["/*\n * This loader is responsible for extracting the metadata image info for rendering in html\n */\n\nimport type webpack from 'webpack'\nimport type {\n  MetadataImageModule,\n  PossibleImageFileNameConvention,\n} from './metadata/types'\nimport { existsSync, promises as fs } from 'fs'\nimport path from 'path'\nimport loaderUtils from 'next/dist/compiled/loader-utils3'\nimport { getImageSize } from '../../../server/image-optimizer'\nimport { imageExtMimeTypeMap } from '../../../lib/mime-type'\nimport { WEBPACK_RESOURCE_QUERIES } from '../../../lib/constants'\nimport { normalizePathSep } from '../../../shared/lib/page-path/normalize-path-sep'\nimport type { PageExtensions } from '../../page-extensions-type'\nimport { getLoaderModuleNamedExports } from './utils'\nimport { installBindings } from '../../swc/install-bindings'\n\ninterface Options {\n  segment: string\n  type: PossibleImageFileNameConvention\n  pageExtensions: PageExtensions\n  basePath: string\n}\n\n// [NOTE] For turbopack, refer to app_page_loader_tree's write_metadata_item for\n// corresponding features.\nasync function nextMetadataImageLoader(\n  this: webpack.LoaderContext<Options>,\n  content: Buffer\n) {\n  // Install bindings early so they are definitely available to the loader.\n  // When run by webpack in next this is already done with correct configuration so this is a no-op.\n  // In turbopack loaders are run in a subprocess so it may or may not be done.\n  await installBindings()\n  const options: Options = this.getOptions()\n  const { type, segment, pageExtensions, basePath } = options\n  const { resourcePath, rootContext: context } = this\n  const { name: fileNameBase, ext } = path.parse(resourcePath)\n  const useNumericSizes = type === 'twitter' || type === 'openGraph'\n\n  let extension = ext.slice(1)\n  if (extension === 'jpg') {\n    extension = 'jpeg'\n  }\n\n  const opts = { context, content }\n\n  const contentHash = loaderUtils.interpolateName(this, '[contenthash]', opts)\n\n  const interpolatedName = loaderUtils.interpolateName(\n    this,\n    '[name].[ext]',\n    opts\n  )\n\n  const isDynamicResource = pageExtensions.includes(extension)\n  const pageSegment = isDynamicResource ? fileNameBase : interpolatedName\n  const hashQuery = contentHash ? '?' + contentHash : ''\n  const pathnamePrefix = normalizePathSep(path.join(basePath, segment))\n\n  if (isDynamicResource) {\n    const exportedFieldsExcludingDefault = (\n      await getLoaderModuleNamedExports(resourcePath, this)\n    ).filter((name) => name !== 'default')\n\n    // re-export and spread as `exportedImageData` to avoid non-exported error\n    return `\\\n    import {\n      ${exportedFieldsExcludingDefault\n        .map((field) => `${field} as _${field}`)\n        .join(',')}\n    } from ${JSON.stringify(\n      // This is an arbitrary resource query to ensure it's a new request, instead\n      // of sharing the same module with next-metadata-route-loader.\n      // Since here we only need export fields such as `size`, `alt` and\n      // `generateImageMetadata`, avoid sharing the same module can make this entry\n      // smaller.\n      resourcePath + '?' + WEBPACK_RESOURCE_QUERIES.metadataImageMeta\n    )}\n    import { fillMetadataSegment } from 'next/dist/lib/metadata/get-metadata-route'\n\n    const imageModule = {\n      ${exportedFieldsExcludingDefault\n        .map((field) => `${field}: _${field}`)\n        .join(',')}\n    }\n\n    function getImageMetadata(imageMetadata, idParam, resolvedParams) {\n      const imageUrl = fillMetadataSegment(${JSON.stringify(\n        pathnamePrefix\n      )}, resolvedParams, ${JSON.stringify(pageSegment)}, false)\n      const data = {\n        alt: imageMetadata.alt,\n        type: imageMetadata.contentType || 'image/png',\n      url: imageUrl + (idParam ? ('/' + idParam) : '') + ${JSON.stringify(\n        hashQuery\n      )},\n      }\n      const { size } = imageMetadata\n      if (size) {\n        ${\n          type === 'twitter' || type === 'openGraph'\n            ? 'data.width = size.width; data.height = size.height;'\n            : 'data.sizes = size.width + \"x\" + size.height;'\n        }\n      }\n      return data\n    }\n\n    export default async function (props) {\n      const { generateImageMetadata } = imageModule\n      const resolvedParams = await props.params\n\n      if (generateImageMetadata) {\n        const imageMetadataArray = await generateImageMetadata({ params: resolvedParams })\n        return imageMetadataArray.map((imageMetadata, index) => {\n          const idParam = imageMetadata.id + ''\n          return getImageMetadata(imageMetadata, idParam, resolvedParams)\n        })\n      } else {\n        return [getImageMetadata(imageModule, '', resolvedParams)]\n      }\n    }`\n  }\n\n  let imageError\n  const imageSize: { width?: number; height?: number } = await getImageSize(\n    content\n  ).catch((error) => {\n    const message = `Process image \"${path.posix.join(segment || '/', interpolatedName)}\" failed: ${error}`\n    imageError = new Error(message)\n    return {}\n  })\n\n  if (imageError) {\n    throw imageError\n  }\n\n  const imageData: Omit<MetadataImageModule, 'url'> = {\n    ...(extension in imageExtMimeTypeMap && {\n      type: imageExtMimeTypeMap[extension as keyof typeof imageExtMimeTypeMap],\n    }),\n    ...(useNumericSizes && imageSize.width != null && imageSize.height != null\n      ? imageSize\n      : {\n          sizes:\n            // For SVGs, skip sizes and use \"any\" to let it scale automatically based on viewport,\n            // For the images doesn't provide the size properly, use \"any\" as well.\n            // If the size is presented, use the actual size for the image.\n            extension !== 'svg' &&\n            imageSize.width != null &&\n            imageSize.height != null\n              ? `${imageSize.width}x${imageSize.height}`\n              : 'any',\n        }),\n  }\n  if (type === 'openGraph' || type === 'twitter') {\n    const altPath = path.join(\n      path.dirname(resourcePath),\n      fileNameBase + '.alt.txt'\n    )\n\n    if (existsSync(altPath)) {\n      imageData.alt = await fs.readFile(altPath, 'utf8')\n    }\n  }\n\n  return `\\\n  import { fillMetadataSegment } from 'next/dist/lib/metadata/get-metadata-route'\n\n  export default async (props) => {\n    const imageData = ${JSON.stringify(imageData)}\n    const imageUrl = fillMetadataSegment(${JSON.stringify(\n      pathnamePrefix\n    )}, await props.params, ${JSON.stringify(pageSegment)}, true)\n\n    return [{\n      ...imageData,\n      url: imageUrl + ${JSON.stringify(hashQuery)},\n    }]\n  }`\n}\n\nexport const raw = true\nexport default nextMetadataImageLoader\n"],"names":["raw","nextMetadataImageLoader","content","installBindings","options","getOptions","type","segment","pageExtensions","basePath","resourcePath","rootContext","context","name","fileNameBase","ext","path","parse","useNumericSizes","extension","slice","opts","contentHash","loaderUtils","interpolateName","interpolatedName","isDynamicResource","includes","pageSegment","hashQuery","pathnamePrefix","normalizePathSep","join","exportedFieldsExcludingDefault","getLoaderModuleNamedExports","filter","map","field","JSON","stringify","WEBPACK_RESOURCE_QUERIES","metadataImageMeta","imageError","imageSize","getImageSize","catch","error","message","posix","Error","imageData","imageExtMimeTypeMap","width","height","sizes","altPath","dirname","existsSync","alt","fs","readFile"],"mappings":"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","ignoreList":[0]}