{"version":3,"file":"index.cjs","names":[],"sources":["../../../src/plugins/image/index.ts"],"sourcesContent":["import { isSupportedType, warnOnce } from \"../../utils\";\nimport { type DocxImageData, type RemarkDocxPlugin } from \"../../types\";\nimport type * as mdast from \"mdast\";\nimport { visit } from \"unist-util-visit\";\nimport { imageSize } from \"image-size\";\n\ntype LoadFn = (url: string) => Promise<ArrayBuffer>;\n\ntype SvgToPngFn = (options: {\n  buffer: ArrayBuffer;\n  width: number;\n  height: number;\n}) => Promise<ArrayBuffer>;\n\nconst loadWithFetch: LoadFn = async (url) => {\n  const res = await fetch(url);\n  return res.arrayBuffer();\n};\n\n/**\n * @internal\n */\nexport const browserSvgToPng: SvgToPngFn = async ({\n  buffer,\n  width,\n  height,\n}) => {\n  const svgBlob = new Blob([buffer], { type: \"image/svg+xml\" });\n  const url = URL.createObjectURL(svgBlob);\n\n  try {\n    const img = new Image();\n    img.src = url;\n    await img.decode();\n\n    const dpr = window.devicePixelRatio;\n\n    const canvas = document.createElement(\"canvas\");\n    const scaledWidth = width * dpr;\n    const scaledHeight = height * dpr;\n    canvas.width = scaledWidth;\n    canvas.height = scaledHeight;\n    const ctx = canvas.getContext(\"2d\")!;\n    ctx.drawImage(img, 0, 0, scaledWidth, scaledHeight);\n\n    return new Promise<ArrayBuffer>((resolve) => {\n      canvas.toBlob((blob) => {\n        blob!.arrayBuffer().then(resolve);\n      }, \"image/png\");\n    });\n  } finally {\n    URL.revokeObjectURL(url);\n  }\n};\n\nexport interface ImagePluginOptions {\n  /**\n   * A function to resolve image data from url.\n   * @default {@link loadWithFetch}\n   */\n  load?: LoadFn;\n  /**\n   * A function to convert SVG to PNG. According to the docx specifications, embedding SVG images also requires including PNG.\n   * @default {@link browserSvgToPng}, which handles conversion only on browser\n   */\n  fallbackSvg?: SvgToPngFn;\n}\n\n/**\n * A plugin to render \"image\" nodes\n */\nexport const imagePlugin = ({\n  load = loadWithFetch,\n  fallbackSvg = browserSvgToPng,\n}: ImagePluginOptions = {}): RemarkDocxPlugin => {\n  const cache = new Map<string, DocxImageData>();\n\n  const maxCacheLength = 100;\n\n  return async ({ root, definition, images }) => {\n    const imageList: (mdast.Image | mdast.Definition)[] = [];\n    visit(root, \"image\", (node) => {\n      imageList.push(node);\n    });\n    visit(root, \"imageReference\", (node) => {\n      const maybeImage = definition(node.identifier)!;\n      if (maybeImage) {\n        imageList.push(maybeImage);\n      }\n    });\n\n    if (imageList.length !== 0) {\n      const promises = new Map<string, Promise<void>>();\n      imageList.forEach(({ url }) => {\n        if (images.has(url)) {\n          return;\n        }\n        if (cache.has(url)) {\n          images.set(url, cache.get(url)!);\n          return;\n        }\n        if (!promises.has(url)) {\n          promises.set(\n            url,\n            (async () => {\n              let data: ArrayBuffer;\n              try {\n                data = await load(url);\n              } catch (e) {\n                warnOnce(`Failed to load image: ${url} ${e}`);\n                return;\n              }\n\n              const { width, height, type } = imageSize(new Uint8Array(data));\n              if (!isSupportedType(type)) {\n                warnOnce(`Not supported image type: ${type}`);\n                return;\n              }\n\n              if (type === \"svg\") {\n                try {\n                  const fallback = await fallbackSvg({\n                    buffer: data,\n                    width,\n                    height,\n                  });\n                  const docxImage: DocxImageData = {\n                    type,\n                    width,\n                    height,\n                    data,\n                    fallback,\n                  };\n                  images.set(url, docxImage);\n                  cache.set(url, docxImage);\n                } catch (e) {\n                  warnOnce(`Failed to create fallback image: ${url} ${e}`);\n                  return;\n                }\n              } else {\n                const docxImage: DocxImageData = { type, width, height, data };\n                images.set(url, docxImage);\n                cache.set(url, docxImage);\n              }\n            })(),\n          );\n        }\n      });\n\n      await Promise.all(promises.values());\n    }\n\n    if (cache.size > maxCacheLength) {\n      let deleteCount = cache.size - maxCacheLength;\n      for (const key of cache.keys()) {\n        cache.delete(key);\n        deleteCount--;\n        if (deleteCount <= 0) {\n          break;\n        }\n      }\n    }\n\n    return {};\n  };\n};\n"],"mappings":"yKAcA,IAAM,EAAwB,KAAO,KAE5B,MADW,MAAM,CAAG,GAChB,YAAY,EAMZ,EAA8B,MAAO,CAChD,SACA,QACA,YACI,CACJ,IAAM,EAAU,IAAI,KAAK,CAAC,CAAM,EAAG,CAAE,KAAM,eAAgB,CAAC,EACtD,EAAM,IAAI,gBAAgB,CAAO,EAEvC,GAAI,CACF,IAAM,EAAM,IAAI,MAChB,EAAI,IAAM,EACV,MAAM,EAAI,OAAO,EAEjB,IAAM,EAAM,OAAO,iBAEb,EAAS,SAAS,cAAc,QAAQ,EACxC,EAAc,EAAQ,EACtB,EAAe,EAAS,EAM9B,MALA,GAAO,MAAQ,EACf,EAAO,OAAS,EAEhB,EADmB,WAAW,IAC9B,EAAI,UAAU,EAAK,EAAG,EAAG,EAAa,CAAY,EAE3C,IAAI,QAAsB,GAAY,CAC3C,EAAO,OAAQ,GAAS,CACtB,EAAM,YAAY,EAAE,KAAK,CAAO,CAClC,EAAG,WAAW,CAChB,CAAC,CACH,QAAU,CACR,IAAI,gBAAgB,CAAG,CACzB,CACF,EAkBa,GAAe,CAC1B,OAAO,EACP,cAAc,GACQ,CAAC,IAAwB,CAC/C,IAAM,EAAQ,IAAI,IAIlB,OAAO,MAAO,CAAE,OAAM,aAAY,YAAa,CAC7C,IAAM,EAAgD,CAAC,EAWvD,IAVA,EAAA,EAAA,OAAM,EAAM,QAAU,GAAS,CAC7B,EAAU,KAAK,CAAI,CACrB,CAAC,GACD,EAAA,EAAA,OAAM,EAAM,iBAAmB,GAAS,CACtC,IAAM,EAAa,EAAW,EAAK,UAAU,EACzC,GACF,EAAU,KAAK,CAAU,CAE7B,CAAC,EAEG,EAAU,SAAW,EAAG,CAC1B,IAAM,EAAW,IAAI,IACrB,EAAU,SAAS,CAAE,SAAU,CACzB,MAAO,IAAI,CAAG,EAGlB,IAAI,EAAM,IAAI,CAAG,EAAG,CAClB,EAAO,IAAI,EAAK,EAAM,IAAI,CAAG,CAAE,EAC/B,MACF,CACK,EAAS,IAAI,CAAG,GACnB,EAAS,IACP,GACC,SAAY,CACX,IAAI,EACJ,GAAI,CACF,EAAO,MAAM,EAAK,CAAG,CACvB,OAAS,EAAG,CACV,EAAA,EAAS,yBAAyB,EAAI,GAAG,GAAG,EAC5C,MACF,CAEA,GAAM,CAAE,QAAO,SAAQ,SAAA,EAAA,EAAA,WAAmB,IAAI,WAAW,CAAI,CAAC,EAC9D,GAAI,CAAC,EAAA,EAAgB,CAAI,EAAG,CAC1B,EAAA,EAAS,6BAA6B,GAAM,EAC5C,MACF,CAEA,GAAI,IAAS,MACX,GAAI,CACF,IAAM,EAAW,MAAM,EAAY,CACjC,OAAQ,EACR,QACA,QACF,CAAC,EACK,EAA2B,CAC/B,OACA,QACA,SACA,OACA,UACF,EACA,EAAO,IAAI,EAAK,CAAS,EACzB,EAAM,IAAI,EAAK,CAAS,CAC1B,OAAS,EAAG,CACV,EAAA,EAAS,oCAAoC,EAAI,GAAG,GAAG,EACvD,MACF,KACK,CACL,IAAM,EAA2B,CAAE,OAAM,QAAO,SAAQ,MAAK,EAC7D,EAAO,IAAI,EAAK,CAAS,EACzB,EAAM,IAAI,EAAK,CAAS,CAC1B,CACF,GAAG,CACL,CA7CF,CA+CF,CAAC,EAED,MAAM,QAAQ,IAAI,EAAS,OAAO,CAAC,CACrC,CAEA,GAAI,EAAM,KAAO,IAAgB,CAC/B,IAAI,EAAc,EAAM,KAAO,IAC/B,IAAK,IAAM,KAAO,EAAM,KAAK,EAG3B,GAFA,EAAM,OAAO,CAAG,EAChB,IACI,GAAe,EACjB,KAGN,CAEA,MAAO,CAAC,CACV,CACF"}