{"version":3,"file":"index.cjs","names":[],"sources":["../../../src/image/index.ts"],"sourcesContent":["// --- image() helper: optimized <img> / <picture> without dependencies ---\n//\n// Emits an `<img>` (or `<picture>` when processed variants are available) with:\n//   - `srcset` / `sizes` for responsive images\n//   - `loading=\"lazy\"` and `decoding=\"async\"` (unless `priority`)\n//   - `width` / `height` to prevent layout shift (CLS)\n//   - `fetchpriority=\"high\"` for above-the-fold images\n//\n// When the build-time pipeline (sharp) is available, `image()` registers the\n// source for processing and emits `<picture>` with `<source>` per format.\n// When sharp is not installed, it falls back to a plain `<img>` with srcset\n// pointing to the original file.\n\nimport { NIX_RENDER_PROTOCOL, type NixTemplate } from \"@deijose/nix-js\";\nimport { getManifestEntry, buildPictureMarkup } from \"./service.js\";\nimport {\n  registerImage,\n  getActiveManifest,\n} from \"./registry.js\";\n\nexport { consumeImageRegistry, setImageManifest, type ImageFormat } from \"./registry.js\";\n\nexport interface ImageOptions {\n  /** Source path relative to the public directory, e.g. \"/images/hero.jpg\". */\n  src: string;\n  /** Alt text (required for accessibility). */\n  alt: string;\n  /** Intrinsic width of the source image in pixels. */\n  width: number;\n  /** Intrinsic height of the source image in pixels. */\n  height: number;\n  /** Responsive widths to generate for srcset. Defaults to [width]. */\n  widths?: number[];\n  /** Sizes attribute for responsive layout, e.g. \"100vw\" or \"(min-width: 768px) 50vw, 100vw\". */\n  sizes?: string;\n  /** If true, loads eagerly with high priority (for above-the-fold images). */\n  priority?: boolean;\n  /** CSS class for the img element. */\n  class?: string;\n  /** Additional HTML attributes. */\n  attributes?: Record<string, string>;\n}\n\n/**\n * Creates a NixTemplate that renders an optimized `<img>` or `<picture>` element.\n *\n * When a manifest is active (post-build or SSR with manifest loaded):\n *   * Emits `<picture>` with `<source>` per format and real hashed variant URLs.\n *   * Uses real dimensions from the manifest.\n *\n * When no manifest is active (first build pass, dev without sharp):\n *   * Emits a plain `<img>` with the original src.\n *   * Does NOT emit srcset with unresolved variant URLs.\n *   * Registers the image for build-time processing.\n */\nexport function image(opts: ImageOptions): NixTemplate {\n  const {\n    src,\n    alt,\n    width,\n    height,\n    widths = [width],\n    sizes,\n    priority = false,\n    class: className,\n    attributes = {},\n  } = opts;\n\n  // Register for build-time processing.\n  registerImage(src, widths);\n\n  // If a manifest is active and has an entry for this src, emit <picture>.\n  let html: string;\n  const manifest = getActiveManifest();\n  const entry = manifest ? getManifestEntry(manifest, src) : undefined;\n  if (entry && entry.variants.length > 0) {\n    html = buildPictureMarkup(entry, {\n      alt,\n      sizes,\n      priority,\n      class: className,\n      attributes,\n      fallbackSrc: src,\n      fallbackWidth: width,\n      fallbackHeight: height,\n    });\n  } else {\n    // No manifest or no variants: emit a plain <img> with the original src.\n    // Do NOT emit srcset — the variant files don't exist yet.\n    const loadingAttr = priority ? \"\" : ' loading=\"lazy\"';\n    const fetchPriorityAttr = priority ? ' fetchpriority=\"high\"' : \"\";\n    const sizesAttr = sizes ? ` sizes=\"${escapeAttr(sizes)}\"` : \"\";\n    const classAttr = className ? ` class=\"${escapeAttr(className)}\"` : \"\";\n    const extraAttrs = Object.entries(attributes)\n      .map(([key, value]) => ` ${escapeAttr(key)}=\"${escapeAttr(String(value))}\"`)\n      .join(\"\");\n    html = `<img src=\"${escapeAttr(src)}\" alt=\"${escapeAttr(alt)}\" width=\"${width}\" height=\"${height}\"${sizesAttr}${loadingAttr} decoding=\"async\"${fetchPriorityAttr}${classAttr}${extraAttrs} />`;\n  }\n\n  return {\n    __isNixTemplate: true as const,\n    [NIX_RENDER_PROTOCOL]: {\n      renderServer: () => html,\n    },\n    mount(container: Element | string) {\n      const el = typeof container === \"string\" ? document.querySelector(container) : container;\n      if (!el) throw new Error(\"[nix-js-kit] image(): container not found\");\n      el.innerHTML = html;\n      return { unmount() { el.innerHTML = \"\"; } };\n    },\n    _render(parent: Node, before: Node | null): () => void {\n      const wrapper = document.createElement(\"template\");\n      wrapper.innerHTML = html;\n      const fragment = wrapper.content;\n      const inserted = Array.from(fragment.childNodes);\n      parent.insertBefore(fragment, before);\n      return () => {\n        for (const node of inserted) {\n          if (node.parentNode) node.parentNode.removeChild(node);\n        }\n      };\n    },\n  } as unknown as NixTemplate;\n}\n\nfunction escapeAttr(value: string): string {\n  return value\n    .replace(/&/g, \"&amp;\")\n    .replace(/\"/g, \"&quot;\")\n    .replace(/</g, \"&lt;\")\n    .replace(/>/g, \"&gt;\");\n}\n\nexport {\n  processImageBatch,\n  readManifest,\n  writeManifest,\n  getManifestEntry,\n  buildSrcset,\n  buildPictureMarkup,\n  validateManifestUrls,\n  isSharpAvailable,\n  getImage,\n  createImageService,\n  transformHash,\n} from \"./service.js\";\nexport type {\n  ImageManifest,\n  ImageEntry,\n  ImageVariant,\n  ProcessOptions,\n  ProcessResult,\n  ImageRequest,\n  ImageMetadata,\n  GeneratedImage,\n  ImageService,\n  ImageServiceCapabilities,\n  ImageServiceContext,\n} from \"./service.js\";\n"],"mappings":"iKAuDA,SAAgB,EAAM,EAAiC,CACrD,GAAM,CACJ,MACA,MACA,QACA,SACA,SAAS,CAAC,CAAK,EACf,QACA,WAAW,GACX,MAAO,EACP,aAAa,CAAC,GACZ,EAGJ,EAAA,cAAc,EAAK,CAAM,EAGzB,IAAI,EACE,EAAW,EAAA,kBAAkB,EAC7B,EAAQ,EAAW,EAAA,iBAAiB,EAAU,CAAG,EAAI,IAAA,GAC3D,GAAI,GAAS,EAAM,SAAS,OAAS,EACnC,EAAO,EAAA,mBAAmB,EAAO,CAC/B,MACA,QACA,WACA,MAAO,EACP,aACA,YAAa,EACb,cAAe,EACf,eAAgB,CAClB,CAAC,MACI,CAGL,IAAM,EAAc,EAAW,GAAK,kBAC9B,EAAoB,EAAW,wBAA0B,GACzD,EAAY,EAAQ,WAAW,EAAW,CAAK,EAAE,GAAK,GACtD,EAAY,EAAY,WAAW,EAAW,CAAS,EAAE,GAAK,GAC9D,EAAa,OAAO,QAAQ,CAAU,CAAC,CAC1C,KAAK,CAAC,EAAK,KAAW,IAAI,EAAW,CAAG,EAAE,IAAI,EAAW,OAAO,CAAK,CAAC,EAAE,EAAE,CAAC,CAC3E,KAAK,EAAE,EACV,EAAO,aAAa,EAAW,CAAG,EAAE,SAAS,EAAW,CAAG,EAAE,WAAW,EAAM,YAAY,EAAO,GAAG,IAAY,EAAY,mBAAmB,IAAoB,IAAY,EAAW,IAC5L,CAEA,MAAO,CACL,gBAAiB,IAChB,EAAA,qBAAsB,CACrB,iBAAoB,CACtB,EACA,MAAM,EAA6B,CACjC,IAAM,EAAK,OAAO,GAAc,SAAW,SAAS,cAAc,CAAS,EAAI,EAC/E,GAAI,CAAC,EAAI,MAAU,MAAM,2CAA2C,EAEpE,MADA,GAAG,UAAY,EACR,CAAE,SAAU,CAAE,EAAG,UAAY,EAAI,CAAE,CAC5C,EACA,QAAQ,EAAc,EAAiC,CACrD,IAAM,EAAU,SAAS,cAAc,UAAU,EACjD,EAAQ,UAAY,EACpB,IAAM,EAAW,EAAQ,QACnB,EAAW,MAAM,KAAK,EAAS,UAAU,EAE/C,OADA,EAAO,aAAa,EAAU,CAAM,MACvB,CACX,IAAK,IAAM,KAAQ,EACb,EAAK,YAAY,EAAK,WAAW,YAAY,CAAI,CAEzD,CACF,CACF,CACF,CAEA,SAAS,EAAW,EAAuB,CACzC,OAAO,EACJ,QAAQ,KAAM,OAAO,CAAC,CACtB,QAAQ,KAAM,QAAQ,CAAC,CACvB,QAAQ,KAAM,MAAM,CAAC,CACrB,QAAQ,KAAM,MAAM,CACzB"}