Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/aj47/big-AGI into aj47-main
Browse files Browse the repository at this point in the history
  • Loading branch information
enricoros committed Feb 4, 2024
2 parents 2e7f2b6 + 8d3377a commit 101237a
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 5 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"prismjs": "^1.29.0",
"react": "^18.2.0",
"react-beautiful-dnd": "^13.1.1",
"react-csv": "^2.2.2",
"react-dom": "^18.2.0",
"react-katex": "^3.0.1",
"react-markdown": "^9.0.1",
Expand All @@ -61,6 +62,7 @@
"@types/prismjs": "^1.26.3",
"@types/react": "^18.2.51",
"@types/react-beautiful-dnd": "^13.1.8",
"@types/react-csv": "^1.1.10",
"@types/react-dom": "^18.2.18",
"@types/react-katex": "^3.0.4",
"@types/react-timeago": "^4.1.7",
Expand Down
82 changes: 77 additions & 5 deletions src/apps/chat/components/message/RenderMarkdown.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import * as React from 'react';

import { Box, styled } from '@mui/joy';
import { CSVDownload, CSVLink } from 'react-csv';

import { Box, Button, styled } from '@mui/joy';

import { lineHeightChatText } from '~/common/app.theme';

import type { TextBlock } from './blocks';

import DownloadIcon from '@mui/icons-material/Download';

/*
* For performance reasons, we style this component here and copy the equivalent of 'props.sx' (the lineHeight) locally.
Expand All @@ -32,14 +35,83 @@ const DynamicReactGFM = React.lazy(async () => {
// NOTE: extracted here instead of inline as a large performance optimization
const remarkPlugins = [remarkGfmModule.default];

// Pass the dynamically imported remarkGfm as children
const ReactMarkdownWithRemarkGfm = (props: any) =>
<markdownModule.default remarkPlugins={remarkPlugins} {...props} />;
//Extracts table data from jsx element in table renderer
const extractTableData = (children: React.JSX.Element) => {
// Function to extract text from a React element or component
const extractText = (element: any): String => {
// Base case: if the element is a string, return it
if (typeof element === 'string') {
return element;
}
// If the element has children, recursively extract text from them
if (element.props && element.props.children) {
if (Array.isArray(element.props.children)) {
return element.props.children.map(extractText).join('');
}
return extractText(element.props.children);
}
return '';
};

// Function to traverse and extract data from table rows and cells
const traverseAndExtract = (elements: any, tableData: any[] = []) => {
React.Children.forEach(elements, (element) => {
if (element.type === 'tr') {
const rowData = React.Children.map(element.props.children, (cell) => {
// Extract and return the text content of each cell
return extractText(cell);
});
tableData.push(rowData);
} else if (element.props && element.props.children) {
traverseAndExtract(element.props.children, tableData);
}
});
return tableData;
};

return traverseAndExtract(children);
};

interface TableRendererProps {
children: React.JSX.Element;
}
// Define a custom table renderer
const TableRenderer = ({ children, ...props }: TableRendererProps) => {
// Apply custom styles or modifications here
const tableData = extractTableData(children);

return (
<>
<table style={{ borderCollapse: 'collapse', width: '100%' }} {...props}>
{children}
</table>
<CSVLink filename='big-agi-export' data={tableData}>
<Button variant="outlined">
<DownloadIcon />
{'Download table as .csv '}
</Button>
</CSVLink>
</>
);
};

// Use the custom renderer for tables
const components = {
table: TableRenderer,
// Add custom renderers for other elements if needed
};

// Pass the dynamically imported remarkGfm as children
const ReactMarkdownWithRemarkGfm = (props: any) =>
<markdownModule.default
remarkPlugins={remarkPlugins}
{...props}
components={components}
/>;

return { default: ReactMarkdownWithRemarkGfm };
});


export const RenderMarkdown = (props: { textBlock: TextBlock }) => {
return (
<RenderMarkdownBox className='markdown-body' /* NODE: see GithubMarkdown.css for the dark/light switch, synced with Joy's */ >
Expand Down

0 comments on commit 101237a

Please sign in to comment.