tailwind-nextjs-blog/lib/remark-img-to-jsx.ts

56 lines
1.6 KiB
TypeScript
Raw Normal View History

2022-10-17 23:37:01 +08:00
import { Literal } from 'unist';
import { visit, Parent, Node } from 'unist-util-visit';
import sizeOf from 'image-size';
import fs from 'fs';
2022-07-17 21:40:41 +08:00
type ImageNode = Parent & {
2022-10-17 23:37:01 +08:00
url: string;
alt: string;
name: string;
attributes: (Literal & { name: string })[];
};
2022-07-17 21:40:41 +08:00
export default function remarkImgToJsx() {
return (tree: Node) => {
2022-07-17 21:40:41 +08:00
visit(
tree,
// only visit p tags that contain an img element
(node: Parent): node is Parent =>
2022-10-17 23:37:01 +08:00
node.type === 'paragraph' &&
node.children.some((n) => n.type === 'image'),
(node: Parent) => {
2022-10-17 23:37:01 +08:00
const imageNode = node.children.find(
(n) => n.type === 'image'
) as ImageNode;
2022-07-17 21:40:41 +08:00
// only local files
if (fs.existsSync(`${process.cwd()}/public${imageNode.url}`)) {
2022-10-17 23:37:01 +08:00
const dimensions = sizeOf(`${process.cwd()}/public${imageNode.url}`);
2022-07-17 21:40:41 +08:00
// Convert original node to next/image
2022-10-17 23:37:01 +08:00
(imageNode.type = 'mdxJsxFlowElement'),
2022-07-17 21:40:41 +08:00
(imageNode.name = 'Image'),
(imageNode.attributes = [
{ type: 'mdxJsxAttribute', name: 'alt', value: imageNode.alt },
{ type: 'mdxJsxAttribute', name: 'src', value: imageNode.url },
2022-10-17 23:37:01 +08:00
{
type: 'mdxJsxAttribute',
name: 'width',
value: dimensions.width,
},
{
type: 'mdxJsxAttribute',
name: 'height',
value: dimensions.height,
},
]);
2022-07-17 21:40:41 +08:00
// Change node type from p to div to avoid nesting error
2022-10-17 23:37:01 +08:00
node.type = 'div';
node.children = [imageNode];
2022-07-17 21:40:41 +08:00
}
}
2022-10-17 23:37:01 +08:00
);
};
2022-07-17 21:40:41 +08:00
}