Skip to content

Commit

Permalink
parse and use more html table cell css (#14)
Browse files Browse the repository at this point in the history
* parse and use more html table cell css
  • Loading branch information
as-op authored Jan 7, 2025
1 parent fe05b4f commit 11a4488
Show file tree
Hide file tree
Showing 6 changed files with 301 additions and 39 deletions.
64 changes: 59 additions & 5 deletions lib/md_to_pdf/elements/html.rb
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ def draw_html_table_tag(tag, opts)
column_alignments = Array.new(column_count, :left)
header_row_count = count_html_header_rows(tag)
table = build_table_settings(header_row_count, opts)
opts[:opts_cell] = table[:opts_cell]
draw_table_data(table, rows, column_alignments, opts)
end

Expand Down Expand Up @@ -314,15 +315,68 @@ def collect_html_table_tag_cell(tag, opts)
cell_data = data_inlinehtml_tag(tag, nil, opts)
if tag.key?('style')
style = tag.get_attribute('style') || ''
res = style.scan(/background-color:(.*?)(?:;|\z)/)
unless res.empty?
cell_data = [{}] if cell_data.empty?
cell_data[0][:cell_background_color] = parse_color(res.last[0])
end
cell_styling = parse_css_stylings(style)
cell_data = [{}] if cell_data.empty?
cell_data[0] = cell_data[0].merge(cell_styling)
end
cell_data
end

def parse_css_stylings(style)
cell_background_color = parse_html_color(style, /background-color:(.*?)(?:;|\z)/)
cell_border_color = parse_html_color(style, /border-color:(.*?)(?:;|\z)/)
cell_border_width = parse_html_pt(style, /border-width:(.*?)(?:;|\z)/)
cell_border_style = parse_html_border_style(style)
cell_border = style.scan(/border:(.*?)(?:;|\z)/)
unless cell_border.empty?
cell_border_compact = cell_border.last[0].split(' ', 3)
if cell_border_width.nil?
test_size = parse_pt(cell_border_compact[0])
cell_border_width = test_size unless test_size.nil?
end
if cell_border_style.nil?
test_style = parse_border_style(cell_border_compact[1])
cell_border_style = test_style unless test_style.nil?
end
if cell_border_color.nil?
test_color = parse_color(cell_border_compact[2])
cell_border_color = test_color unless test_color.nil?
end
end
{
cell_background_color: cell_background_color,
cell_border_color: cell_border_color,
cell_border_width: cell_border_width,
cell_border_style: cell_border_style
}.compact
end

def parse_html_border_style(style)
res = style.scan(/border-style:(.*?)(?:;|\z)/)
parse_border_style(res.last[0]) unless res.empty?
end

def parse_border_style(border_style)
case border_style
when 'dotted'
:dotted
when 'dashed'
:dashed
else
:solid
end
end

def parse_html_pt(style, size_regexp)
res = style.scan(size_regexp)
parse_pt(res.last[0]) unless res.empty?
end

def parse_html_color(style, color_regexp)
res = style.scan(color_regexp)
parse_color(res.last[0]) unless res.empty?
end

def space_stuffing(width, space_width)
amount = (width / space_width).truncate
return '' if amount < 1
Expand Down
20 changes: 13 additions & 7 deletions lib/md_to_pdf/elements/table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,18 @@ def make_subtable_cell(cell_data, opts)

def make_table_cell(cell_data, opts)
additional_cell_settings = cell_data.empty? ? {} : cell_data[0]
Prawn::Table::Cell::Text.new(
@pdf, [0, 0],
cell_opts = {
content: merge_cell_data(cell_data),
font: opts[:font],
size: opts[:size],
padding: opts[:cell_padding] || additional_cell_settings[:cell_padding],
background_color: additional_cell_settings[:cell_background_color],
border_colors: additional_cell_settings[:cell_border_color] || opts.dig(:opts_cell, :border_colors),
border_widths: additional_cell_settings[:cell_border_width] || opts.dig(:opts_cell, :border_widths),
border_line: additional_cell_settings[:cell_border_style] ? [additional_cell_settings[:cell_border_style]] * 4 : opts.dig(:opts_cell, :border_line),
inline_format: true
)
}.compact
Prawn::Table::Cell::Text.new(@pdf, [0, 0], cell_opts)
end

def draw_table_data(table, data_rows, column_alignments, opts)
Expand Down Expand Up @@ -125,19 +128,22 @@ def optional_break_before_table(table, pdf_table)
def build_pdf_table(table, cell_style, data, column_alignments)
column_count = column_alignments.length
column_widths = Array.new(column_count, @pdf.bounds.right / column_count)
# the default border width/color property overrides the already set cell border widths/colors
# so we remove it and set it manually for each cell on creation
default_cell_style = cell_style.except(:border_widths, :border_colors)
@pdf.make_table(
data,
width: @pdf.bounds.right,
header: table[:repeating_header],
cell_style: cell_style,
cell_style: default_cell_style,
column_widths: table[:auto_column_width] ? [] : column_widths
) do
) do |prawn_table|
column_alignments.each_with_index do |alignment, index|
columns(index).align = alignment unless alignment == nil
prawn_table.columns(index).align = alignment unless alignment == nil
end
if table[:header_row_count] > 0
opts_header = table[:opts_header]
header_cells = cells.columns(0..-1).rows(0..(table[:header_row_count] - 1))
header_cells = prawn_table.cells.columns(0..-1).rows(0..(table[:header_row_count] - 1))
header_cells.each do |cell|
cell.background_color = opts_header[:background_color] if cell.background_color.nil? || cell.background_color.empty?
cell.font_style = opts_header[:style]
Expand Down
49 changes: 49 additions & 0 deletions spec/fixtures/table/html_borders.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<table style="border:2px solid hsl(90, 75%, 60%);">
<tbody>
<tr>
<td style="border:10px dotted hsl(0, 0%, 0%);">dotted</td>
<td
style="border-color:hsl(0, 0%, 0%);border-style:solid;"><p
>column1</td>
<td
style="border-color:hsl(0, 0%, 0%);border-style:solid;"><p
>column2</td>
<td
style="border-color:hsl(0, 0%, 0%);border-style:solid;"><p
>column3</td>
<td
style="border-color:hsl(0, 0%, 0%);border-style:solid;"><p
>column4</td>
</tr>
<tr>
<td
style="border-color:hsl(0, 0%, 0%);border-style:solid;">
line1</td>
<td style="border:2px solid hsl(0, 0%, 0%);">width: 2px</td>
<td style="border-color:hsl(0, 0%, 0%);border-style:solid;">
default</td>
<td style="border-color:hsl(0, 0%, 0%);border-style:solid;">
default</td>
<td style="border-color:hsl(219,100%,50%);border-style:solid;border-width: 3px">
blue</td>
</tr>
<tr>
<td
style="border-color:hsl(0, 0%, 0%);border-style:solid;">
line3</td>
<td style="border-color:hsl(0, 0%, 0%);border-style:solid;">
default</td>
<td style="border:2px dashed hsl(30, 75%, 60%);">dashed</td>
<td style="border-color:hsl(0,100%,50%);border-style:solid;">
red</td>
<td style="border:4px solid hsl(0, 0%, 0%);">width: 4px</td>
</tr>
<tr>
<td>line4</td>
<td>none</td>
<td>none</td>
<td>none</td>
<td>none</td>
</tr>
</tbody>
</table>
File renamed without changes.
183 changes: 156 additions & 27 deletions spec/markdown_to_pdf/table_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,33 +134,6 @@
{ x: 306.0, y: 717.012, text: "Text 3" }])
end

