Skip to content

Instantly share code, notes, and snippets.

@mdroidian
Created February 2, 2024 02:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mdroidian/bfaa53299fce4ffe4961e6754f583e13 to your computer and use it in GitHub Desktop.
Save mdroidian/bfaa53299fce4ffe4961e6754f583e13 to your computer and use it in GitHub Desktop.
react-pdf + react-markdown images
import React from "react";
import {
Document,
Page,
Text,
StyleSheet,
View,
Link,
PDFViewer,
Image,
} from "@react-pdf/renderer";
import Markdown, { Components } from "react-markdown";
import remarkGfm from "remark-gfm";
type PdfProps = {
content: string;
};
const FONT_NORMAL = "Times-Roman";
const FONT_BOLD = "Times-Bold";
const FONT_ITALIC = "Times-Italic";
const MARGIN_BOTTOM = 12;
const FONT_SIZE = 14;
const styles = StyleSheet.create({
body: {
fontFamily: FONT_NORMAL,
padding: 35,
},
p: {
marginBottom: MARGIN_BOTTOM,
fontSize: FONT_SIZE,
},
listItem: {
marginBottom: MARGIN_BOTTOM,
fontSize: FONT_SIZE,
},
link: {
color: "blue",
textDecoration: "underline",
},
title: {
fontSize: 32,
fontWeight: "medium",
fontFamily: FONT_NORMAL,
lineHeight: 1.3,
},
h1: {
fontSize: 28,
fontWeight: "normal",
fontFamily: FONT_BOLD,
marginBottom: MARGIN_BOTTOM,
},
h2: {
fontSize: 25,
fontWeight: "normal",
fontFamily: FONT_BOLD,
marginBottom: MARGIN_BOTTOM,
},
h3: {
color: "#5C7080",
fontSize: 17,
fontWeight: "bold",
fontFamily: FONT_BOLD,
marginBottom: MARGIN_BOTTOM,
},
hr: {
marginBottom: MARGIN_BOTTOM,
borderBottomWidth: 1,
borderBottomColor: "black",
},
strong: {
fontFamily: FONT_BOLD,
fontWeight: "bold",
},
italic: {
fontFamily: FONT_ITALIC,
fontStyle: "italic",
},
underline: {
textDecoration: "underline",
},
strike: {
textDecoration: "line-through",
},
code: {
marginBottom: MARGIN_BOTTOM,
fontSize: FONT_SIZE,
},
blockquote: {
fontSize: FONT_SIZE,
fontStyle: "italic",
backgroundColor: "#F5F8FA",
borderLeft: "5px solid #30404D",
padding: 20,
marginBottom: MARGIN_BOTTOM,
},
img: {
marginBottom: MARGIN_BOTTOM,
},
pageNumber: {
position: "absolute",
fontSize: 12,
bottom: 30,
left: 0,
right: 0,
textAlign: "center",
color: "grey",
},
});
const components: Components = {
del: ({ children }) => <Text style={styles.strike}>{children}</Text>,
em: ({ children }) => <Text style={styles.italic}>{children}</Text>,
strong: ({ children }) => <Text style={styles.strong}>{children}</Text>,
a: ({ children, href }) => (
<Link style={styles.link} src={href}>
{children}
</Link>
),
hr: () => <View style={styles.hr}></View>,
input: ({ checked }) => <Text>{checked ? "[x]" : "[ ]"}</Text>,
ul: ({ children }) => <Text>{children}</Text>,
li: ({ children }) => <Text style={styles.listItem}>{children}</Text>,
ol: ({ children }) => <Text style={styles.listItem}>{children}</Text>,
h1: ({ children }) => <Text style={styles.h1}>{children}</Text>,
h2: ({ children }) => <Text style={styles.h2}>{children}</Text>,
h3: ({ children }) => <Text style={styles.h3}>{children}</Text>,
br: ({ children }) => <Text>{children}</Text>,
code: ({ children }) => <Text style={styles.code}>{children}</Text>,
blockquote: ({ children }) => (
<View style={styles.blockquote}>{children}</View>
),
p: ({ children }) => <Text style={styles.p}>{children}</Text>,
img: ({ src }) => <Image style={styles.img} src={src} />,
};
const Pdf: React.FC<PdfProps> = () => {
const title = `[[CLM]] - 123 asdfasdfasdf`;
const code = "```javascript some \ncode```";
const image = "https://placehold.co/600x400";
const content = `# heading 1
## heading 2
### heading 3
some text with **bold** and _italics_ and ~~strike~~
some [link](https://www.google.com/)
> some quote
some other line
In et accumsan libero. Suspendisse eleifend luctus consectetur. Duis faucibus, libero et fermentum vulputate, mi lacus interdum neque, quis viverra eros ex vitae lectus. Ut velit metus, elementum quis tellus nec, euismod consequat massa. Nunc tincidunt, libero vel ultricies egestas, massa leo maximus libero, nec fringilla turpis leo eget turpis. Integer in sem tempus, efficitur orci et, sodales risus. Suspendisse orci dolor, dignissim eget venenatis at, placerat eget sem. Vestibulum luctus diam tortor, vel pellentesque tellus feugiat et. Donec vitae purus lacinia, accumsan nisi vel, blandit tortor. Mauris eu mollis velit, vitae mattis ligula. Pellentesque tempus lectus lobortis erat semper, eu ullamcorper arcu dignissim. Fusce pellentesque tristique ligula ut malesuada. Aenean vel vehicula augue.
![](https://firebasestorage.googleapis.com/v0/b/firescript-577a2.appspot.com/o/imgs%2Fapp%2Froamjs-dev%2FuChedYvt04.png?alt=media&token=404a5b80-3fc0-40e1-ae98-0ce86a36b088)
`;
return (
<PDFViewer style={{ height: "90vh", width: "90vw" }}>
<Document>
<Page style={styles.body}>
<View>
<Text style={styles.title}>{title}</Text>
</View>
{/* <View> <Image style={styles.img} src={image} /> </View> */}
<View>
<Markdown
components={components}
remarkPlugins={[[remarkGfm, { singleTilde: false }]]}
>
{content}
</Markdown>
</View>
<Text
style={styles.pageNumber}
render={({ pageNumber, totalPages }) =>
`${pageNumber} / ${totalPages}`
}
fixed
/>
</Page>
</Document>
</PDFViewer>
);
};
export default Pdf;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment