Custom emoji (#4988)
* Custom emoji - In OStatus: `<link rel="emoji" name="coolcat" href="http://..." />` - In ActivityPub: `{ type: "Emoji", name: ":coolcat:", href: "http://..." }` - In REST API: Status object includes `emojis` array (`shortcode`, `url`) - Domain blocks with reject media stop emojis - Emoji file up to 50KB - Web UI handles custom emojis - Static pages render custom emojis as `<img />` tags Side effects: - Undo #4500 optimization, as I needed to modify it to restore shortcode handling in emojify() - Formatter#plaintext should now make sure stripped out line-breaks and paragraphs are replaced with newlines * Fix emoji at the start not being convertedmain
parent
c155d843f4
commit
81cec35dbf
@ -0,0 +1,38 @@
|
||||
# frozen_string_literal: true
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: custom_emojis
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# shortcode :string default(""), not null
|
||||
# domain :string
|
||||
# image_file_name :string
|
||||
# image_content_type :string
|
||||
# image_file_size :integer
|
||||
# image_updated_at :datetime
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
||||
class CustomEmoji < ApplicationRecord
|
||||
SHORTCODE_RE_FRAGMENT = '[a-zA-Z0-9_]{2,}'
|
||||
|
||||
SCAN_RE = /(?<=[^[:alnum:]:]|\n|^)
|
||||
:(#{SHORTCODE_RE_FRAGMENT}):
|
||||
(?=[^[:alnum:]:]|$)/x
|
||||
|
||||
has_attached_file :image
|
||||
|
||||
validates_attachment :image, content_type: { content_type: 'image/png' }, presence: true, size: { in: 0..50.kilobytes }
|
||||
validates :shortcode, uniqueness: { scope: :domain }, format: { with: /\A#{SHORTCODE_RE_FRAGMENT}\z/ }, length: { minimum: 2 }
|
||||
|
||||
include Remotable
|
||||
|
||||
class << self
|
||||
def from_text(text, domain)
|
||||
return [] if text.blank?
|
||||
shortcodes = text.scan(SCAN_RE).map(&:first)
|
||||
where(shortcode: shortcodes, domain: domain)
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,13 @@
|
||||
class CreateCustomEmojis < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
create_table :custom_emojis do |t|
|
||||
t.string :shortcode, null: false, default: ''
|
||||
t.string :domain
|
||||
t.attachment :image
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :custom_emojis, [:shortcode, :domain], unique: true
|
||||
end
|
||||
end
|
@ -0,0 +1,5 @@
|
||||
Fabricator(:custom_emoji) do
|
||||
shortcode 'coolcat'
|
||||
domain nil
|
||||
image { File.open(Rails.root.join('spec', 'fixtures', 'files', 'emojo.png')) }
|
||||
end
|
After Width: | Height: | Size: 29 KiB |
@ -0,0 +1,25 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe CustomEmoji, type: :model do
|
||||
describe '.from_text' do
|
||||
let!(:emojo) { Fabricate(:custom_emoji) }
|
||||
|
||||
subject { described_class.from_text(text, nil) }
|
||||
|
||||
context 'with plain text' do
|
||||
let(:text) { 'Hello :coolcat:' }
|
||||
|
||||
it 'returns records used via shortcodes in text' do
|
||||
is_expected.to include(emojo)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with html' do
|
||||
let(:text) { '<p>Hello :coolcat:</p>' }
|
||||
|
||||
it 'returns records used via shortcodes in text' do
|
||||
is_expected.to include(emojo)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in new issue