gitlab-org--gitlab-foss/lib/tasks/tanuki_emoji.rake

268 lines
8.2 KiB
Ruby

# frozen_string_literal: true
namespace :tanuki_emoji do
desc 'Generates Emoji aliases fixtures'
task aliases: :environment do
ALLOWED_ALIASES = [':)', ':('].freeze
aliases = {}
TanukiEmoji.index.all.each do |emoji|
emoji.aliases.each do |emoji_alias|
aliases[TanukiEmoji::Character.format_name(emoji_alias)] = emoji.name
end
emoji.ascii_aliases.intersection(ALLOWED_ALIASES).each do |ascii_alias|
# We add an extra space at the end so that when a user types ":) "
# we'd still match this alias and not show "cocos (keeling) islands" as the first result.
# The initial ":" is ignored when matching because it's our emoji prefix in Markdown.
aliases[ascii_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