Skip to content

Commit

Permalink
Merge pull request #33 from blocknotes/v0.6.2
Browse files Browse the repository at this point in the history
v0.6.2
  • Loading branch information
blocknotes committed Sep 20, 2021
2 parents 9230efc + 87b66df commit 3bfb469
Show file tree
Hide file tree
Showing 22 changed files with 165 additions and 130 deletions.
56 changes: 28 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,34 +35,34 @@ To check some examples with the PDF output see [examples](examples/) folder.

## Supported tags & attributes

HTML tags:

- **a**: link
- **b**: bold
- **blockquote**: block quotation element
- **br**: new line
- **code**: inline code element
- **del**: strike-through
- **div**: block element
- **em**: italic
- **h1** - **h6**: headings
- **hr**: horizontal line
- **i**: italic
- **ins**: underline
- **img**: image
- **li**: list item
- **mark**: highlight
- **ol**: ordered list
- **p**: block element
- **pre**: preformatted text element
- **s**: strike-through
- **small**: smaller text
- **span**: inline element
- **strong**: bold
- **sub**: subscript element
- **sup**: superscript element
- **u**: underline
- **ul**: unordered list
HTML tags (using MDN definitions):

- **a**: the Anchor element
- **b**: the Bring Attention To element
- **blockquote**: the Block Quotation element
- **br**: the Line Break element
- **code**: the Inline Code element
- **del**: the Deleted Text element
- **div**: the Content Division element
- **em**: the Emphasis element
- **h1** - **h6**: the HTML Section Heading elements
- **hr**: the Thematic Break (Horizontal Rule) element
- **i**: the Idiomatic Text element
- **ins**: the added text element
- **img**: the Image Embed element
- **li**: the list item element
- **mark**: the Mark Text element
- **ol**: the Ordered List element
- **p**: the Paragraph element
- **pre**: the Preformatted Text element
- **s**: the strike-through text element
- **small**: the side comment element
- **span**: the generic inline element
- **strong**: the Strong Importance element
- **sub**: the Subscript element
- **sup**: the Superscript element
- **u**: the Unarticulated Annotation (Underline) element
- **ul**: the Unordered List element

CSS attributes (dimensional units are ignored and considered in pixel):

Expand Down
44 changes: 44 additions & 0 deletions examples/elements.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<title>Supported elements</title>
</head>
<body style="font-family: 'Times-Roman';">
tag A: <a href="https://www.google.com">link</a> <br>
tag B: <b>bold</b> <br>
tag Blockquote: <blockquote>block quotation element</blockquote>
tag Br: new line <br>
tag Code: <code>inline code element</code> <br>
tag Del: <del>strike-through</del> <br>
tag Div: <div>block element</div>
tag Em: <em>italic</em> <br>
tag H1: <h1>heading h1</h1>
tag H2: <h2>heading h2</h2>
tag H3: <h3>heading h3</h3>
tag H4: <h4>heading h4</h4>
tag H5: <h5>heading h5</h5>
tag H6: <h6>heading h6</h6>
tag Hr: horizontal line <hr>
tag I: <i>italic</i> <br>
tag Ins: <ins>underline</ins> <br>
tag Img: <img src="./examples/image.jpg" style="width: 100px"> image <br>
tag Mark: <mark>highlight</mark> <br>
tag Ol: <ol>
<li>ordered list</li>
<li>tag Li: list item (ordered)</li>
</ol>
tag P: <p>block element</p>
tag Pre: <pre>preformatted text element</pre>
tag S: <s>strike-through</s> <br>
tag Small: <small>smaller text</small> <br>
tag Span: <span>inline element</span> <br>
tag Strong: <strong>bold</strong> <br>
tag Sub: <sub>subscript element</sub> <br>
tag Sup: <sup>superscript element</sup> <br>
tag U: <u>underline</u> <br>
tag Ul: <ul>
<li>unordered list</li>
<li>tag Li: list item (unordered)</li>
</ul>
</body>
</html>
Binary file added examples/elements.pdf
Binary file not shown.
Binary file modified examples/headings.pdf
Binary file not shown.
73 changes: 0 additions & 73 deletions examples/misc_elements.html

