UNPKG

@yozora/gatsby-images

Version:
138 lines (133 loc) 5.11 kB
import { ImageReferenceType, ImageType } from '@yozora/ast'; import { calcDefinitionMap, traverseAst } from '@yozora/ast-util'; import chalk from 'chalk'; import { fluid } from 'gatsby-plugin-sharp'; import path from 'node:path'; import queryString from 'query-string'; const DEFAULT_OPTIONS = { maxWidth: 650, wrapperStyle: '', backgroundColor: 'white', decoding: 'async', disableBgImageOnAlpha: false, disableBgImage: false, linkImagesToOriginal: true, loading: 'lazy', markdownCaptions: false, showCaptions: false, withWebp: false, withAvif: false, tracedSVG: false, }; const EMPTY_ALT = 'YOZORA_EMPTY_ALT'; const supportedImgExts = new Set([ 'jpeg', 'jpg', 'png', 'webp', 'tif', 'tiff', 'avif', ]); function getImageInfo(uri) { const { url, query } = queryString.parseUrl(uri); const ext = path.extname(url).split(`.`).pop() ?? ''; return { ext, url, query }; } function isRelativeUrl(url) { if (/^[a-zA-Z]:\\/.test(url)) return true; return !/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url); } function slash(urlPath) { const isExtendedLengthPath = /^\\\\\?\\/.test(urlPath); if (isExtendedLengthPath) { return urlPath; } return urlPath.replace(/\\/g, `/`); } async function mutateYozoraAst(api, pluginOptions = {}) { const { files, markdownNode, markdownAST, pathPrefix, reporter, cache, getNode } = api; const options = { ...DEFAULT_OPTIONS, pathPrefix, ...pluginOptions }; const { definitionMap } = calcDefinitionMap(markdownAST, undefined, options.presetDefinitions); const markdownImageNodes = []; traverseAst(markdownAST, [ImageReferenceType, ImageType], node => markdownImageNodes.push(node)); async function generateImagesAndUpdateNode(node, overWrites = {}) { if (markdownNode.parent == null) return null; const parentNode = getNode(markdownNode.parent); if (parentNode == null || parentNode.dir == null) return null; const imagePath = slash(path.join(parentNode.dir, getImageInfo(node.url).url)); const imageNode = files.find(file => file != null && file.absolutePath === imagePath); if (imageNode == null || imageNode.absolutePath == null) return null; const fluidResult = await fluid({ file: imageNode, args: { ...options }, reporter, cache, }); if (!fluidResult) return null; const srcSplit = getImageInfo(node.url).url.split(`/`); const fileName = srcSplit[srcSplit.length - 1]; const fileNameNoExt = fileName.replace(/\.[^/.]+$/, ``); const defaultAlt = fileNameNoExt.replace(/[^A-Z0-9]/gi, ` `); const isEmptyAlt = node.alt === EMPTY_ALT; const alt = isEmptyAlt ? '' : overWrites.alt ?? node.alt ?? defaultAlt; const title = node.title ?? alt; const loading = options.loading; if (![`lazy`, `eager`, `auto`].includes(loading)) { reporter.warn(reporter.stripIndent(` ${chalk.bold(loading)} is an invalid value for the ${chalk.bold(`loading`)} option. Please pass one of "lazy", "eager" or "auto". `)); } const decoding = options.decoding; if (![`async`, `sync`, `auto`].includes(decoding)) { reporter.warn(reporter.stripIndent(` ${chalk.bold(decoding)} is an invalid value for the ${chalk.bold(`decoding`)} option. Please pass one of "async", "sync" or "auto". `)); } return { alt: alt, title: title, src: fluidResult.src, srcSet: fluidResult.srcSet, sizes: fluidResult.sizes, loading: loading, decoding: decoding, }; } async function process(node) { let originalNode = node; const overWrites = {}; if (!node.url && node.identifier) { originalNode = node; node = definitionMap[originalNode.identifier]; if (!node) return null; overWrites.alt = originalNode.alt; } const fileType = getImageInfo(node.url).ext; if (isRelativeUrl(node.url) && supportedImgExts.has(fileType)) { const imageData = await generateImagesAndUpdateNode(node, overWrites); if (imageData == null) return null; node.url = imageData.src; originalNode.alt = imageData.alt; originalNode.src = imageData.src; originalNode.srcSet = imageData.srcSet; originalNode.sizes = imageData.sizes; if (imageData.loading) originalNode.loading = imageData.loading; if (imageData.decoding) originalNode.decoding = imageData.decoding; return originalNode; } return null; } return Promise.all(markdownImageNodes.map(process)).then(nodes => nodes.filter((node) => node != null)); } export { mutateYozoraAst as default }; //# sourceMappingURL=index.mjs.map