Welcome to mirror list, hosted at ThFree Co, Russian Federation.

external_issue_reference_filter.rb « references « filter « banzai « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 1061a9917ddde60ac980e504509703292dfdefbb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# frozen_string_literal: true

module Banzai
  module Filter
    module References
      # HTML filter that replaces external issue tracker references with links.
      # References are ignored if the project doesn't use an external issue
      # tracker.
      #
      # This filter does not support cross-project references.
      class ExternalIssueReferenceFilter < ReferenceFilter
        self.reference_type = :external_issue
        self.object_class   = ExternalIssue

        # Public: Find `JIRA-123` issue references in text
        #
        #   references_in(text, pattern) do |match, issue|
        #     "<a href=...>##{issue}</a>"
        #   end
        #
        # text - String text to search.
        #
        # Yields the String match and the String issue reference.
        #
        # Returns a String replaced with the return of the block.
        def references_in(text, pattern = object_reference_pattern)
          text.gsub(pattern) do |match|
            yield match, $~[:issue]
          end
        end

        def call
          # Early return if the project isn't using an external tracker
          return doc if project.nil? || default_issues_tracker?

          super
        end

        private

        # Replace `JIRA-123` issue references in text with links to the referenced
        # issue's details page.
        #
        # text - String text to replace references in.
        # link_content - Original content of the link being replaced.
        #
        # Returns a String with `JIRA-123` references replaced with links. All
        # links have `gfm` and `gfm-issue` class names attached for styling.
        def object_link_filter(text, pattern, link_content: nil, link_reference: false)
          references_in(text) do |match, id|
            url = url_for_issue(id)
            klass = reference_class(:issue)
            data  = data_attribute(project: project.id, external_issue: id)
            content = link_content || match

            %(<a href="#{url}" #{data}
                 title="#{escape_once(issue_title)}"
                 class="#{klass}">#{content}</a>)
          end
        end

        def url_for_issue(issue_id)
          return '' if project.nil?

          url = if only_path?
                  project.external_issue_tracker.issue_path(issue_id)
                else
                  project.external_issue_tracker.issue_url(issue_id)
                end

          # Ensure we return a valid URL to prevent possible XSS.
          URI.parse(url).to_s
        rescue URI::InvalidURIError
          ''
        end

        def default_issues_tracker?
          external_issues_cached(:default_issues_tracker?)
        end

        def object_reference_pattern
          external_issues_cached(:external_issue_reference_pattern)
        end

        def issue_title
          "Issue in #{project.external_issue_tracker.title}"
        end

        def external_issues_cached(attribute)
          cached_attributes = Gitlab::SafeRequestStore[:banzai_external_issues_tracker_attributes] ||= Hash.new { |h, k| h[k] = {} }
          cached_attributes[project.id][attribute] = project.public_send(attribute) if cached_attributes[project.id][attribute].nil? # rubocop:disable GitlabSecurity/PublicSend
          cached_attributes[project.id][attribute]
        end
      end
    end
  end
end