diff --git a/index.ts b/index.ts index 150b91b..dfbed8e 100644 --- a/index.ts +++ b/index.ts @@ -1 +1,2 @@ -export { remarkEleventyImage } from "./src/astro-remark-images"; \ No newline at end of file +export { remarkEleventyImage } from "./src/astro-remark-images"; +export type { createHTMLProps, MarkupValues } from "./src/types"; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 2513412..302e866 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "astro-remark-eleventy-image", - "version": "1.1.2", + "version": "1.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "astro-remark-eleventy-image", - "version": "1.1.2", + "version": "1.2.0", "license": "MIT", "dependencies": { "@11ty/eleventy-img": "^3.0.0", diff --git a/package.json b/package.json index 5bf5ab9..d47b8ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "astro-remark-eleventy-image", - "version": "1.1.2", + "version": "1.2.0", "description": "Remark plugin for Astro that automatically optimizes images referenced in markdown files.", "author": "ChrisOh431", "license": "MIT", diff --git a/src/astro-remark-images.ts b/src/astro-remark-images.ts index 11981fb..103d0f9 100644 --- a/src/astro-remark-images.ts +++ b/src/astro-remark-images.ts @@ -4,6 +4,8 @@ import Image from "@11ty/eleventy-img"; // @ts-ignore import config from "./astro.config.mjs"; +import { createHTML } from "./markupUtil.js"; +import { MarkupValues } from "./types.js"; /* ONlY do this work in prod; don't want to mess up the dev build in any way @@ -14,15 +16,22 @@ import config from "./astro.config.mjs"; 4. Automagically optimized images! */ +type RemarkImagesConfig = { + sizes?: string, + remoteImages?: boolean, + eleventyImageConfig?: Image.ImageOptions, + customMarkup?: ((attributes: MarkupValues) => string), +}; function remarkEleventyImage() { const publicDir = config.publicDir || "./public/"; const outDir = config.outDir || "./dist/"; - const ricfg = (config?.markdown?.remarkImages) ? config.markdown.remarkImages : null; + const ricfg: RemarkImagesConfig = (config?.markdown?.remarkImages) ? config.markdown.remarkImages : null; const ricfgContainerSizes = (ricfg?.sizes) ? ricfg.sizes : "(max-width: 700px) 100vw, 700px"; const ricfgRemoteEnabled = (ricfg?.remoteImages) ? ricfg.remoteImages : false; - const ricfgEleventyImageConfig: Image.ImageOptions = (ricfg?.eleventyImageConfig) ? ricfg.eleventyImageConfig : null; + const ricfgCustomMarkup = (ricfg?.customMarkup) ? ricfg.customMarkup : null; + const ricfgEleventyImageConfig = (ricfg?.eleventyImageConfig) ? ricfg.eleventyImageConfig : null; // setup eleventy image config obj, overwrite with settings from astro.config.mjs const baseEleventyConfig: Image.ImageOptions = Object.assign({ @@ -97,6 +106,7 @@ function remarkEleventyImage() try { console.log(`(astro-remark-images) Optimizing image: ${path.basename(node.url)} referenced in file: ${path.basename(file.path)}`); + if (Image.Util.isRemoteUrl(node.url)) { // Remote image. In this case the optimized images are put @@ -131,14 +141,15 @@ function remarkEleventyImage() currentConfig.outputDir = outputImageDir; const stats: Image.Metadata = await Image(originalImagePath, Object.assign(currentConfig, baseEleventyConfig)); - const responsiveHTML = createPicture( - { - imageDir: outputImageDirHTML, - metadata: stats, - alt: node.alt, - sizes: ricfgContainerSizes - } - ); + const responsiveHTML = createHTML({ + imageDir: outputImageDirHTML, + metadata: stats, + alt: node.alt, + sizes: ricfgContainerSizes, + isRemote: Image.Util.isRemoteUrl(node.url), + mdFilePath: file.path, + customMarkup: ricfgCustomMarkup, + }); if (responsiveHTML) { @@ -157,49 +168,4 @@ function remarkEleventyImage() } }; -export { remarkEleventyImage }; - -interface createPictureProps -{ - imageDir: string, - metadata: Image.Metadata, - alt: string, - sizes: string, -} -function createPicture({ imageDir, metadata, alt, sizes }: createPictureProps) -{ - let baseSource: Image.MetadataEntry[]; - let highsrc: Image.MetadataEntry; - - if (metadata.jpeg && metadata.jpeg.length > 0) - { - baseSource = metadata.jpeg; - highsrc = metadata.jpeg[metadata.jpeg.length - 1]; - } - else - { - baseSource = Object.values(metadata)[0] as Image.MetadataEntry[]; - highsrc = baseSource[baseSource.length - 1]; - } - - function correctSrcset(entry: Image.MetadataEntry) - { - const filename = path.join(imageDir, path.basename(entry.url)) + ` ${entry.width}w`; - return filename; - } - - return ` - - ${Object.values(metadata).map(imageFormat => - { - return ` \n`; - }).join("\n")} - ${alt} - `; -} \ No newline at end of file +export { remarkEleventyImage }; \ No newline at end of file diff --git a/src/markupUtil.ts b/src/markupUtil.ts new file mode 100644 index 0000000..6d2c2f5 --- /dev/null +++ b/src/markupUtil.ts @@ -0,0 +1,71 @@ +import { MarkupValues } from "./types"; +import path from "path"; +import Image from "@11ty/eleventy-img"; + +export function defaultMarkup({ src, sources, width, height, alt }: MarkupValues) +{ + return ` + + ${sources} + ${alt} + `; +} + +interface CreateHTMLProps +{ + imageDir: string, + metadata: Image.Metadata, + alt: string, + sizes: string, + isRemote: boolean, + mdFilePath: string, + customMarkup: ((attributes: MarkupValues) => string) | null, +} +export function createHTML({ imageDir, metadata, alt, sizes, isRemote, mdFilePath, customMarkup }: CreateHTMLProps) +{ + let baseSource: Image.MetadataEntry[]; + let highsrc: Image.MetadataEntry; + + // picking the src for the base tag + if (metadata.jpeg && metadata.jpeg.length > 0) + { + baseSource = metadata.jpeg; + highsrc = metadata.jpeg[metadata.jpeg.length - 1]; + } + else + { + // when the image is remote, there's no jpeg, so just use the first format there is + baseSource = Object.values(metadata)[0] as Image.MetadataEntry[]; + highsrc = baseSource[baseSource.length - 1]; + } + + function generateSrcsets(metadata: Image.Metadata) + { + function correctSrcset(entry: Image.MetadataEntry) + { + const filename = path.join(imageDir, path.basename(entry.url)) + ` ${entry.width}w`; + return filename; + } + + return Object.values(metadata).map(imageFormat => + { + return ` \n`; + }).join("\n"); + } + + if (customMarkup) + { + return customMarkup({ src: path.join(imageDir, path.basename(highsrc.url)), width: highsrc.width, height: highsrc.height, alt: alt, format: baseSource[0].format, sources: generateSrcsets(metadata), isRemote: isRemote, mdFilePath: mdFilePath }); + } + else + { + return defaultMarkup({ src: path.join(imageDir, path.basename(highsrc.url)), width: highsrc.width, height: highsrc.height, alt: alt, format: baseSource[0].format, sources: generateSrcsets(metadata), isRemote: isRemote, mdFilePath: mdFilePath }); + } +} + diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..ad8dbbd --- /dev/null +++ b/src/types.ts @@ -0,0 +1,24 @@ +import type Image from "@11ty/eleventy-img"; + +type MarkupValues = { + src: string, + width: number, + height: number, + alt: string, + format: string, + sources: string, + isRemote: boolean, + mdFilePath: string, +}; + +interface createHTMLProps +{ + imageDir: string, + metadata: Image.Metadata, + alt: string, + sizes: string, + isRemote: boolean, + mdFilePath: string; +} + +export type { MarkupValues, createHTMLProps }; \ No newline at end of file