transform html content synchronously

This commit is contained in:
jasongao97 2022-08-09 10:34:46 -04:00
parent 795b8f1407
commit b083e351be
3 changed files with 50 additions and 57 deletions

View file

@ -1,55 +0,0 @@
import { createElement, Fragment, useEffect, useState } from 'react';
import { unified } from 'unified';
import { visit } from 'unist-util-visit';
import rehypeParse from 'rehype-parse';
import rehypeReact from 'rehype-react';
import Image from '../components/Image';
import Example from '../components/Example';
export function useRehypeProcessor({ html, images }) {
const [Content, setContent] = useState(Fragment);
useEffect(() => {
const replaceImages = () => (tree) => {
visit(tree, { tagName: 'img' }, (node, index, parent) => {
const relativePath = node.properties.src;
// If the image src exist as a local file
// use Gatsby Image to handle
const imageSharp = images.find(
(image) => image.relativePath === relativePath,
);
if (imageSharp) {
node.tagName = 'gatsby-image';
node.properties.image = imageSharp;
}
});
visit(tree, { tagName: 'div' }, (node, index, parent) => {
if (
node.properties.dataType === 'example' &&
node.properties.dataExamplePath
) {
node.tagName = 'embed-example';
}
});
};
unified()
.use(rehypeParse, { fragment: true })
.use(replaceImages)
.use(rehypeReact, {
createElement,
Fragment,
components: {
'gatsby-image': Image,
'embed-example': Example,
},
})
.process(html)
.then((file) => {
setContent(file.result);
});
}, [html, images]);
return Content;
}

View file

@ -2,12 +2,13 @@ import React from 'react';
import { graphql } from 'gatsby'; import { graphql } from 'gatsby';
import Layout from '../components/Layout'; import Layout from '../components/Layout';
import { useRehypeProcessor } from '../hooks/useRehypeProcessor';
import { transformContent } from '../utils/transformContent';
export default function ChapterLayout({ data }) { export default function ChapterLayout({ data }) {
const { chaptersJson: chapter } = data; const { chaptersJson: chapter } = data;
const body = useRehypeProcessor({ const { result: body } = transformContent({
html: chapter.src.fields.html, html: chapter.src.fields.html,
images: chapter.images, images: chapter.images,
}); });

View file

@ -0,0 +1,47 @@
import { createElement, Fragment } from 'react';
import { unified } from 'unified';
import { visit } from 'unist-util-visit';
import rehypeParse from 'rehype-parse';
import rehypeReact from 'rehype-react';
import Image from '../components/Image';
import Example from '../components/Example';
export function transformContent({ html, images }) {
const replaceMedia = () => (tree) => {
visit(tree, { tagName: 'img' }, (node, index, parent) => {
const relativePath = node.properties.src;
// If the image src exist as a local file
// use Gatsby Image to handle
const imageSharp = images.find(
(image) => image.relativePath === relativePath,
);
if (imageSharp) {
node.tagName = 'gatsby-image';
node.properties.image = imageSharp;
}
});
visit(tree, { tagName: 'div' }, (node, index, parent) => {
if (
node.properties.dataType === 'example' &&
node.properties.dataExamplePath
) {
node.tagName = 'embed-example';
}
});
};
const processor = unified()
.use(rehypeParse, { fragment: true })
.use(replaceMedia)
.use(rehypeReact, {
createElement,
Fragment,
components: {
'gatsby-image': Image,
'embed-example': Example,
},
});
return processor.processSync(html);
}