From 80c0f9a8f6779b76e090456b8ea29d486179b35c Mon Sep 17 00:00:00 2001
From: btzr-io <btzr.io@gmail.com>
Date: Wed, 1 Aug 2018 22:56:17 -0600
Subject: [PATCH] extend support for human-readable files

---
 src/renderer/component/fileRender/view.jsx    | 16 +++++++++++++--
 .../component/fileViewer/internal/player.jsx  |  2 +-
 src/renderer/component/viewers/codeViewer.jsx | 12 +++++++++--
 src/renderer/component/viewers/htmlViewer.jsx | 20 +++++++++++++++++++
 src/renderer/page/file/view.jsx               |  3 ++-
 src/renderer/util/getMediaType.js             |  1 +
 6 files changed, 48 insertions(+), 6 deletions(-)
 create mode 100644 src/renderer/component/viewers/htmlViewer.jsx

diff --git a/src/renderer/component/fileRender/view.jsx b/src/renderer/component/fileRender/view.jsx
index 34194b213..ce0494f6a 100644
--- a/src/renderer/component/fileRender/view.jsx
+++ b/src/renderer/component/fileRender/view.jsx
@@ -5,6 +5,7 @@ import PdfViewer from 'component/viewers/pdfViewer';
 import ThreeViewer from 'component/viewers/threeViewer';
 import DocumentViewer from 'component/viewers/documentViewer';
 import DocxViewer from 'component/viewers/docxViewer';
+import HtmlViewer from 'component/viewers/htmlViewer';
 
 type Props = {
   mediaType: string,
@@ -25,10 +26,12 @@ class FileRender extends React.PureComponent<Props> {
     // Extract relevant data to render file
     const { blob, stream, fileName, fileType, contentType, downloadPath } = source;
 
+    // Human-readable files (scripts and plain-text files)
+    const readableFiles = ['text', 'document', 'script'];
+
     // Supported mediaTypes
     const mediaTypes = {
       '3D-file': <ThreeViewer source={{ fileType, downloadPath }} theme={currentTheme} />,
-      document: <DocumentViewer source={{ stream, fileType, contentType }} theme={currentTheme} />,
       // Add routes to viewer...
     };
 
@@ -36,10 +39,19 @@ class FileRender extends React.PureComponent<Props> {
     const fileTypes = {
       pdf: <PdfViewer source={downloadPath} />,
       docx: <DocxViewer source={downloadPath} />,
+      html: <HtmlViewer source={downloadPath} />,
       // Add routes to viewer...
     };
 
-    const viewer = mediaType && source && (fileTypes[fileType] || mediaTypes[mediaType]);
+    // Check for a valid fileType or mediaType
+    let viewer = fileTypes[fileType] || mediaTypes[mediaType];
+
+    // Check for Human-readable files
+    if (!viewer && readableFiles.includes(mediaType)) {
+      viewer = <DocumentViewer source={{ stream, fileType, contentType }} theme={currentTheme} />;
+    }
+
+    // Message Error
     const unsupportedMessage = __("Sorry, looks like we can't preview this file.");
     const unsupported = <LoadingScreen status={unsupportedMessage} spinner={false} />;
 
diff --git a/src/renderer/component/fileViewer/internal/player.jsx b/src/renderer/component/fileViewer/internal/player.jsx
index 1482146bf..375f8d152 100644
--- a/src/renderer/component/fileViewer/internal/player.jsx
+++ b/src/renderer/component/fileViewer/internal/player.jsx
@@ -11,7 +11,7 @@ import LoadingScreen from 'component/common/loading-screen';
 
 class MediaPlayer extends React.PureComponent {
   static MP3_CONTENT_TYPES = ['audio/mpeg3', 'audio/mpeg'];
-  static FILE_MEDIA_TYPES = ['e-book', 'comic-book', 'document', '3D-file'];
+  static FILE_MEDIA_TYPES = ['text', 'script', 'e-book', 'comic-book', 'document', '3D-file'];
 
   constructor(props) {
     super(props);
diff --git a/src/renderer/component/viewers/codeViewer.jsx b/src/renderer/component/viewers/codeViewer.jsx
index c076ddac2..1d5164468 100644
--- a/src/renderer/component/viewers/codeViewer.jsx
+++ b/src/renderer/component/viewers/codeViewer.jsx
@@ -8,9 +8,17 @@ import { openSnippetMenu, stopContextMenu } from 'util/contextMenu';
 import 'codemirror/addon/selection/mark-selection';
 
 // Syntax mode
-import 'codemirror/mode/javascript/javascript';
-import 'codemirror/mode/markdown/markdown';
+import 'codemirror/mode/go/go';
+import 'codemirror/mode/jsx/jsx';
+import 'codemirror/mode/css/css';
 import 'codemirror/mode/xml/xml';
+import 'codemirror/mode/php/php';
+import 'codemirror/mode/ruby/ruby';
+import 'codemirror/mode/clike/clike';
+import 'codemirror/mode/shell/shell';
+import 'codemirror/mode/python/python';
+import 'codemirror/mode/markdown/markdown';
+import 'codemirror/mode/javascript/javascript';
 
 type Props = {
   theme: string,
diff --git a/src/renderer/component/viewers/htmlViewer.jsx b/src/renderer/component/viewers/htmlViewer.jsx
new file mode 100644
index 000000000..029d7e15d
--- /dev/null
+++ b/src/renderer/component/viewers/htmlViewer.jsx
@@ -0,0 +1,20 @@
+// @flow
+import React from 'react';
+import { stopContextMenu } from 'util/contextMenu';
+
+type Props = {
+  source: string,
+};
+
+class HtmlViewer extends React.PureComponent<Props> {
+  render() {
+    const { source } = this.props;
+    return (
+      <div className="file-render__viewer" onContextMenu={stopContextMenu}>
+        <iframe sandbox="" title={__('File preview')} src={`file://${source}`} />
+      </div>
+    );
+  }
+}
+
+export default HtmlViewer;
diff --git a/src/renderer/page/file/view.jsx b/src/renderer/page/file/view.jsx
index 1c29794ac..8c8833dd4 100644
--- a/src/renderer/page/file/view.jsx
+++ b/src/renderer/page/file/view.jsx
@@ -55,8 +55,9 @@ class FilePage extends React.Component<Props> {
     'text',
     'model',
     'image',
-    '3D-file',
+    'script',
     'document',
+    '3D-file',
     // Bypass unplayable files
     // TODO: Find a better way to detect supported types
     'application',
diff --git a/src/renderer/util/getMediaType.js b/src/renderer/util/getMediaType.js
index 49ca3e735..a028f6655 100644
--- a/src/renderer/util/getMediaType.js
+++ b/src/renderer/util/getMediaType.js
@@ -3,6 +3,7 @@ import mime from 'mime';
 const formats = [
   [/\.(mp4|m4v|webm|flv|f4v|ogv)$/i, 'video'],
   [/\.(mp3|m4a|aac|wav|flac|ogg|opus)$/i, 'audio'],
+  [/\.(h|go|ja|java|js|jsx|c|cpp|cs|css|rb|scss|sh|php|py)$/i, 'script'],
   [/\.(json|csv|txt|log|md|markdown|docx|pdf|xml|yml|yaml)$/i, 'document'],
   [/\.(pdf|odf|doc|docx|epub|org|rtf)$/i, 'e-book'],
   [/\.(stl|obj|fbx|gcode)$/i, '3D-file'],