This file was deleted.

Binary file removed examples/misc_elements.pdf
Binary file not shown.
30 changes: 27 additions & 3 deletions examples/random_content.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,22 @@
<title>Random content</title>
</head>
<body style="font-family: 'Times-Roman';">
<h1>A test document <small>(with the supported elements)</small></h1>
This is <i style="color: #df2818">italic</i>, <u>underline</u> and <b>bold, <i>bold italic</i></b>
<h1>Random content <small>(with various elements and styles)</small></h1>

Test inline elements:
this is <i style="color: #df2818">italic</i>, <u>underline</u> and <b>bold, <i>bold italic</i></b>

<br />
<br />
<br />

<div>div element</div>
<div>div (2) element</div>
<span>span element</span>
<span>span (2) element</span>

<blockquote>The Block Quotation element</blockquote>

<hr style="color: #080" />

<div style="text-align: left">text-align: left</div>
Expand All @@ -26,7 +36,7 @@ <h1>A test document <small>(with the supported elements)</small></h1>
<hr/>

Begin of list
<ul style="margin-bottom: 20px">
<ul>
<li>Level 1a</li>
<li>Level 1b
<ul>
Expand All @@ -35,10 +45,13 @@ <h1>A test document <small>(with the supported elements)</small></h1>
<ul>
<li>Level 3a</li>
<li>Level 3b</li>
<li>Level 3c</li>
</ul>
</li>
<li>Level 2c</li>
</ul>
</li>
<li>Level 1c</li>
</ul>
End of list

Expand Down Expand Up @@ -86,10 +99,21 @@ <h3>More text</h3>
<hr />
<br />

This is an inline <code>code</code> element.
<pre> this is pre element </pre>
last line.

<div style="text-align: center">
An image:<br/>
<img src="./examples/image.jpg" style="width: 50%" />
</div>
<p>Some other paragraph</p>

<div style="color: red; position: absolute; top: 100px; left: 300px">
<em>Position: absolute</em>
</div>

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

<b>End of document</b>
</body>
Expand Down
Binary file modified examples/random_content.pdf
Binary file not shown.
Binary file modified examples/styles.pdf
Binary file not shown.
1 change: 1 addition & 0 deletions lib/prawn-html.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

module PrawnHtml
ADJUST_LEADING = { nil => 0.18, 'Courier' => -0.07, 'Helvetica' => -0.17, 'Times-Roman' => 0.03 }.freeze
PX = 0.6 # conversion constant for pixel sixes

