BigW Consortium Gitlab

base_linker.rb 2.12 KB
Newer Older
1 2 3
module Gitlab
  module DependencyLinker
    class BaseLinker
4 5
      URL_REGEX = %r{https?://[^'" ]+}.freeze
      REPO_REGEX = %r{[^/'" ]+/[^/'" ]+}.freeze
6

7 8 9 10 11 12 13 14
      class_attribute :file_type

      def self.support?(blob_name)
        Gitlab::FileDetector.type_of(blob_name) == file_type
      end

      def self.link(*args)
        new(*args).link
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
      end

      attr_accessor :plain_text, :highlighted_text

      def initialize(plain_text, highlighted_text)
        @plain_text = plain_text
        @highlighted_text = highlighted_text
      end

      def link
        link_dependencies

        highlighted_lines.join.html_safe
      end

      private

      def link_dependencies
        raise NotImplementedError
      end

36 37
      def license_url(name)
        Licensee::License.find(name)&.url
38 39
      end

40 41 42
      def github_url(name)
        "https://github.com/#{name}"
      end
43

44 45
      def link_tag(name, url)
        %{<a href="#{ERB::Util.html_escape_once(url)}" rel="nofollow noreferrer noopener" target="_blank">#{ERB::Util.html_escape_once(name)}</a>}
46 47 48 49 50 51 52
      end

      # Links package names based on regex.
      #
      # Example:
      #   link_regex(/(github:|:github =>)\s*['"](?<name>[^'"]+)['"]/)
      #   # Will link `user/repo` in `github: "user/repo"` or `:github => "user/repo"`
53
      def link_regex(regex, &url_proc)
54
        highlighted_lines.map!.with_index do |rich_line, i|
55
          marker = StringRegexMarker.new(plain_lines[i].chomp, rich_line.html_safe)
56 57

          marker.mark(regex, group: :name) do |text, left:, right:|
58 59
            url = yield(text)
            url ? link_tag(text, url) : text
60 61 62 63 64 65 66 67 68 69 70
          end
        end
      end

      def plain_lines
        @plain_lines ||= plain_text.lines
      end

      def highlighted_lines
        @highlighted_lines ||= highlighted_text.lines
      end
71

72
      def regexp_for_value(value, default: /[^'" ]+/)
73 74 75 76 77 78 79 80 81 82 83
        case value
        when Array
          Regexp.union(value.map { |v| regexp_for_value(v, default: default) })
        when String
          Regexp.escape(value)
        when Regexp
          value
        else
          default
        end
      end
84 85 86
    end
  end
end