Skip to content

Instantly share code, notes, and snippets.

@rarous
Last active December 6, 2021 11:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rarous/3b26b5e5346664deab1717b029bff14b to your computer and use it in GitHub Desktop.
Save rarous/3b26b5e5346664deab1717b029bff14b to your computer and use it in GitHub Desktop.
/**
* @copyright 2015-2016 TopMonks s.r.o.
* @flow weak
*/
import React, {Children, cloneElement} from 'react';
import component from '../component';
import {Map} from 'immutable';
type Crop = 'scale' | 'fill' | 'lfill' | 'fit' | 'mfit' | 'limit' | 'pad' | 'lpad' | 'mpad' | 'crop' | 'thumb';
type Gravity = 'north' | 'east' | 'south' | 'west' | 'north_west' | 'south_west' | 'north_east' | 'south_east' | 'xy_center' | 'face' | 'faces' | 'face:center' | 'faces:center' | 'custom';
type Quality = number | 'jpegmini';
type Radius = number | 'max';
type Format = 'auto' | 'jpg' | 'png' | 'webp' | 'jxr' | 'jp2';
type Transformations = {
width: number,
height: number,
x: number,
y: number,
dpr: number | 'auto',
crop: Crop,
gravity: Gravity,
quality: Quality,
radius: Radius,
effect: string,
opacity: number,
density: number,
format: Format,
transformation: string | string[]
};
type CloudinaryImgProps = {
alt: string,
src: string,
title: string,
width: string | number,
height: string | number,
transformations: Transformations
};
const trans = Map([
['width', x => `w_${x}`],
['height', x => `h_${x}`],
['x', x => `x_${x}`],
['y', x => `y_${x}`],
['dpr', x => `dpr_${x}`],
['crop', x => `c_${x}`],
['gravity', x => `g_${x}`],
['quality', x => `q_${x}`],
['radius', x => `r_${x}`],
['effect', x => `e_${x}`],
['opacity', x => `o_${x}`],
['density', x => `dn_${x}`],
['format', x => `f_${x}`],
['transformation', x => Array.isArray(x) ? `t_${x.join('.')}` : `t_${x}`]
]);
export function cloudinayImgUrl(url, transformations) {
const segment = Map(transformations).map((v, k) => trans.get(k)(v)).toArray().join();
return (url && segment) ? url.replace('/upload/', `/upload/${segment}/`) : url;
}
export default component(function CloudinaryImg({alt, src, title, width, height, transformations, children: _ch, ...imgProps}: CloudinaryImgProps, _, children) {
const props = {
alt, title, width, height,
src: cloudinayImgUrl(src, transformations),
...imgProps
};
if (!children) return <img {...props} />;
const sources = Children.toArray(children).map(x => cloneElement(x, {src}));
return (
<picture>
{sources}
<img {...props} />
</picture>
);
});
type SourceProps = {
media: string,
type: string,
src: string,
transformations: Transformations
};
export const Source = component(function Source({media, type, src, transformations}: SourceProps) {
const props = {
media, type,
srcSet: cloudinayImgUrl(src, transformations)
};
return (<source {...props} />);
});
const kTestImages = {
lossy: 'UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA',
lossless: 'UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==',
alpha: 'UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==',
animation: 'UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA'
};
type Feature = 'lossy' | 'lossless' | 'alpha' | 'animation';
/**
* Checks WebP support
* @param feature can be one of 'lossy', 'lossless', 'alpha' or 'animation'.
* @returns Promise<boolean> with the detection result (in an asynchronous way!)
*/
export function checkWebpFeature(feature: Feature): Promise<boolean> {
const img = new Image();
const promise = new Promise((resolve, _reject) => {
img.onload = function () {
var result = (img.width > 0) && (img.height > 0);
resolve(result);
};
img.onerror = function () {
resolve(false);
};
img.src = `data:image/webp;base64,${kTestImages[feature]}`;
});
return promise;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment