139 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| module Gitlab
 | |
|   module Diff
 | |
|     class Line
 | |
|       # When SERIALIZE_KEYS is updated, to reset the redis cache entries you'll
 | |
|       #   need to bump the VERSION constant on Gitlab::Diff::HighlightCache
 | |
|       #
 | |
|       SERIALIZE_KEYS = %i[line_code rich_text text type index old_pos new_pos].freeze
 | |
| 
 | |
|       attr_reader :marker_ranges
 | |
|       attr_writer :text, :rich_text
 | |
|       attr_accessor :index, :old_pos, :new_pos, :line_code, :type, :embedded_image
 | |
| 
 | |
|       def initialize(text, type, index, old_pos, new_pos, parent_file: nil, line_code: nil, rich_text: nil)
 | |
|         @text = text
 | |
|         @type = type
 | |
|         @index = index
 | |
|         @old_pos = old_pos
 | |
|         @new_pos = new_pos
 | |
|         @parent_file = parent_file
 | |
|         @rich_text = rich_text
 | |
| 
 | |
|         # When line code is not provided from cache store we build it
 | |
|         # using the parent_file(Diff::File or Conflict::File).
 | |
|         @line_code = line_code || calculate_line_code
 | |
|         @marker_ranges = []
 | |
|       end
 | |
| 
 | |
|       def self.init_from_hash(hash)
 | |
|         new(hash[:text],
 | |
|           hash[:type],
 | |
|           hash[:index],
 | |
|           hash[:old_pos],
 | |
|           hash[:new_pos],
 | |
|           parent_file: hash[:parent_file],
 | |
|           line_code: hash[:line_code],
 | |
|           rich_text: hash[:rich_text])
 | |
|       end
 | |
| 
 | |
|       def self.safe_init_from_hash(hash)
 | |
|         line = hash.with_indifferent_access
 | |
|         rich_text = line[:rich_text]
 | |
|         line[:rich_text] = rich_text&.html_safe
 | |
| 
 | |
|         init_from_hash(line)
 | |
|       end
 | |
| 
 | |
|       def to_hash
 | |
|         hash = {}
 | |
|         SERIALIZE_KEYS.each { |key| hash[key] = send(key) } # rubocop:disable GitlabSecurity/PublicSend
 | |
|         hash
 | |
|       end
 | |
| 
 | |
|       def set_marker_ranges(marker_ranges)
 | |
|         @marker_ranges = marker_ranges
 | |
|       end
 | |
| 
 | |
|       def text(prefix: true)
 | |
|         return @text if prefix
 | |
| 
 | |
|         @text&.slice(1..).to_s
 | |
|       end
 | |
| 
 | |
|       def old_line
 | |
|         old_pos unless added? || meta?
 | |
|       end
 | |
| 
 | |
|       def new_line
 | |
|         new_pos unless removed? || meta?
 | |
|       end
 | |
| 
 | |
|       def line
 | |
|         new_line || old_line
 | |
|       end
 | |
| 
 | |
|       def unchanged?
 | |
|         type.nil?
 | |
|       end
 | |
| 
 | |
|       def added?
 | |
|         %w[new new-nonewline new-nomappinginraw].include?(type)
 | |
|       end
 | |
| 
 | |
|       def removed?
 | |
|         %w[old old-nonewline old-nomappinginraw].include?(type)
 | |
|       end
 | |
| 
 | |
|       def meta?
 | |
|         %w[match new-nonewline old-nonewline].include?(type)
 | |
|       end
 | |
| 
 | |
|       def has_mapping_in_raw?
 | |
|         # Used for rendered diff, when the displayed line doesn't have a matching line in the raw diff
 | |
|         !type&.ends_with?('nomappinginraw')
 | |
|       end
 | |
| 
 | |
|       def match?
 | |
|         type == :match
 | |
|       end
 | |
| 
 | |
|       def discussable?
 | |
|         has_mapping_in_raw? && !meta?
 | |
|       end
 | |
| 
 | |
|       def suggestible?
 | |
|         !removed?
 | |
|       end
 | |
| 
 | |
|       def rich_text
 | |
|         @parent_file.try(:highlight_lines!) if @parent_file && !@rich_text
 | |
| 
 | |
|         @rich_text
 | |
|       end
 | |
| 
 | |
|       def meta_positions
 | |
|         return unless meta?
 | |
| 
 | |
|         {
 | |
|           old_pos: old_pos,
 | |
|           new_pos: new_pos
 | |
|         }
 | |
|       end
 | |
| 
 | |
|       # We have to keep this here since it is still used for conflict resolution
 | |
|       # Conflict::File#as_json renders json diff lines in sections
 | |
|       def as_json(opts = nil)
 | |
|         DiffLineSerializer.new.represent(self)
 | |
|       end
 | |
| 
 | |
|       private
 | |
| 
 | |
|       def calculate_line_code
 | |
|         @parent_file&.line_code(self)
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| end
 |