5

I have an image type field in Sanity (docs) and I need to make sure that the dimensions are within a particular range to avoid breaking the website they're going on. Sanity offers validations, but the image type only has “required” and “custom” rules, and the field information passed into the custom validator doesn't include the image metadata.

How can I work around this limitation and offer in-CMS validation of the dimensions?

1 Answer 1

10

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
  },
})
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.