Skip to content

Commit

Permalink
Merge branch 'v0.3.2' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
blocknotes committed Aug 27, 2021
2 parents a243736 + cb70897 commit 326e330
Show file tree
Hide file tree
Showing 35 changed files with 514 additions and 243 deletions.
4 changes: 4 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ Naming/FileName:
Exclude:
- lib/prawn-html.rb

Naming/MethodParameterName:
Exclude:
- lib/prawn_html/pdf_wrapper.rb

RSpec/ExampleLength:
# default: 5
Max: 10
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ HTML tags:
CSS attributes (dimensional units are ignored and considered in pixel):

- **background**: for *mark* tag (3/6 hex digits or RGB or color name), ex. `style="background: #FECD08"`
- **break-after**: go to a new page after some elements, ex. `style="break-after: auto"`
- **break-before**: go to a new page before some elements, ex. `style="break-before: auto"`
- **color**: (3/6 hex digits or RGB or color name) ex. `style="color: #FB1"`
- **font-family**: font must be registered, quotes are optional, ex. `style="font-family: Courier"`
- **font-size**: ex. `style="font-size: 20px"`
Expand Down
4 changes: 4 additions & 0 deletions examples/misc_elements.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
</head>
<body>
<div style="font-family: 'Times-Roman';">
<h2>Misc elements</h2>

<i>i element</i>
<b>b element</b>
<u>u element</u>
Expand Down Expand Up @@ -36,6 +38,8 @@
<li>Level 1c</li>
</ul>

<h2 style="break-before: auto">New page</h2>

HTML entities: &euro; &times; &divide; &half; &laquo; &raquo; &copy;

<p>p element</p>
Expand Down
Binary file modified examples/misc_elements.pdf
Binary file not shown.
9 changes: 6 additions & 3 deletions lib/prawn-html.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

require 'prawn'

module PrawnHtml
PX = 0.66 # conversion constant for pixel sixes

Expand Down Expand Up @@ -157,13 +155,17 @@ module PrawnHtml
}.freeze

def append_html(pdf, html)
html_parser = PrawnHtml::HtmlParser.new(pdf)
pdf_wrapper = PdfWrapper.new(pdf)
renderer = DocumentRenderer.new(pdf_wrapper)
html_parser = PrawnHtml::HtmlParser.new(renderer)
html_parser.process(html)
end

module_function :append_html
end

require 'prawn'

require 'prawn_html/utils'

require 'prawn_html/tag'
Expand All @@ -172,5 +174,6 @@ def append_html(pdf, html)

require 'prawn_html/attributes'
require 'prawn_html/context'
require 'prawn_html/pdf_wrapper'
require 'prawn_html/document_renderer'
require 'prawn_html/html_parser'
6 changes: 4 additions & 2 deletions lib/prawn_html/attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ class Attributes < OpenStruct

STYLES_APPLY = {
block: %i[align leading left margin_left padding_left position top],
tag_close: %i[margin_bottom padding_bottom],
tag_open: %i[margin_top padding_top],
tag_close: %i[margin_bottom padding_bottom break_after],
tag_open: %i[margin_top padding_top break_before],
text_node: %i[background callback character_spacing color font link list_style_type size styles]
}.freeze

Expand All @@ -27,9 +27,11 @@ class Attributes < OpenStruct
'list-style-type' => { key: :list_style_type, set: :unquote },
'text-decoration' => { key: :styles, set: :append_symbol },
# tag opening styles
'break-before' => { key: :break_before, set: :convert_symbol },
'margin-top' => { key: :margin_top, set: :convert_size },
'padding-top' => { key: :padding_top, set: :convert_size },
# tag closing styles
'break-after' => { key: :break_after, set: :convert_symbol },
'margin-bottom' => { key: :margin_bottom, set: :convert_size },
'padding-bottom' => { key: :padding_bottom, set: :convert_size },
# block styles
Expand Down
6 changes: 2 additions & 4 deletions lib/prawn_html/callbacks/highlight.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ def initialize(pdf, item)
end

def render_behind(fragment)
original_color = @pdf.fill_color
@pdf.fill_color = @color
@pdf.fill_rectangle(fragment.top_left, fragment.width, fragment.height)
@pdf.fill_color = original_color
top, left = fragment.top_left
@pdf.draw_rectangle(x: left, y: top, width: fragment.width, height: fragment.height, color: @color)
end
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/prawn_html/callbacks/strike_through.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ def initialize(pdf, _item)
end

