1
0
mirror of https://github.com/quay/quay.git synced 2025-04-18 10:44:06 +03:00

ui: render modelcard markdown tables (PROJQUAY-8680) (#3708)

* ui: render modelcard markdown tables (PROJQUAY-8680)

* ui: oembed to render embeded video in markdown (PROJQUAY-8679)

* ui: render tables and embeded links in markdown (PROJQUAY-8673)

* Github linked videos and Patternfly code block

* Limit img source to github and huggingface
This commit is contained in:
Kenny Lee Sin Cheong 2025-04-04 10:18:20 -04:00 committed by GitHub
parent a6713a669d
commit 1af42c0b5a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 2630 additions and 916 deletions

3437
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -27,12 +27,15 @@
"null-loader": "^4.0.1", "null-loader": "^4.0.1",
"process": "^0.11.10", "process": "^0.11.10",
"react": "^17.0.2", "react": "^17.0.2",
"react-remark": "^2.1.0", "react-markdown": "^10.1.0",
"react-router-dom": "^6.15.0", "react-router-dom": "^6.15.0",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"recoil": "^0.7.7", "recoil": "^0.7.7",
"recoil-persist": "^4.2.0", "recoil-persist": "^4.2.0",
"rehype-raw": "^7.0.0",
"rehype-video": "^2.3.0",
"remark-gemoji": "^8.0.0", "remark-gemoji": "^8.0.0",
"remark-gfm": "^4.0.1",
"ts-jest": "^29.1.1", "ts-jest": "^29.1.1",
"typescript": "^4.6.3", "typescript": "^4.6.3",
"use-react-router-breadcrumbs": "^4.0.1", "use-react-router-breadcrumbs": "^4.0.1",

View File

@ -1,14 +1,110 @@
import React from 'react';
import {
CodeBlock,
CodeBlockAction,
CodeBlockCode,
ClipboardCopyButton,
} from '@patternfly/react-core';
import {PageSection, Divider, TextContent} from '@patternfly/react-core'; import {PageSection, Divider, TextContent} from '@patternfly/react-core';
import {Table, Caption, Th, Td} from '@patternfly/react-table';
import {Remark} from 'react-remark'; import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import rehypeRaw from 'rehype-raw';
import rehypeVideo from 'rehype-video';
export const MarkdownCodeBlock: React.FunctionComponent = (props) => {
const [copied, setCopied] = React.useState(false);
const clipboardCopyFunc = (event, text) => {
navigator.clipboard.writeText(text.toString());
};
const onClick = (event, text) => {
clipboardCopyFunc(event, text);
setCopied(true);
};
const actions = (
<React.Fragment>
<CodeBlockAction>
<ClipboardCopyButton
id="basic-copy-button"
textId="code-content"
aria-label="Copy to clipboard"
onClick={(e) => onClick(e, props.code)}
exitDelay={copied ? 1500 : 600}
maxWidth="110px"
variant="plain"
onTooltipHidden={() => setCopied(false)}
>
{copied ? 'Successfully copied to clipboard!' : 'Copy to clipboard'}
</ClipboardCopyButton>
</CodeBlockAction>
</React.Fragment>
);
return (
<CodeBlock actions={actions}>
<CodeBlockCode id="code-content">{props.code}</CodeBlockCode>
</CodeBlock>
);
};
export function ModelCard(props: ModelCardProps) { export function ModelCard(props: ModelCardProps) {
const modelcard = props.modelCard;
const isValidImgSrc = (src) =>
src &&
(src.startsWith('https://github.com/') ||
src.startsWith('https://huggingface.co/'));
return ( return (
<> <>
<Divider /> <Divider />
<PageSection> <PageSection>
<TextContent> <TextContent>
<Remark>{props.modelCard}</Remark> <Markdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[
[rehypeRaw],
[
rehypeVideo,
{
test: new RegExp(
'(.*)(githubusercontent.com|github.com|huggingface.co)(.*)(.mp4|.mov)$',
),
},
],
]}
components={{
code({node, inline, className, children, ...props}) {
return <MarkdownCodeBlock code={children} />;
},
table: ({children}) => (
<Table borders={true} variant={'compact'}>
{children}
</Table>
),
caption: 'Caption',
th: ({children}) => (
<Th style={{border: '1px solid black', padding: '8px'}}>
{children}
</Th>
),
td: ({children}) => (
<Td style={{border: '1px solid black', padding: '8px'}}>
{children}
</Td>
),
img: ({src, alt}) =>
isValidImgSrc(src) ? (
<img src={src} alt={alt} style={{maxWidth: '100%'}} />
) : null,
iframe: () => null,
}}
>
{modelcard}
</Markdown>
</TextContent> </TextContent>
</PageSection> </PageSection>
</> </>

View File

@ -160,6 +160,10 @@ module.exports = (env) => {
], ],
symlinks: false, symlinks: false,
cacheWithContext: false, cacheWithContext: false,
alias: {
'react/jsx-dev-runtime': 'react/jsx-dev-runtime.js',
'react/jsx-runtime': 'react/jsx-runtime.js',
},
}, },
}; };
}; };