Commit 5cb27e9f authored by Douwe Maan's avatar Douwe Maan

Add rich blob viewers

parent f112a03c
......@@ -134,12 +134,15 @@ module BlobHelper
end
end
def blob_raw_url
namespace_project_raw_path(@project.namespace, @project, @id)
end
# SVGs can contain malicious JavaScript; only include whitelisted
# elements and attributes. Note that this whitelist is by no means complete
# and may omit some elements.
def sanitize_svg(blob)
blob.data = Gitlab::Sanitizers::SVG.clean(blob.data)
blob
def sanitize_svg_data(data)
Gitlab::Sanitizers::SVG.clean(data)
end
# If we blindly set the 'real' content type when serving a Git blob we
......
......@@ -6,6 +6,14 @@ class Blob < SimpleDelegator
MAXIMUM_TEXT_HIGHLIGHT_SIZE = 1.megabyte
RICH_VIEWERS = [
BlobViewer::Image,
BlobViewer::PDF,
BlobViewer::Sketch,
BlobViewer::BinarySTL,
BlobViewer::TextSTL,
BlobViewer::Notebook,
BlobViewer::SVG,
BlobViewer::Markup,
].freeze
attr_reader :project
......
module BlobViewer
class BinarySTL < Base
include Rich
include ClientSide
self.partial_name = 'stl'
self.extensions = %w(stl)
self.text_based = false
end
end
module BlobViewer
class Image < Base
include Rich
include ClientSide
self.partial_name = 'image'
self.extensions = UploaderHelper::IMAGE_EXT
self.text_based = false
self.switcher_icon = 'picture-o'
self.switcher_title = 'image'
end
end
module BlobViewer
class Markup < Base
include Rich
include ServerSide
self.partial_name = 'markup'
self.extensions = Gitlab::MarkupHelper::EXTENSIONS
self.text_based = true
end
end
module BlobViewer
class Notebook < Base
include Rich
include ClientSide
self.partial_name = 'notebook'
self.extensions = %w(ipynb)
self.text_based = true
self.switcher_icon = 'file-text-o'
self.switcher_title = 'notebook'
end
end
module BlobViewer
class PDF < Base
include Rich
include ClientSide
self.partial_name = 'pdf'
self.extensions = %w(pdf)
self.text_based = false
self.switcher_icon = 'file-pdf-o'
self.switcher_title = 'PDF'
end
end
module BlobViewer
module Rich
extend ActiveSupport::Concern
included do
self.type = :rich
self.switcher_icon = 'file-text-o'
self.switcher_title = 'rendered file'
end
end
end
module BlobViewer
module ServerSide
extend ActiveSupport::Concern
included do
self.client_side = false
self.max_size = 2.megabytes
self.absolute_max_size = 5.megabytes
end
end
end
module BlobViewer
class Sketch < Base
include Rich
include ClientSide
self.partial_name = 'sketch'
self.extensions = %w(sketch)
self.text_based = false
self.switcher_icon = 'file-image-o'
self.switcher_title = 'preview'
end
end
module BlobViewer
class SVG < Base
include Rich
include ServerSide
self.partial_name = 'svg'
self.extensions = %w(svg)
self.text_based = true
self.switcher_icon = 'picture-o'
self.switcher_title = 'image'
end
end
module BlobViewer
class TextSTL < Base
include Rich
include ClientSide
self.partial_name = 'stl'
self.extensions = %w(stl)
self.text_based = true
end
end
.file-content.image_file
%img{ src: namespace_project_raw_path(@project.namespace, @project, @id), alt: blob.name }
- if blob.size_within_svg_limits?
-# We need to scrub SVG but we cannot do so in the RawController: it would
-# be wrong/strange if RawController modified the data.
- blob.load_all_data!(@repository)
- blob = sanitize_svg(blob)
.file-content.image_file
%img{ src: "data:#{blob.mime_type};base64,#{Base64.encode64(blob.data)}", alt: blob.name }
- else
= render 'too_large'
.file-content.image_file
%img{ src: blob_raw_url, alt: viewer.blob.name }
- blob = viewer.blob
.file-content.wiki
= render_markup(blob.name, blob.data)
......@@ -2,4 +2,4 @@
= page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('notebook_viewer')
.file-content#js-notebook-viewer{ data: { endpoint: namespace_project_raw_path(@project.namespace, @project, @id) } }
.file-content#js-notebook-viewer{ data: { endpoint: blob_raw_url } }
......@@ -2,4 +2,4 @@
= page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('pdf_viewer')
.file-content#js-pdf-viewer{ data: { endpoint: namespace_project_raw_path(@project.namespace, @project, @id) } }
.file-content#js-pdf-viewer{ data: { endpoint: blob_raw_url } }
......@@ -2,6 +2,6 @@
= page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('sketch_viewer')
.file-content#js-sketch-viewer{ data: { endpoint: namespace_project_raw_path(@project.namespace, @project, @id) } }
.file-content#js-sketch-viewer{ data: { endpoint: blob_raw_url } }
.js-loading-icon.text-center.prepend-top-default.append-bottom-default.js-loading-icon{ 'aria-label' => 'Loading Sketch preview' }
= icon('spinner spin 2x', 'aria-hidden' => 'true');
......@@ -2,7 +2,7 @@
= page_specific_javascript_bundle_tag('stl_viewer')
.file-content.is-stl-loading
.text-center#js-stl-viewer{ data: { endpoint: namespace_project_raw_path(@project.namespace, @project, @id) } }
.text-center#js-stl-viewer{ data: { endpoint: blob_raw_url } }
= icon('spinner spin 2x', class: 'prepend-top-default append-bottom-default', 'aria-hidden' => 'true', 'aria-label' => 'Loading')
.text-center.prepend-top-default.append-bottom-default.stl-controls
.btn-group
......
- blob = viewer.blob
- data = sanitize_svg_data(blob.data)
.file-content.image_file
%img{ src: "data:#{blob.mime_type};base64,#{Base64.encode64(data)}", alt: blob.name }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment