CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

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