[ENG-1412] Fix blog/docs image sizes (#1758)

* fix

* Add image placeholder to NextImage component
This commit is contained in:
Utku 2023-11-09 10:33:47 +03:00 committed by GitHub
parent efbb4ef689
commit cda07b5f63
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 100 additions and 9 deletions

View file

@ -14,6 +14,10 @@ import rehypeSlug from 'rehype-slug';
import remarkGfm from 'remark-gfm'; import remarkGfm from 'remark-gfm';
// support for math // support for math
import remarkMath from 'remark-math'; import remarkMath from 'remark-math';
import remarkMdxImages from 'remark-mdx-images';
// adds width and height to images
import rehypeImageSize from './src/plugins/rehype-image-size';
// Blog // Blog
export const Post = defineDocumentType(() => ({ export const Post = defineDocumentType(() => ({
@ -112,8 +116,13 @@ export default makeSource({
contentDirInclude: ['docs', 'apps/landing/posts'], contentDirInclude: ['docs', 'apps/landing/posts'],
documentTypes: [Post, Document], documentTypes: [Post, Document],
mdx: { mdx: {
remarkPlugins: [remarkGfm, remarkMath], remarkPlugins: [
remarkGfm,
remarkMath,
remarkMdxImages // does this even do anything??
],
rehypePlugins: [ rehypePlugins: [
[rehypeImageSize, { root: `${process.cwd()}/public` }],
rehypeSlug, rehypeSlug,
rehypeAutolinkHeadings, rehypeAutolinkHeadings,
rehypeKatex, rehypeKatex,

View file

@ -22,6 +22,7 @@
"contentlayer": "^0.3.4", "contentlayer": "^0.3.4",
"dayjs": "^1.11.10", "dayjs": "^1.11.10",
"framer-motion": "^10.16.4", "framer-motion": "^10.16.4",
"image-size": "^1.0.2",
"katex": "^0.16.9", "katex": "^0.16.9",
"markdown-to-jsx": "^7.3.2", "markdown-to-jsx": "^7.3.2",
"next": "13.5.6", "next": "13.5.6",
@ -42,9 +43,11 @@
"rehype-slug": "^5.1.0", "rehype-slug": "^5.1.0",
"remark-gfm": "^3.0.1", "remark-gfm": "^3.0.1",
"remark-math": "^5.1.1", "remark-math": "^5.1.1",
"remark-mdx-images": "^2.0.0",
"tailwind-merge": "^1.14.0", "tailwind-merge": "^1.14.0",
"three": "^0.157.0", "three": "^0.157.0",
"tsparticles": "^2.12.0", "tsparticles": "^2.12.0",
"unist-util-visit": "^5.0.0",
"zod": "~3.22.4" "zod": "~3.22.4"
}, },
"devDependencies": { "devDependencies": {

View file

@ -1,8 +1,13 @@
import { MDXComponents } from 'mdx/types';
import NextImage, { ImageProps } from 'next/image'; import NextImage, { ImageProps } from 'next/image';
import Notice from './Notice'; import Notice from './Notice';
const Image = (props: ImageProps) => <NextImage {...props} />; const Image = (props: ImageProps) => <NextImage placeholder="blur" {...props} />;
export const BlogMDXComponents = { Image }; export const BlogMDXComponents = {
export const DocMDXComponents = { Image, Notice }; img: Image, // we remap 'img' to 'Image'
Image
} as MDXComponents;
export const DocMDXComponents = { img: Image, Image, Notice } as MDXComponents;

View file

@ -0,0 +1,55 @@
/**
* rehype-image-size.js
*
* Requires:
* - image-size
* - unist-util-visit
*/
import getImageSize from 'image-size';
import { visit } from 'unist-util-visit';
/**
* Analyze local MDX images and add `width` and `height` attributes to the
* generated `img` elements.
* Supports both markdown-style images and MDX <Image /> components.
* @param {string} options.root - The root path when reading the image file.
*/
export const rehypeImageSize = (options) => {
return (tree) => {
// This matches all images that use the markdown standard format ![label](path).
visit(tree, { type: 'element', tagName: 'img' }, (node) => {
if (node.properties.width || node.properties.height) {
return;
}
const imagePath = `${options?.root ?? ''}${node.properties.src}`;
const imageSize = getImageSize(imagePath);
node.properties.width = imageSize.width;
node.properties.height = imageSize.height;
});
// This matches all MDX' <Image /> components.
visit(tree, { type: 'mdxJsxFlowElement', name: 'Image' }, (node) => {
const srcAttr = node.attributes?.find((attr) => attr.name === 'src');
const imagePath = `${options?.root ?? ''}${srcAttr.value}`;
const imageSize = getImageSize(imagePath);
const widthAttr = node.attributes?.find((attr) => attr.name === 'width');
const heightAttr = node.attributes?.find((attr) => attr.name === 'height');
if (widthAttr || heightAttr) {
// If `width` or `height` have already been set explicitly we
// don't want to override them.
return;
}
node.attributes.push({
type: 'mdxJsxAttribute',
name: 'width',
value: imageSize.width
});
node.attributes.push({
type: 'mdxJsxAttribute',
name: 'height',
value: imageSize.height
});
});
};
};
export default rehypeImageSize;

View file

@ -29,6 +29,7 @@
] ]
}, },
"include": [ "include": [
"src/plugins",
"next-env.d.ts", "next-env.d.ts",
"**/*.ts", "**/*.ts",
"**/*.tsx", "**/*.tsx",

View file

@ -184,6 +184,9 @@ importers:
framer-motion: framer-motion:
specifier: ^10.16.4 specifier: ^10.16.4
version: 10.16.4(react-dom@18.2.0)(react@18.2.0) version: 10.16.4(react-dom@18.2.0)(react@18.2.0)
image-size:
specifier: ^1.0.2
version: 1.0.2
katex: katex:
specifier: ^0.16.9 specifier: ^0.16.9
version: 0.16.9 version: 0.16.9
@ -244,6 +247,9 @@ importers:
remark-math: remark-math:
specifier: ^5.1.1 specifier: ^5.1.1
version: 5.1.1 version: 5.1.1
remark-mdx-images:
specifier: ^2.0.0
version: 2.0.0
tailwind-merge: tailwind-merge:
specifier: ^1.14.0 specifier: ^1.14.0
version: 1.14.0 version: 1.14.0
@ -253,6 +259,9 @@ importers:
tsparticles: tsparticles:
specifier: ^2.12.0 specifier: ^2.12.0
version: 2.12.0 version: 2.12.0
unist-util-visit:
specifier: ^5.0.0
version: 5.0.0
zod: zod:
specifier: ~3.22.4 specifier: ~3.22.4
version: 3.22.4 version: 3.22.4
@ -4284,7 +4293,7 @@ packages:
magic-string: 0.27.0 magic-string: 0.27.0
react-docgen-typescript: 2.2.2(typescript@5.2.2) react-docgen-typescript: 2.2.2(typescript@5.2.2)
typescript: 5.2.2 typescript: 5.2.2
vite: 4.5.0(less@4.2.0) vite: 4.5.0(@types/node@18.17.19)
/@jridgewell/gen-mapping@0.3.3: /@jridgewell/gen-mapping@0.3.3:
resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
@ -7317,7 +7326,7 @@ packages:
magic-string: 0.30.5 magic-string: 0.30.5
rollup: 3.29.4 rollup: 3.29.4
typescript: 5.2.2 typescript: 5.2.2
vite: 4.5.0(less@4.2.0) vite: 4.5.0(@types/node@18.17.19)
transitivePeerDependencies: transitivePeerDependencies:
- encoding - encoding
- supports-color - supports-color
@ -7670,7 +7679,7 @@ packages:
react: 18.2.0 react: 18.2.0
react-docgen: 6.0.4 react-docgen: 6.0.4
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
vite: 4.5.0(less@4.2.0) vite: 4.5.0(@types/node@18.17.19)
transitivePeerDependencies: transitivePeerDependencies:
- '@preact/preset-vite' - '@preact/preset-vite'
- encoding - encoding
@ -8769,7 +8778,7 @@ packages:
'@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.23.2) '@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.23.2)
magic-string: 0.27.0 magic-string: 0.27.0
react-refresh: 0.14.0 react-refresh: 0.14.0
vite: 4.5.0(less@4.2.0) vite: 4.5.0(@types/node@18.17.19)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -18207,6 +18216,15 @@ packages:
toml: 3.0.0 toml: 3.0.0
dev: false dev: false
/remark-mdx-images@2.0.0:
resolution: {integrity: sha512-Eh9sutDjzBPRBMnD7C9tn8DdqCaVNFo3rrqEryqPBJzMZ33i/MMO68ucINsOP3lNGSsCA2N2X+Zws1pHphWSpg==}
engines: {node: '>=14.0.0'}
dependencies:
'@types/mdast': 3.0.14
unified: 10.1.2
unist-util-visit: 4.1.2
dev: false
/remark-mdx@2.3.0: /remark-mdx@2.3.0:
resolution: {integrity: sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==} resolution: {integrity: sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==}
dependencies: dependencies:
@ -20865,7 +20883,6 @@ packages:
rollup: 3.29.4 rollup: 3.29.4
optionalDependencies: optionalDependencies:
fsevents: 2.3.3 fsevents: 2.3.3
dev: true
/vite@4.5.0(less@4.2.0): /vite@4.5.0(less@4.2.0):
resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==} resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==}
@ -20901,6 +20918,7 @@ packages:
rollup: 3.29.4 rollup: 3.29.4
optionalDependencies: optionalDependencies:
fsevents: 2.3.3 fsevents: 2.3.3
dev: true
/vite@4.5.0(sass@1.69.5): /vite@4.5.0(sass@1.69.5):
resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==} resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==}