it 'creates a html table with cell colors' do
generator.parse_file('table/html_cellcolor.md', { table: { header: { background_color: "F0F0F0" } } })
expect_pdf_color_rects([
["99e64d", 36.0, 728.256, 135.0, 27.744],
["f0f0f0", 171.0, 728.256, 135.0, 27.744],
["f0f0f0", 306.0, 728.256, 135.0, 27.744],
["f0f0f0", 441.0, 728.256, 135.0, 27.744],
["99e64d", 36.0, 700.512, 135.0, 27.744],
["4ce6e6", 171.0, 700.512, 135.0, 27.744],
["1b8ed7", 306.0, 700.512, 135.0, 27.744],
["e64da4", 441.0, 700.512, 135.0, 27.744],
["4ce6e6", 171.0, 672.768, 135.0, 27.744],
["1b8ed7", 306.0, 672.768, 135.0, 27.744],
["e64da4", 441.0, 672.768, 135.0, 27.744]
])
expect_pdf([
{ x: 36.0, y: 744.756, text: "Header with custom cell" },
{ x: 36.0, y: 730.884, text: "color" },
{ x: 36.0, y: 717.012, text: "With multiple colors, last" },
{ x: 36.0, y: 703.14, text: "is selected" },
{ x: 171.0, y: 717.012, text: "HSL color support" },
{ x: 306.0, y: 717.012, text: "RGB color support" },
{ x: 441.0, y: 717.012, text: "Partial RGBA support" },
{ x: 36.0, y: 689.268, text: "Color empty cells to the" },
{ x: 36.0, y: 675.396, text: "right" }])
end

