Skip to content

Commit

Permalink
Fixes #267
Browse files Browse the repository at this point in the history
  • Loading branch information
zachleat committed Jan 3, 2025
1 parent 7bf0f04 commit 04e803a
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 32 deletions.
18 changes: 10 additions & 8 deletions src/generate-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function generateSrcset(metadataFormatEntry) {
]
}
*/
function generateObject(metadata, userDefinedImgAttributes = {}, userDefinedPictureAttributes = {}, options = {}) {
function generateObject(metadata, userDefinedImgAttributes = {}, userDefinedPictureAttributes = {}, htmlOptions = {}) {
let imgAttributes = Object.assign({}, userDefinedImgAttributes);
let pictureAttributes = Object.assign({}, userDefinedPictureAttributes);

Expand Down Expand Up @@ -71,14 +71,14 @@ function generateObject(metadata, userDefinedImgAttributes = {}, userDefinedPict

imgAttributes.src = lowsrc[0].url;

if(options.fallback === "largest" || options.fallback === undefined) {
if(htmlOptions.fallback === "largest" || htmlOptions.fallback === undefined) {
imgAttributes.width = lowsrc[lowsrc.length - 1].width;
imgAttributes.height = lowsrc[lowsrc.length - 1].height;
} else if(options.fallback === "smallest") {
} else if(htmlOptions.fallback === "smallest") {
imgAttributes.width = lowsrc[0].width;
imgAttributes.height = lowsrc[0].height;
} else {
throw new Error("Invalid `fallback` option specified. 'largest' and 'smallest' are supported. Received: " + options.fallback);
throw new Error("Invalid `fallback` option specified. 'largest' and 'smallest' are supported. Received: " + htmlOptions.fallback);
}

let imgAttributesWithoutSizes = Object.assign({}, imgAttributes);
Expand Down Expand Up @@ -182,12 +182,14 @@ function mapObjectToHTML(tagName, attrs = {}) {
return `<${tagName}${attrHtml ? ` ${attrHtml}` : ""}>`;
}

function generateHTML(metadata, attributes = {}, optionsOverride = {}) {
let options = Object.assign({}, metadata?.eleventyImage?.options, optionsOverride);
let isInline = options.whitespaceMode !== "block";
function generateHTML(metadata, attributesOverride = {}, htmlOptionsOverride = {}) {
let attributes = Object.assign({}, metadata?.eleventyImage?.htmlOptions?.imgAttributes, attributesOverride);
let htmlOptions = Object.assign({}, metadata?.eleventyImage?.htmlOptions, htmlOptionsOverride);

let isInline = htmlOptions.whitespaceMode !== "block";
let markup = [];

let obj = generateObject(metadata, attributes, options.pictureAttributes, options);
let obj = generateObject(metadata, attributes, htmlOptions.pictureAttributes, htmlOptions);
for(let tag in obj) {
markup.push(mapObjectToHTML(tag, obj[tag]));

Expand Down
17 changes: 14 additions & 3 deletions src/global-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,20 @@ const DEFAULTS = {
// operate on Sharp instance manually.
transform: undefined,

// the <img> will use the largest dimensions for width/height (when multiple output widths are specified)
// see https://github.com/11ty/eleventy-img/issues/63
fallback: "largest", // or "smallest"
// return HTML from generateHTML directly
return: "object", // or "html"

// Defaults used when generateHTML is called from a result set
htmlOptions: {
imgAttributes: {},
pictureAttributes: {},

whitespaceMode: "inline", // "block"

// the <img> will use the largest dimensions for width/height (when multiple output widths are specified)
// see https://github.com/11ty/eleventy-img/issues/63
fallback: "largest", // or "smallest"
},

// v5.0.0 Removed `extensions`, option to override output format with new file extension. It wasn’t being used anywhere or documented.
// v6.0.0, removed `useCacheValidityInHash: true` see https://github.com/11ty/eleventy-img/issues/146#issuecomment-2555741376
Expand Down
47 changes: 27 additions & 20 deletions src/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const { Fetch } = require("@11ty/eleventy-fetch");

const Util = require("./util.js");
const ImagePath = require("./image-path.js");
const generateHTML = require("./generate-html.js");

const GLOBAL_OPTIONS = require("./global-options.js").defaults;
const { existsCache, memCache, diskCache } = require("./caches.js");
Expand Down Expand Up @@ -242,7 +243,7 @@ class Image {
return [];
}

_transformRawFiles(files = []) {
#transformRawFiles(files = []) {
let byType = {};
for(let file of files) {
if(!byType[file.format]) {
Expand Down Expand Up @@ -290,11 +291,31 @@ class Image {
}
}

this.addHiddenMetadata(byType);

return byType;
}

#finalizeResults(results = {}) {
// used when results are passed to generate HTML, we maintain some internal metadata about the options used.
Object.defineProperty(results, "eleventyImage", {
enumerable: false,
writable: false,
value: {
htmlOptions: {
whitespaceMode: this.options.htmlOptions?.whitespaceMode,
imgAttributes: this.options.htmlOptions?.imgAttributes,
pictureAttributes: this.options.htmlOptions?.pictureAttributes,
fallback: this.options.htmlOptions?.fallback,
},
}
});

if(this.options.return === "html") {
return generateHTML(results);
}

return results;
}

getSharpOptionsForFormat(format) {
if(format === "webp") {
return this.options.sharpWebpOptions;
Expand Down Expand Up @@ -511,7 +532,7 @@ class Image {
}
}

return this._transformRawFiles(results);
return this.#transformRawFiles(results);
}

getOutputSize(contents, filePath) {
Expand Down Expand Up @@ -565,6 +586,7 @@ class Image {
let outputFilePromises = [];

let fullStats = this.getFullStats(metadata);

for(let outputFormat in fullStats) {
for(let stat of fullStats[outputFormat]) {
if(this.isOutputCached(stat.outputPath, input)) {
Expand Down Expand Up @@ -679,22 +701,7 @@ class Image {
}
}

return Promise.all(outputFilePromises).then(files => this._transformRawFiles(files));
}

addHiddenMetadata(results) {
// used when results are passed to generate HTML, we maintain some internal metadata about the options used.
Object.defineProperty(results, "eleventyImage", {
enumerable: false,
writable: false,
value: {
options: {
pictureAttributes: this.options.pictureAttributes,
whitespaceMode: this.options.whitespaceMode,
fallback: this.options.fallback,
},
}
});
return Promise.all(outputFilePromises).then(files => this.#finalizeResults(this.#transformRawFiles(files)));
}

async getStatsOnly() {
Expand Down
41 changes: 40 additions & 1 deletion test/test-markup.js
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,50 @@ test("Image markup with smallest fallback dimensions", async t => {
dryRun: true,
widths: [300, "auto"],
formats: ["auto"],
fallback: "smallest",
htmlOptions: {
fallback: "smallest",
},
});

t.is(generateHTML(results, {
alt: "",
sizes: "100vw"
}), `<img alt="" src="/img/KkPMmHd3hP-300.jpeg" width="300" height="199" srcset="/img/KkPMmHd3hP-300.jpeg 300w, /img/KkPMmHd3hP-1280.jpeg 1280w" sizes="100vw">`);
});

test("return: html to <img>", async t => {
let html = await eleventyImage("./test/bio-2017.jpg", {
dryRun: true,
formats: ["auto"],
return: "html",

// passed to generateHTML
htmlOptions: {
imgAttributes: {
alt: "",
},
},
});

t.is(html, `<img alt="" src="/img/KkPMmHd3hP-1280.jpeg" width="1280" height="853">`);
});

test("return: html to <picture>", async t => {
let html = await eleventyImage("./test/bio-2017.jpg", {
dryRun: true,
return: "html",

// passed to generateHTML
htmlOptions: {
imgAttributes: {
alt: "",
class: "inner",
},
pictureAttributes: {
class: "outer"
}
},
});

t.is(html, `<picture class="outer"><source type="image/webp" srcset="/img/KkPMmHd3hP-1280.webp 1280w"><img alt="" class="inner" src="/img/KkPMmHd3hP-1280.jpeg" width="1280" height="853"></picture>`);
});

0 comments on commit 04e803a

Please sign in to comment.