Browse Source

feat: rehype-image-size, prevent image jump

fix/headings-faq
Thomas Osmonson 4 years ago
committed by Thomas Osmonson
parent
commit
a8af12711f
  1. 36
      lib/rehype-image-size.js
  2. 3
      lib/rehype-plugins.js
  3. 1
      package.json
  4. 46
      src/components/mdx/image.tsx
  5. 4
      src/components/mdx/md-contents.tsx
  6. 14
      yarn.lock

36
lib/rehype-image-size.js

@ -0,0 +1,36 @@
const memoize = require('micro-memoize');
const visit = require('unist-util-visit');
const pAll = require('p-all');
const sizeOf = require('image-size');
/**
* Simple plugin to get the size of local images so we can use it in react
*/
const rehypeImageSize = () => {
async function transformer(tree) {
const nodes = [];
visit(tree, 'element', node => {
if (node.tagName !== 'img') {
return;
} else {
nodes.push(node);
}
});
await pAll(
nodes.map(node => () => visitor(node)),
{ concurrency: 25 }
);
return tree;
}
async function visitor(node) {
const isRelative =
node && node.properties && node.properties.src && node.properties.src.startsWith('/');
if (isRelative) {
const dimensions = sizeOf(`public/${node.properties.src}`);
node.properties['dimensions'] = dimensions;
}
}
return transformer;
};
module.exports = memoize(rehypeImageSize);

3
lib/rehype-plugins.js

@ -1,6 +1,7 @@
const memoize = require('micro-memoize');
const { rehypeVscode } = require('unified-vscode');
const rehypeImgs = require('./rehype-image-size');
const rehypePlugins = [memoize(rehypeVscode)];
const rehypePlugins = [memoize(rehypeVscode), rehypeImgs];
module.exports = { rehypePlugins };

1
package.json

@ -32,6 +32,7 @@
"gray-matter": "^4.0.2",
"hast-util-to-string": "^1.0.4",
"html-react-parser": "^0.13.0",
"image-size": "^0.8.3",
"lodash.debounce": "^4.0.8",
"mdi-react": "7.3.0",
"micro-memoize": "^4.0.9",

46
src/components/mdx/image.tsx

@ -40,15 +40,49 @@ const useImgix = (src: string) => {
};
};
export const Img: React.FC<BoxProps & { loading?: string; src?: string; alt?: string }> = ({
src: _src,
...rest
}) => {
const getAspectRatio = dimensions => {
if (!dimensions) return;
const { width, height } = dimensions;
return (height / width) * 100;
};
const BaseImg: React.FC<any> = props => (
<Box
loading="lazy"
maxWidth="100%"
width={['100%', '100%', 'inherit', 'inherit']}
display="block"
as="img"
{...props}
/>
);
export const Img: React.FC<
BoxProps & { loading?: string; src?: string; alt?: string; dimensions?: any }
> = React.memo(({ src: _src, dimensions, ...rest }) => {
const { src, srcset } = useImgix(_src);
const props = {
src,
srcSet: srcset,
...rest,
};
return <Box loading="lazy" maxWidth="100%" display="block" as="img" {...props} />;
};
if (dimensions) {
// means the image is local and we can generate the aspect ratio
// and prevent the page from jumping due to lack of an image being loaded
// (because of the built in lazy-loading)
const aspectRatio = getAspectRatio(dimensions);
const width = dimensions.width <= 720 ? dimensions.width : '100%';
return (
<Box width={width} maxWidth="100%" padding="0 !important" position="relative" className="img">
<Box height="0" paddingBottom={`${aspectRatio}%`} width="100%" />
<BaseImg position="absolute" top={0} left={0} {...props} />
</Box>
);
}
return <BaseImg className="img" {...props} />;
});

4
src/components/mdx/md-contents.tsx

@ -38,7 +38,7 @@ export const styleOverwrites = {
pre: {
// px: space(['none', 'none', 'extra-loose', 'extra-loose']),
},
img: {
'.img': {
mx: 'auto',
},
},
@ -210,7 +210,7 @@ export const styleOverwrites = {
mt: space('extra-loose'),
},
},
img: {
'.img': {
my: space('extra-loose'),
},
table: {

14
yarn.lock

@ -4960,6 +4960,13 @@ ignore@^4.0.6:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
image-size@^0.8.3:
version "0.8.3"
resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.8.3.tgz#f0b568857e034f29baffd37013587f2c0cad8b46"
integrity sha512-SMtq1AJ+aqHB45c3FsB4ERK0UCiA2d3H1uq8s+8T0Pf8A3W4teyBQyaFaktH6xvZqh+npwlKU7i4fJo0r7TYTg==
dependencies:
queue "6.0.1"
immediate@^3.2.3:
version "3.3.0"
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266"
@ -6987,6 +6994,13 @@ querystring@0.2.0, querystring@^0.2.0:
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
queue@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.1.tgz#abd5a5b0376912f070a25729e0b6a7d565683791"
integrity sha512-AJBQabRCCNr9ANq8v77RJEv73DPbn55cdTb+Giq4X0AVnNVZvMHlYp7XlQiN+1npCZj1DuSmaA2hYVUUDgxFDg==
dependencies:
inherits "~2.0.3"
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"

Loading…
Cancel
Save