COLORS = {
Expand Down
2 changes: 1 addition & 1 deletion lib/prawn_html/attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def apply_rule!(merged_styles:, rule:, value:, options:)
return (@initial << rule) if value == 'initial'

if rule[:set] == :append_styles
val = Utils.normalize_style(value)
val = Utils.normalize_style(value, rule[:values])
(merged_styles[rule[:key]] ||= []) << val if val
else
opts = rule[:options] ? options[rule[:options]] : nil
Expand Down
9 changes: 8 additions & 1 deletion lib/prawn_html/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,17 @@ def remove_last
last.on_context_remove(self) if last.respond_to?(:on_context_remove)
@merged_styles = nil
@last_text_node = false
@previous_tag = last.tag
@previous_tag = last
pop
end

# White space is equal to 'pre'?
#
# @return [boolean] white space property of the last element is equal to 'pre'
def white_space_pre?
last && last.styles[:white_space] == :pre
end

private

def evaluate_element_styles(element, res)
Expand Down
31 changes: 19 additions & 12 deletions lib/prawn_html/document_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ def initialize(pdf)
@buffer = []
@context = Context.new
@last_margin = 0
@last_text = ''
@last_tag_open = false
@pdf = pdf
end

Expand All @@ -22,6 +24,8 @@ def on_tag_close(element)
render_if_needed(element)
apply_tag_close_styles(element)
context.remove_last
@last_tag_open = false
@last_text = ''
end

# On tag open callback
Expand All @@ -38,6 +42,7 @@ def on_tag_open(tag_name, attributes:, element_styles: '')
options = { width: pdf.page_width, height: pdf.page_height }
tag_class.new(tag_name, attributes: attributes, options: options).tap do |element|
setup_element(element, element_styles: element_styles)
@last_tag_open = true
end
end

Expand All @@ -47,9 +52,10 @@ def on_tag_open(tag_name, attributes:, element_styles: '')
#
# @return [NilClass] nil value (=> no element)
def on_text_node(content)
return if content.match?(/\A\s*\Z/)
return if context.previous_tag&.block? && content.match?(/\A\s*\Z/)

buffer << context.merged_styles.merge(text: prepare_text(content))
text = prepare_text(content)
buffer << context.merged_styles.merge(text: text) unless text.empty?
context.last_text_node = true
nil
end
Expand All @@ -70,17 +76,13 @@ def render
attr_reader :buffer, :context, :last_margin, :pdf

def setup_element(element, element_styles:)
add_space_if_needed unless render_if_needed(element)
render_if_needed(element)
context.add(element)
element.process_styles(element_styles: element_styles)
apply_tag_open_styles(element)
element.custom_render(pdf, context) if element.respond_to?(:custom_render)
end

def add_space_if_needed
buffer << SPACE if buffer.any? && !context.last_text_node && ![NEW_LINE, SPACE].include?(buffer.last)
end

def render_if_needed(element)
render_needed = element&.block? && buffer.any? && buffer.last != NEW_LINE
return false unless render_needed
Expand All @@ -104,10 +106,12 @@ def apply_tag_open_styles(element)
end

def prepare_text(content)
white_space_pre = context.last && context.last.styles[:white_space] == :pre
text = ::Oga::HTML::Entities.decode(context.before_content)
text += white_space_pre ? content : content.gsub(/\A\s*\n\s*|\s*\n\s*\Z/, '').delete("\n").squeeze(' ')
text
text = context.before_content ? ::Oga::HTML::Entities.decode(context.before_content) : ''
return (@last_text = text + content) if context.white_space_pre?

content = content.lstrip if @last_text[-1] == ' ' || @last_tag_open
text += content.tr("\n", ' ').squeeze(' ')
@last_text = text
end

def output_content(buffer, block_styles)
Expand All @@ -129,7 +133,10 @@ def apply_callbacks(buffer)
def adjust_leading(buffer, leading)
return leading if leading

(buffer.map { |item| item[:size] || Context::DEFAULT_STYLES[:size] }.max * 0.055).round(4)
leadings = buffer.map do |item|
(item[:size] || Context::DEFAULT_STYLES[:size]) * (ADJUST_LEADING[item[:font]] || ADJUST_LEADING[nil])
end
leadings.max.round(4)
end

def bounds(buffer, options, block_styles)
Expand Down
2 changes: 1 addition & 1 deletion lib/prawn_html/tags/br.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def block?
end

def custom_render(pdf, context)
return if context.last_text_node || context.previous_tag != :br
return if context.last_text_node || !context.previous_tag.is_a?(Br)

pdf.advance_cursor(BR_SPACING)
end
Expand Down
6 changes: 4 additions & 2 deletions lib/prawn_html/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,13 @@ def copy_value(value, options: nil)
# Normalize a style value
#
# @param value [String] string value
# @param accepted_values [Array] allowlist of valid values (symbols)
#
# @return [Symbol] style value or nil
def normalize_style(value)
def normalize_style(value, accepted_values)
val = value&.strip&.downcase
NORMALIZE_STYLES[val]
ret = NORMALIZE_STYLES[val]
accepted_values.include?(ret) ? ret : nil
end

# Unquotes a string
Expand Down
Loading

0 comments on commit 3bfb469

Please sign in to comment.