Refactor Blob and add BlobViewer::Base

This commit is contained in:
Douwe Maan 2017-04-13 12:14:08 -05:00
parent 7f625f06d3
commit 13891a03c7
2 changed files with 161 additions and 66 deletions

View File

@ -3,8 +3,10 @@ class Blob < SimpleDelegator
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
# The maximum size of an SVG that can be displayed.
MAXIMUM_SVG_SIZE = 2.megabytes
MAXIMUM_TEXT_HIGHLIGHT_SIZE = 1.megabyte
RICH_VIEWERS = [
].freeze
attr_reader :project
@ -43,82 +45,94 @@ class Blob < SimpleDelegator
end
def no_highlighting?
size && size > 1.megabyte
size && size > MAXIMUM_TEXT_HIGHLIGHT_SIZE
end
def only_display_raw?
def too_large?
size && truncated?
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
extname.downcase.delete('.')
end
def svg?
text? && language && language.name == 'SVG'
end
def pdf?
extension == 'pdf'
end
def ipython_notebook?
text? && language&.name == 'Jupyter Notebook'
end
def sketch?
binary? && extension == 'sketch'
end
def stl?
extension == 'stl'
end
def markup?
text? && Gitlab::MarkupHelper.markup?(name)
end
def size_within_svg_limits?
size <= MAXIMUM_SVG_SIZE
@extension ||= extname.downcase.delete('.')
end
def video?
UploaderHelper::VIDEO_EXT.include?(extname.downcase.delete('.'))
UploaderHelper::VIDEO_EXT.include?(extension)
end
def to_partial_path(project)
if lfs_pointer?
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
elsif text?
if only_display_raw?
'too_large'
else
'text'
end
def readable_text?
text? && !valid_lfs_pointer? && !too_large?
end
def valid_lfs_pointer?
lfs_pointer? && project.lfs_enabled?
end
def invalid_lfs_pointer?
lfs_pointer? && !project.lfs_enabled?
end
def simple_viewer_class
if empty?
BlobViewer::Empty
elsif raw_binary?
BlobViewer::Download
else # text
BlobViewer::Text
end
end
def rich_viewer_class
if invalid_lfs_pointer? || empty?
nil
else
'download'
rich_viewers_classes.find { |viewer_class| viewer_class.can_render?(self) }
end
end
def simple_viewer
@simple_viewer ||= simple_viewer_class.new(self)
end
def rich_viewer
return @rich_viewer if defined?(@rich_viewer)
@rich_viewer ||= rich_viewer_class&.new(self)
end
def rendered_as_text?(override_max_size: false)
simple_viewer.is_a?(BlobViewer::Text) && !simple_viewer.render_error(override_max_size: override_max_size)
end
def show_viewer_switcher?
simple_viewer.is_a?(BlobViewer::Text) && rich_viewer
end
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

View File

@ -0,0 +1,81 @@
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