Render file as readable with ext (#1446)

This commit is contained in:
Ajay Bura 2023-10-10 17:07:28 +11:00 committed by GitHub
parent 609b132106
commit 152576e85d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 11 deletions

View file

@ -4,7 +4,6 @@ import classNames from 'classnames';
import { Box, Chip, Header, Icon, IconButton, Icons, Scroll, Text, as } from 'folds'; import { Box, Chip, Header, Icon, IconButton, Icons, Scroll, Text, as } from 'folds';
import { ErrorBoundary } from 'react-error-boundary'; import { ErrorBoundary } from 'react-error-boundary';
import * as css from './TextViewer.css'; import * as css from './TextViewer.css';
import { mimeTypeToExt } from '../../utils/mimeTypes';
import { copyToClipboard } from '../../utils/dom'; import { copyToClipboard } from '../../utils/dom';
const ReactPrism = lazy(() => import('../../plugins/react-prism/ReactPrism')); const ReactPrism = lazy(() => import('../../plugins/react-prism/ReactPrism'));
@ -12,12 +11,12 @@ const ReactPrism = lazy(() => import('../../plugins/react-prism/ReactPrism'));
export type TextViewerProps = { export type TextViewerProps = {
name: string; name: string;
text: string; text: string;
mimeType: string; langName: string;
requestClose: () => void; requestClose: () => void;
}; };
export const TextViewer = as<'div', TextViewerProps>( export const TextViewer = as<'div', TextViewerProps>(
({ className, name, text, mimeType, requestClose, ...props }, ref) => { ({ className, name, text, langName, requestClose, ...props }, ref) => {
const handleCopy = () => { const handleCopy = () => {
copyToClipboard(text); copyToClipboard(text);
}; };
@ -51,10 +50,7 @@ export const TextViewer = as<'div', TextViewerProps>(
alignItems="Center" alignItems="Center"
> >
<Scroll hideTrack variant="Background" visibility="Hover"> <Scroll hideTrack variant="Background" visibility="Hover">
<Text <Text as="pre" className={classNames(css.TextViewerPre, `language-${langName}`)}>
as="pre"
className={classNames(css.TextViewerPre, `language-${mimeTypeToExt(mimeType)}`)}
>
<ErrorBoundary fallback={<code>{text}</code>}> <ErrorBoundary fallback={<code>{text}</code>}>
<Suspense fallback={<code>{text}</code>}> <Suspense fallback={<code>{text}</code>}>
<ReactPrism>{(codeRef) => <code ref={codeRef}>{text}</code>}</ReactPrism> <ReactPrism>{(codeRef) => <code ref={codeRef}>{text}</code>}</ReactPrism>

View file

@ -23,7 +23,12 @@ import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { getFileSrcUrl, getSrcFile } from './util'; import { getFileSrcUrl, getSrcFile } from './util';
import { bytesToSize } from '../../../utils/common'; import { bytesToSize } from '../../../utils/common';
import { TextViewer } from '../../../components/text-viewer'; import { TextViewer } from '../../../components/text-viewer';
import { READABLE_TEXT_MIME_TYPES } from '../../../utils/mimeTypes'; import {
READABLE_EXT_TO_MIME_TYPE,
READABLE_TEXT_MIME_TYPES,
getFileNameExt,
mimeTypeToExt,
} from '../../../utils/mimeTypes';
import { PdfViewer } from '../../../components/Pdf-viewer'; import { PdfViewer } from '../../../components/Pdf-viewer';
import * as css from './styles.css'; import * as css from './styles.css';
@ -103,7 +108,11 @@ function ReadTextFile({ body, mimeType, url, encInfo }: Omit<FileContentProps, '
<TextViewer <TextViewer
name={body} name={body}
text={textState.data} text={textState.data}
mimeType={mimeType} langName={
READABLE_TEXT_MIME_TYPES.includes(mimeType)
? mimeTypeToExt(mimeType)
: mimeTypeToExt(READABLE_EXT_TO_MIME_TYPE[getFileNameExt(body)] ?? mimeType)
}
requestClose={() => setTextViewer(false)} requestClose={() => setTextViewer(false)}
/> />
</Modal> </Modal>
@ -247,7 +256,8 @@ function DownloadFile({ body, mimeType, url, info, encInfo }: FileContentProps)
export const FileContent = as<'div', FileContentProps>( export const FileContent = as<'div', FileContentProps>(
({ body, mimeType, url, info, encInfo, ...props }, ref) => ( ({ body, mimeType, url, info, encInfo, ...props }, ref) => (
<Box direction="Column" gap="300" {...props} ref={ref}> <Box direction="Column" gap="300" {...props} ref={ref}>
{READABLE_TEXT_MIME_TYPES.includes(mimeType) && ( {(READABLE_TEXT_MIME_TYPES.includes(mimeType) ||
READABLE_EXT_TO_MIME_TYPE[getFileNameExt(body)]) && (
<ReadTextFile body={body} mimeType={mimeType} url={url} encInfo={encInfo} /> <ReadTextFile body={body} mimeType={mimeType} url={url} encInfo={encInfo} />
)} )}
{mimeType === 'application/pdf' && ( {mimeType === 'application/pdf' && (

View file

@ -246,7 +246,7 @@ export const MessageSourceCodeItem = as<
<Modal variant="Surface" size="500"> <Modal variant="Surface" size="500">
<TextViewer <TextViewer
name="Source Code" name="Source Code"
mimeType="application/json" langName="json"
text={text} text={text}
requestClose={handleClose} requestClose={handleClose}
/> />

View file

@ -57,6 +57,43 @@ export const READABLE_TEXT_MIME_TYPES = [
...TEXT_MIME_TYPE, ...TEXT_MIME_TYPE,
]; ];
export const READABLE_EXT_TO_MIME_TYPE: Record<string, string> = {
go: 'text/go',
rs: 'text/rust',
py: 'text/python',
swift: 'text/swift',
c: 'text/c',
cpp: 'text/cpp',
java: 'text/java',
kt: 'text/kotlin',
lua: 'text/lua',
php: 'text/php',
ts: 'text/typescript',
js: 'text/javascript',
jsx: 'text/jsx',
tsx: 'text/tsx',
html: 'text/html',
xhtml: 'text/xhtml',
xht: 'text/xhtml',
css: 'text/css',
scss: 'text/scss',
sass: 'text/sass',
json: 'text/json',
md: 'text/markdown',
yaml: 'text/yaml',
yni: 'text/yni',
xml: 'text/xml',
txt: 'text/plain',
text: 'text/plain',
conf: 'text/conf',
cfg: 'text/conf',
cnf: 'text/conf',
log: 'text/log',
me: 'text/me',
cvs: 'text/cvs',
tvs: 'text/tvs',
};
export const ALLOWED_BLOB_MIME_TYPES = [ export const ALLOWED_BLOB_MIME_TYPES = [
...IMAGE_MIME_TYPES, ...IMAGE_MIME_TYPES,
...VIDEO_MIME_TYPES, ...VIDEO_MIME_TYPES,
@ -92,3 +129,7 @@ export const mimeTypeToExt = (mimeType: string): string => {
const extStart = mimeType.lastIndexOf('/') + 1; const extStart = mimeType.lastIndexOf('/') + 1;
return mimeType.slice(extStart); return mimeType.slice(extStart);
}; };
export const getFileNameExt = (fileName: string): string => {
const extStart = fileName.lastIndexOf('.') + 1;
return fileName.slice(extStart);
};