{"version":3,"file":"images-BzlmoG5C.mjs","names":[],"sources":["../src/utils/concurrency.ts","../src/assets/images.ts"],"sourcesContent":["import { availableParallelism } from \"os\";\n\n/**\n * Default bounded-concurrency limit derived from the host's available\n * parallelism (never less than 1). Used as the cap for CPU- and IO-bound fan-out\n * so a large collection or asset set does not spawn an unbounded number of\n * in-flight promises at once.\n */\nexport function defaultConcurrency(): number {\n  return Math.max(1, availableParallelism());\n}\n\n/**\n * Map over `items` with an async `mapper`, running at most `concurrency`\n * invocations in flight at any time. Results are returned in the same order as\n * `items` regardless of completion order.\n *\n * This is the single shared worker-pool primitive for `@pagesmith/core`; use it\n * anywhere an unbounded `Promise.all(items.map(...))` would otherwise spawn one\n * promise per item (content loading, image variant emission, …).\n *\n * The `mapper` is responsible for its own error handling if partial failures\n * should not reject the whole batch — a thrown error propagates and rejects the\n * returned promise, mirroring `Promise.all`.\n *\n * @param items - Items to process. An empty list resolves to an empty array.\n * @param mapper - Async transform invoked with each item and its index.\n * @param concurrency - Maximum in-flight invocations. Defaults to\n *   {@link defaultConcurrency}. Values below 1 are clamped to 1.\n */\nexport async function mapWithConcurrency<T, R>(\n  items: readonly T[],\n  mapper: (item: T, index: number) => Promise<R>,\n  concurrency: number = defaultConcurrency(),\n): Promise<R[]> {\n  const total = items.length;\n  const results: R[] = Array.from({ length: total });\n  if (total === 0) return results;\n\n  const limit = Math.max(1, Math.min(Math.floor(concurrency) || 1, total));\n  let next = 0;\n\n  async function worker(): Promise<void> {\n    while (next < total) {\n      const current = next++;\n      results[current] = await mapper(items[current], current);\n    }\n  }\n\n  await Promise.all(Array.from({ length: limit }, () => worker()));\n  return results;\n}\n","import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from \"fs\";\nimport { dirname, extname, join } from \"path\";\nimport sharp from \"sharp\";\nimport { mapWithConcurrency } from \"../utils/concurrency\";\nimport type { ContentAssetMap } from \"./index\";\n\nexport const CONVERTIBLE_IMAGE_EXTS = new Set([\".jpg\", \".jpeg\", \".png\", \".webp\", \".gif\"]);\nexport const GENERATED_IMAGE_FORMATS = [\"avif\", \"webp\"] as const;\n\nexport type GeneratedImageFormat = (typeof GENERATED_IMAGE_FORMATS)[number];\n\n/**\n * Maximum width (in pixels) of the rendered display variants (avif/webp).\n * Designed for ~800px content columns at 2x DPR.\n */\nexport const DISPLAY_MAX_WIDTH = 1600;\n\n/**\n * Maximum width (in pixels) of the zoom variant served to the full-screen\n * image-zoom modal. Smaller-than-cap sources keep their native width.\n */\nexport const ZOOM_MAX_WIDTH = 4800;\n\n/** File-name suffix used by the zoom variant: `<stem>.zoom.webp`. */\nexport const ZOOM_VARIANT_SUFFIX = \".zoom.webp\";\n\nexport type LocalImageDimensions = {\n  width: number;\n  height: number;\n};\n\nconst SVG_EXT = \".svg\";\nconst SVG_ROOT_TAG_PATTERN = /<svg\\b([^>]*)>/i;\nconst VIEWBOX_PATTERN = /viewBox\\s*=\\s*(['\"])([^'\"]+)\\1/i;\nconst WIDTH_PATTERN = /width\\s*=\\s*(['\"])([^'\"]+)\\1/i;\nconst HEIGHT_PATTERN = /height\\s*=\\s*(['\"])([^'\"]+)\\1/i;\nconst SIMPLE_LENGTH_PATTERN = /^\\s*([+-]?(?:\\d+\\.?\\d*|\\.\\d+))(?:px)?\\s*$/i;\n\nconst dimensionCache = new Map<string, Promise<LocalImageDimensions | undefined>>();\nconst MAX_DIMENSION_CACHE_ENTRIES = 512;\n\nfunction normalizeAssetPath(assetPath: string): string {\n  return assetPath.replace(/\\\\/g, \"/\");\n}\n\nfunction findAssetPathKey(assets: ContentAssetMap, assetPath: string): string | undefined {\n  if (assets.byPath.has(assetPath)) return assetPath;\n\n  const normalized = normalizeAssetPath(assetPath);\n  if (assets.byPath.has(normalized)) return normalized;\n\n  for (const key of assets.byPath.keys()) {\n    if (normalizeAssetPath(key) === normalized) return key;\n  }\n\n  return undefined;\n}\n\nfunction setDimensionCacheEntry(\n  cacheKey: string,\n  pending: Promise<LocalImageDimensions | undefined>,\n): void {\n  dimensionCache.set(cacheKey, pending);\n  if (dimensionCache.size <= MAX_DIMENSION_CACHE_ENTRIES) return;\n\n  const oldestKey = dimensionCache.keys().next().value;\n  if (typeof oldestKey === \"string\") {\n    dimensionCache.delete(oldestKey);\n  }\n}\n\nfunction roundPositiveDimension(value: number | undefined): number | undefined {\n  if (value == null || !Number.isFinite(value) || value <= 0) return undefined;\n  return Math.max(1, Math.round(value));\n}\n\nfunction parseSimpleLength(value: string | undefined): number | undefined {\n  if (!value) return undefined;\n  const match = value.match(SIMPLE_LENGTH_PATTERN);\n  if (!match) return undefined;\n  const parsed = Number(match[1]);\n  return roundPositiveDimension(parsed);\n}\n\nfunction parseSvgViewBox(source: string): { width: number; height: number } | undefined {\n  const match = source.match(VIEWBOX_PATTERN);\n  if (!match) return undefined;\n\n  const parts = match[2]\n    .split(/[\\s,]+/u)\n    .map((part) => Number(part))\n    .filter((part) => Number.isFinite(part));\n\n  if (parts.length !== 4) return undefined;\n\n  const width = roundPositiveDimension(parts[2]);\n  const height = roundPositiveDimension(parts[3]);\n  if (!width || !height) return undefined;\n\n  return { width, height };\n}\n\nfunction parseSvgDimensions(sourcePath: string): LocalImageDimensions | undefined {\n  const svg = readFileSync(sourcePath, \"utf-8\");\n  const rootMatch = svg.match(SVG_ROOT_TAG_PATTERN);\n  if (!rootMatch) return undefined;\n\n  const rootTag = rootMatch[0];\n  const width = parseSimpleLength(rootTag.match(WIDTH_PATTERN)?.[2]);\n  const height = parseSimpleLength(rootTag.match(HEIGHT_PATTERN)?.[2]);\n  const viewBox = parseSvgViewBox(rootTag);\n\n  if (width && height) return { width, height };\n\n  if (viewBox) {\n    if (width && !height) {\n      return {\n        width,\n        height: roundPositiveDimension((width * viewBox.height) / viewBox.width) ?? viewBox.height,\n      };\n    }\n    if (height && !width) {\n      return {\n        width: roundPositiveDimension((height * viewBox.width) / viewBox.height) ?? viewBox.width,\n        height,\n      };\n    }\n    return viewBox;\n  }\n\n  return undefined;\n}\n\nexport async function getLocalImageDimensions(\n  sourcePath: string,\n): Promise<LocalImageDimensions | undefined> {\n  if (!existsSync(sourcePath)) return undefined;\n\n  const stat = statSync(sourcePath);\n  const cacheKey = `${sourcePath}:${stat.mtimeMs}:${stat.size}`;\n  const cached = dimensionCache.get(cacheKey);\n  if (cached) return cached;\n\n  const ext = extname(sourcePath).toLowerCase();\n  const pending =\n    ext === SVG_EXT\n      ? Promise.resolve(parseSvgDimensions(sourcePath))\n      : sharp(sourcePath)\n          .metadata()\n          .then((metadata) => {\n            const width = roundPositiveDimension(metadata.autoOrient.width ?? metadata.width);\n            const height = roundPositiveDimension(metadata.autoOrient.height ?? metadata.height);\n            if (!width || !height) return undefined;\n            return { width, height };\n          })\n          .catch((error) => {\n            console.warn(\n              `[pagesmith] Failed to read local image metadata for ${sourcePath}: ${error instanceof Error ? error.message : String(error)}`,\n            );\n            return undefined;\n          });\n\n  setDimensionCacheEntry(cacheKey, pending);\n  return pending;\n}\n\nexport function isConvertibleImagePath(assetPath: string): boolean {\n  return CONVERTIBLE_IMAGE_EXTS.has(extname(assetPath).toLowerCase());\n}\n\nexport function getGeneratedImageVariantPath(\n  assetPath: string,\n  format: GeneratedImageFormat,\n): string {\n  const ext = extname(assetPath);\n  return `${assetPath.slice(0, -ext.length)}.${format}`;\n}\n\n/**\n * Path of the zoom variant generated next to the display variants:\n * `path/to/foo.png` → `path/to/foo.zoom.webp`.\n */\nexport function getZoomImageVariantPath(assetPath: string): string {\n  const ext = extname(assetPath);\n  return `${assetPath.slice(0, -ext.length)}${ZOOM_VARIANT_SUFFIX}`;\n}\n\nexport function resolveGeneratedImageSourceAssetPath(\n  assetPath: string,\n  assets: ContentAssetMap,\n): string | undefined {\n  const lower = assetPath.toLowerCase();\n  const ext = extname(assetPath).toLowerCase();\n  if (ext !== \".avif\" && ext !== \".webp\") return undefined;\n\n  // The high-resolution zoom variant (`<stem>.zoom.webp`) shares its source\n  // with the display webp variant. Strip the full `.zoom.webp` so we map\n  // back to the original raster (`.png` / `.jpg` / …).\n  const stem = lower.endsWith(ZOOM_VARIANT_SUFFIX)\n    ? assetPath.slice(0, -ZOOM_VARIANT_SUFFIX.length)\n    : assetPath.slice(0, -ext.length);\n  for (const sourceExt of CONVERTIBLE_IMAGE_EXTS) {\n    const candidate = `${stem}${sourceExt}`;\n    const resolvedKey = findAssetPathKey(assets, candidate);\n    if (resolvedKey) return resolvedKey;\n  }\n\n  return undefined;\n}\n\nexport function resolveGeneratedImageSourcePath(\n  assetPath: string,\n  assets: ContentAssetMap,\n): string | undefined {\n  const sourceAssetPath = resolveGeneratedImageSourceAssetPath(assetPath, assets);\n  return sourceAssetPath ? assets.byPath.get(sourceAssetPath) : undefined;\n}\n\nexport async function renderGeneratedImageVariant(\n  sourcePath: string,\n  format: GeneratedImageFormat,\n  options?: { maxWidth?: number },\n): Promise<Buffer> {\n  let pipeline = sharp(sourcePath).autoOrient();\n  if (options?.maxWidth && options.maxWidth > 0) {\n    pipeline = pipeline.resize({\n      width: options.maxWidth,\n      withoutEnlargement: true,\n    });\n  }\n  if (format === \"avif\") {\n    return pipeline.avif().toBuffer();\n  }\n  return pipeline.webp().toBuffer();\n}\n\n/**\n * Render the dedicated zoom variant for a convertible source image.\n * Always webp; capped at `ZOOM_MAX_WIDTH` but never upscaled.\n */\nexport async function renderZoomImageVariant(sourcePath: string): Promise<Buffer> {\n  return sharp(sourcePath)\n    .autoOrient()\n    .resize({ width: ZOOM_MAX_WIDTH, withoutEnlargement: true })\n    .webp()\n    .toBuffer();\n}\n\n/** A single image-variant render + write unit of work. */\ntype ImageVariantTask = {\n  destPath: string;\n  label: string;\n  render: () => Promise<Buffer>;\n};\n\nexport async function emitGeneratedImageVariants(\n  assetsDir: string,\n  assets: ContentAssetMap,\n): Promise<void> {\n  // Flatten every convertible source into individual render tasks up front so\n  // they can be run through the shared bounded worker pool. Sharp spins up\n  // native threads per call, so an unbounded `Promise.all` over a large asset\n  // set can oversubscribe CPU and memory; capping in-flight renders keeps peak\n  // resource use proportional to the host's parallelism.\n  const tasks: ImageVariantTask[] = [];\n\n  for (const [assetPath, sourcePath] of assets.byPath) {\n    if (!isConvertibleImagePath(assetPath)) continue;\n\n    for (const format of GENERATED_IMAGE_FORMATS) {\n      const destPath = join(assetsDir, getGeneratedImageVariantPath(assetPath, format));\n      tasks.push({\n        destPath,\n        label: `${format} variant for ${sourcePath}`,\n        render: () =>\n          renderGeneratedImageVariant(sourcePath, format, { maxWidth: DISPLAY_MAX_WIDTH }),\n      });\n    }\n\n    const zoomDestPath = join(assetsDir, getZoomImageVariantPath(assetPath));\n    tasks.push({\n      destPath: zoomDestPath,\n      label: `zoom variant for ${sourcePath}`,\n      render: () => renderZoomImageVariant(sourcePath),\n    });\n  }\n\n  const failures: string[] = [];\n  await mapWithConcurrency(tasks, async (task) => {\n    try {\n      const buffer = await task.render();\n      mkdirSync(dirname(task.destPath), { recursive: true });\n      writeFileSync(task.destPath, buffer);\n    } catch (error) {\n      failures.push(`${task.label}: ${error instanceof Error ? error.message : String(error)}`);\n    }\n  });\n\n  if (failures.length > 0) {\n    console.warn(\n      `pagesmith: failed to emit ${failures.length} generated image variant(s):\\n${failures.map((f) => `  - ${f}`).join(\"\\n\")}`,\n    );\n  }\n}\n"],"mappings":"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"}