def render_in_front(fragment)
y = (fragment.top_left[1] + fragment.bottom_left[1]) / 2
@pdf.stroke do
@pdf.line [fragment.top_left[0], y], [fragment.top_right[0], y]
end
x1 = fragment.left
x2 = fragment.right
y = (fragment.top + fragment.bottom) / 2
@pdf.underline(x1: x1, x2: x2, y: y)
end
end
end
Expand Down
21 changes: 6 additions & 15 deletions lib/prawn_html/document_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class DocumentRenderer

# Init the DocumentRenderer
#
# @param pdf [Prawn::Document] target Prawn PDF document
# @param pdf [PdfWrapper] target PDF wrapper
def initialize(pdf)
@buffer = []
@context = Context.new
Expand Down Expand Up @@ -103,32 +103,23 @@ def render_if_needed(element)
def apply_tag_close_styles(element)
tag_styles = element.tag_close_styles
context.last_margin = tag_styles[:margin_bottom].to_f
move_down = context.last_margin + tag_styles[:padding_bottom].to_f
pdf.move_down(move_down) if move_down > 0
pdf.advance_cursor(context.last_margin + tag_styles[:padding_bottom].to_f)
pdf.start_new_page if tag_styles[:break_after]
end

def apply_tag_open_styles(element)
tag_styles = element.tag_open_styles
move_down = (tag_styles[:margin_top].to_f - context.last_margin) + tag_styles[:padding_top].to_f
pdf.move_down(move_down) if move_down > 0
pdf.advance_cursor(move_down) if move_down > 0
pdf.start_new_page if tag_styles[:break_before]
end

def output_content(buffer, block_styles)
buffer.each { |item| item[:callback] = item[:callback].new(pdf, item) if item[:callback] }
left_indent = block_styles[:margin_left].to_f + block_styles[:padding_left].to_f
options = block_styles.slice(:align, :leading, :mode, :padding_left)
options[:indent_paragraphs] = left_indent if left_indent > 0
formatted_text(buffer, options, bounding_box: bounds(block_styles))
end

def formatted_text(buffer, options, bounding_box: nil)
return pdf.formatted_text(buffer, options) unless bounding_box

current_y = pdf.cursor
pdf.bounding_box(*bounding_box) do
pdf.formatted_text(buffer, options)
end
pdf.move_cursor_to(current_y)
pdf.puts(buffer, options, bounding_box: bounds(block_styles))
end

def bounds(block_styles)
Expand Down
8 changes: 4 additions & 4 deletions lib/prawn_html/html_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ module PrawnHtml
class HtmlParser
# Init the HtmlParser
#
# @param pdf [Prawn::Document] Target Prawn PDF document
def initialize(pdf)
# @param renderer [DocumentRenderer] document renderer
def initialize(renderer)
@processing = false
@renderer = DocumentRenderer.new(pdf)
@renderer = renderer
end

# Processes HTML and renders it on the PDF document
# Processes HTML and renders it
#
# @param html [String] The HTML content to process
def process(html)
Expand Down
94 changes: 94 additions & 0 deletions lib/prawn_html/pdf_wrapper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# frozen_string_literal: true

require 'forwardable'

module PrawnHtml
class PdfWrapper
extend Forwardable

def_delegators :@pdf, :bounds, :start_new_page

# Wrapper for Prawn PDF Document
#
# @param pdf_document [Prawn::Document] PDF document to wrap
def initialize(pdf_document)
@pdf = pdf_document
end

# Advance the cursor
#
# @param move_down [Float] Quantity to advance (move down)
def advance_cursor(move_down)
return if !move_down || move_down == 0

pdf.move_down(move_down)
end

# Draw a rectangle
#
# @param x [Float] left position of the rectangle
# @param y [Float] top position of the rectangle
# @param width [Float] width of the rectangle
# @param height [Float] height of the rectangle
# @param color [String] fill color
def draw_rectangle(x:, y:, width:, height:, color:)
current_fill_color = pdf.fill_color
pdf.fill_color = color
pdf.fill_rectangle([y, x], width, height)
pdf.fill_color = current_fill_color
end

# Horizontal line
#
# @param color [String] line color
# @param dash [Integer|Array] integer or array of integer with dash options
def horizontal_rule(color:, dash:)
current_color = pdf.stroke_color
pdf.dash(dash) if dash
pdf.stroke_color = color if color
pdf.stroke_horizontal_rule
pdf.stroke_color = current_color if color
pdf.undash if dash
end

# Image
#
# @param src [String] image source path
# @param options [Hash] hash of options
def image(src, options = {})
return unless src

pdf.image(src, options)
end

# Output to the PDF document
#
# @param buffer [Array] array of text items
# @param options [Hash] hash of options
# @param bounding_box [Array] bounding box arguments, if bounded
def puts(buffer, options, bounding_box: nil)
return pdf.formatted_text(buffer, options) unless bounding_box

