Class: Jekyll::Emoji::Converter

Inherits:
Converter
  • Object
show all
Defined in:
lib/jekyll/emoji/converter.rb

Constant Summary collapse

DEFAULTS =
{
  'format' => 'html',
  'ascii' => false,
  'shortname' => true
}.freeze
BLACKLIST_ATTRIBUTES =
%w{
  data-no-emoji
  data-no-emojis
}
BLACKLIST_CLASSES =
%w{
  no-emoji
  no-emojis

  no_emoji
  no_emojis
}
BLACKLIST_ELEMENTS =
%w{
  code
  pre
}
SUPPORTED_FORMATS =
%w{
  html
  unicode
  emojione-png
  emojione-svg
}
EMOJI_JSON_FILE =
'../../../../emoji.json'

Instance Method Summary collapse

Constructor Details

#initialize(conf = {'emoji' => DEFAULTS}) ⇒ Converter

Initialize the object. conf Hash should be the following format:

{
  ...
  'emoji' => {
    'format' => [String],
    'ascii' => [TrueClass|FalseClass],
    'shortcode' => [TrueClass|FalseClass]
  }
  ...
}

Parameters:

  • conf (Hash) (defaults to: {'emoji' => DEFAULTS})


60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/jekyll/emoji/converter.rb', line 60

def initialize(conf = {'emoji' => DEFAULTS})
  @initialized = false
  configure(@initial_conf = conf)

  validate_format

  @emoji_map    = {}
  @encoding_map = {}

  @shortname_aliases = []
  @ascii_aliases     = []

  load_emoji_data
  build_emoji_regexp
  build_encoding_regexp
  @initialized = true
end

Instance Method Details

#add_ascii_alias(emoji_alias, codepoints) ⇒ FalseClass|TrueClass

Add an ASCII alias for an emoji Used similarly to ‘add_shortname_alias`.

Returns true if the key was added, false if it already existed.

Examples:

conv = Converter.new()
conv.add_shortname_alias(";-)", '1F609')

Parameters:

  • emoji_alias (String)
  • codepoints (String)

Returns:

  • (FalseClass|TrueClass)


216
217
218
219
220
221
222
# File 'lib/jekyll/emoji/converter.rb', line 216

def add_ascii_alias(emoji_alias, codepoints)
  return false unless map_emoji(emoji_alias, codepoints)
  @ascii_aliases << emoji_alias

  build_emoji_regexp if @initialized
  return true
end

#add_emojis(node) ⇒ NilClass

Recursively add emojis to all child nodes.

Parameters:

  • node (Oga::XML::Document|Oga::XML::Node|Oga::XML::Element)

Returns:

  • (NilClass)


336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/jekyll/emoji/converter.rb', line 336

def add_emojis(node)
  return unless emoji_enabled?(node)

  node.children.each do |child|
    if child.is_a?(Oga::XML::Text)
      process_node(child)
    else
      add_emojis(child)
    end
  end

  # return nil
end

#add_shortname_alias(emoji_alias, codepoints) ⇒ FalseClass|TrueClass

Add a shortname alias for an emoji Used similarly to ‘map_emoji`, except that `k` is a string alias:

Returns true if the key was added, false if it already existed.

Examples:

conv = Converter.new()
conv.add_shortname_alias(":wink:", '1F609')

Parameters:

  • emoji_alias (String)
  • codepoints (String)

Returns:

  • (FalseClass|TrueClass)


194
195
196
197
198
199
200
# File 'lib/jekyll/emoji/converter.rb', line 194

def add_shortname_alias(emoji_alias, codepoints)
  return false unless map_emoji(emoji_alias, codepoints)
  @shortname_aliases << emoji_alias

  build_emoji_regexp if @initialized
  return true
end

#configure(h) ⇒ Hash

Configure the internal state.

Parameters:

  • h (Hash)

Returns:

  • (Hash)


266
267
268
269
270
271
272
# File 'lib/jekyll/emoji/converter.rb', line 266

def configure(h)
  if h['emoji']
    @conf = DEFAULTS.merge(h['emoji'])
  else
    @conf = DEFAULTS
  end
end

#convert(content) ⇒ String

Emojify the string. If the string is an HTML strings, certain elements won’t be emojified. Check the ‘BLACKLIST_*“ constants, or the docs for more information.

Parameters:

  • content (String)

Returns:

  • (String)


