Skip to content

Commit 97d72d5

Browse files
authored
Merge pull request #270 from learningtapestry/hotfix-tables-with-headers
fixed parsing tables with thead
2 parents c087cea + 506d8ad commit 97d72d5

File tree

10 files changed

+361
-5
lines changed

10 files changed

+361
-5
lines changed

lib/doc_template/tables/activity.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def parse(fragment, *args)
1313
idx = 0
1414
[].tap do |result|
1515
fragment.xpath(xpath_meta_headers, XpathFunctions.new).each do |el|
16-
table = el.ancestors('table').first
16+
table = self.class.flatten_table(el.ancestors('table').first)
1717
data = fetch table
1818

1919
data = process_title(data)

lib/doc_template/tables/base.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,20 @@ def self.parse(fragment, *)
1212
new.parse(fragment, *)
1313
end
1414

15+
def self.flatten_table(table)
16+
return unless table.present?
17+
18+
# remove blank tbody
19+
table.xpath('.//tbody').each { |tbody| tbody.remove if tbody.text.blank? }
20+
# move data from thead to tbody (first children)
21+
table.xpath('.//thead').each do |thead|
22+
tbody = table.at_xpath('.//tbody').presence || table.add_child('<tbody></tbody>').first
23+
thead.children.reverse.each { |child| tbody.prepend_child child }
24+
thead.remove
25+
end
26+
table
27+
end
28+
1529
def initialize
1630
@data = {}
1731
@errors = []
@@ -65,7 +79,8 @@ def parse(fragment, *args)
6579

6680
# get the table
6781
table_key_cell = fragment.at_xpath("table//tr[1]/td[1][contains(., '#{self.class::HEADER_LABEL}')]")
68-
table = table_key_cell&.ancestors('table')&.first
82+
# flatten table to simple structure with tbody only
83+
table = self.class.flatten_table(table_key_cell&.ancestors('table')&.first)
6984
@table_exists = table.present?
7085
return self unless @table_exists
7186

lib/doc_template/tables/section.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def parse(fragment, *args)
1616

1717
[].tap do |result|
1818
section_tables.each do |el|
19-
table = el.ancestors('table').first
19+
table = self.class.flatten_table(el.ancestors('table').first)
2020
data = fetch table
2121

2222
value = data['section-title'].parameterize

lib/doc_template/tables/target.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class Target < Base
99
def parse(fragment, *_args)
1010
path = ".//table/*/tr[1]/td[1][case_insensitive_contains(.//*/text(), '#{HEADER_LABEL_PIECE}')]"
1111
return unless (element = fragment.at_xpath path, XpathFunctions.new)
12-
return unless (table = element.ancestors('table').first)
12+
return unless (table = self.class.flatten_table(element.ancestors('table').first))
1313

1414
@target_data = fetch table
1515

lib/doc_template/tags/table_tag.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module DocTemplate
44
module Tags
55
class TableTag < BaseTag
66
def parse(node, opts = {})
7-
unless (table = node.ancestors('table').first)
7+
unless (table = ::DocTemplate::Tables::Base.flatten_table(node.ancestors('table').first))
88
raise ::Lcms::Engine::DocumentError, "Tag #{self.class::TAG_NAME.upcase} placed outside table"
99
end
1010

sig/lib/doc_template/tables/base.rbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module DocTemplate
1414
attr_reader data: untyped
1515

1616
def self.parse: (untyped fragment, *untyped) -> untyped
17+
def self.flatten_table: (untyped table) -> untyped
1718

1819
def initialize: () -> void
1920
def collect_and_render_tags: (untyped data, untyped fields, ?::Hash[untyped, untyped] opts) -> untyped

spec/fixtures/tables/material-metadata-theader.html

Lines changed: 278 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
5+
describe DocTemplate::Tables::MaterialMetadata do
6+
let(:table) { described_class.new }
7+
8+
describe '#parse' do
9+
let(:html) { Lcms::Engine::HtmlSanitizer.sanitize(data) }
10+
let(:fragment) { Nokogiri::HTML.fragment html }
11+
12+
subject { table.parse fragment }
13+
14+
context 'table with headers' do
15+
let(:data) { file_fixture('tables/material-metadata-theader.html').read }
16+
17+
include_examples 'removes metadata table'
18+
19+
it 'fetching all fields' do
20+
expect(subject.data['type']).to eq 'AK'
21+
expect(subject.data['title']).to eq 'Ashoka Reading (Teacher Version)'
22+
expect(subject.data['grade']).to eq '7'
23+
expect(subject.data['unit']).to eq '1'
24+
expect(subject.data['cluster']).to eq '4'
25+
end
26+
end
27+
end
28+
end
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
5+
describe DocTemplate::Tags::ImageTag do
6+
let(:node) do
7+
html = Nokogiri::HTML original_content
8+
html.at_xpath('*//table/thead/tr[1]/td[1]')
9+
end
10+
let(:metadata) { { 'grade' => '5', 'unit' => '1', 'subject' => 'Math' } }
11+
let(:opts) { { value: 'example_image', metadata: } }
12+
let(:original_content) do
13+
<<-HTML
14+
<table>
15+
<thead>
16+
<tr><td>[#{described_class::TAG_NAME}]</td></tr>
17+
<tr><td>Caption text</td></tr>
18+
</thead>
19+
</table>
20+
HTML
21+
end
22+
let(:tag) { described_class.new }
23+
subject { tag.parse(node, opts) }
24+
25+
describe '#parse_table' do
26+
it 'removes original node' do
27+
expect(subject.content).to_not include("[#{described_class::TAG_NAME}]")
28+
end
29+
30+
it 'substitues tag with image with caption' do
31+
expect(subject.content).to include('figcaption>Caption text</figcaption>')
32+
end
33+
end
34+
end
File renamed without changes.

0 commit comments

Comments
 (0)