UNPKG

@sanity/image-url

Version:

Tools to generate image urls from Sanity content

1 lines 29.5 kB
{"version":3,"file":"image-url.mjs","sources":["../../src/parseAssetId.ts","../../src/parseSource.ts","../../src/urlForImage.ts","../../src/builder.ts"],"sourcesContent":["const example = 'image-Tb9Ew8CXIwaY6R1kjMvI0uRR-2000x3000-jpg'\n\nexport default function parseAssetId(ref: string) {\n const [, id, dimensionString, format] = ref.split('-')\n\n if (!id || !dimensionString || !format) {\n throw new Error(`Malformed asset _ref '${ref}'. Expected an id like \"${example}\".`)\n }\n\n const [imgWidthStr, imgHeightStr] = dimensionString.split('x')\n\n const width = +imgWidthStr\n const height = +imgHeightStr\n\n const isValidAssetId = isFinite(width) && isFinite(height)\n if (!isValidAssetId) {\n throw new Error(`Malformed asset _ref '${ref}'. Expected an id like \"${example}\".`)\n }\n\n return {id, width, height, format}\n}\n","import {\n SanityAsset,\n SanityImageObject,\n SanityImageSource,\n SanityImageWithAssetStub,\n SanityReference\n} from './types'\n\nconst isRef = (src: SanityImageSource): src is SanityReference => {\n const source = src as SanityReference\n return source ? typeof source._ref === 'string' : false\n}\n\nconst isAsset = (src: SanityImageSource): src is SanityAsset => {\n const source = src as SanityAsset\n return source ? typeof source._id === 'string' : false\n}\n\nconst isAssetStub = (src: SanityImageSource): src is SanityImageWithAssetStub => {\n const source = src as SanityImageWithAssetStub\n return source && source.asset ? typeof source.asset.url === 'string' : false\n}\n\n// Convert an asset-id, asset or image to an image record suitable for processing\n// eslint-disable-next-line complexity\nexport default function parseSource(source?: SanityImageSource) {\n if (!source) {\n return null\n }\n\n let image: SanityImageObject\n\n if (typeof source === 'string' && isUrl(source)) {\n // Someone passed an existing image url?\n image = {\n asset: {_ref: urlToId(source)}\n }\n } else if (typeof source === 'string') {\n // Just an asset id\n image = {\n asset: {_ref: source}\n }\n } else if (isRef(source)) {\n // We just got passed an asset directly\n image = {\n asset: source\n }\n } else if (isAsset(source)) {\n // If we were passed an image asset document\n image = {\n asset: {\n _ref: source._id || ''\n }\n }\n } else if (isAssetStub(source)) {\n // If we were passed a partial asset (`url`, but no `_id`)\n image = {\n asset: {\n _ref: urlToId(source.asset.url)\n }\n }\n } else if (typeof source.asset === 'object') {\n // Probably an actual image with materialized asset\n image = source\n } else {\n // We got something that does not look like an image, or it is an image\n // that currently isn't sporting an asset.\n return null\n }\n\n const img = source as SanityImageObject\n if (img.crop) {\n image.crop = img.crop\n }\n\n if (img.hotspot) {\n image.hotspot = img.hotspot\n }\n\n return applyDefaults(image)\n}\n\nfunction isUrl(url: string) {\n return /^https?:\\/\\//.test(`${url}`)\n}\n\nfunction urlToId(url: string) {\n const parts = url.split('/').slice(-1)\n return `image-${parts[0]}`.replace(/\\.([a-z]+)$/, '-$1')\n}\n\n// Mock crop and hotspot if image lacks it\nfunction applyDefaults(image: SanityImageObject) {\n if (image.crop && image.hotspot) {\n return image as Required<SanityImageObject>\n }\n\n // We need to pad in default values for crop or hotspot\n const result = {...image}\n\n if (!result.crop) {\n result.crop = {\n left: 0,\n top: 0,\n bottom: 0,\n right: 0\n }\n }\n\n if (!result.hotspot) {\n result.hotspot = {\n x: 0.5,\n y: 0.5,\n height: 1.0,\n width: 1.0\n }\n }\n\n return result as Required<SanityImageObject>\n}\n","import parseAssetId from './parseAssetId'\nimport parseSource from './parseSource'\nimport {\n CropSpec,\n HotspotSpec,\n ImageUrlBuilderOptions,\n ImageUrlBuilderOptionsWithAsset,\n SanityAsset,\n SanityImageFitResult,\n SanityImageRect,\n SanityReference\n} from './types'\n\nexport const SPEC_NAME_TO_URL_NAME_MAPPINGS = [\n ['width', 'w'],\n ['height', 'h'],\n ['format', 'fm'],\n ['download', 'dl'],\n ['blur', 'blur'],\n ['sharpen', 'sharp'],\n ['invert', 'invert'],\n ['orientation', 'or'],\n ['minHeight', 'min-h'],\n ['maxHeight', 'max-h'],\n ['minWidth', 'min-w'],\n ['maxWidth', 'max-w'],\n ['quality', 'q'],\n ['fit', 'fit'],\n ['crop', 'crop'],\n ['auto', 'auto'],\n ['dpr', 'dpr']\n]\n\nexport default function urlForImage(options: ImageUrlBuilderOptions) {\n let spec = {...(options || {})}\n const source = spec.source\n delete spec.source\n\n const image = parseSource(source)\n if (!image) {\n return null\n }\n\n const id = (image.asset as SanityReference)._ref || (image.asset as SanityAsset)._id || ''\n const asset = parseAssetId(id)\n\n // Compute crop rect in terms of pixel coordinates in the raw source image\n const cropLeft = Math.round(image.crop.left * asset.width)\n const cropTop = Math.round(image.crop.top * asset.height)\n const crop = {\n left: cropLeft,\n top: cropTop,\n width: Math.round(asset.width - image.crop.right * asset.width - cropLeft),\n height: Math.round(asset.height - image.crop.bottom * asset.height - cropTop)\n }\n\n // Compute hot spot rect in terms of pixel coordinates\n const hotSpotVerticalRadius = (image.hotspot.height * asset.height) / 2\n const hotSpotHorizontalRadius = (image.hotspot.width * asset.width) / 2\n const hotSpotCenterX = image.hotspot.x * asset.width\n const hotSpotCenterY = image.hotspot.y * asset.height\n const hotspot = {\n left: hotSpotCenterX - hotSpotHorizontalRadius,\n top: hotSpotCenterY - hotSpotVerticalRadius,\n right: hotSpotCenterX + hotSpotHorizontalRadius,\n bottom: hotSpotCenterY + hotSpotVerticalRadius\n }\n\n // If irrelevant, or if we are requested to: don't perform crop/fit based on\n // the crop/hotspot.\n if (!(spec.rect || spec.focalPoint || spec.ignoreImageParams || spec.crop)) {\n spec = {...spec, ...fit({crop, hotspot}, spec)}\n }\n\n return specToImageUrl({...spec, asset})\n}\n\n// eslint-disable-next-line complexity\nfunction specToImageUrl(spec: ImageUrlBuilderOptionsWithAsset) {\n const cdnUrl = spec.baseUrl || 'https://cdn.sanity.io'\n const filename = `${spec.asset.id}-${spec.asset.width}x${spec.asset.height}.${spec.asset.format}`\n const baseUrl = `${cdnUrl}/images/${spec.projectId}/${spec.dataset}/${filename}`\n\n const params = []\n\n if (spec.rect) {\n // Only bother url with a crop if it actually crops anything\n const {left, top, width, height} = spec.rect\n const isEffectiveCrop =\n left !== 0 || top !== 0 || height !== spec.asset.height || width !== spec.asset.width\n\n if (isEffectiveCrop) {\n params.push(`rect=${left},${top},${width},${height}`)\n }\n }\n\n if (spec.bg) {\n params.push(`bg=${spec.bg}`)\n }\n\n if (spec.focalPoint) {\n params.push(`fp-x=${spec.focalPoint.x}`)\n params.push(`fp-x=${spec.focalPoint.y}`)\n }\n\n const flip = [spec.flipHorizontal && 'h', spec.flipVertical && 'v'].filter(Boolean).join('')\n if (flip) {\n params.push(`flip=${flip}`)\n }\n\n // Map from spec name to url param name, and allow using the actual param name as an alternative\n SPEC_NAME_TO_URL_NAME_MAPPINGS.forEach(mapping => {\n const [specName, param] = mapping\n if (typeof spec[specName] !== 'undefined') {\n params.push(`${param}=${encodeURIComponent(spec[specName])}`)\n } else if (typeof spec[param] !== 'undefined') {\n params.push(`${param}=${encodeURIComponent(spec[param])}`)\n }\n })\n\n if (params.length === 0) {\n return baseUrl\n }\n\n return `${baseUrl}?${params.join('&')}`\n}\n\nfunction fit(\n source: {crop: CropSpec; hotspot: HotspotSpec},\n spec: ImageUrlBuilderOptions\n): SanityImageFitResult {\n let cropRect: SanityImageRect\n\n const imgWidth = spec.width\n const imgHeight = spec.height\n\n // If we are not constraining the aspect ratio, we'll just use the whole crop\n if (!(imgWidth && imgHeight)) {\n return {width: imgWidth, height: imgHeight, rect: source.crop}\n }\n\n const crop = source.crop\n const hotspot = source.hotspot\n\n // If we are here, that means aspect ratio is locked and fitting will be a bit harder\n const desiredAspectRatio = imgWidth / imgHeight\n const cropAspectRatio = crop.width / crop.height\n\n if (cropAspectRatio > desiredAspectRatio) {\n // The crop is wider than the desired aspect ratio. That means we are cutting from the sides\n const height = crop.height\n const width = height * desiredAspectRatio\n const top = crop.top\n\n // Center output horizontally over hotspot\n const hotspotXCenter = (hotspot.right - hotspot.left) / 2 + hotspot.left\n let left = hotspotXCenter - width / 2\n\n // Keep output within crop\n if (left < crop.left) {\n left = crop.left\n } else if (left + width > crop.left + crop.width) {\n left = crop.left + crop.width - width\n }\n\n cropRect = {\n left: Math.round(left),\n top: Math.round(top),\n width: Math.round(width),\n height: Math.round(height)\n }\n } else {\n // The crop is taller than the desired ratio, we are cutting from top and bottom\n const width = crop.width\n const height = width / desiredAspectRatio\n const left = crop.left\n\n // Center output vertically over hotspot\n const hotspotYCenter = (hotspot.bottom - hotspot.top) / 2 + hotspot.top\n let top = hotspotYCenter - height / 2\n\n // Keep output rect within crop\n if (top < crop.top) {\n top = crop.top\n } else if (top + height > crop.top + crop.height) {\n top = crop.top + crop.height - height\n }\n\n cropRect = {\n left: Math.max(0, Math.floor(left)),\n top: Math.max(0, Math.floor(top)),\n width: Math.round(width),\n height: Math.round(height)\n }\n }\n\n return {\n width: imgWidth,\n height: imgHeight,\n rect: cropRect\n }\n}\n\n// For backwards-compatibility\nexport {parseSource}\n","import {\n AutoMode,\n CropMode,\n FitMode,\n ImageFormat,\n ImageUrlBuilderOptions,\n ImageUrlBuilderOptionsWithAliases,\n Orientation,\n SanityClient,\n SanityImageSource,\n SanityProjectDetails\n} from './types'\nimport urlForImage, {SPEC_NAME_TO_URL_NAME_MAPPINGS} from './urlForImage'\n\nconst validFits = ['clip', 'crop', 'fill', 'fillmax', 'max', 'scale', 'min']\nconst validCrops = ['top', 'bottom', 'left', 'right', 'center', 'focalpoint', 'entropy']\nconst validAutoModes = ['format']\n\nfunction isSanityClient(client?: SanityClient): client is SanityClient {\n return client ? typeof client.clientConfig === 'object' : false\n}\n\nfunction rewriteSpecName(key: string) {\n const specs = SPEC_NAME_TO_URL_NAME_MAPPINGS\n for (const entry of specs) {\n const [specName, param] = entry\n if (key === specName || key === param) {\n return specName\n }\n }\n\n return key\n}\n\nexport default function urlBuilder(options?: SanityClient | SanityProjectDetails) {\n // Did we get a SanityClient?\n const client = options as SanityClient\n if (isSanityClient(client)) {\n // Inherit config from client\n const {apiHost, projectId, dataset} = client.clientConfig\n return new ImageUrlBuilder(null, {\n baseUrl: apiHost.replace(/^https:\\/\\/api\\./, 'https://cdn.'),\n projectId,\n dataset\n })\n }\n\n // Or just accept the options as given\n return new ImageUrlBuilder(null, options as ImageUrlBuilderOptions)\n}\n\nclass ImageUrlBuilder {\n public options: ImageUrlBuilderOptions\n\n constructor(parent: ImageUrlBuilder | null, options: ImageUrlBuilderOptions) {\n this.options = parent\n ? {...(parent.options || {}), ...(options || {})} // Merge parent options\n : {...(options || {})} // Copy options\n }\n\n withOptions(options: Partial<ImageUrlBuilderOptionsWithAliases>) {\n const baseUrl = options.baseUrl || ''\n\n const newOptions: {[key: string]: any} = {baseUrl}\n for (const key in options) {\n if (options.hasOwnProperty(key)) {\n const specKey = rewriteSpecName(key)\n newOptions[specKey] = options[key]\n }\n }\n\n return new ImageUrlBuilder(this, {baseUrl, ...newOptions})\n }\n\n // The image to be represented. Accepts a Sanity 'image'-document, 'asset'-document or\n // _id of asset. To get the benefit of automatic hot-spot/crop integration with the content\n // studio, the 'image'-document must be provided.\n image(source: SanityImageSource) {\n return this.withOptions({source})\n }\n\n // Specify the dataset\n dataset(dataset: string) {\n return this.withOptions({dataset})\n }\n\n // Specify the projectId\n projectId(projectId: string) {\n return this.withOptions({projectId})\n }\n\n // Specify background color\n bg(bg: string) {\n return this.withOptions({bg})\n }\n\n // Set DPR scaling factor\n dpr(dpr: number) {\n return this.withOptions({dpr})\n }\n\n // Specify the width of the image in pixels\n width(width: number) {\n return this.withOptions({width})\n }\n\n // Specify the height of the image in pixels\n height(height: number) {\n return this.withOptions({height})\n }\n\n // Specify focal point in fraction of image dimensions. Each component 0.0-1.0\n focalPoint(x: number, y: number) {\n return this.withOptions({focalPoint: {x, y}})\n }\n\n maxWidth(maxWidth: number) {\n return this.withOptions({maxWidth})\n }\n\n minWidth(minWidth: number) {\n return this.withOptions({minWidth})\n }\n\n maxHeight(maxHeight: number) {\n return this.withOptions({maxHeight})\n }\n\n minHeight(minHeight: number) {\n return this.withOptions({minHeight})\n }\n\n // Specify width and height in pixels\n size(width: number, height: number) {\n return this.withOptions({width, height})\n }\n\n // Specify blur between 0 and 100\n blur(blur: number) {\n return this.withOptions({blur})\n }\n\n sharpen(sharpen: number) {\n return this.withOptions({sharpen})\n }\n\n // Specify the desired rectangle of the image\n rect(left: number, top: number, width: number, height: number) {\n return this.withOptions({rect: {left, top, width, height}})\n }\n\n // Specify the image format of the image. 'jpg', 'pjpg', 'png', 'webp'\n format(format: ImageFormat) {\n return this.withOptions({format})\n }\n\n invert(invert: boolean) {\n return this.withOptions({invert})\n }\n\n // Rotation in degrees 0, 90, 180, 270\n orientation(orientation: Orientation) {\n return this.withOptions({orientation})\n }\n\n // Compression quality 0-100\n quality(quality: number) {\n return this.withOptions({quality})\n }\n\n // Make it a download link. Parameter is default filename.\n forceDownload(download: boolean | string) {\n return this.withOptions({download})\n }\n\n // Flip image horizontally\n flipHorizontal() {\n return this.withOptions({flipHorizontal: true})\n }\n\n // Flip image verically\n flipVertical() {\n return this.withOptions({flipVertical: true})\n }\n\n // Ignore crop/hotspot from image record, even when present\n ignoreImageParams() {\n return this.withOptions({ignoreImageParams: true})\n }\n\n fit(value: FitMode) {\n if (validFits.indexOf(value) === -1) {\n throw new Error(`Invalid fit mode \"${value}\"`)\n }\n\n return this.withOptions({fit: value})\n }\n\n crop(value: CropMode) {\n if (validCrops.indexOf(value) === -1) {\n throw new Error(`Invalid crop mode \"${value}\"`)\n }\n\n return this.withOptions({crop: value})\n }\n\n auto(value: AutoMode) {\n if (validAutoModes.indexOf(value) === -1) {\n throw new Error(`Invalid auto mode \"${value}\"`)\n }\n\n return this.withOptions({auto: value})\n }\n\n // Gets the url based on the submitted parameters\n url() {\n return urlForImage(this.options)\n }\n\n // Synonym for url()\n toString() {\n return this.url()\n }\n}\n"],"names":["const","example","parseAssetId","ref","split","id","dimensionString","format","Error","imgWidthStr","imgHeightStr","width","height","isValidAssetId","isFinite","isRef","src","source","_ref","isAsset","_id","isAssetStub","asset","url","parseSource","image","isUrl","urlToId","img","crop","hotspot","applyDefaults","test","parts","slice","replace","result","left","top","bottom","right","x","y","SPEC_NAME_TO_URL_NAME_MAPPINGS","urlForImage","options","spec","cropLeft","Math","round","cropTop","hotSpotVerticalRadius","hotSpotHorizontalRadius","hotSpotCenterX","hotSpotCenterY","rect","focalPoint","ignoreImageParams","fit","specToImageUrl","cdnUrl","baseUrl","filename","projectId","dataset","params","isEffectiveCrop","push","bg","flip","flipHorizontal","flipVertical","filter","Boolean","join","forEach","mapping","param","specName","encodeURIComponent","length","cropRect","imgWidth","imgHeight","desiredAspectRatio","cropAspectRatio","hotspotXCenter","hotspotYCenter","max","floor","validFits","validCrops","validAutoModes","isSanityClient","client","clientConfig","rewriteSpecName","key","specs","entry","urlBuilder","apiHost","ImageUrlBuilder","constructor","parent","withOptions","newOptions","hasOwnProperty","specKey","dpr","maxWidth","minWidth","maxHeight","minHeight","size","blur","sharpen","invert","orientation","quality","forceDownload","download","value","indexOf","auto","toString"],"mappings":"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"}