it 'creates a html table with linefeeds inside' do
generator.parse_file('table/linefeed_in_cell.md')
expect_pdf([
Expand Down Expand Up @@ -221,4 +194,160 @@
{ x: 306.0, y: 619.908, text: "First" },
{ x: 306.0, y: 606.036, text: "Second" }])
end

it 'creates a html table with cell colors' do
generator.parse_file('table/html_cellcolor.html', { table: { header: { background_color: "F0F0F0" } } })
expect_pdf_color_rects([
["99e64d", 36.0, 728.256, 135.0, 27.744],
["f0f0f0", 171.0, 728.256, 135.0, 27.744],
["f0f0f0", 306.0, 728.256, 135.0, 27.744],
["f0f0f0", 441.0, 728.256, 135.0, 27.744],
["99e64d", 36.0, 700.512, 135.0, 27.744],
["4ce6e6", 171.0, 700.512, 135.0, 27.744],
["1b8ed7", 306.0, 700.512, 135.0, 27.744],
["e64da4", 441.0, 700.512, 135.0, 27.744],
["4ce6e6", 171.0, 672.768, 135.0, 27.744],
["1b8ed7", 306.0, 672.768, 135.0, 27.744],
["e64da4", 441.0, 672.768, 135.0, 27.744]
])
expect_pdf([
{ x: 36.0, y: 744.756, text: "Header with custom cell" },
{ x: 36.0, y: 730.884, text: "color" },
{ x: 36.0, y: 717.012, text: "With multiple colors, last" },
{ x: 36.0, y: 703.14, text: "is selected" },
{ x: 171.0, y: 717.012, text: "HSL color support" },
{ x: 306.0, y: 717.012, text: "RGB color support" },
{ x: 441.0, y: 717.012, text: "Partial RGBA support" },
{ x: 36.0, y: 689.268, text: "Color empty cells to the" },
{ x: 36.0, y: 675.396, text: "right" }])
end

it 'creates a html table with cell borders' do
generator.parse_file('table/html_borders.html')
expect_pdf_border_rects(
[
7.5, [0.0, 0.0, 0.0],
7.5, [0.0, 0.0, 0.0],
7.5, [0.0, 0.0, 0.0],
7.5, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
1.5, [0.0, 0.0, 0.0],
1.5, [0.0, 0.0, 0.0],
1.5, [0.0, 0.0, 0.0],
1.5, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
2.25, [0.0, 0.34902, 1.0],
2.25, [0.0, 0.34902, 1.0],
2.25, [0.0, 0.34902, 1.0],
2.25, [0.0, 0.34902, 1.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
1.5, [0.90196, 0.6, 0.29804],
1.5, [0.90196, 0.6, 0.29804],
1.5, [0.90196, 0.6, 0.29804],
1.5, [0.90196, 0.6, 0.29804],
1, [0.0, 0.0, 0.0],
0.25, [1.0, 0.0, 0.0],
0.25, [1.0, 0.0, 0.0],
0.25, [1.0, 0.0, 0.0],
0.25, [1.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
3.0, [0.0, 0.0, 0.0],
3.0, [0.0, 0.0, 0.0],
3.0, [0.0, 0.0, 0.0],
3.0, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
0.25, [0.0, 0.0, 0.0],
1, [0.0, 0.0, 0.0]
]
)
expect_pdf([
{ x: 36.0, y: 744.756, text: "dotted" },
{ x: 144.0, y: 744.756, text: "column1" },
{ x: 252.0, y: 744.756, text: "column2" },
{ x: 360.0, y: 744.756, text: "column3" },
{ x: 468.0, y: 744.756, text: "column4" },
{ x: 36.0, y: 730.884, text: "line1" },
{ x: 144.0, y: 730.884, text: "width: 2px" },
{ x: 252.0, y: 730.884, text: "default" },
{ x: 360.0, y: 730.884, text: "default" },
{ x: 468.0, y: 730.884, text: "blue" },
{ x: 36.0, y: 717.012, text: "line3" },
{ x: 144.0, y: 717.012, text: "default" },
{ x: 252.0, y: 717.012, text: "dashed" },
{ x: 360.0, y: 717.012, text: "red" },
{ x: 468.0, y: 717.012, text: "width: 4px" },
{ x: 36.0, y: 703.14, text: "line4" },
{ x: 144.0, y: 703.14, text: "none" },
{ x: 252.0, y: 703.14, text: "none" },
{ x: 360.0, y: 703.14, text: "none" },
{ x: 468.0, y: 703.14, text: "none" }])
end
end
Loading

0 comments on commit 11a4488

Please sign in to comment.