Class: ActionText::Content

Inherits:
Object
  • Object
show all
Includes:
ContentHelper, Rendering, Serialization
Defined in:
lib/action_text/content.rb

Overview

Action Text Content

The ActionText::Content class wraps an HTML fragment to add support for parsing, rendering and serialization. It can be used to extract links and attachments, convert the fragment to plain text, or serialize the fragment to the database.

The ActionText::RichText record serializes the ‘body` attribute as ActionText::Content.

class Message < ActiveRecord::Base
  has_rich_text :content
end

message = Message.create!(content: "<h1>Funny times!</h1>")
body = message.content.body # => #<ActionText::Content "<div class=\"trix-conte...">
body.to_s # => "<h1>Funny times!</h1>"
body.to_plain_text # => "Funny times!"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Serialization

#_dump

Methods included from ContentHelper

#render_action_text_attachment, #render_action_text_attachments, #render_action_text_content, #sanitize_action_text_content, #sanitize_content_attachment, #sanitizer_allowed_attributes, #sanitizer_allowed_tags

Constructor Details

#initialize(content = nil, options = {}) ⇒ Content

Returns a new instance of Content.



37
38
39
40
41
42
43
44
45
# File 'lib/action_text/content.rb', line 37

def initialize(content = nil, options = {})
  options.with_defaults! canonicalize: true

  if options[:canonicalize]
    @fragment = self.class.fragment_by_canonicalizing_content(content)
  else
    @fragment = ActionText::Fragment.wrap(content)
  end
end

Instance Attribute Details

#fragmentObject (readonly)

Returns the value of attribute fragment.



25
26
27
# File 'lib/action_text/content.rb', line 25

def fragment
  @fragment
end

Class Method Details

.fragment_by_canonicalizing_content(content) ⇒ Object



30
31
32
33
34
# File 'lib/action_text/content.rb', line 30

def fragment_by_canonicalizing_content(content)
  fragment = ActionText::Attachment.fragment_by_canonicalizing_attachments(content)
  fragment = ActionText::AttachmentGallery.fragment_by_canonicalizing_attachment_galleries(fragment)
  fragment
end

Instance Method Details

#==(other) ⇒ Object



149
150
151
152
153
154
155
# File 'lib/action_text/content.rb', line 149

def ==(other)
  if self.class == other.class
    to_html == other.to_html
  elsif other.is_a?(self.class)
    to_s == other.to_s
  end
end

#append_attachables(attachables) ⇒ Object



90
91
92
93
# File 'lib/action_text/content.rb', line 90

def append_attachables(attachables)
  attachments = ActionText::Attachment.from_attachables(attachables)
  self.class.new([self.to_s.presence, *attachments].compact.join("\n"))
end

#as_jsonObject



141
142
143
# File 'lib/action_text/content.rb', line 141

def as_json(*)
  to_html
end

#attachablesObject

Extracts ActionText::Attachables from the HTML fragment:

attachable = ActiveStorage::Blob.first
html = %Q(<action-text-attachment sgid="#{attachable.attachable_sgid}" caption="Captioned"></action-text-attachment>)
content = ActionText::Content.new(html)
content.attachables # => [attachable]


84
85
86
87
88
# File 'lib/action_text/content.rb', line 84

def attachables
  @attachables ||= attachment_nodes.map do |node|
    ActionText::Attachable.from_node(node)
  end
end

#attachment_galleriesObject



68
69
70
71
72
# File 'lib/action_text/content.rb', line 68

def attachment_galleries
  @attachment_galleries ||= attachment_gallery_nodes.map do |node|
    attachment_gallery_for_node(node)
  end
end

#attachmentsObject

Extracts ActionText::Attachments from the HTML fragment:

attachable = ActiveStorage::Blob.first
html = %Q(<action-text-attachment sgid="#{attachable.attachable_sgid}" caption="Captioned"></action-text-attachment>)
content = ActionText::Content.new(html)
content.attachments # => [#<ActionText::Attachment attachable=#<ActiveStorage::Blob...


62
63
64
65
66
# File 'lib/action_text/content.rb', line 62

def attachments
  @attachments ||= attachment_nodes.map do |node|
    attachment_for_node(node)
  end
end


74
75
76
# File 'lib/action_text/content.rb', line 74

def gallery_attachments
  @gallery_attachments ||= attachment_galleries.flat_map(&:attachments)
end

#inspectObject



145
146
147
# File 'lib/action_text/content.rb', line 145

def inspect
  "#<#{self.class.name} #{to_html.truncate(25).inspect}>"
end

Extracts links from the HTML fragment:

html = '<a href="http://example.com/">Example</a>'
content = ActionText::Content.new(html)
content.links # => ["http://example.com/"]


52
53
54
# File 'lib/action_text/content.rb', line 52

def links
  @links ||= fragment.find_all("a[href]").map { |a| a["href"] }.uniq
end

#render_attachment_galleries(&block) ⇒ Object



106
107
108
109
110
111
# File 'lib/action_text/content.rb', line 106

def render_attachment_galleries(&block)
  content = ActionText::AttachmentGallery.fragment_by_replacing_attachment_gallery_nodes(fragment) do |node|
    block.call(attachment_gallery_for_node(node))
  end
  self.class.new(content, canonicalize: false)
end

#render_attachments(**options, &block) ⇒ Object



95
96
97
98
99
100
101
102
103
104
# File 'lib/action_text/content.rb', line 95

def render_attachments(**options, &block)
  content = fragment.replace(ActionText::Attachment.tag_name) do |node|
    if node.key?("content")
      sanitized_content = sanitize_content_attachment(node.remove_attribute("content").to_s)
      node["content"] = sanitized_content if sanitized_content.present?
    end
    block.call(attachment_for_node(node, **options))
  end
  self.class.new(content, canonicalize: false)
end

#to_htmlObject



125
126
127
# File 'lib/action_text/content.rb', line 125

def to_html
  fragment.to_html
end

#to_partial_pathObject



133
134
135
# File 'lib/action_text/content.rb', line 133

def to_partial_path
  "action_text/contents/content"
end

#to_plain_textObject

Returns the content as plain text with all HTML tags removed.

content = ActionText::Content.new("<h1>Funny times!</h1>")
content.to_plain_text # => "Funny times!"


117
118
119
# File 'lib/action_text/content.rb', line 117

def to_plain_text
  render_attachments(with_full_attributes: false, &:to_plain_text).fragment.to_plain_text
end

#to_rendered_html_with_layoutObject



129
130
131
# File 'lib/action_text/content.rb', line 129

def to_rendered_html_with_layout
  render layout: "action_text/contents/content", partial: to_partial_path, formats: :html, locals: { content: self }
end

#to_sObject



137
138
139
# File 'lib/action_text/content.rb', line 137

def to_s
  to_rendered_html_with_layout
end

#to_trix_htmlObject



121
122
123
# File 'lib/action_text/content.rb', line 121

def to_trix_html
  render_attachments(&:to_trix_attachment).to_html
end