UNPKG

remark-docx

Version:

remark plugin to compile markdown to docx (Microsoft Word, Office Open XML).

1 lines 6.75 kB
{"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"}