Refactor Blob and add BlobViewer::Base
This commit is contained in:
parent
7f625f06d3
commit
13891a03c7
|
@ -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
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def video?
|
def video?
|
||||||
UploaderHelper::VIDEO_EXT.include?(extname.downcase.delete('.'))
|
UploaderHelper::VIDEO_EXT.include?(extension)
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_partial_path(project)
|
def readable_text?
|
||||||
if lfs_pointer?
|
text? && !valid_lfs_pointer? && !too_large?
|
||||||
if project.lfs_enabled?
|
end
|
||||||
'download'
|
|
||||||
else
|
def valid_lfs_pointer?
|
||||||
'text'
|
lfs_pointer? && project.lfs_enabled?
|
||||||
end
|
end
|
||||||
elsif image?
|
|
||||||
'image'
|
def invalid_lfs_pointer?
|
||||||
elsif svg?
|
lfs_pointer? && !project.lfs_enabled?
|
||||||
'svg'
|
end
|
||||||
elsif pdf?
|
|
||||||
'pdf'
|
def simple_viewer_class
|
||||||
elsif ipython_notebook?
|
if empty?
|
||||||
'notebook'
|
BlobViewer::Empty
|
||||||
elsif sketch?
|
elsif raw_binary?
|
||||||
'sketch'
|
BlobViewer::Download
|
||||||
elsif stl?
|
else # text
|
||||||
'stl'
|
BlobViewer::Text
|
||||||
elsif markup?
|
end
|
||||||
if only_display_raw?
|
end
|
||||||
'too_large'
|
|
||||||
else
|
def rich_viewer_class
|
||||||
'markup'
|
if invalid_lfs_pointer? || empty?
|
||||||
end
|
nil
|
||||||
elsif text?
|
|
||||||
if only_display_raw?
|
|
||||||
'too_large'
|
|
||||||
else
|
|
||||||
'text'
|
|
||||||
end
|
|
||||||
else
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue