proforma-prawn-renderer 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 023bb2b06bdf92d4065a6c52bf6e6e522e21bf20ffe1c058797a68c8c83455bc
4
- data.tar.gz: 9553acd72e862cff0b2d1b186bffd646187f51b17a9cf543f2ae3add94a3d3d6
3
+ metadata.gz: e102e10642ac6d4cd56c0d2be9143dcf646f58a8eecd5fa27e870f38e7635539
4
+ data.tar.gz: 21e212f81d1a5941f5b14ac8a769e9b598b574ef614f2235b19e152e13229ca7
5
5
  SHA512:
6
- metadata.gz: 204cabc54005e2f46ea269a8de1a4353ceffb952bb75af3de0051239bb78ff20f2d37bbcbdc3687b2a134f455dcb2c99fb3067ca296feda338d630eb7ad0c18a
7
- data.tar.gz: e789d0114fa922808f7b373e0c2cae1044a53fb102a1a838a5e179d440fb2e7f123aa4016b536c509ad2d88e8d3529d4fb3920779aa10dde9b754d167d8f29b8
6
+ metadata.gz: 031420d94dc6a34f808fa04e7e05ce91f04397306378d2b6429026aee6b0c5bb548d47f5a6827419aceab97af0bedcd8e72b2a88206fca089c6e1361259d85c8
7
+ data.tar.gz: b6839ef41b244af0e93dd2f66a0cac51f7e3b70a3720892a357c4f464eebae85472bdee938fcc196a62633c0399d1b5e49112cf821a09474bd0b0606c745cd61
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # 1.1.0 (July 25th, 2019)
2
+
3
+ * Added support for external font loading.
4
+
1
5
  # 1.0.3 (July 7th, 2019)
2
6
 
3
7
  * Added better pane width balancing algorithm that fixes some width assignment bugs.
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- proforma-prawn-renderer (1.0.3)
4
+ proforma-prawn-renderer (1.1.0)
5
+ acts_as_hashable (~> 1)
5
6
  prawn (~> 2)
6
7
  prawn-table (~> 0)
7
8
  proforma (~> 1)
data/README.md CHANGED
@@ -79,16 +79,45 @@ The `contents` attribute will contain the native PDF data.
79
79
 
80
80
  ### Prawn Customization
81
81
 
82
- All options for Prawn are passed through the Proforma::PrawnRenderer::Options object:
82
+ All options for Prawn are passed through the Util::Options object:
83
83
 
84
- Name | Default
85
- ---------------- | -------
86
- bold_font_style | bold
87
- header_font_size | 15
88
- text_font_size | 10
89
- font_name | null
84
+ Name | Default | Type
85
+ ---------------- | ------- | -----------------
86
+ bold_font_style | bold | symbol or string
87
+ header_font_size | 15 | number
88
+ text_font_size | 10 | number
89
+ font_name | nil | nil or string
90
+ fonts | [] | array of Util::Font objects or hashes with same attribute keys.
90
91
 
91
- These options will be used during the PDF rendering process.
92
+ You can choose to pass in either a Util::Options instance or a hash with the same attribute keys. These options will be used during the PDF rendering process.
93
+
94
+ ### Custom Fonts
95
+
96
+ The fonts option above allows you to specify different fonts to use. This is particularly useful if you wish to use fonts that better support internationalization. Here is an example of defining and using a custom font:
97
+
98
+ ````
99
+ options = {
100
+ font_name: 'Tuffy',
101
+ fonts: [
102
+ {
103
+ bold_path: File.join('fonts', 'Tuffy_Bold.ttf'),
104
+ name: 'Tuffy',
105
+ normal_path: File.join('fonts', 'Tuffy.ttf')
106
+ }
107
+ ]
108
+ }
109
+
110
+ renderer = Proforma::PrawnRenderer.new(options)
111
+
112
+ # ...
113
+ # Omitted data declaration
114
+ # Omitted template declaration
115
+ # ...
116
+
117
+ documents = Proforma.render(data, template, renderer: renderer)
118
+ ````
119
+
120
+ Note: Update the paths to reflect the actual locations on your machine/server.
92
121
 
93
122
  ## Contributing
94
123
 
@@ -7,6 +7,7 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
+ require 'acts_as_hashable'
10
11
  require 'forwardable'
11
12
  require 'prawn'
12
13
  require 'prawn/table'
@@ -20,19 +21,14 @@ require_relative 'prawn_renderer/separator_renderer'
20
21
  require_relative 'prawn_renderer/spacer_renderer'
21
22
  require_relative 'prawn_renderer/table_renderer'
22
23
  require_relative 'prawn_renderer/text_renderer'
24
+ require_relative 'prawn_renderer/util/font'
25
+ require_relative 'prawn_renderer/util/options'
23
26
 
24
27
  module Proforma
25
28
  # This main class to use as a Proforma renderer.
26
29
  class PrawnRenderer
27
30
  EXTENSION = '.pdf'
28
31
 
29
- DEFAULT_OPTIONS = {
30
- bold_font_style: :bold,
31
- font_name: nil,
32
- text_font_size: 10,
33
- header_font_size: 15
34
- }.freeze
35
-
36
32
  RENDERERS = {
37
33
  Modeling::Banner => BannerRenderer,
38
34
  Modeling::Header => HeaderRenderer,
@@ -48,7 +44,7 @@ module Proforma
48
44
  attr_reader :options
49
45
 
50
46
  def initialize(options = {})
51
- @options = OpenStruct.new(DEFAULT_OPTIONS.merge(options))
47
+ @options = Util::Options.make(options)
52
48
 
53
49
  clear
54
50
  end
@@ -70,13 +66,23 @@ module Proforma
70
66
  attr_reader :pdf, :renderers
71
67
 
72
68
  def clear
73
- @pdf = Prawn::Document.new
69
+ @pdf = fresh_pdf
74
70
 
75
71
  @renderers = RENDERERS.each_with_object({}) do |(model_class, renderer_class), hash|
76
72
  hash[model_class] = renderer_class.new(pdf, options)
77
73
  end
78
74
  end
79
75
 
76
+ def fresh_pdf
77
+ Prawn::Document.new.tap do |p|
78
+ options.fonts.each do |font|
79
+ p.font_families.update(font.prawn_config)
80
+ end
81
+
82
+ p.font(options.font_name)
83
+ end
84
+ end
85
+
80
86
  def render_children(children)
81
87
  children.each do |child|
82
88
  raise ArgumentError, "Cannot render: #{child.class.name}" unless renderable?(child)
@@ -13,6 +13,9 @@ module Proforma
13
13
  class PrawnRenderer
14
14
  # This class understands how to ender a Proforma::Modeling::Banner component.
15
15
  class BannerRenderer < Renderer
16
+ PAD_LEFT = [0, 0, 0, 10].freeze
17
+ NO_PADDING = [0, 0, 0, 0].freeze
18
+
16
19
  def render(banner)
17
20
  pdf.table(
18
21
  make_rows(banner),
@@ -64,7 +67,6 @@ module Proforma
64
67
  def cell_style
65
68
  @cell_style ||= {
66
69
  border_width: 0,
67
- font: font_name,
68
70
  min_font_size: 1,
69
71
  overflow: :shrink_to_fit,
70
72
  padding: 0,
@@ -73,7 +75,7 @@ module Proforma
73
75
  end
74
76
 
75
77
  def text_cell_style(pad_left)
76
- padding = pad_left ? [0, 0, 0, 10] : [0, 0, 0, 0]
78
+ padding = pad_left ? PAD_LEFT : NO_PADDING
77
79
 
78
80
  cell_style.merge(
79
81
  inline_format: true,
@@ -16,7 +16,6 @@ module Proforma
16
16
  def render(text)
17
17
  pdf.text(
18
18
  text.value.to_s,
19
- font: font_name,
20
19
  size: header_font_size,
21
20
  style: bold_font_style
22
21
  )
@@ -7,7 +7,7 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- require_relative 'balanced_set'
10
+ require_relative 'util/balanced_set'
11
11
  require_relative 'renderer'
12
12
 
13
13
  module Proforma
@@ -81,16 +81,15 @@ module Proforma
81
81
  def make_column_widths(columns)
82
82
  widths = columns.map { |col| [col.label_width, col.value_width] }.flatten
83
83
 
84
- BalancedSet.calculate(widths, 100)
85
- .map
86
- .with_index { |v, i| [i, calculate_width(v)] }
87
- .to_h
84
+ Util::BalancedSet.calculate(widths, 100)
85
+ .map
86
+ .with_index { |v, i| [i, calculate_width(v)] }
87
+ .to_h
88
88
  end
89
89
 
90
90
  def base_value_cell_style
91
91
  @base_value_cell_style ||= {
92
92
  border_width: 0,
93
- font: font_name,
94
93
  min_font_size: 1,
95
94
  overflow: :shrink_to_fit,
96
95
  padding: [2, 0, 2, 2],
@@ -59,7 +59,6 @@ module Proforma
59
59
  def cell_style
60
60
  @cell_style ||= {
61
61
  border_width: 0.5,
62
- font: font_name,
63
62
  min_font_size: 1,
64
63
  overflow: :shrink_to_fit,
65
64
  padding: 3,
@@ -16,7 +16,6 @@ module Proforma
16
16
  def render(text)
17
17
  pdf.text(
18
18
  text.value.to_s,
19
- font: font_name,
20
19
  size: text_font_size
21
20
  )
22
21
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2019-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ module Proforma
11
+ class PrawnRenderer
12
+ module Util
13
+ # This class can balance out an un-even set of values.
14
+ class BalancedSet
15
+ class << self
16
+ def calculate(values, sum, round: 2)
17
+ free_spots = values.count(&:nil?)
18
+
19
+ if free_spots.positive?
20
+ available_value = sum - values.map(&:to_f).reduce(0, :+)
21
+
22
+ new_values = divide(free_spots, available_value, round)
23
+
24
+ values = values.map { |v| v || new_values.shift }
25
+ end
26
+
27
+ balance(values, sum, round)
28
+ end
29
+
30
+ private
31
+
32
+ def balance(values, sum, round)
33
+ difference = sum - values.map(&:to_f).reduce(0, :+)
34
+
35
+ return values if difference.zero?
36
+
37
+ diff_spots = divide(values.length, difference, round)
38
+
39
+ values.map.with_index { |value, index| value + diff_spots[index] }
40
+ end
41
+
42
+ def divide(count, sum, round)
43
+ spot_value = (sum / count.to_f).round(round)
44
+
45
+ remainder = sum - (spot_value * count)
46
+
47
+ Array.new(count) { |i| i.zero? ? spot_value + remainder : spot_value }
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2019-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ module Proforma
11
+ class PrawnRenderer
12
+ module Util
13
+ # Defines what we & prawn need in a font.
14
+ class Font
15
+ acts_as_hashable
16
+
17
+ attr_reader :bold_path,
18
+ :name,
19
+ :normal_path
20
+
21
+ def initialize(bold_path:, name:, normal_path:)
22
+ raise ArgumentError, 'bold_path is required' if bold_path.to_s.empty?
23
+ raise ArgumentError, 'name is required' if name.to_s.empty?
24
+ raise ArgumentError, 'normal_path is required' if normal_path.to_s.empty?
25
+
26
+ @bold_path = bold_path
27
+ @name = name
28
+ @normal_path = normal_path
29
+
30
+ freeze
31
+ end
32
+
33
+ def prawn_config
34
+ {
35
+ name.to_s => {
36
+ normal: normal_path.to_s,
37
+ bold: bold_path.to_s
38
+ }
39
+ }
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2019-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ module Proforma
11
+ class PrawnRenderer
12
+ module Util
13
+ # Defines what is allowed to be customized per rendering.
14
+ class Options
15
+ acts_as_hashable
16
+
17
+ attr_reader :bold_font_style,
18
+ :font_name,
19
+ :fonts,
20
+ :header_font_size,
21
+ :text_font_size
22
+
23
+ def initialize(
24
+ bold_font_style: :bold,
25
+ font_name: nil,
26
+ fonts: [],
27
+ text_font_size: 10,
28
+ header_font_size: 15
29
+ )
30
+ @bold_font_style = bold_font_style
31
+ @font_name = font_name
32
+ @fonts = Font.array(fonts)
33
+ @text_font_size = text_font_size
34
+ @header_font_size = header_font_size
35
+
36
+ freeze
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -9,6 +9,6 @@
9
9
 
10
10
  module Proforma
11
11
  class PrawnRenderer
12
- VERSION = '1.0.3'
12
+ VERSION = '1.1.0'
13
13
  end
14
14
  end
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.required_ruby_version = '>= 2.3.8'
23
23
 
24
+ s.add_dependency('acts_as_hashable', '~>1')
24
25
  s.add_dependency('prawn', '~>2')
25
26
  s.add_dependency('prawn-table', '~>0')
26
27
  s.add_dependency('proforma', '~>1')
Binary file
Binary file
@@ -9,7 +9,7 @@
9
9
 
10
10
  require './spec/spec_helper'
11
11
 
12
- describe ::Proforma::PrawnRenderer::BalancedSet do
12
+ describe ::Proforma::PrawnRenderer::Util::BalancedSet do
13
13
  describe '#calculate' do
14
14
  specify 'with no explicit values' do
15
15
  expect(described_class.calculate([nil], 100)).to eq([100])
@@ -112,6 +112,43 @@ describe ::Proforma::PrawnRenderer do
112
112
  ]
113
113
  }
114
114
 
115
- Proforma.render(data, template, renderer: Proforma::PrawnRenderer.new)
115
+ actual_documents = Proforma.render(data, template, renderer: Proforma::PrawnRenderer.new)
116
+
117
+ expect(actual_documents.length).to eq(1)
118
+ end
119
+
120
+ specify 'Custom fonts can be used' do
121
+ data = [{ name: '井友' }]
122
+
123
+ template = {
124
+ children: [
125
+ { type: 'Header', value: '井友' },
126
+ { type: 'Header', value: 'Text - 井友' },
127
+ { type: 'Separator' },
128
+ {
129
+ type: 'DataTable',
130
+ columns: [
131
+ { header: '井友', body: '$name' }
132
+ ]
133
+ }
134
+ ]
135
+ }
136
+
137
+ options = {
138
+ font_name: 'Tuffy',
139
+ fonts: [
140
+ {
141
+ bold_path: File.join(Dir.pwd, 'spec', 'fixtures', 'fonts', 'Tuffy_Bold.ttf'),
142
+ name: 'Tuffy',
143
+ normal_path: File.join(Dir.pwd, 'spec', 'fixtures', 'fonts', 'Tuffy.ttf')
144
+ }
145
+ ]
146
+ }
147
+
148
+ renderer = Proforma::PrawnRenderer.new(options)
149
+
150
+ actual_documents = Proforma.render(data, template, renderer: renderer)
151
+
152
+ expect(actual_documents.length).to eq(1)
116
153
  end
117
154
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: proforma-prawn-renderer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Ruggio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-08 00:00:00.000000000 Z
11
+ date: 2019-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: acts_as_hashable
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: prawn
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -203,7 +217,6 @@ files:
203
217
  - bin/console
204
218
  - bin/render
205
219
  - lib/proforma/prawn_renderer.rb
206
- - lib/proforma/prawn_renderer/balanced_set.rb
207
220
  - lib/proforma/prawn_renderer/banner_renderer.rb
208
221
  - lib/proforma/prawn_renderer/header_renderer.rb
209
222
  - lib/proforma/prawn_renderer/pane_renderer.rb
@@ -212,13 +225,18 @@ files:
212
225
  - lib/proforma/prawn_renderer/spacer_renderer.rb
213
226
  - lib/proforma/prawn_renderer/table_renderer.rb
214
227
  - lib/proforma/prawn_renderer/text_renderer.rb
228
+ - lib/proforma/prawn_renderer/util/balanced_set.rb
229
+ - lib/proforma/prawn_renderer/util/font.rb
230
+ - lib/proforma/prawn_renderer/util/options.rb
215
231
  - lib/proforma/prawn_renderer/version.rb
216
232
  - proforma-prawn-renderer.gemspec
217
233
  - spec/fixtures/component_test.pdf
218
234
  - spec/fixtures/component_test.yml
235
+ - spec/fixtures/fonts/Tuffy.ttf
236
+ - spec/fixtures/fonts/Tuffy_Bold.ttf
219
237
  - spec/fixtures/snapshots/user_details.yml
220
238
  - spec/fixtures/snapshots/user_list.yml
221
- - spec/proforma/prawn_renderer/balanced_set_spec.rb
239
+ - spec/proforma/prawn_renderer/util/balanced_set_spec.rb
222
240
  - spec/proforma/prawn_renderer_spec.rb
223
241
  - spec/spec_helper.rb
224
242
  homepage: https://github.com/bluemarblepayroll/proforma-prawn-renderer
@@ -247,8 +265,10 @@ summary: Proforma renderer plugin for generating PDFs using Prawn
247
265
  test_files:
248
266
  - spec/fixtures/component_test.pdf
249
267
  - spec/fixtures/component_test.yml
268
+ - spec/fixtures/fonts/Tuffy.ttf
269
+ - spec/fixtures/fonts/Tuffy_Bold.ttf
250
270
  - spec/fixtures/snapshots/user_details.yml
251
271
  - spec/fixtures/snapshots/user_list.yml
252
- - spec/proforma/prawn_renderer/balanced_set_spec.rb
272
+ - spec/proforma/prawn_renderer/util/balanced_set_spec.rb
253
273
  - spec/proforma/prawn_renderer_spec.rb
254
274
  - spec/spec_helper.rb
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright (c) 2019-present, Blue Marble Payroll, LLC
5
- #
6
- # This source code is licensed under the MIT license found in the
7
- # LICENSE file in the root directory of this source tree.
8
- #
9
-
10
- module Proforma
11
- class PrawnRenderer
12
- # This class can balance out an un-even set of values.
13
- class BalancedSet
14
- class << self
15
- def calculate(values, sum, round: 2)
16
- free_spots = values.count(&:nil?)
17
-
18
- if free_spots.positive?
19
- available_value = sum - values.map(&:to_f).reduce(0, :+)
20
-
21
- new_values = divide(free_spots, available_value, round)
22
-
23
- values = values.map { |v| v || new_values.shift }
24
- end
25
-
26
- balance(values, sum, round)
27
- end
28
-
29
- private
30
-
31
- def balance(values, sum, round)
32
- difference = sum - values.map(&:to_f).reduce(0, :+)
33
-
34
- return values if difference.zero?
35
-
36
- diff_spots = divide(values.length, difference, round)
37
-
38
- values.map.with_index { |value, index| value + diff_spots[index] }
39
- end
40
-
41
- def divide(count, sum, round)
42
- spot_value = (sum / count.to_f).round(round)
43
-
44
- remainder = sum - (spot_value * count)
45
-
46
- Array.new(count) { |i| i.zero? ? spot_value + remainder : spot_value }
47
- end
48
- end
49
- end
50
- end
51
- end