While Sanity doesn't pass the image metadata into the validator, you can extract image format and dimension information from the asset ID that is provided. According to this documentation, this is a supported, stable way of accessing this information without loading the image object from Sanity.
For example, here's the first argument passed to the Rule.custom
validator:
{
"_type": "image",
"alt": "Example Image",
"asset": {
"_ref": "image-bff149a0b87f5b0e00d9dd364e9ddaa0-700x650-jpg",
"_type": "reference"
}
}
Getting to the image dimensions can be accomplished like this:
{
title: "My Image",
name: "image",
type: "image",
options: {
accept: "image/*",
},
validation: Rule => Rule.custom(image => {
if (!image) return true
const { dimensions } = decodeAssetId(image.asset._ref)
return dimensions.width >= 500 || "Image must be wider"
}
}
const pattern = /^image-([a-f\d]+)-(\d+x\d+)-(\w+)$/
const decodeAssetId = id => {
const [, assetId, dimensions, format] = pattern.exec(id)
const [width, height] = dimensions.split("x").map(v => parseInt(v, 10))
return {
assetId,
dimensions: { width, height },
format,
}
}
I have also rolled this functionality into the sanity-pills library that makes it easier to do like this:
import { createImageField } from "sanity-pills"
createImageField({
name: "image",
validations: {
required: true,
minWidth: 500,
maxHeight: 9000
},
})