use local gatsby-transformer-cloudinary

This commit is contained in:
Eli Kinsey
2024-09-12 15:57:32 -07:00
parent 29a9aba70c
commit 49b269e682
4 changed files with 176 additions and 204 deletions

View File

@@ -340,7 +340,7 @@ module.exports = {
},
},
{
resolve: `gatsby-transformer-cloudinary`,
resolve: require.resolve(`./plugins/gatsby-transformer-cloudinary`),
options: {
transformTypes: [
`RoadmapMedia`,

View File

@@ -1,63 +1,64 @@
const axios = require('axios');
const probe = require('probe-image-size');
const { generateCloudinaryAssetUrl } = require('./generate-asset-url');
const axios = require('axios')
const probe = require('probe-image-size')
const { generateCloudinaryAssetUrl } = require('./generate-asset-url')
const dataCache = {};
const probeCache = {};
const dataCache = {}
const probeCache = {}
const getData = async (url, options) => {
if (!dataCache[url]) {
dataCache[url] = axios.get(url, options);
}
if (!dataCache[url]) {
dataCache[url] = axios.get(url, options)
}
const { data } = await dataCache[url];
return data;
};
const { data } = await dataCache[url]
return data
}
const probeImage = async (url) => {
if (!probeCache[url]) {
probeCache[url] = probe(url);
}
console.log('Probing image', url)
if (!probeCache[url]) {
probeCache[url] = probe(url)
}
return await probeCache[url];
};
return await probeCache[url]
}
exports.getAssetAsTracedSvg = async ({ source, args }) => {
const svgUrl = generateCloudinaryAssetUrl({
publicId: source.publicId,
cloudName: source.cloudName,
format: 'svg',
options: args,
tracedSvg: {
options: {
colors: 2,
detail: 0.3,
despeckle: 0.1,
},
width: 300,
},
});
const data = await getData(svgUrl);
return `data:image/svg+xml,${encodeURIComponent(data)}`;
};
const svgUrl = generateCloudinaryAssetUrl({
publicId: source.publicId,
cloudName: source.cloudName,
format: 'svg',
options: args,
tracedSvg: {
options: {
colors: 2,
detail: 0.3,
despeckle: 0.1,
},
width: 300,
},
})
const data = await getData(svgUrl)
return `data:image/svg+xml,${encodeURIComponent(data)}`
}
exports.getAssetMetadata = async ({ source, args }) => {
const metaDataUrl = generateCloudinaryAssetUrl({
publicId: source.publicId,
cloudName: source.cloudName,
options: args,
});
const metaDataUrl = generateCloudinaryAssetUrl({
publicId: source.publicId,
cloudName: source.cloudName,
options: args,
})
const result = await probeImage(metaDataUrl);
return {
width: result.width,
height: result.height,
format: result.type,
};
};
const result = await probeImage(metaDataUrl)
return {
width: result.width,
height: result.height,
format: result.type,
}
}
exports.getUrlAsBase64Image = async (url) => {
const data = await getData(url, { responseType: 'arraybuffer' });
const base64 = Buffer.from(data, 'binary').toString('base64');
return `data:image/jpeg;base64,${base64}`;
};
const data = await getData(url, { responseType: 'arraybuffer' })
const base64 = Buffer.from(data, 'binary').toString('base64')
return `data:image/jpeg;base64,${base64}`
}

View File

