Commit 13891a03 authored by Douwe Maan's avatar Douwe Maan

Refactor Blob and add BlobViewer::Base

parent 7f625f06
...@@ -3,8 +3,10 @@ class Blob < SimpleDelegator ...@@ -3,8 +3,10 @@ class Blob < SimpleDelegator
CACHE_TIME = 60 # Cache raw blobs referred to by a (mutable) ref for 1 minute CACHE_TIME = 60 # Cache raw blobs referred to by a (mutable) ref for 1 minute
CACHE_TIME_IMMUTABLE = 3600 # Cache blobs referred to by an immutable reference for 1 hour CACHE_TIME_IMMUTABLE = 3600 # Cache blobs referred to by an immutable reference for 1 hour
# The maximum size of an SVG that can be displayed. MAXIMUM_TEXT_HIGHLIGHT_SIZE = 1.megabyte
MAXIMUM_SVG_SIZE = 2.megabytes
RICH_VIEWERS = [
].freeze
attr_reader :project attr_reader :project
...@@ -43,82 +45,94 @@ class Blob < SimpleDelegator ...@@ -43,82 +45,94 @@ class Blob < SimpleDelegator
end end
def no_highlighting? def no_highlighting?
size && size > 1.megabyte size && size > MAXIMUM_TEXT_HIGHLIGHT_SIZE
end end
def only_display_raw? def too_large?
size && truncated? size && truncated?
end end
def raw_size
if valid_lfs_pointer?
lfs_size
else
size
end
end
def raw_binary?
if valid_lfs_pointer?
!rich_viewer&.text_based?
else
binary?
end
end
def extension def extension
extname.downcase.delete('.') @extension ||= extname.downcase.delete('.')
end end
def svg? def video?
text? && language && language.name == 'SVG' UploaderHelper::VIDEO_EXT.include?(extension)
end end
def pdf? def readable_text?
extension == 'pdf' text? && !valid_lfs_pointer? && !too_large?
end end
def ipython_notebook? def valid_lfs_pointer?
text? && language&.name == 'Jupyter Notebook' lfs_pointer? && project.lfs_enabled?
end end
def sketch? def invalid_lfs_pointer?
binary? && extension == 'sketch' lfs_pointer? && !project.lfs_enabled?
end end
def stl? def simple_viewer_class
extension == 'stl' if empty?
BlobViewer::Empty
elsif raw_binary?
BlobViewer::Download
else # text
BlobViewer::Text
end
end end
def markup? def rich_viewer_class
text? && Gitlab::MarkupHelper.markup?(name) if invalid_lfs_pointer? || empty?
nil
else
rich_viewers_classes.find { |viewer_class| viewer_class.can_render?(self) }
end
end end
def size_within_svg_limits? def simple_viewer
size <= MAXIMUM_SVG_SIZE @simple_viewer ||= simple_viewer_class.new(self)
end end
def video? def rich_viewer
UploaderHelper::VIDEO_EXT.include?(extname.downcase.delete('.')) return @rich_viewer if defined?(@rich_viewer)
@rich_viewer ||= rich_viewer_class&.new(self)
end end
def to_partial_path(project) def rendered_as_text?(override_max_size: false)
if lfs_pointer? simple_viewer.is_a?(BlobViewer::Text) && !simple_viewer.render_error(override_max_size: override_max_size)
if project.lfs_enabled?
'download'
else
'text'
end
elsif image?
'image'
elsif svg?
'svg'
elsif pdf?
'pdf'
elsif ipython_notebook?
'notebook'
elsif sketch?
'sketch'
elsif stl?
'stl'
elsif markup?
if only_display_raw?
'too_large'
else
'markup'
end end
elsif text?
if only_display_raw? def show_viewer_switcher?
'too_large' simple_viewer.is_a?(BlobViewer::Text) && rich_viewer
else
'text'
end end
else
'download' private
def rich_viewers_classes
if valid_lfs_pointer?
RICH_VIEWERS
elsif binary?
RICH_VIEWERS.reject(&:text_based?)
else # text
RICH_VIEWERS.select(&:text_based?)
end end
end end
end end
module BlobViewer
class Base
class_attribute :partial_name, :type, :extensions, :client_side, :text_based, :switcher_icon, :switcher_title, :max_size, :absolute_max_size
delegate :partial_path, :rich?, :simple?, :client_side?, :text_based?, to: :class
attr_reader :blob
def initialize(blob)
@blob = blob
end
def self.partial_path
"projects/blob/viewers/#{partial_name}"
end
def self.rich?
type == :rich
end
def self.simple?
type == :simple
end
def self.client_side?
client_side
end
def server_side?
!client_side?
end
def self.text_based?
text_based
end
def self.can_render?(blob)
!extensions || extensions.include?(blob.extension)
end
def can_override_max_size?
too_large? && !too_large?(override_max_size: true)
end
def relevant_max_size
if too_large?(override_max_size: true)
absolute_max_size
elsif too_large?
max_size
end
end
def render_error(override_max_size: false)
if too_large?(override_max_size: override_max_size)
:too_large
elsif server_side_but_stored_in_lfs?
:server_side_but_stored_in_lfs
end
end
def prepare!
if server_side? && blob.project
blob.load_all_data!(blob.project.repository)
end
end
private
def too_large?(override_max_size: false)
if override_max_size
blob.raw_size > absolute_max_size
else
blob.raw_size > max_size
end
end
def server_side_but_stored_in_lfs?
!client_side? && blob.valid_lfs_pointer?
end
end
end
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