Issue
I am trying to get load a markdown file to be loaded on build. I have setup a create-react-app that uses Typescript and using a material_ui blog theme.
import ReactMarkdown from 'markdown-to-jsx';
import post1 from './blog-post.1.md';
export default function Main(props: MainProps) {
const classes = useStyles();
const { posts, title } = props;
return (
<Grid item xs={12} md={8}>
<Typography variant="h6" gutterBottom>
{title}
</Typography>
<Divider />
{posts.map((post) => (
<Markdown className={classes.markdown} key={post.substring(0, 40)}>
{post}
</Markdown>
))}
</Grid>
);
}
If a post is assigned to be markdown, it will render correctly: const post = '# Sample blog post #### April 1, 2020 by [Olivier](/)'
So the issue is that .md file is not loading into the variable.
When npm start is run, the html displays: /static/media/blog-post.1.09e7833f.md
Why would this be and what is that number: 09e7833f in the filepath?
I would ideally like to load the file in during build time so that it can be served more quickly on somewhere like Netlify. I do not want to use an asynchronous fetch like this answer suggests.
I assume I would have to create a webpack loader? The problem with this is that create-react-app has webpack.config.js in the node_modules which means customising it would be overwritten during a new build. I don't think using raw-loader helps if I can't configure it.
I've also tried import post1 from 'raw-loader!./blog-post.1.md'; as suggested here but Typescript doesn't know what to do with that.
Any suggestions would be helpful.
Solution
This seems to be something that's been asked previously (https://github.com/facebook/create-react-app/issues/3025), but unfortunately it doesn't seem possible right now to directly import markdown as a string in JavaScript/TypeScript.
When asking create-react-app to import an md file, it seems to get a URL (with a hex string) to the file instead of the raw string contained within. A workaround is as follows:
- Create a
.d.tsfile to tell TypeScript how to interpret anmdfile:
declare module '*.md' {
const value: string; // markdown is just a string
export default value;
}
- Import your
mdfile (the_text.md) as follows
import theTextFile from './the_text.md';
fetchthe contents of the file to get the actual markdown (https://github.com/facebook/create-react-app/issues/2961#issuecomment-322916352)
const [postMarkdown, setPostMarkdown] = useState('');
// useEffect with an empty dependency array (`[]`) runs only once
useEffect(() => {
fetch(theTextFile)
.then((response) => response.text())
.then((text) => {
// Logs a string of Markdown content.
// Now you could use e.g. <rexxars/react-markdown> to render it.
// console.log(text);
setPostMarkdown(text);
});
}, []);
- Place the markdown text into the Markdown tag and it will be rendered:
<Markdown className={classes.markdown}>
{post}
</Markdown>
Keep in mind you can also override the JSX elements used to display the final thing. For Material-UI, this could look something like:
import { Typography } from '@material-ui/core';
import { MarkdownToJSX } from 'markdown-to-jsx';
const Foo = (): JSX.Element => {
const MdOverrideTypography = ({
children,
}: // ...props
React.DetailedHTMLProps<
React.HTMLAttributes<HTMLParagraphElement>,
HTMLParagraphElement
>): JSX.Element => (
<Typography paragraph>
{children}
</Typography>
);
const mdOverrides: MarkdownToJSX.Overrides = {
// "p" paragraph elements are substituted with MUI "Typography"
p: MdOverrideTypography,
};
// ...
return (
<Markdown options={{ overrides: mdOverrides }}>
{post}
</Markdown>
)
}
Answered By - jmaio
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.