Change Gitlab::Markdown to a module; add emoji parsing
This commit is contained in:
parent
90f587f4ee
commit
67a6a0b29b
1 changed files with 69 additions and 13 deletions
|
@ -1,7 +1,8 @@
|
||||||
module Gitlab
|
module Gitlab
|
||||||
# Custom parser for Gitlab-flavored Markdown
|
# Custom parser for Gitlab-flavored Markdown
|
||||||
#
|
#
|
||||||
# It replaces references in the text with links to the appropriate items in Gitlab.
|
# It replaces references in the text with links to the appropriate items in
|
||||||
|
# Gitlab.
|
||||||
#
|
#
|
||||||
# Supported reference formats are:
|
# Supported reference formats are:
|
||||||
# * @foo for team members
|
# * @foo for team members
|
||||||
|
@ -10,19 +11,20 @@ module Gitlab
|
||||||
# * $123 for snippets
|
# * $123 for snippets
|
||||||
# * 123456 for commits
|
# * 123456 for commits
|
||||||
#
|
#
|
||||||
|
# It also parses Emoji codes to insert images. See
|
||||||
|
# http://www.emoji-cheat-sheet.com/ for a list of the supported icons.
|
||||||
|
#
|
||||||
# Examples
|
# Examples
|
||||||
#
|
#
|
||||||
# >> m = Markdown.new(...)
|
# >> gfm("Hey @david, can you fix this?")
|
||||||
#
|
|
||||||
# >> m.parse("Hey @david, can you fix this?")
|
|
||||||
# => "Hey <a href="/gitlab/team_members/1">@david</a>, can you fix this?"
|
# => "Hey <a href="/gitlab/team_members/1">@david</a>, can you fix this?"
|
||||||
#
|
#
|
||||||
# >> m.parse("Commit 35d5f7c closes #1234")
|
# >> gfm("Commit 35d5f7c closes #1234")
|
||||||
# => "Commit <a href="/gitlab/commits/35d5f7c">35d5f7c</a> closes <a href="/gitlab/issues/1234">#1234</a>"
|
# => "Commit <a href="/gitlab/commits/35d5f7c">35d5f7c</a> closes <a href="/gitlab/issues/1234">#1234</a>"
|
||||||
class Markdown
|
#
|
||||||
include Rails.application.routes.url_helpers
|
# >> gfm(":trollface:")
|
||||||
include ActionView::Helpers
|
# => "<img alt=\":trollface:\" class=\"emoji\" src=\"/images/trollface.png" title=\":trollface:\" />
|
||||||
|
module Markdown
|
||||||
REFERENCE_PATTERN = %r{
|
REFERENCE_PATTERN = %r{
|
||||||
([^\w&;])? # Prefix (1)
|
([^\w&;])? # Prefix (1)
|
||||||
( # Reference (2)
|
( # Reference (2)
|
||||||
|
@ -33,15 +35,52 @@ module Gitlab
|
||||||
([^\w&;])? # Suffix (6)
|
([^\w&;])? # Suffix (6)
|
||||||
}x.freeze
|
}x.freeze
|
||||||
|
|
||||||
|
EMOJI_PATTERN = %r{(:([\w\-\+]+):)}.freeze
|
||||||
|
|
||||||
attr_reader :html_options
|
attr_reader :html_options
|
||||||
|
|
||||||
def initialize(project, html_options = {})
|
# Public: Parse the provided text with GitLab-Flavored Markdown
|
||||||
@project = project
|
#
|
||||||
|
# text - the source text
|
||||||
|
# html_options - extra options for the reference links as given to link_to
|
||||||
|
#
|
||||||
|
# Note: reference links will only be generated if @project is set
|
||||||
|
def gfm(text, html_options = {})
|
||||||
|
return text if text.nil?
|
||||||
|
return text if @project.nil?
|
||||||
|
|
||||||
@html_options = html_options
|
@html_options = html_options
|
||||||
|
|
||||||
|
# Extract pre blocks so they are not altered
|
||||||
|
# from http://github.github.com/github-flavored-markdown/
|
||||||
|
extractions = {}
|
||||||
|
text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) do |match|
|
||||||
|
md5 = Digest::MD5.hexdigest(match)
|
||||||
|
extractions[md5] = match
|
||||||
|
"{gfm-extraction-#{md5}}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO: add popups with additional information
|
||||||
|
|
||||||
|
text = parse(text)
|
||||||
|
|
||||||
|
# Insert pre block extractions
|
||||||
|
text.gsub!(/\{gfm-extraction-(\h{32})\}/) do
|
||||||
|
extractions[$1]
|
||||||
|
end
|
||||||
|
|
||||||
|
sanitize text.html_safe, attributes: ActionView::Base.sanitized_allowed_attributes + %w(id class)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Private: Parses text for references and emoji
|
||||||
|
#
|
||||||
|
# text - Text to parse
|
||||||
|
#
|
||||||
|
# Returns parsed text
|
||||||
def parse(text)
|
def parse(text)
|
||||||
text.gsub(REFERENCE_PATTERN) do |match|
|
text = text.gsub(REFERENCE_PATTERN) do |match|
|
||||||
prefix = $1 || ''
|
prefix = $1 || ''
|
||||||
reference = $2
|
reference = $2
|
||||||
identifier = $3 || $4 || $5
|
identifier = $3 || $4 || $5
|
||||||
|
@ -53,9 +92,26 @@ module Gitlab
|
||||||
match
|
match
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
text = text.gsub(EMOJI_PATTERN) do |match|
|
||||||
|
if valid_emoji?($2)
|
||||||
|
helper.image_tag("#{$2}.png", class: 'emoji', title: $1, alt: $1)
|
||||||
|
else
|
||||||
|
match
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
text
|
||||||
|
end
|
||||||
|
|
||||||
|
# Private: Checks if an emoji icon exists in the image asset directory
|
||||||
|
#
|
||||||
|
# emoji - Identifier of the emoji as a string (e.g., "+1", "heart")
|
||||||
|
#
|
||||||
|
# Returns boolean
|
||||||
|
def valid_emoji?(emoji)
|
||||||
|
File.exists?(Rails.root.join('app', 'assets', 'images', 'emoji', "#{emoji}.png"))
|
||||||
|
end
|
||||||
|
|
||||||
# Private: Dispatches to a dedicated processing method based on reference
|
# Private: Dispatches to a dedicated processing method based on reference
|
||||||
#
|
#
|
||||||
|
|
Loading…
Reference in a new issue