{"version":3,"sources":["../src/lib/constants.ts","../src/lib/get-storyblok-src-host.ts","../src/lib/parse-storyblok-src.ts","../src/lib/get-storyblok-image-filename.ts","../src/lib/get-storyblok-image-quality.ts","../src/lib/get-storyblok-image-filters.ts","../src/lib/storyblok-image-size-limit.ts","../src/lib/get-storyblok-image-size.ts","../src/lib/img-src-is-storyblok.ts","../src/lib/get-storyblok-src.ts","../src/lib/get-storyblok-image-loader.ts","../src/lib/storyblok-image-loader.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export const IMAGE_SIZE_LIMIT = 4000 as const;\nexport const DEFAULT_HOST = \"a.storyblok.com\" as const;\n","import { DEFAULT_HOST } from \"./constants\";\n\n/**\n * Gets the host for Storyblok images. Defaults to \"a.storyblok.com\"\n * if no override is provided or STORYBLOK_IMAGE_LOADER_HOST environment\n * variable isn't set.\n * @param {string} override Manual override for the host\n * @returns\n */\nexport function getStoryblokSrcHost(override?: string): string {\n  // Regex to match a hostname with an optional port\n  const pattern = /^\\w+(\\.\\w+)*(:\\d+)?$/;\n\n  // Return override if set and valid\n  if (override && pattern.test(override)) {\n    return override;\n  }\n\n  // Return environment variable if set and valid\n  if (\n    process.env.STORYBLOK_IMAGE_LOADER_HOST &&\n    pattern.test(process.env.STORYBLOK_IMAGE_LOADER_HOST)\n  ) {\n    return process.env.STORYBLOK_IMAGE_LOADER_HOST;\n  }\n\n  // If no valid override or environment variable is provided, return default\n  return DEFAULT_HOST;\n}\n","import type { ParsedStoryblokSrc } from \"../types/parsed-storyblok-src\";\nimport type { StoryblokImageFormat } from \"../types/storyblok-image-format\";\nimport type { StoryblokImageLoaderOptions } from \"../types/storyblok-image-loader-options\";\nimport type { StoryblokImageResize } from \"../types/storyblok-image-resize\";\n\nimport { StoryblokImageFocus } from \"../types/storyblok-image-focus\";\nimport { getStoryblokSrcHost } from \"./get-storyblok-src-host\";\n\n// Precompiled regex patterns (compiled once per module load)\nconst SIZE_PATTERN = /^(\\d+)x(\\d+)$/;\nconst FOCAL_PATTERN = /focal\\((\\d+)x(\\d+):(\\d+)x(\\d+)\\)/;\n\n// Allow only explicitly supported formats to avoid unsafe casting\nconst ALLOWED_FORMATS: readonly StoryblokImageFormat[] = [\n  \"avif\",\n  \"jpeg\",\n  \"png\",\n  \"webp\",\n];\n\ntype ParsedFilters = {\n  focus?: StoryblokImageFocus;\n  format?: StoryblokImageFormat;\n  quality?: number;\n};\n\nexport function parseStoryblokSrc(\n  src: string,\n  options?: StoryblokImageLoaderOptions,\n): ParsedStoryblokSrc {\n  let url: URL;\n  try {\n    url = new URL(src);\n  } catch (error) {\n    console.error(error);\n    throw new TypeError(`Invalid Storyblok image URL: ${src}`);\n  }\n\n  // Normalize host (retain original protocol)\n  url.host = getStoryblokSrcHost(options?.host);\n\n  const pathSegments = url.pathname.split(\"/\").filter(Boolean); // drop empty leading segment\n  const mIndex = pathSegments.indexOf(\"m\");\n\n  // Base filename should point to the original asset root, i.e., everything before /m/... (if present)\n  // Examples:\n  //  /f/123456/image.jpg -> /f/123456/image.jpg (no transformation)\n  //  /f/123456/m/800x600/filters:.../image.jpg -> /f/123456\n  const baseSegments =\n    mIndex >= 0 ? pathSegments.slice(0, mIndex) : pathSegments;\n  // If we have a direct asset (no m) keep full path; if transformed, only keep first 2 segments after /f\n  // Previous implementation sliced first 6 raw splits; replicating intent by reconstructing then trimming '/m'\n  // Build a preliminary filename URL\n  const basePath = `/${baseSegments.join(\"/\")}`;\n  const filename = new URL(basePath, url).href;\n\n  const result: ParsedStoryblokSrc = { filename };\n\n  // Size parsing (only when 'm' segment is present and followed by \\d+x\\d+)\n  if (mIndex >= 0) {\n    const sizeCandidate = pathSegments[mIndex + 1];\n    const sizeMatch = SIZE_PATTERN.exec(sizeCandidate || \"\");\n    if (sizeMatch) {\n      const width = Number.parseInt(sizeMatch[1], 10);\n      const height = Number.parseInt(sizeMatch[2], 10);\n      if (!Number.isNaN(width) && !Number.isNaN(height)) {\n        const resize: StoryblokImageResize = { height, width };\n        result.resize = resize;\n      }\n    }\n  }\n\n  // Filters parsing (look for the first segment that starts with filters:)\n  const filtersSegment = pathSegments.find((segment) =>\n    segment.startsWith(\"filters:\"),\n  );\n  const { focus, format, quality } = parseFilters(filtersSegment);\n  if (typeof quality !== \"undefined\") {\n    result.quality = quality;\n  }\n  if (typeof format !== \"undefined\") {\n    result.format = format;\n  }\n  if (typeof focus !== \"undefined\") {\n    result.focus = focus;\n  }\n\n  return result;\n}\n\nfunction parseFilters(segment?: string): ParsedFilters {\n  if (!segment || !segment.startsWith(\"filters:\")) return {};\n  // Remove the leading \"filters:\" then split into individual filters preserving order\n  const rawFilters = segment\n    .substring(\"filters:\".length)\n    // Convert :x to __x so we can split safely while keeping order\n    .replace(/:([a-z])/g, \"__$1\")\n    .split(\"__\");\n\n  const parsed: ParsedFilters = {};\n  for (const filter of rawFilters) {\n    if (filter.startsWith(\"quality\")) {\n      const value = Number.parseInt(\n        filter.replace(/quality\\((.+)\\)/, \"$1\"),\n        10,\n      );\n      if (!Number.isNaN(value) && value >= 1 && value <= 100) {\n        parsed.quality = value;\n      }\n    } else if (filter.startsWith(\"format\")) {\n      const value = filter.replace(\n        /format\\((.+)\\)/,\n        \"$1\",\n      ) as StoryblokImageFormat;\n      if (ALLOWED_FORMATS.includes(value)) {\n        parsed.format = value;\n      }\n    } else if (filter.startsWith(\"focal\") && FOCAL_PATTERN.test(filter)) {\n      parsed.focus = filter.replace(\n        FOCAL_PATTERN,\n        \"$1x$2:$3x$4\",\n      ) as StoryblokImageFocus;\n    }\n  }\n  return parsed;\n}\n","import type { AssetStoryblok } from \"../types/asset-storyblok\";\nimport type { StoryblokImageLoaderOptions } from \"../types/storyblok-image-loader-options\";\n\nimport { parseStoryblokSrc } from \"./parse-storyblok-src\";\n\nexport function getStoryblokImageFilename(\n  image: AssetStoryblok | string | undefined,\n  imageOptions?: null | StoryblokImageLoaderOptions,\n) {\n  let filename = \"\";\n  const options: StoryblokImageLoaderOptions = imageOptions || {};\n  if (image && typeof image !== \"string\" && !!image?.focus) {\n    options.focus = image?.focus;\n  }\n  if (typeof image === \"string\") {\n    const parsed = parseStoryblokSrc(image, options);\n    filename = parsed.filename;\n    if (typeof parsed.focus !== \"undefined\") {\n      options.focus = parsed.focus;\n    }\n    if (typeof parsed.format !== \"undefined\") {\n      options.format = parsed.format;\n    }\n    if (typeof parsed.quality !== \"undefined\") {\n      options.quality = parsed.quality;\n    }\n    if (typeof parsed.resize !== \"undefined\") {\n      options.resize = parsed.resize;\n    }\n  }\n  if (typeof image !== \"string\" && image?.filename) {\n    filename = image?.filename;\n  }\n\n  return {\n    filename,\n    options,\n  };\n}\n","export function getStoryblokImageQuality(input: number): string {\n  const quality = Math.floor(Math.max(0, Math.min(100, input)));\n  return `quality(${quality})`;\n}\n","import type { StoryblokImageLoaderOptions } from \"../types/storyblok-image-loader-options\";\n\nimport { getStoryblokImageQuality } from \"./get-storyblok-image-quality\";\n\nexport function getStoryblokImageFilters(\n  options?: StoryblokImageLoaderOptions,\n): string | undefined {\n  const filters: string[] = [];\n\n  if (options?.format) {\n    filters.push(`format(${options.format})`);\n  }\n  if (typeof options?.quality === \"number\") {\n    filters.push(getStoryblokImageQuality(options.quality));\n  }\n  if (options?.resize && options?.focus) {\n    filters.push(`focal(${options.focus})`);\n  }\n  const filtersString = filters.filter(Boolean).join(\":\");\n  return filtersString ? `filters:${filtersString}` : undefined;\n}\n","export const STORYBLOK_IMAGE_SIZE_LIMIT = 4000 as const;\n","import type { StoryblokImageResize } from \"../types/storyblok-image-resize\";\n\nimport { STORYBLOK_IMAGE_SIZE_LIMIT } from \"./storyblok-image-size-limit\";\n\nexport function getStoryblokImageSize(\n  resize: StoryblokImageResize,\n): string | undefined {\n  if (!resize.width) {\n    return;\n  }\n\n  let { height = 0, width } = resize;\n\n  if (width > height && width > STORYBLOK_IMAGE_SIZE_LIMIT) {\n    width = STORYBLOK_IMAGE_SIZE_LIMIT;\n    height = resize.height\n      ? Math.floor((resize.height / resize.width) * width)\n      : 0;\n  }\n  if (resize.height && height > width && height > STORYBLOK_IMAGE_SIZE_LIMIT) {\n    height = STORYBLOK_IMAGE_SIZE_LIMIT;\n    width = Math.floor((resize.width / resize.height) * height);\n  }\n  return `${width}x${height}`;\n}\n","import { DEFAULT_HOST } from \"./constants\";\n\nexport function imgSrcIsStoryblok(\n  src: string,\n  host: string = DEFAULT_HOST,\n): boolean {\n  const url = new URL(src);\n  return url.host.includes(host);\n}\n","import type { AssetStoryblok } from \"../types/asset-storyblok\";\nimport type { StoryblokImageLoaderOptions } from \"../types/storyblok-image-loader-options\";\n\nimport { getStoryblokImageFilename } from \"./get-storyblok-image-filename\";\nimport { getStoryblokImageFilters } from \"./get-storyblok-image-filters\";\nimport { getStoryblokImageSize } from \"./get-storyblok-image-size\";\nimport { imgSrcIsStoryblok } from \"./img-src-is-storyblok\";\n\n/**\n * Get Storyblok image src URL from given asset and options\n * @param image Storyblok asset or image URL\n * @param imageOptions Options for constructing the image URL\n * @returns URL string or undefined if no URL could be constructed\n */\nexport function getStoryblokSrc(\n  image: AssetStoryblok | string | undefined,\n  imageOptions?: null | StoryblokImageLoaderOptions,\n): string | undefined {\n  // Exit if image is a string and not a Storyblok asset URL\n  if (\n    typeof image === \"string\" &&\n    !imgSrcIsStoryblok(image, imageOptions?.host)\n  ) {\n    return image;\n  }\n\n  // Get filename\n  const { filename, options } = getStoryblokImageFilename(image, imageOptions);\n\n  // Exit if no filename could be constructed\n  if (!filename) {\n    return;\n  }\n\n  // Create an array of path based options\n  const parts: (string | undefined)[] = [filename, \"m\"];\n\n  // Add resize options if set\n  if (options?.resize) {\n    parts.push(getStoryblokImageSize(options.resize));\n  }\n\n  // Add smart format option if not explicitly disabled\n  if ((options?.resize || options?.focus) && options?.smart !== false) {\n    parts.push(\"smart\");\n  }\n\n  // Add filters if set\n  if (typeof options !== \"undefined\") {\n    parts.push(getStoryblokImageFilters(options));\n  }\n\n  // Join parts into a path string\n  const src = parts.filter(Boolean).join(\"/\");\n\n  // If a prefix is set, remove host and prepend prefix\n  if (imageOptions?.prefix || process.env.STORYBLOK_IMAGE_LOADER_PREFIX) {\n    const prefix =\n      imageOptions?.prefix || process.env.STORYBLOK_IMAGE_LOADER_PREFIX;\n    const url = new URL(src);\n    return `${prefix}${url.pathname}`.replace(\"//\", \"/\");\n  }\n\n  // Return the constructed URL\n  return src;\n}\n","import type { ImageLoader } from \"next/image\";\n\nimport type { StoryblokImageLoaderOptions } from \"../types/storyblok-image-loader-options\";\n\nimport { getStoryblokSrc } from \"./get-storyblok-src\";\nimport { imgSrcIsStoryblok } from \"./img-src-is-storyblok\";\nimport { parseStoryblokSrc } from \"./parse-storyblok-src\";\n\n/**\n * Get a Storyblok image loader for Next.js Image component.\n * @param options Options for the loader\n * @returns Image loader function\n */\nexport function getStoryblokImageLoader(\n  options: StoryblokImageLoaderOptions = {},\n): ImageLoader {\n  return ({ quality, src, width: inputWidth }) => {\n    // Check if it's a Storyblok URL first\n    if (!imgSrcIsStoryblok(src, options.host)) {\n      return src;\n    }\n\n    const url = new URL(src);\n\n    const parsed = parseStoryblokSrc(src);\n\n    const parts = url.pathname.split(\"/\");\n    const size = parts[3]?.split(\"x\");\n\n    if (!size || size.length < 2) {\n      // If URL doesn't have the expected format, use getStoryblokSrc directly\n      const loaderOptions: StoryblokImageLoaderOptions = {\n        ...options,\n        resize: { width: inputWidth },\n      };\n      if (typeof quality === \"number\") {\n        loaderOptions.quality = quality;\n      }\n      return getStoryblokSrc(src, loaderOptions) || src;\n    }\n\n    const originalWidth = Number.parseInt(size[0], 10);\n    const originalHeight = Number.parseInt(size[1], 10);\n\n    const originalAspectRatio = originalWidth / originalHeight;\n    let resizedAspectRatio = originalAspectRatio;\n\n    if (parsed.resize?.height) {\n      resizedAspectRatio = parsed.resize.width / parsed.resize.height;\n    }\n\n    const resize = {\n      height: resizedAspectRatio\n        ? Math.floor(inputWidth / resizedAspectRatio)\n        : 0,\n      width: inputWidth,\n    };\n\n    if (typeof quality !== \"undefined\") {\n      options.quality = quality;\n    }\n    if (inputWidth !== undefined && typeof resize !== \"undefined\") {\n      options.resize = resize;\n    }\n\n    return getStoryblokSrc(src, options) || src;\n  };\n}\n","import type { ImageLoader } from \"next/image\";\n\nimport { getStoryblokImageLoader } from \"./get-storyblok-image-loader\";\n\n/**\n * Storyblok image loader for Next.js Image component with default options.\n */\nexport const storyblokImageLoader: ImageLoader = getStoryblokImageLoader();\n"]}