443
444
445
446
447
448
449
450
451
452
453
454
# File 'lib/jekyll/emoji/converter.rb', line 443

def convert(content)
  document = Oga.parse_html(content)
  add_emojis(document)
  docstr = document.to_xml

  # Now we only need to encode the Emojis into HTML Entities
  if @conf['format'] == 'html'
    docstr.gsub!(@encoding_regexp, @encoding_map)
  end

  return docstr
end

#emoji_enabled?(node) ⇒ TrueClass|FalseClass

Return whether whether ‘node` should contain emojis or not.

Parameters:

  • node (Oga::XML::Node)

Returns:

  • (TrueClass|FalseClass)


314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/jekyll/emoji/converter.rb', line 314

def emoji_enabled?(node)

  return true if node.is_a? Oga::XML::Document

  if node.is_a? Oga::XML::Element
    classes = node.get('class')

    return false if BLACKLIST_ELEMENTS.any? {|e| e == node.name }
    return false if BLACKLIST_ATTRIBUTES.any? {|a| node.attr(a) }
    return false unless (BLACKLIST_CLASSES & classes.split).empty? unless classes.nil?

  end

  return true
end

#initial_confObject

convert



456
457
458
# File 'lib/jekyll/emoji/converter.rb', line 456

def initial_conf
  @initial_conf
end

#map_emoji(k, v) ⇒ FalseClass|TrueClass

Add an emoji to the map of all supported emojis.

  • ‘k` is an string corresponding to the emoji.

  • ‘v` is a dash(`-`)-delimited string of hex-formated codepoints.

Returns true if the key was added, false if it already existed.

NOTE: Keys added through ‘map_encoding`, `map_emoji`, `add_shortname_alias`, and `add_ascii_alias` are all used in the same fashion during the lookup of the emoji. So, the code below would work, but the `:wink:` key would be added to the wrong lookup table, which would mean this key wouldn’t be converted to an emoji if ASCII keys were disabled.

This is a design choice added on purpose to allow addition of different types of emoji aliases, which aren’t limited to ‘:shortcode` or the traditional smiley faces (`:)`, or `:P`), but also allowing the ability to toggle them off if needed.

Examples:

conv = Converter.new()
conv.map_emoji("\u{1F609}", '1F609')
conv = Converter.new()
conv.add_ascii_alias(":wink:", '1F609')

Parameters:

  • k (String)
  • v (String)

Returns:

  • (FalseClass|TrueClass)


172
173
174
175
176
177
178
# File 'lib/jekyll/emoji/converter.rb', line 172

def map_emoji(k, v)
  return false if @emoji_map.has_key? k
  @emoji_map[k] = v

  build_emoji_regexp if @initialized
  return true
end

#map_encoding(k, v) ⇒ Object

Map an key to an HTML Entity string for faster encoding. The keys also serve as an array of strings used in the emoji regexp.

  • ‘k` is the unicode string

  • ‘v` is a dash(`-`)-delimited string of hex-formated codepoints

Parameters:

  • k (String)
  • v (String)


133
134
135
136
137
# File 'lib/jekyll/emoji/converter.rb', line 133

def map_encoding(k, v)
  @encoding_map[k] = v.split('-').map{|cp| "&#x#{cp};" }.join

  build_encoding_regexp if @initialized
end

#matches(ext) ⇒ TrueClass|FalseClass

Return whether we should convert a file based on its extension.

Parameters:

  • ext (String)

Returns:

  • (TrueClass|FalseClass)


295
296
297
# File 'lib/jekyll/emoji/converter.rb', line 295

def matches(ext)
  ext =~ /^\.(md|markdown)$/i
end

#output_ext(ext) ⇒ String

Returns the extension with the Converter should output.

Parameters:

  • ext (String)

Returns:

  • (String)


304
305
306
# File 'lib/jekyll/emoji/converter.rb', line 304

def output_ext(ext)
  ".html"
end

#reconfigure(h) ⇒ Hash

Reconfigure the internal state.

Parameters:

  • h (Hash)

Returns:

  • (Hash)


280
281
282
283
284
285
286
287
# File 'lib/jekyll/emoji/converter.rb', line 280

def reconfigure(h)
  previous_conf = @conf
  @conf = configure(@initial_conf).merge(h){|k, o, n| n.nil? ? o : n }
  validate_format
  build_emoji_regexp(previous_conf)

  return @conf
end