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  }