Skip to content

Commit

Permalink
feat(gatsby-transform-url): allow ar to be set as a string for fluid …
Browse files Browse the repository at this point in the history
…images
  • Loading branch information
frederickfogerty committed Aug 27, 2020
1 parent e1972f8 commit fa5eac8
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 3 deletions.
31 changes: 31 additions & 0 deletions packages/gatsby-transform-url/src/common/ar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as t from 'io-ts';
import * as R from 'ramda';
import { roundToDP } from './number';
interface AspectRatioBrand {
readonly StringAspectRatio: unique symbol;
}

export const StringAspectRatio = t.brand(
t.string,
(v): v is t.Branded<string, AspectRatioBrand> => aspectRatioIsValid(v),
'StringAspectRatio',
);
export type StringAspectRatio = t.TypeOf<typeof StringAspectRatio>;

/**
* Validates that an aspect ratio is in the format w:h. If false is returned, the aspect ratio is in the wrong format.
*/
function aspectRatioIsValid(aspectRatio: string): boolean {
if (typeof aspectRatio !== 'string') {
return false;
}

return /^\d+(\.\d+)?:\d+(\.\d+)?$/.test(aspectRatio);
}
export const parseStringARParam = (ar: StringAspectRatio): number =>
R.pipe(
(v: StringAspectRatio) => v.split(':') as [string, string],
R.map((part) => parseFloat(part)),
([width, height]) => width / height,
(v) => roundToDP(3, v),
)(ar);
6 changes: 6 additions & 0 deletions packages/gatsby-transform-url/src/common/number.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { curry } from 'ramda';

export const roundToDP = curry(
(dp: number, num: number): number =>
Math.round(num * Math.pow(10, dp)) / Math.pow(10, dp),
);
34 changes: 31 additions & 3 deletions packages/gatsby-transform-url/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import * as E from 'fp-ts/lib/Either';
import { pipe } from 'fp-ts/lib/function';
import ImgixClient from 'imgix-core-js';
import { Errors } from 'io-ts';
import { parseStringARParam, StringAspectRatio } from './common/ar';
import { parseHost, parsePath } from './common/uri';
import {
IGatsbyImageFixedData,
Expand All @@ -15,7 +19,7 @@ function buildImageData(
): IGatsbyImageFixedData;
function buildImageData(
url: string,
imgixParams: IImgixParams,
imgixParams: IImgixParams & { ar: number },
options: { type: 'fluid' },
): IGatsbyImageFluidData;
function buildImageData(
Expand Down Expand Up @@ -127,7 +131,7 @@ export function buildFluidImageData(
* The aspect ratio to set for the rendered image and the placeholder.
* Format: float. Can be calculated with ar = width/height.
*/
ar: number;
ar: number | string;
} & IImgixParams,
/**
* Options that are not imgix parameters.
Expand All @@ -144,5 +148,29 @@ export function buildFluidImageData(
sizes?: string;
} = {},
): IGatsbyImageFluidData {
return buildImageData(url, imgixParams, { ...options, type: 'fluid' });
const aspectRatioFloat = (() => {
const throwError = () => {
throw new Error(
'An invalid string ar parameter was provided. Either provide an aspect ratio as a number, or as a string in the format w:h, e.g. 1.61:1.',
);
};
if (typeof imgixParams.ar === 'number' && isNaN(imgixParams.ar)) {
throwError();
}
if (typeof imgixParams.ar === 'number') {
return imgixParams.ar;
}

return pipe(
StringAspectRatio.decode(imgixParams.ar),
E.map(parseStringARParam),
E.getOrElse<Errors, number>(throwError),
);
})();

return buildImageData(
url,
{ imgixParams, ar: aspectRatioFloat },
{ ...options, type: 'fluid' },
);
}

0 comments on commit fa5eac8

Please sign in to comment.