Class: Katalyst::Content::Tables::Importer
- Inherits:
-
Object
- Object
- Katalyst::Content::Tables::Importer
- Includes:
- ActiveModel::Model
- Defined in:
- app/models/katalyst/content/tables/importer.rb
Instance Attribute Summary collapse
-
#table ⇒ Object
readonly
Returns the value of attribute table.
Class Method Summary collapse
-
.call(table, value) ⇒ Object
Update a table from an HTML5 fragment and apply normalisation rules.
- .wrap(value) ⇒ Object
Instance Method Summary collapse
- #call(fragment) ⇒ Object
- #caption? ⇒ Boolean
- #header_row_caption? ⇒ Boolean
-
#initialize(table) ⇒ Importer
constructor
A new instance of Importer.
- #normalize_emphasis! ⇒ Object
-
#promote_cell_to_heading!(cell) ⇒ Object
Converts a ‘td > strong` cell to a `th` cell by updating the cell name and replacing the cell’s content with the strong tag’s content.
- #promote_header_cells! ⇒ Object
-
#promote_header_row_caption! ⇒ Object
Promotes the first row to a caption if it only has one cell.
- #promote_header_rows! ⇒ Object
-
#promote_row_to_head!(row) ⇒ Object
Moves a row from <tbody> to <thead>.
-
#set_heading! ⇒ Object
Set heading from caption and remove the caption from the table.
Constructor Details
#initialize(table) ⇒ Importer
Returns a new instance of Importer.
35 36 37 38 39 |
# File 'app/models/katalyst/content/tables/importer.rb', line 35 def initialize(table) super() @table = table end |
Instance Attribute Details
#table ⇒ Object (readonly)
Returns the value of attribute table.
13 14 15 |
# File 'app/models/katalyst/content/tables/importer.rb', line 13 def table @table end |
Class Method Details
.call(table, value) ⇒ Object
Update a table from an HTML5 fragment and apply normalisation rules.
19 20 21 |
# File 'app/models/katalyst/content/tables/importer.rb', line 19 def self.call(table, value) new(table).call(wrap(value)) end |
.wrap(value) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 |
# File 'app/models/katalyst/content/tables/importer.rb', line 23 def self.wrap(value) case value when Nokogiri::XML::Node value when ActionText::RichText # clone body to avoid modifying the original Nokogiri::HTML5.fragment(value.body.to_html) else Nokogiri::HTML5.fragment(value.to_s) end end |
Instance Method Details
#call(fragment) ⇒ Object
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 |
# File 'app/models/katalyst/content/tables/importer.rb', line 41 def call(fragment) @node = fragment.name == "table" ? fragment : fragment.at_css("table") unless @node&.name == "table" table.content.body = nil return self end # Convert b and i to strong and em normalize_emphasis! # Convert `td > strong` to th headings promote_header_cells! # Promote any rows with only <th> cells to <thead> # This captures the pattern where a table has a header row but its # in the tbody instead of the thead promote_header_rows! # Promote first row to caption if it only has one cell. # This captures the pattern where a table has as single cell that spans # the entire width of the table, and is used as a heading. promote_header_row_caption! if header_row_caption? # Update the table heading with the caption, if present, and remove from table set_heading! if caption? # Update the table's content with the normalized HTML. table.content.body = to_html table end |
#caption? ⇒ Boolean
74 75 76 |
# File 'app/models/katalyst/content/tables/importer.rb', line 74 def caption? at_css("caption")&.text&.present? end |
#header_row_caption? ⇒ Boolean
78 79 80 81 82 83 |
# File 'app/models/katalyst/content/tables/importer.rb', line 78 def header_row_caption? !at_css("caption") && (tr = at_css("thead > tr:first-child"))&.elements&.one? && (colspan = tr.elements.first.attributes["colspan"]&.value) && colspan.to_i > 1 end |
#normalize_emphasis! ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'app/models/katalyst/content/tables/importer.rb', line 85 def normalize_emphasis! traverse do |node| case node.name when "b" node.name = "strong" when "i" node.name = "em" else node end end end |
#promote_cell_to_heading!(cell) ⇒ Object
Converts a ‘td > strong` cell to a `th` cell by updating the cell name and replacing the cell’s content with the strong tag’s content.
104 105 106 107 108 109 110 111 112 113 114 |
# File 'app/models/katalyst/content/tables/importer.rb', line 104 def promote_cell_to_heading!(cell) strong = cell.at_css("strong") return unless cell.text.strip == strong.text.strip cell.name = "th" # remove strong by promoting its children strong.before(strong.children) strong.remove end |
#promote_header_cells! ⇒ Object
98 99 100 |
# File 'app/models/katalyst/content/tables/importer.rb', line 98 def promote_header_cells! css("td:has(strong)").each { |cell| promote_cell_to_heading!(cell) } end |
#promote_header_row_caption! ⇒ Object
Promotes the first row to a caption if it only has one cell.
132 133 134 135 136 137 138 139 140 |
# File 'app/models/katalyst/content/tables/importer.rb', line 132 def promote_header_row_caption! tr = at_css("thead > tr:first-child") cell = tr.elements.first tr.remove thead = at_css("thead") thead.before("<caption></caption>") thead.remove if thead.elements.empty? at_css("caption").inner_html = cell.inner_html.strip end |
#promote_header_rows! ⇒ Object
116 117 118 119 120 121 122 |
# File 'app/models/katalyst/content/tables/importer.rb', line 116 def promote_header_rows! css("tbody > tr").each do |tr| break unless tr.elements.all? { |td| td.name == "th" } promote_row_to_head!(tr) end end |
#promote_row_to_head!(row) ⇒ Object
Moves a row from <tbody> to <thead>. If the table doesn’t have a <thead>, one will be created.
126 127 128 129 |
# File 'app/models/katalyst/content/tables/importer.rb', line 126 def promote_row_to_head!(row) at_css("tbody").before("<thead></thead>") unless at_css("thead") at_css("thead") << row end |
#set_heading! ⇒ Object
Set heading from caption and remove the caption from the table.
143 144 145 146 147 148 |
# File 'app/models/katalyst/content/tables/importer.rb', line 143 def set_heading! caption = at_css("caption") table.heading = caption.text.strip table.heading_style = "default" caption.remove end |