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. if # Update the table heading with the caption, if present, and remove from table set_heading! if # 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 at_css("caption")&.text&.present? end |
#header_row_caption? ⇒ Boolean
78 79 80 81 82 |
# File 'app/models/katalyst/content/tables/importer.rb', line 78 def !at_css("caption") && (tr = at_css("thead > tr:first-child"))&.elements&.count == 1 && (tr.elements.first.attributes["colspan"]&.value&.to_i&.> 1) end |
#normalize_emphasis! ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'app/models/katalyst/content/tables/importer.rb', line 84 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.
103 104 105 106 107 108 109 110 111 112 113 |
# File 'app/models/katalyst/content/tables/importer.rb', line 103 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
97 98 99 |
# File 'app/models/katalyst/content/tables/importer.rb', line 97 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.
131 132 133 134 135 136 137 138 139 |
# File 'app/models/katalyst/content/tables/importer.rb', line 131 def 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
115 116 117 118 119 120 121 |
# File 'app/models/katalyst/content/tables/importer.rb', line 115 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.
125 126 127 128 |
# File 'app/models/katalyst/content/tables/importer.rb', line 125 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.
142 143 144 145 146 147 |
# File 'app/models/katalyst/content/tables/importer.rb', line 142 def set_heading! = at_css("caption") table.heading = .text.strip table.heading_style = "default" .remove end |