summaryrefslogtreecommitdiff
path: root/lib/tasks/tanuki_emoji.rake
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tasks/tanuki_emoji.rake')
-rw-r--r--lib/tasks/tanuki_emoji.rake260
1 files changed, 260 insertions, 0 deletions
diff --git a/lib/tasks/tanuki_emoji.rake b/lib/tasks/tanuki_emoji.rake
new file mode 100644
index 00000000000..98d3920c07f
--- /dev/null
+++ b/lib/tasks/tanuki_emoji.rake
@@ -0,0 +1,260 @@
+# frozen_string_literal: true
+
+namespace :tanuki_emoji do
+ desc 'Generates Emoji aliases fixtures'
+ task aliases: :environment do
+ aliases = {}
+
+ TanukiEmoji.index.all.each do |emoji|
+ emoji.aliases.each do |emoji_alias|
+ aliases[TanukiEmoji::Character.format_name(emoji_alias)] = emoji.name
+ end
+ end
+
+ aliases_json_file = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json')
+ File.open(aliases_json_file, 'w') do |handle|
+ handle.write(Gitlab::Json.pretty_generate(aliases, indent: ' ', space: '', space_before: ''))
+ end
+ end
+
+ desc 'Generates Emoji SHA256 digests'
+ task digests: :environment do
+ require 'digest/sha2'
+
+ digest_emoji_map = {}
+ emojis_map = {}
+
+ TanukiEmoji.index.all.each do |emoji|
+ emoji_path = Gitlab::Emoji.emoji_public_absolute_path.join("#{emoji.name}.png")
+
+ digest_entry = {
+ category: emoji.category,
+ moji: emoji.codepoints,
+ description: emoji.description,
+ unicodeVersion: emoji.unicode_version,
+ digest: Digest::SHA256.file(emoji_path).hexdigest
+ }
+
+ digest_emoji_map[emoji.name] = digest_entry
+
+ # Our new map is only characters to make the json substantially smaller
+ emoji_entry = {
+ c: emoji.category,
+ e: emoji.codepoints,
+ d: emoji.description,
+ u: emoji.unicode_version
+ }
+
+ emojis_map[emoji.name] = emoji_entry
+ end
+
+ digests_json = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json')
+ File.open(digests_json, 'w') do |handle|
+ handle.write(Gitlab::Json.pretty_generate(digest_emoji_map))
+ end
+
+ emojis_json = Gitlab::Emoji.emoji_public_absolute_path.join('emojis.json')
+ File.open(emojis_json, 'w') do |handle|
+ handle.write(Gitlab::Json.pretty_generate(emojis_map))
+ end
+ end
+
+ desc 'Import emoji assets from TanukiEmoji to versioned folder'
+ task import: :environment do
+ require 'mini_magick'
+
+ # Setting to the same size as previous gemojione images
+ EMOJI_SIZE = 64
+
+ emoji_dir = Gitlab::Emoji.emoji_public_absolute_path
+
+ puts "Importing emojis into: #{emoji_dir} ..."
+
+ # Re-create the assets folder and copy emojis renaming them to use name instead of unicode hex
+ FileUtils.rm_rf(emoji_dir) if Dir.exist?(emoji_dir)
+ FileUtils.mkdir_p(emoji_dir, mode: 0700)
+
+ TanukiEmoji.index.all.each do |emoji|
+ source = File.join(TanukiEmoji.images_path, emoji.image_name)
+ destination = File.join(emoji_dir, "#{emoji.name}.png")
+
+ FileUtils.cp(source, destination)
+ resize!(destination, EMOJI_SIZE)
+ print emoji.codepoints
+ end
+
+ puts
+ puts 'Done!'
+ end
+
+ # This task will generate a standard and Retina sprite of all of the current
+ # TanukiEmoji Emojis, with the accompanying SCSS map.
+ #
+ # It will not appear in `rake -T` output, and the dependent gems are not
+ # included in the Gemfile by default, because this task will only be needed
+ # occasionally, such as when new Emojis are added to TanukiEmoji.
+ task sprite: :environment do
+ begin
+ require 'sprite_factory'
+ # Sprite-Factory still requires rmagick, but maybe could be migrated to support minimagick
+ # Upstream issue: https://github.com/jakesgordon/sprite-factory/issues/47#issuecomment-929302890
+ require 'rmagick'
+ rescue LoadError
+ # noop
+ end
+
+ check_requirements!
+
+ SIZE = 20
+ RETINA = SIZE * 2
+
+ # Update these values to the width and height of the spritesheet when
+ # new emoji are added.
+ SPRITESHEET_WIDTH = 860
+ SPRITESHEET_HEIGHT = 840
+
+ emoji_dir = Gitlab::Emoji.emoji_public_absolute_path
+
+ puts "Preparing sprites for regular size: #{SIZE}px..."
+
+ Dir.mktmpdir do |tmpdir|
+ FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
+
+ Dir.chdir(tmpdir) do
+ Dir["**/*.png"].each do |png|
+ tmp_image_path = File.join(tmpdir, png)
+ resize!(tmp_image_path, SIZE)
+ print '.'
+ end
+ end
+ puts ' Done!'
+
+ puts "\n"
+
+ style_path = Rails.root.join(*%w(app assets stylesheets emoji_sprites.scss))
+
+ print 'Compiling sprites regular sprites... '
+
+ # Combine the resized assets into a packed sprite and re-generate the SCSS
+ SpriteFactory.cssurl = "image-url('$IMAGE')"
+ SpriteFactory.run!(tmpdir, {
+ output_style: style_path,
+ output_image: "app/assets/images/emoji.png",
+ selector: '.emoji-',
+ style: :scss,
+ nocomments: true,
+ pngcrush: true,
+ layout: :packed
+ })
+
+ # SpriteFactory's SCSS is a bit too verbose for our purposes here, so
+ # let's simplify it
+ system(%Q(sed -i '' "s/width: #{SIZE}px; height: #{SIZE}px; background: image-url('emoji.png')/background-position:/" #{style_path}))
+ system(%Q(sed -i '' "s/ no-repeat//" #{style_path}))
+ system(%Q(sed -i '' "s/ 0px/ 0/g" #{style_path}))
+
+ # Append a generic rule that applies to all Emojis
+ File.open(style_path, 'a') do |f|
+ f.puts
+ f.puts <<-CSS.strip_heredoc
+ .emoji-icon {
+ background-image: image-url('emoji.png');
+ background-repeat: no-repeat;
+ color: transparent;
+ text-indent: -99em;
+ height: #{SIZE}px;
+ width: #{SIZE}px;
+
+ /* stylelint-disable media-feature-name-no-vendor-prefix */
+ @media only screen and (-webkit-min-device-pixel-ratio: 2),
+ only screen and (min--moz-device-pixel-ratio: 2),
+ only screen and (-o-min-device-pixel-ratio: 2/1),
+ only screen and (min-device-pixel-ratio: 2),
+ only screen and (min-resolution: 192dpi),
+ only screen and (min-resolution: 2dppx) {
+ background-image: image-url('emoji@2x.png');
+ background-size: #{SPRITESHEET_WIDTH}px #{SPRITESHEET_HEIGHT}px;
+ }
+ /* stylelint-enable media-feature-name-no-vendor-prefix */
+ }
+ CSS
+ end
+ end
+ puts 'Done!'
+
+ puts "\n"
+
+ puts "Preparing sprites for HiDPI size: #{RETINA}px..."
+
+ # Now do it again but for Retina
+ Dir.mktmpdir do |tmpdir|
+ # Copy the TanukiEmoji assets to the temporary folder for resizing
+ FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
+
+ Dir.chdir(tmpdir) do
+ Dir["**/*.png"].each do |png|
+ tmp_image_path = File.join(tmpdir, png)
+ resize!(tmp_image_path, RETINA)
+ print '.'
+ end
+ end
+ puts ' Done!'
+
+ puts "\n"
+
+ print 'Compiling HiDPI sprites...'
+
+ # Combine the resized assets into a packed sprite and re-generate the SCSS
+ SpriteFactory.run!(tmpdir, {
+ output_image: "app/assets/images/emoji@2x.png",
+ style: false,
+ nocomments: true,
+ pngcrush: true,
+ layout: :packed
+ })
+ end
+
+ puts ' Done!'
+ end
+
+ def check_requirements!
+ unless defined?(Magick)
+ puts <<~MSG
+ This task is disabled by default and should only be run when the TanukiEmoji
+ gem is updated with new Emojis.
+
+ To enable this task, *temporarily* add the following lines to Gemfile and
+ re-bundle:
+
+ gem 'rmagick', '~> 3.2'
+
+ It depends on ImageMagick 6, which can be installed via HomeBrew with:
+
+ brew unlink imagemagick
+ brew install imagemagick@6 && brew link imagemagick@6 --force
+ MSG
+
+ exit 1
+ end
+
+ return if Dir.exist? Gitlab::Emoji.emoji_public_absolute_path
+
+ puts <<~MSG
+ You first need to import the assets for Emoji version: #{Gitlab::Emoji::EMOJI_VERSION}
+
+ Run the following task:
+
+ rake tanuki_emoji:import
+ MSG
+
+ exit 1
+ end
+
+ def resize!(image_path, size)
+ # Resize the image in-place, save it, and free the object
+ image = MiniMagick::Image.open(image_path)
+ image.quality(100)
+ image.resize("#{size}x#{size}")
+ image.write(image_path)
+ end
+end