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 convertedmaster
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