class Jekyll::Mentioji

Constants

IGNORE_EMOJI_PARENTS
IGNORE_MENTION_PARENTS
MENTIONPATTERNS
OPENING_BODY_TAG_REGEX

Public Class Methods

transform(doc) click to toggle source
# File lib/jekyll-mentioji.rb, line 16
def transform(doc)
  content = doc.output
  return unless prelim_check_regex.match?(content)

  setup_transformer(doc.site.config)
  doc.output = if content.include?("<body")
                 process_html_body(content)
               else
                 process(content)
               end
end
transformable?(doc) click to toggle source
# File lib/jekyll-mentioji.rb, line 28
def transformable?(doc)
  (doc.is_a?(Jekyll::Page) || doc.write?) &&
    doc.output_ext == ".html" || (doc.permalink&.end_with?("/"))
end

Private Class Methods

compute_base(config, key, subkey, default_value) click to toggle source

rubocop:enable Naming/MemoizedInstanceVariableName

# File lib/jekyll-mentioji.rb, line 72
def compute_base(config, key, subkey, default_value)
  subject = config[key]
  case subject
  when nil, NilClass
    default_value
  when String
    subject
  when Hash
    subject.fetch(subkey, default_value)
  else
    raise TypeError, "Your #{key} config has to either be a string or a hash. It's a " \
      "kind of #{subject.class} right now."
  end
end
default_asset_root() click to toggle source
# File lib/jekyll-mentioji.rb, line 96
def default_asset_root
  if ENV["ASSET_HOST_URL"].to_s.empty?
    File.join("https://github.githubassets.com", "/images/icons")
  else
    File.join(ENV["ASSET_HOST_URL"], "/images/icons")
  end
end
default_mention_base() click to toggle source
# File lib/jekyll-mentioji.rb, line 87
def default_mention_base
  if !ENV["SSL"].to_s.empty? && !ENV["GITHUB_HOSTNAME"].to_s.empty?
    scheme = ENV["SSL"] == "true" ? "https://" : "http://"
    "#{scheme}#{ENV["GITHUB_HOSTNAME"].chomp("/")}"
  else
    "https://github.com"
  end
end
emoji_markup(name) click to toggle source
# File lib/jekyll-mentioji.rb, line 132
def emoji_markup(name)
  emoji_stash[name] ||= begin
    "<img class='emoji' title=':#{name}:' alt=':#{name}:' " \
    "src='#{emoji_url(name)}' height='20' width='20'>"
  end
end
emoji_names() click to toggle source
# File lib/jekyll-mentioji.rb, line 147
def emoji_names
  ::Emoji.all.flat_map(&:aliases).map! { |name| Regexp.escape(name) }
end
emoji_pattern() click to toggle source
# File lib/jekyll-mentioji.rb, line 151
def emoji_pattern
  @emoji_pattern ||= %r!:(#{emoji_names.join('|')}):!
end
emoji_renderer(node, text) click to toggle source
# File lib/jekyll-mentioji.rb, line 118
def emoji_renderer(node, text)
  return text unless text.include?(":")
  return text if has_ancestor?(node, IGNORE_EMOJI_PARENTS)

  text.gsub(emoji_pattern) { emoji_markup(Regexp.last_match(1)) }
end
emoji_stash() click to toggle source
# File lib/jekyll-mentioji.rb, line 143
def emoji_stash
  @emoji_stash ||= {}
end
emoji_url(name) click to toggle source
# File lib/jekyll-mentioji.rb, line 125
def emoji_url(name)
  File.join(
    @transconfig["emoji_source"], "emoji",
    ::Emoji.find_by_alias(name).image_filename
  )
end
has_ancestor?(node, tags) click to toggle source

rubocop:disable Naming/PredicateName

# File lib/jekyll-mentioji.rb, line 160
def has_ancestor?(node, tags)
  while (node = node.respond_to?(:parent) && node.parent)
    break true if tags.include?(node.name.downcase)
  end
end
mention_markup(username) click to toggle source
# File lib/jekyll-mentioji.rb, line 104
def mention_markup(username)
  mention_stash[username] ||= begin
    "<a href='#{@transconfig["mention_base"]}/#{username}' " \
    "class='user-mention'>@#{username}</a>"
  end
end
mention_renderer(node, text) click to toggle source
# File lib/jekyll-mentioji.rb, line 111
def mention_renderer(node, text)
  return text unless text.include?("@")
  return text if has_ancestor?(node, IGNORE_MENTION_PARENTS)

  text.gsub(MENTIONPATTERNS) { mention_markup(Regexp.last_match(1)) }
end
mention_stash() click to toggle source
# File lib/jekyll-mentioji.rb, line 139
def mention_stash
  @mention_stash ||= {}
end
prelim_check_regex() click to toggle source
# File lib/jekyll-mentioji.rb, line 155
def prelim_check_regex
  @prelim_check_regex ||= %r!#{MENTIONPATTERNS}|#{emoji_pattern}!
end
process(body_content) click to toggle source
# File lib/jekyll-mentioji.rb, line 42
def process(body_content)
  return body_content unless prelim_check_regex.match?(body_content)

  parsed_body = Nokogiri::HTML::DocumentFragment.parse(body_content)
  parsed_body.search(".//text()").each do |node|
    content = node.text
    next unless prelim_check_regex.match?(content)

    node.replace(
      mention_renderer(
        node, emoji_renderer(node, content)
      )
    )
  end
  parsed_body.to_html
end
process_html_body(content) click to toggle source
# File lib/jekyll-mentioji.rb, line 35
def process_html_body(content)
  head, opener, tail  = content.partition(OPENING_BODY_TAG_REGEX)
  body_content, *rest = tail.partition("</body>")

  String.new(head) << opener << process(body_content) << rest.join
end
setup_transformer(config) click to toggle source

rubocop:disable Naming/MemoizedInstanceVariableName

# File lib/jekyll-mentioji.rb, line 60
def setup_transformer(config)
  @transconfig ||= {
    "mention_base" => compute_base(
      config, "jekyll-mentions", "base_url", default_mention_base
    ),
    "emoji_source" => compute_base(
      config, "emoji", "src", default_asset_root
    ),
  }
end