@@ -1,175 +1,157 @@
const {
getLowResolutionImageURL,
generateImageData,
} = require('gatsby-plugin-image');
const { getLowResolutionImageURL, generateImageData } = require('gatsby-plugin-image')
const { generateCloudinaryAssetUrl } = require('./generate-asset-url');
const {
getAssetAsTracedSvg,
getUrlAsBase64Image,
getAssetMetadata,
} = require('./asset-data');
const { Joi } = require('gatsby-plugin-utils/joi');
const { generateCloudinaryAssetUrl } = require('./generate-asset-url')
const { getAssetAsTracedSvg, getUrlAsBase64Image, getAssetMetadata } = require('./asset-data')
const { Joi } = require('gatsby-plugin-utils/joi')
const { resolverReporter } = require('./resolver-reporter');
const { resolverReporter } = require('./resolver-reporter')
const generateCloudinaryAssetSource = (
filename,
width,
height,
format,
_fit,
options
) => {
const [cloudName, publicId] = filename.split('>>>');
const cloudinarySrcUrl = generateCloudinaryAssetUrl({
cloudName: cloudName,
publicId: publicId,
width,
height,
format,
options,
});
const generateCloudinaryAssetSource = (filename, width, height, format, _fit, options) => {
const [cloudName, publicId] = filename.split('>>>')
const cloudinarySrcUrl = generateCloudinaryAssetUrl({
cloudName: cloudName,
publicId: publicId,
width,
height,
format,
options,
})
const imageSource = {
src: cloudinarySrcUrl,
width: width,
height: height,
format: format,
};
const imageSource = {
src: cloudinarySrcUrl,
width: width,
height: height,
format: format,
}
return imageSource;
};
return imageSource
}
const generateMetadata = async (source, args, transformType, reporter) => {
const schema = Joi.object({
width: Joi.number().positive().required(),
height: Joi.number().positive().required(),
format: Joi.string().default('auto'),
}).required();
const schema = Joi.object({
width: Joi.number().positive().required(),
height: Joi.number().positive().required(),
format: Joi.string().default('auto'),
}).required()
const originalMetadata = {
width: source.originalWidth,
height: source.originalHeight,
format: source.originalFormat,
};
const originalMetadata = {
width: source.originalWidth,
height: source.originalHeight,
format: source.originalFormat,
}
const { value, error } = schema.validate(originalMetadata);
if (!error) {
// Original metadata is valid,
// use validated value
return value;
}
try {
// Lacking metadata, so let's fetch it
reporter.verbose(
`[gatsby-transformer-cloudinary] Missing metadata fields on ${transformType}: cloudName=${source.cloudName}, publicId=${source.publicId} >>> To save on network requests add originalWidth, originalHeight and originalFormat to ${transformType}`
);
const fetchedMetadata = await getAssetMetadata({ source, args });
const { value, error } = schema.validate(fetchedMetadata);
const { value, error } = schema.validate(originalMetadata)
if (!error) {
// Fetched metadata is valid,
// use validated value
return value;
// Original metadata is valid,
// use validated value
return value
} else {
// Fetched metadata is not valid
reporter.verbose(
`[gatsby-transformer-cloudinary] Invalid fetched metadata for ${transformType}: cloudName=${source.cloudName}, publicId=${source.publicId} >>> ${error.message}`
);
return null;
return null
}
} catch (error) {
// Error fetching
reporter.verbose(
`[gatsby-transformer-cloudinary] Could not fetch metadata for ${transformType}: cloudName=${source.cloudName}, publicId=${source.publicId} >>> ${error.message}`
);
return null;
}
};
try {
// Lacking metadata, so let's fetch it
reporter.verbose(
`[gatsby-transformer-cloudinary] Missing metadata fields on ${transformType}: cloudName=${source.cloudName}, publicId=${source.publicId} >>> To save on network requests add originalWidth, originalHeight and originalFormat to ${transformType}`
)
const fetchedMetadata = await getAssetMetadata({ source, args })
const { value, error } = schema.validate(fetchedMetadata)
if (!error) {
// Fetched metadata is valid,
// use validated value
return value
} else {
// Fetched metadata is not valid
reporter.verbose(
`[gatsby-transformer-cloudinary] Invalid fetched metadata for ${transformType}: cloudName=${source.cloudName}, publicId=${source.publicId} >>> ${error.message}`
)
return null
}
} catch (error) {
// Error fetching
reporter.verbose(
`[gatsby-transformer-cloudinary] Could not fetch metadata for ${transformType}: cloudName=${source.cloudName}, publicId=${source.publicId} >>> ${error.message}`
)
return null
}
}
// Make it testable
exports._generateCloudinaryAssetSource = generateCloudinaryAssetSource;
exports._generateCloudinaryAssetSource = generateCloudinaryAssetSource
exports.createResolveCloudinaryAssetData =
(gatsbyUtils) => async (source, args, _context, info) => {
let { reporter } = gatsbyUtils;
reporter = resolverReporter({ reporter, logLevel: args.logLevel });
const transformType = info.parentType || 'UnknownTransformType';
exports.createResolveCloudinaryAssetData = (gatsbyUtils) => async (source, args, _context, info) => {
let { reporter } = gatsbyUtils
reporter = resolverReporter({ reporter, logLevel: args.logLevel })
const transformType = info.parentType || 'UnknownTransformType'
const schema = Joi.object({
cloudName: Joi.string().required(),
publicId: Joi.string().required(),
}).required();
cloudName: Joi.string().required(),
publicId: Joi.string().required(),
}).required()
const { error } = schema.validate(source, {
allowUnknown: true,
abortEarly: false,
});
allowUnknown: true,
abortEarly: false,
})
if (error) {
if (error.details.length < 2 && error.details[0].path.length > 0) {
reporter.warn(
`[gatsby-transformer-cloudinary] Missing required field on ${transformType}: cloudName=${source?.cloudName}, publicId=${source?.publicId} >>> gatsbyImageData will resolve to null`
);
} else {
reporter.verbose(
`[gatsby-transformer-cloudinary] Missing cloudName and publicId on ${transformType} >>> gatsbyImageData will resolve to null`
);
}
if (error.details.length < 2 && error.details[0].path.length > 0) {
reporter.warn(
`[gatsby-transformer-cloudinary] Missing required field on ${transformType}: cloudName=${source?.cloudName}, publicId=${source?.publicId} >>> gatsbyImageData will resolve to null`
)
} else {
reporter.verbose(
`[gatsby-transformer-cloudinary] Missing cloudName and publicId on ${transformType} >>> gatsbyImageData will resolve to null`
)
}
return null;
return null
}
const metadata = await generateMetadata(
source,
args,
transformType,
reporter
);
const metadata = await generateMetadata(source, args, transformType, reporter)
if (!metadata) {
reporter.warn(
`[gatsby-transformer-cloudinary] No metadata for ${transformType}: cloudName=${source.cloudName}, publicId=${source.publicId} >>> gatsbyImageData will resolve to null`
);
return null;
reporter.warn(
`[gatsby-transformer-cloudinary] No metadata for ${transformType}: cloudName=${source.cloudName}, publicId=${source.publicId} >>> gatsbyImageData will resolve to null`
)
return null
}
const assetDataArgs = {
...args,
filename: source.cloudName + '>>>' + source.publicId,
// Passing the plugin name allows for better error messages
pluginName: `gatsby-transformer-cloudinary`,
sourceMetadata: metadata,
generateImageSource: generateCloudinaryAssetSource,
options: args,
};
try {
if (args.placeholder === 'blurred') {
if (source.defaultBase64) {
assetDataArgs.placeholderURL = source.defaultBase64;
} else {
const lowResolutionUrl = getLowResolutionImageURL(assetDataArgs);
const base64 = await getUrlAsBase64Image(lowResolutionUrl);
assetDataArgs.placeholderURL = base64;
}
} else if (args.placeholder === 'tracedSVG') {
if (source.defaultTracedSVG) {
assetDataArgs.placeholderURL = source.defaultTracedSVG;
} else {
const tracedSvg = await getAssetAsTracedSvg({ source, args });
assetDataArgs.placeholderURL = tracedSvg;
}
}
} catch (error) {
reporter.error(
`[gatsby-transformer-cloudinary] Could not generate placeholder (${args.placeholder}) for ${source.cloudName} > ${source.publicId}: ${error.message}`
);
...args,
filename: source.cloudName + '>>>' + source.publicId,
// Passing the plugin name allows for better error messages
pluginName: `gatsby-transformer-cloudinary`,
sourceMetadata: metadata,
generateImageSource: generateCloudinaryAssetSource,
options: args,
}
return generateImageData(assetDataArgs);
};
try {
if (args.placeholder === 'blurred') {
if (source.defaultBase64) {
assetDataArgs.placeholderURL = source.defaultBase64
} else {
const lowResolutionUrl = getLowResolutionImageURL(assetDataArgs)
const base64 = await getUrlAsBase64Image(lowResolutionUrl)
assetDataArgs.placeholderURL = base64
}
} else if (args.placeholder === 'tracedSVG') {
if (source.defaultTracedSVG) {
assetDataArgs.placeholderURL = source.defaultTracedSVG
} else {
const tracedSvg = await getAssetAsTracedSvg({ source, args })
assetDataArgs.placeholderURL = tracedSvg
}
}
} catch (error) {
reporter.error(
`[gatsby-transformer-cloudinary] Could not generate placeholder (${args.placeholder}) for ${source.cloudName} > ${source.publicId}: ${error.message}`
)
}
return generateImageData(assetDataArgs)
}

View File

@@ -11417,17 +11417,6 @@ gatsby-telemetry@^3.25.0:
lodash "^4.17.21"
node-fetch "^2.6.7"
gatsby-transformer-cloudinary@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/gatsby-transformer-cloudinary/-/gatsby-transformer-cloudinary-4.5.0.tgz#02a99f5e12de932b9d8e6424a8c29c5c32413f9e"
integrity sha512-btiynpmXUVkkjnTDXb0Ei3vxAEyCV6G5jpcwun6eHg6jM7S0GvqkRle6GvlaguKtLAJzb30GbIzU9IBGwb3xlg==
dependencies:
axios "~1.1.3"
cloudinary "^1.35.0"
fast-json-stable-stringify "2.1.0"
gatsby-plugin-utils "^4.0.0"
probe-image-size "7.2.3"
gatsby-transformer-json@^4.20.0:
version "4.23.0"
resolved "https://registry.yarnpkg.com/gatsby-transformer-json/-/gatsby-transformer-json-4.23.0.tgz#ad3699cabc1499d055ef6d41ff33a99bd9d2d8a1"