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