Path: blob/master/src/packages/next/components/share/file-contents.tsx
1450 views
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import Markdown from "@cocalc/frontend/editors/slate/static-markdown";6import {7isAudio,8isCodemirror,9isHTML,10isImage,11isMarkdown,12isVideo,13} from "@cocalc/frontend/file-extensions";14import Slides from "@cocalc/frontend/frame-editors/slides-editor/share";15import Whiteboard from "@cocalc/frontend/frame-editors/whiteboard-editor/share/index";16import JupyterNotebook from "@cocalc/frontend/jupyter/nbviewer/nbviewer";17import { FileContext } from "@cocalc/frontend/lib/file-context";18import A from "components/misc/A";19import { isIOS, isSafari } from "lib/share/feature";20import rawURL from "lib/share/raw-url";21import getUrlTransform from "lib/share/url-transform";22import { containingPath, getExtension } from "lib/share/util";23import useCustomize from "lib/use-customize";24import getAnchorTagComponent from "./anchor-tag-component";25import CodeMirror from "./codemirror";26import SageWorksheet from "./sage-worksheet";2728import type { JSX } from "react";2930interface Props {31id: string;32content?: string;33relativePath: string;34path: string;35truncated?: boolean;36jupyter_api?: boolean;37}3839export default function FileContents({40id,41content,42path,43relativePath,44jupyter_api,45}: Props): JSX.Element {46const filename = relativePath ? relativePath : path;47const ext = getExtension(filename);48const raw = rawURL({ id, path, relativePath });49const { jupyterApiEnabled } = useCustomize();5051const withFileContext = (x) => {52const relPath = containingPath(relativePath);53const value = {54urlTransform: getUrlTransform({ id, path, relativePath: relPath }),55AnchorTagComponent: getAnchorTagComponent({ id, relativePath: relPath }),56jupyterApiEnabled: jupyterApiEnabled && jupyter_api,57noSanitize: false, // We **MUST** sanitize, since we users could launch XSS attacks, mess up style, etc.,58// This will, of course, break things, in which case users will have to open them in their own projects.59};60return <FileContext.Provider value={value}>{x}</FileContext.Provider>;61};6263if (isImage(ext)) {64return <img src={raw} style={{ maxWidth: "100%" }} />;65} else if (isVideo(ext)) {66return (67<video68controls={true}69autoPlay={true}70loop={true}71style={{ width: "100%", height: "auto" }}72src={raw}73/>74);75} else if (isAudio(ext)) {76return <audio src={raw} autoPlay={true} controls={true} loop={false} />;77} else if (ext === "pdf") {78// iOS and iPADOS does not have any way to embed PDF's in pages.79// I think pretty much every other web browser does, though80// strangely even desktop Safari seems often broken, so we also block that.81// Amazingly, nextjs handles this sort of thing fine!82return isIOS() || isSafari() ? (83<h1 style={{ textAlign: "center", margin: "30px" }}>84<A href={raw} external>85View this PDF...86</A>87</h1>88) : (89<embed90style={{ width: "100%", height: "100vh" }}91src={raw}92type="application/pdf"93/>94);95} else if (content == null) {96return (97<h1 style={{ textAlign: "center", margin: "30px" }}>98<A href={raw} external>99Open or Download...100</A>{" "}101</h1>102);103} else if (isCodemirror(ext)) {104return <CodeMirror content={content} filename={filename} />;105} else if (isMarkdown(ext)) {106return withFileContext(<Markdown value={content} />);107} else if (isHTML(ext)) {108// We use a sandboxed iframe since it is much more likely to be109// useful to users than our HTML component. Most use of our110// HTML component with math rendering, etc., is much better done111// via a Markdown file. This makes it easy to show, e.g.,112// static k3d plots, which CUP is doing. HTML files tend to113// be independent of cocalc anyways.114return (115<iframe116srcDoc={content}117style={{ width: "100%", height: "100vh" }}118sandbox="allow-scripts"119/>120);121// return withFileContext(122// <HTML value={content} style={{ width: "100%", height: "100vh" }} />123// );124} else if (ext == "sagews") {125return withFileContext(<SageWorksheet content={content} />);126} else if (ext == "ipynb") {127return withFileContext(<JupyterNotebook content={content} />);128} else if (ext == "board") {129return withFileContext(<Whiteboard content={content} />);130} else if (ext == "slides") {131return withFileContext(<Slides content={content} />);132}133return <pre>{content}</pre>;134}135136137