2018-10-08 17:44:25 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2018-04-13 19:23:04 -04:00
|
|
|
module ActionText
|
2018-02-07 19:26:19 -05:00
|
|
|
class TrixAttachment
|
|
|
|
TAG_NAME = "figure"
|
|
|
|
SELECTOR = "[data-trix-attachment]"
|
|
|
|
|
2018-10-03 12:11:39 -04:00
|
|
|
COMPOSED_ATTRIBUTES = %w( caption presentation )
|
|
|
|
ATTRIBUTES = %w( sgid contentType url href filename filesize width height previewable content ) + COMPOSED_ATTRIBUTES
|
2018-02-07 19:26:19 -05:00
|
|
|
ATTRIBUTE_TYPES = {
|
|
|
|
"previewable" => ->(value) { value.to_s == "true" },
|
|
|
|
"filesize" => ->(value) { Integer(value.to_s) rescue value },
|
|
|
|
"width" => ->(value) { Integer(value.to_s) rescue nil },
|
|
|
|
"height" => ->(value) { Integer(value.to_s) rescue nil },
|
|
|
|
:default => ->(value) { value.to_s }
|
|
|
|
}
|
|
|
|
|
|
|
|
class << self
|
|
|
|
def from_attributes(attributes)
|
|
|
|
attributes = process_attributes(attributes)
|
|
|
|
|
2018-10-03 12:11:39 -04:00
|
|
|
trix_attachment_attributes = attributes.except(*COMPOSED_ATTRIBUTES)
|
|
|
|
trix_attributes = attributes.slice(*COMPOSED_ATTRIBUTES)
|
2018-02-07 19:26:19 -05:00
|
|
|
|
2018-04-13 19:23:04 -04:00
|
|
|
node = ActionText::HtmlConversion.create_element(TAG_NAME)
|
2018-02-07 19:26:19 -05:00
|
|
|
node["data-trix-attachment"] = JSON.generate(trix_attachment_attributes)
|
|
|
|
node["data-trix-attributes"] = JSON.generate(trix_attributes) if trix_attributes.any?
|
|
|
|
|
|
|
|
new(node)
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
def process_attributes(attributes)
|
|
|
|
typecast_attribute_values(transform_attribute_keys(attributes))
|
|
|
|
end
|
|
|
|
|
|
|
|
def transform_attribute_keys(attributes)
|
|
|
|
attributes.transform_keys { |key| key.to_s.underscore.camelize(:lower) }
|
|
|
|
end
|
|
|
|
|
|
|
|
def typecast_attribute_values(attributes)
|
|
|
|
attributes.map do |key, value|
|
|
|
|
typecast = ATTRIBUTE_TYPES[key] || ATTRIBUTE_TYPES[:default]
|
|
|
|
[key, typecast.call(value)]
|
|
|
|
end.to_h
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
attr_reader :node
|
|
|
|
|
|
|
|
def initialize(node)
|
|
|
|
@node = node
|
|
|
|
end
|
|
|
|
|
|
|
|
def attributes
|
|
|
|
@attributes ||= attachment_attributes.merge(composed_attributes).slice(*ATTRIBUTES)
|
|
|
|
end
|
|
|
|
|
|
|
|
def to_html
|
2018-04-13 19:23:04 -04:00
|
|
|
ActionText::HtmlConversion.node_to_html(node)
|
2018-02-07 19:26:19 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def to_s
|
|
|
|
to_html
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
def attachment_attributes
|
|
|
|
read_json_object_attribute("data-trix-attachment")
|
|
|
|
end
|
|
|
|
|
|
|
|
def composed_attributes
|
|
|
|
read_json_object_attribute("data-trix-attributes")
|
|
|
|
end
|
|
|
|
|
|
|
|
def read_json_object_attribute(name)
|
|
|
|
read_json_attribute(name) || {}
|
|
|
|
end
|
|
|
|
|
|
|
|
def read_json_attribute(name)
|
|
|
|
if value = node[name]
|
|
|
|
begin
|
|
|
|
JSON.parse(value)
|
|
|
|
rescue => e
|
|
|
|
Rails.logger.error "[#{self.class.name}] Couldn't parse JSON #{value} from NODE #{node.inspect}"
|
|
|
|
Rails.logger.error "[#{self.class.name}] Failed with #{e.class}: #{e.backtrace}"
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|