current_y = pdf.cursor
pdf.bounding_box(*bounding_box) do
pdf.formatted_text(buffer, options)
end
pdf.move_cursor_to(current_y)
end

# Underline
#
# @param x1 [Float] left position of the line
# @param x2 [Float] right position of the line
# @param y [Float] vertical position of the line
def underline(x1:, x2:, y:)
pdf.stroke do
pdf.line [x1, y], [x2, y]
end
end

private

attr_reader :pdf
end
end
5 changes: 2 additions & 3 deletions lib/prawn_html/tags/br.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Tags
class Br < Tag
ELEMENTS = [:br].freeze

BR_SPACING = 12
BR_SPACING = Utils.convert_size('12')

def block?
true
Expand All @@ -14,8 +14,7 @@ def block?
def custom_render(pdf, context)
return if context.last_text_node

@spacing ||= Utils.convert_size(BR_SPACING.to_s)
pdf.move_down(@spacing)
pdf.advance_cursor(BR_SPACING)
end
end
end
Expand Down
14 changes: 2 additions & 12 deletions lib/prawn_html/tags/hr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ def block?
end

def custom_render(pdf, _context)
dash = parse_dash_value(attrs.data['dash']) if attrs.data.include?('dash')
around_stroke(pdf, old_color: pdf.stroke_color, new_color: attrs.styles[:color], dash: dash) do
pdf.stroke_horizontal_rule
end
dash = attrs.data.include?('dash') ? parse_dash_value(attrs.data['dash']) : nil
pdf.horizontal_rule(color: attrs.styles[:color], dash: dash)
end

def tag_styles
Expand All @@ -28,14 +26,6 @@ def tag_styles

private

def around_stroke(pdf, old_color:, new_color:, dash:)
pdf.dash(dash) if dash
pdf.stroke_color = new_color if new_color
yield
pdf.stroke_color = old_color if new_color
pdf.undash if dash
end

def parse_dash_value(dash_string)
if dash_string.match? /\A\d+\Z/
dash_string.to_i
Expand Down
2 changes: 1 addition & 1 deletion lib/prawn_html/tags/img.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def custom_render(pdf, context)
parsed_styles = Attributes.parse_styles(attrs.style)
block_styles = context.block_styles
evaluated_styles = evaluate_styles(pdf, block_styles.merge(parsed_styles))
pdf.image(@attrs.src, evaluated_styles) if @attrs.src
pdf.image(@attrs.src, evaluated_styles)
end

private
Expand Down
2 changes: 1 addition & 1 deletion lib/prawn_html/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def convert_size(value, container_size = nil)
if container_size && value.include?('%')
val.to_f * container_size * 0.01
else
val.to_f * PX
val.to_f * PrawnHtml::PX
end
val.round(4)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/prawn_html/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module PrawnHtml # :nodoc:
VERSION = '0.3.0'
VERSION = '0.3.2'
end
14 changes: 9 additions & 5 deletions spec/integrations/blocks_spec.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
# frozen_string_literal: true

RSpec.describe 'Blocks' do
let(:pdf_doc) { TestUtils.styled_text_document(html) }
let(:pdf) { Prawn::Document.new(page_size: 'A4', page_layout: :portrait) }
let(:size) { PrawnHtml::Context::DEF_FONT_SIZE }

before do
PrawnHtml.append_html(pdf, html)
end

context 'with some content in an element div' do
let(:html) { '<div>Some content in a element div</div>' }

let(:expected_content) { ['Some content in a element div'] }
let(:expected_positions) do
[[
pdf_doc.page.margins[:left],
(pdf_doc.y - TestUtils.default_font.ascender).round(4)
pdf.page.margins[:left],
(pdf.y - TestUtils.default_font.ascender).round(4)
]]
end
let(:expected_font_settings) { [{ name: TestUtils.default_font_family, size: size }] }
Expand All @@ -25,8 +29,8 @@
let(:expected_content) { ['Some content in a element p'] }
let(:expected_positions) do
margin = PrawnHtml::Utils.convert_size(PrawnHtml::Tags::P::MARGIN_TOP.to_s)
y = pdf_doc.y - TestUtils.default_font.ascender - margin
[[pdf_doc.page.margins[:left], y.round(4)]]
y = pdf.y - TestUtils.default_font.ascender - margin
[[pdf.page.margins[:left], y.round(4)]]
end
let(:expected_font_settings) { [{ name: TestUtils.default_font_family, size: size }] }

Expand Down
Loading

0 comments on commit 326e330

Please sign in to comment.