UNPKG

ghost

Version:

The professional publishing platform

132 lines (111 loc) 4.87 kB
const {getAvailableImageWidths} = require('../render-utils/get-available-image-widths'); const {isLocalContentImage} = require('../render-utils/is-local-content-image'); const {setSrcsetAttribute} = require('../render-utils/srcset-attribute'); const {getResizedImageDimensions} = require('../render-utils/get-resized-image-dimensions'); const {addCreateDocumentOption} = require('../render-utils/add-create-document-option'); const {renderEmptyContainer} = require('../render-utils/render-empty-container'); function renderImageNode(node, options = {}) { addCreateDocumentOption(options); const document = options.createDocument(); if (!node.src || node.src.trim() === '') { return renderEmptyContainer(document); } const figure = document.createElement('figure'); let figureClasses = 'kg-card kg-image-card'; if (node.cardWidth !== 'regular') { figureClasses += ` kg-width-${node.cardWidth}`; } if (node.caption) { figureClasses += ' kg-card-hascaption'; } figure.setAttribute('class', figureClasses); const img = document.createElement('img'); img.setAttribute('src', node.src); img.setAttribute('class', 'kg-image'); img.setAttribute('alt', node.alt); img.setAttribute('loading', 'lazy'); if (node.title) { img.setAttribute('title', node.title); } if (node.width && node.height) { img.setAttribute('width', node.width); img.setAttribute('height', node.height); } // images can be resized to max width, if that's the case output // the resized width/height attrs to ensure 3rd party gallery plugins // aren't affected by differing sizes const {canTransformImage} = options; const {defaultMaxWidth} = options.imageOptimization || {}; if ( defaultMaxWidth && node.width > defaultMaxWidth && isLocalContentImage(node.src, options.siteUrl) && canTransformImage && canTransformImage(node.src) ) { const imageDimensions = { width: node.width, height: node.height }; const {width, height} = getResizedImageDimensions(imageDimensions, {width: defaultMaxWidth}); img.setAttribute('width', width); img.setAttribute('height', height); } if (options.target !== 'email') { const imgAttributes = { src: node.src, width: node.width, height: node.height }; setSrcsetAttribute(img, imgAttributes, options); if (img.getAttribute('srcset') && node.width && node.width >= 720) { // standard size if (!node.cardWidth || node.cardWidth === 'regular') { img.setAttribute('sizes', '(min-width: 720px) 720px'); } if (node.cardWidth === 'wide' && node.width >= 1200) { img.setAttribute('sizes', '(min-width: 1200px) 1200px'); } } } // Outlook is unable to properly resize images without a width/height // so we add that at the expected size in emails (600px) and use a higher // resolution image to keep images looking good on retina screens if (options.target === 'email' && node.width && node.height) { let imageDimensions = { width: node.width, height: node.height }; if (node.width >= 600) { imageDimensions = getResizedImageDimensions(imageDimensions, {width: 600}); } img.setAttribute('width', imageDimensions.width); img.setAttribute('height', imageDimensions.height); if (isLocalContentImage(node.src, options.siteUrl) && options.canTransformImage?.(node.src)) { // find available image size next up from 2x600 so we can use it for the "retina" src const availableImageWidths = getAvailableImageWidths(node, options.imageOptimization.contentImageSizes); const srcWidth = availableImageWidths.find(width => width >= 1200); if (!srcWidth || srcWidth === node.width) { // do nothing, width is smaller than retina or matches the original node src } else { const [, imagesPath, filename] = node.src.match(/(.*\/content\/images)\/(.*)/); img.setAttribute('src', `${imagesPath}/size/w${srcWidth}/${filename}`); } } } if (node.href) { const a = document.createElement('a'); a.setAttribute('href', node.href); a.appendChild(img); figure.appendChild(a); } else { figure.appendChild(img); } if (node.caption) { const caption = document.createElement('figcaption'); caption.innerHTML = node.caption; figure.appendChild(caption); } return {element: figure}; } module.exports = renderImageNode;