Module: MarkupHelper

Extended by:
MarkupHelper
Includes:
ActionView::Context, ActionView::Helpers::TextHelper
Included in:
API::Entities::CommitWithLink, API::Entities::WikiPage, AppearancesHelper, Emails::ServiceDesk, ForkNamespaceEntity, Gitlab::TreeSummary, GroupChildEntity, MarkupHelper, MergeRequestPresenter, Profile::EventEntity
Defined in:
app/helpers/markup_helper.rb

Instance Method Summary collapse

Instance Method Details

#cross_project_reference(project, entity) ⇒ Object

Returns the text necessary to reference ‘entity` across projects

project - Project to reference entity - Object that responds to ‘to_reference`

Examples:

cross_project_reference(project, project.issues.first)
# => 'namespace1/project1#123'

cross_project_reference(project, project.merge_requests.first)
# => 'namespace1/project1!345'

Returns a String



147
148
149
150
151
152
153
# File 'app/helpers/markup_helper.rb', line 147

def cross_project_reference(project, entity)
  if entity.respond_to?(:to_reference)
    entity.to_reference(project, full: true)
  else
    ''
  end
end

#first_line_in_markdown(object, attribute, max_chars = nil, is_todo: false, **options) ⇒ Object

Return the first line of text, up to max_chars, after parsing the line as Markdown. HTML tags in the parsed output are not counted toward the max_chars limit. If the length limit falls within a tag’s contents, then the tag contents are truncated without removing the closing tag.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'app/helpers/markup_helper.rb', line 62

def first_line_in_markdown(object, attribute, max_chars = nil, is_todo: false, **options)
  md = markdown_field(object, attribute, options.merge(post_process: false))
  return unless md.present?

  tags = %w[a gl-emoji b strong i em pre code p span]

  context = markdown_field_render_context(object, attribute, options)
  context.reverse_merge!(truncate_visible_max_chars: max_chars || md.length)

  text = prepare_for_rendering(md, context)
  text = sanitize(
    text,
    tags: tags,
    attributes: Rails::Html::WhiteListSanitizer.allowed_attributes +
      %w[
        style data-src data-name data-unicode-version data-html
        data-reference-type data-project-path data-iid data-mr-title
        data-user
      ]
  )

  render_links(text)
end

It solves a problem occurring with nested links (i.e. “<a>outer text <a>gfm ref</a> more outer text</a>”). This will not be interpreted as intended. Browsers will parse something like “<a>outer text </a><a>gfm ref</a> more outer text” (notice the last part is not linked any more). link_to_html corrects that. It wraps all parts to explicitly produce the correct linking behavior (i.e. “<a>outer text </a><a>gfm ref</a><a> more outer text</a>”).



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
# File 'app/helpers/markup_helper.rb', line 29

def link_to_html(redacted, url, html_options = {})
  fragment = Nokogiri::HTML::DocumentFragment.parse(redacted)

  if fragment.children.size == 1 && fragment.children[0].name == 'a'
    # Fragment has only one node, and it's a link generated by `gfm`.
    # Replace it with our requested link.
    text = fragment.children[0].text
    fragment.children[0].replace(link_to(text, url, html_options))
  else
    # Traverse the fragment's first generation of children looking for
    # either pure text or emojis, wrapping anything found in the
    # requested link
    fragment.children.each do |node|
      if node.text?
        node.replace(link_to(node.text, url, html_options))
      elsif node.name == 'gl-emoji'
        node.replace(link_to(node.to_html.html_safe, url, html_options))
      end
    end
  end

  # Add any custom CSS classes to the GFM-generated reference links
  if html_options[:class]
    fragment.css('a.gfm').add_class(html_options[:class])
  end

  fragment.to_html.html_safe
end

Use this in places where you would normally use link_to(gfm(…), …).



10
11
12
13
14
# File 'app/helpers/markup_helper.rb', line 10

def link_to_markdown(body, url, html_options = {})
  return '' if body.blank?

  link_to_html(markdown(body, pipeline: :single_line), url, html_options)
end


16
17
18
19
20
# File 'app/helpers/markup_helper.rb', line 16

def link_to_markdown_field(object, field, url, html_options = {})
  rendered_field = markdown_field(object, field)

  link_to_html(rendered_field, url, html_options)
end

#markdown(text, context = {}) ⇒ Object



86
87
88
89
90
91
92
93
94
95
# File 'app/helpers/markup_helper.rb', line 86

def markdown(text, context = {})
  return '' unless text.present?

  context[:project] ||= @project
  context[:group] ||= @group

  html = Markup::RenderingService.new(text, context: context, postprocess_context: postprocess_context).execute

  Hamlit::RailsHelpers.preserve(html)
end

#markdown_field(object, field, context = {}) ⇒ Object



97
98
99
100
101
102
103
104
105
# File 'app/helpers/markup_helper.rb', line 97

def markdown_field(object, field, context = {})
  object = object.for_display if object.respond_to?(:for_display)
  return '' unless object.present?

  redacted_field_html = object.try(:"redacted_#{field}_html")
  return redacted_field_html if redacted_field_html

  render_markdown_field(object, field, context)
end

#markup(file_name, text, context = {}) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
# File 'app/helpers/markup_helper.rb', line 107

def markup(file_name, text, context = {})
  context[:project] ||= @project
  context[:text_source] ||= :blob
  prepare_asciidoc_context(file_name, context)

  html = Markup::RenderingService
           .new(text, file_name: file_name, context: context, postprocess_context: postprocess_context)
           .execute

  Hamlit::RailsHelpers.preserve(html)
end

#render_wiki_content(wiki_page, context = {}) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'app/helpers/markup_helper.rb', line 119

def render_wiki_content(wiki_page, context = {})
  text = wiki_page.content
  return '' unless text.present?

  context = render_wiki_content_context(wiki_page.wiki, wiki_page, context)
  prepare_asciidoc_context(wiki_page.path, context)

  html = Markup::RenderingService
           .new(text, file_name: wiki_page.path, context: context, postprocess_context: postprocess_context)
           .execute

  Hamlit::RailsHelpers.preserve(html)
end