github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/webui/src/pages/repositories/repository/fileRenderers/index.tsx (about) 1 import React, {FC} from "react"; 2 import SyntaxHighlighter from "react-syntax-highlighter"; 3 import {FileType, RendererComponent} from "./types"; 4 import {DuckDBRenderer} from "./data"; 5 import { 6 ImageRenderer, 7 IpynbRenderer, 8 MarkdownRenderer, 9 ObjectTooLarge, 10 PDFRenderer, 11 TextDownloader, 12 TextRenderer, 13 UnsupportedFileType 14 } from "./simple"; 15 16 17 const MAX_FILE_SIZE = 20971520; // 20MiB 18 19 20 export const Renderers: {[fileType in FileType] : FC<RendererComponent> } = { 21 [FileType.DATA]: props => ( 22 <DuckDBRenderer {...props}/> 23 ), 24 [FileType.MARKDOWN]: props => ( 25 <TextDownloader {...props} onReady={text => 26 <MarkdownRenderer {...props} text={text}/> 27 } /> 28 ), 29 [FileType.IPYNB]: props => ( 30 <TextDownloader {...props} onReady={text => 31 <IpynbRenderer {...props} text={text}/>} 32 /> 33 ), 34 [FileType.IMAGE]: props => ( 35 <ImageRenderer {...props}/> 36 ), 37 [FileType.PDF]: props => ( 38 <PDFRenderer {...props}/> 39 ), 40 [FileType.TEXT]: props => ( 41 <TextDownloader {...props} onReady={text => 42 <TextRenderer {...props} text={text}/>} 43 /> 44 ), 45 [FileType.UNSUPPORTED]: props => ( 46 <UnsupportedFileType {...props}/> 47 ), 48 [FileType.TOO_LARGE]: props => ( 49 <ObjectTooLarge {...props}/> 50 ), 51 } 52 53 export const guessLanguage = (extension: string | null, contentType: string | null) => { 54 if (extension && SyntaxHighlighter.supportedLanguages.includes(extension)) { 55 return extension; 56 } 57 if (contentType) { 58 if (contentType.startsWith("application/x-")) { 59 let lang = contentType.substring(14); 60 if (lang.endsWith('-script')) { 61 lang = lang.substring(0, lang.length - 7); 62 } 63 if (SyntaxHighlighter.supportedLanguages.includes(lang)) { 64 return lang; 65 } 66 } 67 if (contentType.startsWith("application/")) { 68 const lang = contentType.substring(12); 69 if (SyntaxHighlighter.supportedLanguages.includes(lang)) { 70 return lang; 71 } 72 } 73 if (contentType.startsWith("text/x-")) { 74 let lang = contentType.substring(7); 75 if (lang.endsWith('-script')) { 76 lang = lang.substring(0, lang.length - 7); 77 } 78 if (SyntaxHighlighter.supportedLanguages.includes(lang)) { 79 return lang; 80 } 81 } 82 if (contentType.startsWith("text/")) { 83 const lang = contentType.substring(5); 84 if (SyntaxHighlighter.supportedLanguages.includes(lang)) { 85 return lang; 86 } 87 return "plaintext" 88 } 89 } 90 return null; 91 } 92 93 94 export function guessType(contentType: string | null, fileExtension: string | null): FileType { 95 switch (contentType) { 96 case 'application/x-yaml': 97 case 'application/yaml': 98 case 'application/x-yml': 99 case 'application/yml': 100 case 'application/x-json': 101 case 'application/json': 102 case 'application/x-toml': 103 case 'application/toml': 104 return FileType.TEXT 105 case 'application/x-ipynb+json': 106 case 'application/x-ipynb': 107 case 'application/ipynb': 108 return FileType.IPYNB 109 case 'text/markdown': 110 return FileType.MARKDOWN 111 case 'image/jpeg': 112 case 'image/jpg': 113 case 'image/png': 114 case 'image/gif': 115 case 'image/webm': 116 return FileType.IMAGE 117 case 'application/pdf': 118 case 'application/x-pdf': 119 return FileType.PDF 120 } 121 switch (fileExtension) { 122 case 'parquet': 123 case 'csv': 124 case 'tsv': 125 return FileType.DATA 126 case 'md': 127 return FileType.MARKDOWN 128 case 'ipynb': 129 case 'pynb': 130 return FileType.IPYNB 131 case 'png': 132 case 'jpeg': 133 case 'jpg': 134 case 'webm': 135 case 'gif': 136 return FileType.IMAGE 137 case 'pdf': 138 return FileType.PDF 139 case 'txt': 140 case 'text': 141 case 'yaml': 142 case 'yml': 143 case 'json': 144 return FileType.TEXT 145 } 146 if (guessLanguage(fileExtension, contentType)) 147 return FileType.TEXT 148 return FileType.UNSUPPORTED 149 } 150 151 export const ObjectRenderer: FC<RendererComponent> = (props: RendererComponent) => { 152 const fileType = guessType(props.contentType, props.fileExtension) 153 if (fileType !== FileType.DATA && props.sizeBytes > MAX_FILE_SIZE) 154 return Renderers[FileType.TOO_LARGE](props) 155 return Renderers[fileType](props) 156 }