Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/chart #272

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/components/Editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ import {
} from 'features/docSlices';
import { makeStyles } from 'styles/common';
import { Presence, syncPeer } from 'features/peerSlices';
import { Alert, Box, CircularProgress, Snackbar } from '@mui/material';
import Alert from '@mui/material/Alert';
import Box from '@mui/material/Box';
import CircularProgress from '@mui/material/CircularProgress';
import Snackbar from '@mui/material/Snackbar';

import WhiteBoardEditor from './mime/application/whiteboard/Editor';
import Editor from './mime/text/md/Editor';

Expand Down
68 changes: 9 additions & 59 deletions src/components/Editor/mime/text/md/CodeEditor/ChartView.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import React, { useId, useLayoutEffect, useMemo, useState } from 'react';
import mermaid from 'mermaid';
import React, { useId, useMemo } from 'react';
import { makeStyles } from 'styles/common';
import { Theme } from 'features/settingSlices';
import { TabContext, TabList, TabPanel } from '@mui/lab';
import { Box, Tab, ThemeProvider, createTheme } from '@mui/material';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';

import oneLight from 'react-syntax-highlighter/dist/esm/styles/prism/one-light';
import oneDark from 'react-syntax-highlighter/dist/esm/styles/prism/one-dark';
import { ThemeProvider, createTheme } from '@mui/material';

