display svg images in code blocks
parent
47892360b2
commit
869ba3ec1f
|
@ -30,7 +30,7 @@
|
|||
<link href="https://fonts.googleapis.com/css?family=Work+Sans:300,400,500,600,700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css"
|
||||
integrity="sha384-Xi8rHCmBmhbuyyhbI88391ZKP2dmfnOl4rT9ZfRI7mLTdk1wblIUnrIq35nqwEvC" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tailwindcss/typography@0.4.1/dist/typography.min.css" />
|
||||
<link rel="stylesheet" href="/prose.css" />
|
||||
<style>
|
||||
body {
|
||||
background: #292933;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,4 @@
|
|||
import styled from '@emotion/styled';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
|
@ -8,6 +9,47 @@ import { Button, CopyButton } from '@mantine/core';
|
|||
import { useMemo } from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
const Code = styled.div`
|
||||
padding: 0;
|
||||
border-radius: 0.25rem;
|
||||
overflow: hidden;
|
||||
|
||||
&>div {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.fa {
|
||||
font-style: normal !important;
|
||||
}
|
||||
`;
|
||||
|
||||
const Header = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
background: #191919;
|
||||
height: 2.5rem;
|
||||
padding: 0.1rem 0.1rem 0 0.5rem;
|
||||
|
||||
.mantine-Button-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
* {
|
||||
font-size: 90%;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const ImagePreview = styled.div`
|
||||
text-align: center;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
|
||||
export interface MarkdownProps {
|
||||
content: string;
|
||||
className?: string;
|
||||
|
@ -28,14 +70,30 @@ export function Markdown(props: MarkdownProps) {
|
|||
|
||||
const elem = useMemo(() => (
|
||||
<div className={classes.join(' ')}>
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm, remarkMath]}
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm, remarkMath]}
|
||||
rehypePlugins={[rehypeKatex]}
|
||||
components={{
|
||||
code({ node, inline, className, children, ...props }) {
|
||||
const match = /language-(\w+)/.exec(className || '')
|
||||
return !inline ? (
|
||||
<div>
|
||||
<CopyButton value={String(children)}>
|
||||
const code = String(children);
|
||||
return !inline ? (<>
|
||||
<Code>
|
||||
<Header>
|
||||
{code.startsWith('<svg') && code.includes('</svg>') && (
|
||||
<Button variant="subtle" size="sm" compact onClick={() => {
|
||||
const blob = new Blob([code], { type: 'image/svg+xml' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'image.svg';
|
||||
a.click();
|
||||
}}>
|
||||
<i className="fa fa-download" />
|
||||
<span><FormattedMessage defaultMessage="Download SVG" /></span>
|
||||
</Button>
|
||||
)}
|
||||
<CopyButton value={code}>
|
||||
{({ copy, copied }) => (
|
||||
<Button variant="subtle" size="sm" compact onClick={copy}>
|
||||
<i className="fa fa-clipboard" />
|
||||
|
@ -43,15 +101,20 @@ export function Markdown(props: MarkdownProps) {
|
|||
</Button>
|
||||
)}
|
||||
</CopyButton>
|
||||
</Header>
|
||||
<SyntaxHighlighter
|
||||
children={String(children).replace(/\n$/, '')}
|
||||
children={code}
|
||||
style={vscDarkPlus as any}
|
||||
language={match?.[1] || 'text'}
|
||||
PreTag="div"
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
{...props} />
|
||||
</Code>
|
||||
{code.startsWith('<svg') && code.includes('</svg>') && (
|
||||
<ImagePreview>
|
||||
<img src={`data:image/svg+xml;base64,${btoa(code)}`} />
|
||||
</ImagePreview>
|
||||
)}
|
||||
</>) : (
|
||||
<code className={className} {...props}>
|
||||
{children}
|
||||
</code>
|
||||
|
|
Loading…
Reference in New Issue