/
attachment.rb
148 lines (123 loc) · 4.41 KB
/
attachment.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# frozen_string_literal: true
# :markup: markdown
require "active_support/core_ext/object/try"
module ActionText
# # Action Text Attachment
#
# Attachments serialize attachables to HTML or plain text.
#
# class Person < ApplicationRecord
# include ActionText::Attachable
# end
#
# attachable = Person.create! name: "Javan"
# attachment = ActionText::Attachment.from_attachable(attachable)
# attachment.to_html # => "<action-text-attachment sgid=\"BAh7CEk..."
class Attachment
include Attachments::TrixConversion, Attachments::Minification, Attachments::Caching
mattr_accessor :tag_name, default: "action-text-attachment"
ATTRIBUTES = %w( sgid content-type url href filename filesize width height previewable presentation caption content )
class << self
def fragment_by_canonicalizing_attachments(content)
fragment_by_minifying_attachments(fragment_by_converting_trix_attachments(content))
end
def from_node(node, attachable = nil)
new(node, attachable || ActionText::Attachable.from_node(node))
end
def from_attachables(attachables)
Array(attachables).filter_map { |attachable| from_attachable(attachable) }
end
def from_attachable(attachable, attributes = {})
if node = node_from_attributes(attachable.to_rich_text_attributes(attributes))
new(node, attachable)
end
end
def from_attributes(attributes, attachable = nil)
if node = node_from_attributes(attributes)
from_node(node, attachable)
end
end
private
def node_from_attributes(attributes)
if attributes = process_attributes(attributes).presence
ActionText::HtmlConversion.create_element(tag_name, attributes)
end
end
def process_attributes(attributes)
attributes.transform_keys { |key| key.to_s.underscore.dasherize }.slice(*ATTRIBUTES)
end
end
attr_reader :node, :attachable
delegate :to_param, to: :attachable
delegate_missing_to :attachable
def initialize(node, attachable)
@node = node
@attachable = attachable
end
def caption
node_attributes["caption"].presence
end
def full_attributes
node_attributes.merge(attachable_attributes).merge(sgid_attributes)
end
def with_full_attributes
self.class.from_attributes(full_attributes, attachable)
end
# Converts the attachment to plain text.
#
# attachable = ActiveStorage::Blob.find_by filename: "racecar.jpg"
# attachment = ActionText::Attachment.from_attachable(attachable)
# attachment.to_plain_text # => "[racecar.jpg]"
#
# Use the `caption` when set:
#
# attachment = ActionText::Attachment.from_attachable(attachable, caption: "Vroom vroom")
# attachment.to_plain_text # => "[Vroom vroom]"
#
# The presentation can be overridden by implementing the
# `attachable_plain_text_representation` method:
#
# class Person < ApplicationRecord
# include ActionText::Attachable
#
# def attachable_plain_text_representation
# "[#{name}]"
# end
# end
#
# attachable = Person.create! name: "Javan"
# attachment = ActionText::Attachment.from_attachable(attachable)
# attachment.to_plain_text # => "[Javan]"
def to_plain_text
if respond_to?(:attachable_plain_text_representation)
attachable_plain_text_representation(caption)
else
caption.to_s
end
end
# Converts the attachment to HTML.
#
# attachable = Person.create! name: "Javan"
# attachment = ActionText::Attachment.from_attachable(attachable)
# attachment.to_html # => "<action-text-attachment sgid=\"BAh7CEk...
def to_html
HtmlConversion.node_to_html(node)
end
def to_s
to_html
end
def inspect
"#<#{self.class.name} attachable=#{attachable.inspect}>"
end
private
def node_attributes
@node_attributes ||= ATTRIBUTES.to_h { |name| [ name.underscore, node[name] ] }.compact
end
def attachable_attributes
@attachable_attributes ||= (attachable.try(:to_rich_text_attributes) || {}).stringify_keys
end
def sgid_attributes
@sgid_attributes ||= node_attributes.slice("sgid").presence || attachable_attributes.slice("sgid")
end
end
end