const useStyles = makeStyles<{ theme: string }>()((_, { theme }) => {
return {
root: {
backgroundColor: theme === Theme.Dark ? '#282c34' : '#fff',
borderRadius: 8,
backgroundColor: theme === Theme.Dark ? '#282c34' : '#f6f6f6',
// borderRadius: 8,
padding: 8,
border: theme === Theme.Dark ? '1px solid #555555' : '1px solid rgba(0, 0, 0, 0.12)',
// border: theme === Theme.Dark ? '1px solid #555555' : '1px solid rgba(0, 0, 0, 0.12)',
},
};
});
Expand All @@ -25,7 +19,7 @@ function ChartView({ code, theme }: { code: string; theme: string }) {
const { classes } = useStyles({
theme,
});
const [value, setValue] = useState('viewer');

const themeValue = useMemo(
() =>
createTheme({
Expand All @@ -36,57 +30,13 @@ function ChartView({ code, theme }: { code: string; theme: string }) {
[theme],
);

const handleChange = (event: React.SyntheticEvent, newValue: string) => {
setValue(newValue);
};

useLayoutEffect(() => {
mermaid.initialize({
startOnLoad: false,
theme,
});

if (value === 'code') return;

(async () => {
const currentId = id.replaceAll(':', 'mermaid');
const element = document.querySelector(`#${currentId}`);

if (element) {
const graphDefinition = code.trim();

const { svg } = await mermaid.render(`${currentId}svg`, graphDefinition, element);

element.innerHTML = svg;
}
})();
}, [code, theme, id, value]);

/* eslint-disable react/no-danger */
return (
<ThemeProvider theme={themeValue}>
<div className={classes.root}>
<TabContext value={value}>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<TabList onChange={handleChange} aria-label="lab API tabs example">
<Tab label="Mermaid" value="viewer" />
<Tab label="Code" value="code" />
</TabList>
</Box>
<TabPanel value="viewer">
<div id={id.replaceAll(':', 'mermaid')}>fdsafdsf</div>
</TabPanel>
<TabPanel
value="code"
style={{
padding: 10,
}}
>
<SyntaxHighlighter style={theme === Theme.Dark ? oneDark : oneLight} language="mermaid" PreTag="div">
{code}
</SyntaxHighlighter>
</TabPanel>
</TabContext>
<div id={id.replaceAll(':', 'chart')}>
<pre>{code}</pre>
</div>
</div>
</ThemeProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { CodeKeyMap, TabSize, setCodeKeyMap, setTabSize } from 'features/setting
import { AppDispatch } from 'app/store';
import { AppState } from 'app/rootReducer';
import { makeStyles } from 'styles/common';
import { FormControl, NativeSelect } from '@mui/material';
import FormControl from '@mui/material/FormControl';
import NativeSelect from '@mui/material/NativeSelect';

const useStyles = makeStyles()((theme) => ({
root: {
Expand Down
116 changes: 116 additions & 0 deletions src/components/Editor/mime/text/md/CodeEditor/MarkdownRenderer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import React from 'react';

import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { Theme } from 'features/settingSlices';
import oneLight from 'react-syntax-highlighter/dist/esm/styles/prism/one-light';
import oneDark from 'react-syntax-highlighter/dist/esm/styles/prism/one-dark';

import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math';
import remarkToc from 'remark-toc';
import remarkEmoji from 'remark-emoji';

import rehypeKatex from 'rehype-katex';
import fenceparser from 'fenceparser';
import { MetaInfo } from 'constants/editor';
import MermaidView from './MermaidView';
import MiniDraw from './MiniDraw';

import ChartView from './ChartView';

interface MarkdownRendererProps {
theme: string;
markdown: string;
}

type StyleObject = {
[key: string]: string;
};

export function MarkdownRenderer({ theme, markdown }: MarkdownRendererProps) {
return (
<div className="markdown-renderer">
<ReactMarkdown
remarkPlugins={[remarkMath, remarkGfm, remarkToc, remarkEmoji]}
rehypePlugins={[rehypeKatex]}
components={{
// eslint-disable-next-line react/no-unstable-nested-components
code: ({ node, inline, className, children, ...props }) => {
const match = /language-(\w+)/.exec(className || '');

const text = children[0];

const tempMetaInfo = fenceparser(`${node.data?.meta}`);

const metaInfo: MetaInfo = {};
Object.keys(tempMetaInfo).reduce((acc: any, key) => {
if (!key || key === 'undefined') {
return acc;
}

acc[key] = tempMetaInfo[key];

return acc;
}, metaInfo);

if (className === 'language-chart') {
return <ChartView code={text as string} theme={theme} />;
}

if (className === 'language-mermaid') {
return <MermaidView code={text as string} theme={theme} />;
}

if (className === 'language-tldraw') {
return <MiniDraw content={`${text}`.trim()} theme={theme} readOnly meta={metaInfo} />;
}

return !inline && match ? (
<SyntaxHighlighter
{...props}
showLineNumbers={metaInfo.showlinenumbers}
showInlineLineNumbers={metaInfo.showinlinelinenumbers}
data-language={match[1]}
style={theme === Theme.Dark ? oneDark : oneLight}
language={match[1]}
wrapLines
lineProps={(lineNumber) => {
console.log(lineNumber, metaInfo.highlight);
const style: StyleObject = { display: 'block' };

// check line numbers
const hasHighlightedLineNumbers = Object.keys(metaInfo.highlight as any).some((key) => {
const lines = key.split('-');

if (lines.length === 1) {
if (key === `${lineNumber}`) {
return true;
}
} else if (lineNumber >= Number(lines[0]) && lineNumber <= Number(lines[1])) {
return true;
}
return false;
});
if (hasHighlightedLineNumbers) {
style.backgroundColor = '#ffe7a4';
}
return { style };
}}
PreTag="div"
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code {...props} className={className}>
{children}
</code>
);
},
}}
>
{markdown}
</ReactMarkdown>
</div>
);
}
102 changes: 3 additions & 99 deletions src/components/Editor/mime/text/md/CodeEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ import { ActorID, DocEvent, TextChange } from 'yorkie-js-sdk';
import CodeMirror from 'codemirror';
import SimpleMDE from 'easymde';
import SimpleMDEReact from 'react-simplemde-editor';
import ReactMarkdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';

import oneLight from 'react-syntax-highlighter/dist/esm/styles/prism/one-light';
import oneDark from 'react-syntax-highlighter/dist/esm/styles/prism/one-dark';

import { AppState } from 'app/rootReducer';
import { ConnectionStatus, Presence } from 'features/peerSlices';
Expand All @@ -32,17 +27,10 @@ import {
Theme,
Typography,
} from '@mui/material';
import { MetaInfo, NAVBAR_HEIGHT } from 'constants/editor';
import { NAVBAR_HEIGHT } from 'constants/editor';
import { addRecentPage } from 'features/currentSlices';
import { setActionStatus } from 'features/actionSlices';
import { updateLinkNameWithHeading } from 'features/linkSlices';
import remarkMath from 'remark-math';
import remarkGfm from 'remark-gfm';
import remarkToc from 'remark-toc';
import remarkEmoji from 'remark-emoji';

import rehypeKatex from 'rehype-katex';
import fenceparser from 'fenceparser';

import 'katex/dist/katex.min.css'; // `rehype-katex` does not import the CSS for you
import 'easymde/dist/easymde.min.css';
Expand All @@ -65,14 +53,10 @@ import Cursor from './Cursor';
import SlideView from './slideView';
import { CodeEditorMenu } from './Menu';

import MermaidView from './MermaidView';
import MiniDraw from './MiniDraw';
import MiniMermaid from './MiniMermaid';
import { MermaidSampleType, samples } from './mermaid-samples';

type StyleObject = {
[key: string]: string;
};
import { MarkdownRenderer } from './MarkdownRenderer';

const WIDGET_HEIGHT = 40;

Expand Down Expand Up @@ -544,87 +528,7 @@ export default function CodeEditor() {
globalContainer.rootElement = createRoot(previewElement) as any;
}

(globalContainer.rootElement as any)?.render(
<ReactMarkdown
remarkPlugins={[remarkMath, remarkGfm, remarkToc, remarkEmoji]}
rehypePlugins={[rehypeKatex]}
components={{
code: ({ node, inline, className, children, ...props }) => {
const match = /language-(\w+)/.exec(className || '');

const text = children[0];

const tempMetaInfo = fenceparser(`${node.data?.meta}`);

const metaInfo: MetaInfo = {};
Object.keys(tempMetaInfo).reduce((acc: any, key) => {
if (!key || key === 'undefined') {
return acc;
}

acc[key] = tempMetaInfo[key];

return acc;
}, metaInfo);

// if (className === 'language-chart') {
// return <ChartView code={text as string} theme={menu.theme} />;
// }

if (className === 'language-mermaid') {
return <MermaidView code={text as string} theme={menu.theme} />;
}

if (className === 'language-tldraw') {
return <MiniDraw content={`${text}`.trim()} theme={menu.theme} readOnly meta={metaInfo} />;
}

return !inline && match ? (
<SyntaxHighlighter
{...props}
showLineNumbers={metaInfo.showlinenumbers}
showInlineLineNumbers={metaInfo.showinlinelinenumbers}
data-language={match[1]}
style={menu.theme === ThemeType.Dark ? oneDark : oneLight}
language={match[1]}
wrapLines
lineProps={(lineNumber) => {
console.log(lineNumber, metaInfo.highlight);
const style: StyleObject = { display: 'block' };

// check line numbers
const hasHighlightedLineNumbers = Object.keys(metaInfo.highlight as any).some((key) => {
const lines = key.split('-');

if (lines.length === 1) {
if (key === `${lineNumber}`) {
return true;
}
} else if (lineNumber >= Number(lines[0]) && lineNumber <= Number(lines[1])) {
return true;
}
return false;
});
if (hasHighlightedLineNumbers) {
style.backgroundColor = '#ffe7a4';
}
return { style };
}}
PreTag="div"
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code {...props} className={className}>
{children}
</code>
);
},
}}
>
{markdown}
</ReactMarkdown>,
);
(globalContainer.rootElement as any)?.render(<MarkdownRenderer theme={menu.theme} markdown={markdown} />);
} catch (err) {
console.error(err);
}
Expand Down
4 changes: 3 additions & 1 deletion src/components/NavBar/LinkNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import Home from '@mui/icons-material/Home';
import { MimeType } from 'constants/editor';
import BorderAll from '@mui/icons-material/BorderAll';
import Gesture from '@mui/icons-material/Gesture';
import { AccountTree, DescriptionOutlined, Folder } from '@mui/icons-material';
import AccountTree from '@mui/icons-material/AccountTree';
import DescriptionOutlined from '@mui/icons-material/DescriptionOutlined';
import Folder from '@mui/icons-material/Folder';
import { Theme } from 'features/settingSlices';
import MoreHoriz from '@mui/icons-material/MoreHoriz';

Expand Down
2 changes: 1 addition & 1 deletion src/components/NavBar/PageButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { makeStyles } from 'styles/common';
import { MimeType } from 'constants/editor';
import { useNavigate } from 'react-router-dom';
import { createDocumentKey, createRandomColor } from 'utils/document';
import { DescriptionOutlined } from '@mui/icons-material';
import DescriptionOutlined from '@mui/icons-material/DescriptionOutlined';

const useStyles = makeStyles()(() => ({
menu: {
Expand Down
Loading