import { Box, Chip, Header, Icon, IconButton, Icons, Scroll, Text, as } from 'folds';
import { ErrorBoundary } from 'react-error-boundary';
import * as css from './TextViewer.css';
-import { mimeTypeToExt } from '../../utils/mimeTypes';
import { copyToClipboard } from '../../utils/dom';
const ReactPrism = lazy(() => import('../../plugins/react-prism/ReactPrism'));
export type TextViewerProps = {
name: string;
text: string;
- mimeType: string;
+ langName: string;
requestClose: () => void;
};
export const TextViewer = as<'div', TextViewerProps>(
- ({ className, name, text, mimeType, requestClose, ...props }, ref) => {
+ ({ className, name, text, langName, requestClose, ...props }, ref) => {
const handleCopy = () => {
copyToClipboard(text);
};
alignItems="Center"
>
<Scroll hideTrack variant="Background" visibility="Hover">
- <Text
- as="pre"
- className={classNames(css.TextViewerPre, `language-${mimeTypeToExt(mimeType)}`)}
- >
+ <Text as="pre" className={classNames(css.TextViewerPre, `language-${langName}`)}>
<ErrorBoundary fallback={<code>{text}</code>}>
<Suspense fallback={<code>{text}</code>}>
<ReactPrism>{(codeRef) => <code ref={codeRef}>{text}</code>}</ReactPrism>
import { getFileSrcUrl, getSrcFile } from './util';
import { bytesToSize } from '../../../utils/common';
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 * as css from './styles.css';
<TextViewer
name={body}
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)}
/>
</Modal>
export const FileContent = as<'div', FileContentProps>(
({ body, mimeType, url, info, encInfo, ...props }, 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} />
)}
{mimeType === 'application/pdf' && (
<Modal variant="Surface" size="500">
<TextViewer
name="Source Code"
- mimeType="application/json"
+ langName="json"
text={text}
requestClose={handleClose}
/>
...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 = [
...IMAGE_MIME_TYPES,
...VIDEO_MIME_TYPES,
const extStart = mimeType.lastIndexOf('/') + 1;
return mimeType.slice(extStart);
};
+export const getFileNameExt = (fileName: string): string => {
+ const extStart = fileName.lastIndexOf('.') + 1;
+ return fileName.slice(extStart);
+};