/*! * Copyright (c) 2024 PLANKA Software GmbH * Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md */ import React, { useEffect, useMemo, useState } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import Frame from 'react-frame-component'; import { Loader } from 'semantic-ui-react'; import syntaxHighlighter from '../../../lib/syntax-highlighter'; import Markdown from '../../common/Markdown'; import styles from './ContentViewer.module.scss'; const Languages = { PLAINTEXT: 'plaintext', MARKDOWN: 'markdown', }; const ContentViewer = React.memo(({ src, filename, className }) => { const [content, setContent] = useState(null); const frameStyles = useMemo( () => [ ...Array.from(document.styleSheets).flatMap((styleSheet) => Array.from(styleSheet.cssRules).map((cssRule) => cssRule.cssText), ), 'body{background:rgb(248,248,248);min-width:fit-content;overflow-x:visible}', '.frame-content{padding:40px}', '.frame-content>pre{margin:0}', '.hljs{padding:0}', '::-webkit-scrollbar{height:10px}', ], [], ); const languages = useMemo( () => syntaxHighlighter.detectLanguagesByFilename(filename), [filename], ); useEffect(() => { async function fetchFile() { await syntaxHighlighter.loadLanguages(languages); let response; try { response = await fetch(src, { credentials: 'include', }); } catch { return; } const text = await response.text(); setContent(text); } fetchFile(); }, [src, languages]); if (content === null) { return ; } let contentNode; if (languages.includes(Languages.PLAINTEXT)) { contentNode = (
        {content}
      
); } else if (languages.includes(Languages.MARKDOWN)) { contentNode = {content}; } else { const hljsResult = syntaxHighlighter.highlight(content, languages); contentNode = (
        
      
); } return ( {frameStyles.join('')}} className={classNames(styles.wrapper, className)} > {contentNode} ); }); ContentViewer.propTypes = { src: PropTypes.string.isRequired, filename: PropTypes.string.isRequired, className: PropTypes.string, }; ContentViewer.defaultProps = { className: undefined, }; export default ContentViewer;