prawn 2.3.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/prawn/document/bounding_box.rb +223 -143
- data/lib/prawn/document/column_box.rb +61 -26
- data/lib/prawn/document/internals.rb +25 -16
- data/lib/prawn/document/span.rb +21 -18
- data/lib/prawn/document.rb +273 -182
- data/lib/prawn/encoding.rb +2 -5
- data/lib/prawn/errors.rb +23 -34
- data/lib/prawn/font.rb +254 -139
- data/lib/prawn/font_metric_cache.rb +18 -16
- data/lib/prawn/fonts/afm.rb +99 -57
- data/lib/prawn/fonts/dfont.rb +7 -1
- data/lib/prawn/fonts/otf.rb +4 -1
- data/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
- data/lib/prawn/fonts/ttc.rb +7 -2
- data/lib/prawn/fonts/ttf.rb +345 -107
- data/lib/prawn/fonts.rb +14 -0
- data/lib/prawn/graphics/blend_mode.rb +25 -28
- data/lib/prawn/graphics/cap_style.rb +9 -12
- data/lib/prawn/graphics/color.rb +75 -50
- data/lib/prawn/graphics/dash.rb +45 -42
- data/lib/prawn/graphics/join_style.rb +18 -12
- data/lib/prawn/graphics/patterns.rb +239 -110
- data/lib/prawn/graphics/transformation.rb +51 -44
- data/lib/prawn/graphics/transparency.rb +16 -40
- data/lib/prawn/graphics.rb +370 -260
- data/lib/prawn/grid.rb +219 -57
- data/lib/prawn/image_handler.rb +27 -10
- data/lib/prawn/images/image.rb +8 -10
- data/lib/prawn/images/jpg.rb +46 -20
- data/lib/prawn/images/png.rb +94 -42
- data/lib/prawn/images.rb +70 -81
- data/lib/prawn/measurement_extensions.rb +39 -8
- data/lib/prawn/measurements.rb +60 -5
- data/lib/prawn/outline.rb +120 -113
- data/lib/prawn/repeater.rb +52 -36
- data/lib/prawn/security/arcfour.rb +4 -4
- data/lib/prawn/security.rb +106 -98
- data/lib/prawn/soft_mask.rb +42 -30
- data/lib/prawn/stamp.rb +38 -42
- data/lib/prawn/text/box.rb +156 -105
- data/lib/prawn/text/formatted/arranger.rb +121 -41
- data/lib/prawn/text/formatted/box.rb +239 -163
- data/lib/prawn/text/formatted/fragment.rb +130 -14
- data/lib/prawn/text/formatted/line_wrap.rb +49 -38
- data/lib/prawn/text/formatted/parser.rb +116 -74
- data/lib/prawn/text/formatted/wrap.rb +25 -26
- data/lib/prawn/text/formatted.rb +75 -0
- data/lib/prawn/text.rb +456 -211
- data/lib/prawn/transformation_stack.rb +29 -10
- data/lib/prawn/utilities.rb +13 -13
- data/lib/prawn/version.rb +2 -1
- data/lib/prawn/view.rb +69 -54
- data/lib/prawn.rb +24 -18
- data.tar.gz.sig +0 -0
- metadata +55 -262
- metadata.gz.sig +3 -4
- data/.yardopts +0 -10
- data/Gemfile +0 -5
- data/Rakefile +0 -54
- data/manual/absolute_position.pdf +0 -0
- data/manual/basic_concepts/adding_pages.rb +0 -26
- data/manual/basic_concepts/basic_concepts.rb +0 -43
- data/manual/basic_concepts/creation.rb +0 -38
- data/manual/basic_concepts/cursor.rb +0 -32
- data/manual/basic_concepts/measurement.rb +0 -24
- data/manual/basic_concepts/origin.rb +0 -37
- data/manual/basic_concepts/other_cursor_helpers.rb +0 -39
- data/manual/basic_concepts/view.rb +0 -48
- data/manual/bounding_box/bounding_box.rb +0 -41
- data/manual/bounding_box/bounds.rb +0 -48
- data/manual/bounding_box/canvas.rb +0 -23
- data/manual/bounding_box/creation.rb +0 -22
- data/manual/bounding_box/indentation.rb +0 -45
- data/manual/bounding_box/nesting.rb +0 -52
- data/manual/bounding_box/russian_boxes.rb +0 -40
- data/manual/bounding_box/stretchy.rb +0 -29
- data/manual/contents.rb +0 -35
- data/manual/cover.rb +0 -43
- data/manual/document_and_page_options/background.rb +0 -25
- data/manual/document_and_page_options/document_and_page_options.rb +0 -34
- data/manual/document_and_page_options/metadata.rb +0 -25
- data/manual/document_and_page_options/page_margins.rb +0 -36
- data/manual/document_and_page_options/page_size.rb +0 -34
- data/manual/document_and_page_options/print_scaling.rb +0 -22
- data/manual/example_helper.rb +0 -8
- data/manual/graphics/blend_mode.rb +0 -52
- data/manual/graphics/circle_and_ellipse.rb +0 -21
- data/manual/graphics/color.rb +0 -22
- data/manual/graphics/common_lines.rb +0 -29
- data/manual/graphics/fill_and_stroke.rb +0 -41
- data/manual/graphics/fill_rules.rb +0 -37
- data/manual/graphics/gradients.rb +0 -43
- data/manual/graphics/graphics.rb +0 -64
- data/manual/graphics/helper.rb +0 -27
- data/manual/graphics/line_width.rb +0 -36
- data/manual/graphics/lines_and_curves.rb +0 -40
- data/manual/graphics/polygon.rb +0 -27
- data/manual/graphics/rectangle.rb +0 -20
- data/manual/graphics/rotate.rb +0 -25
- data/manual/graphics/scale.rb +0 -42
- data/manual/graphics/soft_masks.rb +0 -44
- data/manual/graphics/stroke_cap.rb +0 -30
- data/manual/graphics/stroke_dash.rb +0 -47
- data/manual/graphics/stroke_join.rb +0 -29
- data/manual/graphics/translate.rb +0 -28
- data/manual/graphics/transparency.rb +0 -33
- data/manual/how_to_read_this_manual.rb +0 -39
- data/manual/images/absolute_position.rb +0 -22
- data/manual/images/fit.rb +0 -20
- data/manual/images/horizontal.rb +0 -24
- data/manual/images/images.rb +0 -41
- data/manual/images/plain_image.rb +0 -17
- data/manual/images/scale.rb +0 -21
- data/manual/images/vertical.rb +0 -27
- data/manual/images/width_and_height.rb +0 -24
- data/manual/layout/boxes.rb +0 -26
- data/manual/layout/content.rb +0 -24
- data/manual/layout/layout.rb +0 -27
- data/manual/layout/simple_grid.rb +0 -22
- data/manual/outline/add_subsection_to.rb +0 -60
- data/manual/outline/insert_section_after.rb +0 -46
- data/manual/outline/outline.rb +0 -33
- data/manual/outline/sections_and_pages.rb +0 -66
- data/manual/repeatable_content/alternate_page_numbering.rb +0 -36
- data/manual/repeatable_content/page_numbering.rb +0 -55
- data/manual/repeatable_content/repeatable_content.rb +0 -35
- data/manual/repeatable_content/repeater.rb +0 -54
- data/manual/repeatable_content/stamp.rb +0 -40
- data/manual/security/encryption.rb +0 -28
- data/manual/security/permissions.rb +0 -41
- data/manual/security/security.rb +0 -28
- data/manual/table.rb +0 -16
- data/manual/text/alignment.rb +0 -43
- data/manual/text/color.rb +0 -24
- data/manual/text/column_box.rb +0 -30
- data/manual/text/fallback_fonts.rb +0 -41
- data/manual/text/font.rb +0 -40
- data/manual/text/font_size.rb +0 -44
- data/manual/text/font_style.rb +0 -22
- data/manual/text/formatted_callbacks.rb +0 -65
- data/manual/text/formatted_text.rb +0 -58
- data/manual/text/free_flowing_text.rb +0 -50
- data/manual/text/inline.rb +0 -40
- data/manual/text/kerning_and_character_spacing.rb +0 -38
- data/manual/text/leading.rb +0 -24
- data/manual/text/line_wrapping.rb +0 -60
- data/manual/text/paragraph_indentation.rb +0 -32
- data/manual/text/positioned_text.rb +0 -37
- data/manual/text/registering_families.rb +0 -51
- data/manual/text/rendering_and_color.rb +0 -36
- data/manual/text/right_to_left_text.rb +0 -54
- data/manual/text/rotation.rb +0 -47
- data/manual/text/single_usage.rb +0 -36
- data/manual/text/text.rb +0 -75
- data/manual/text/text_box_excess.rb +0 -35
- data/manual/text/text_box_extensions.rb +0 -48
- data/manual/text/text_box_overflow.rb +0 -49
- data/manual/text/utf8.rb +0 -27
- data/manual/text/win_ansi_charset.rb +0 -62
- data/prawn.gemspec +0 -57
- data/spec/data/curves.pdf +0 -66
- data/spec/extensions/encoding_helpers.rb +0 -11
- data/spec/prawn/document/bounding_box_spec.rb +0 -546
- data/spec/prawn/document/column_box_spec.rb +0 -75
- data/spec/prawn/document/security_spec.rb +0 -176
- data/spec/prawn/document_annotations_spec.rb +0 -76
- data/spec/prawn/document_destinations_spec.rb +0 -15
- data/spec/prawn/document_grid_spec.rb +0 -99
- data/spec/prawn/document_reference_spec.rb +0 -27
- data/spec/prawn/document_span_spec.rb +0 -36
- data/spec/prawn/document_spec.rb +0 -802
- data/spec/prawn/font_metric_cache_spec.rb +0 -54
- data/spec/prawn/font_spec.rb +0 -542
- data/spec/prawn/graphics/blend_mode_spec.rb +0 -63
- data/spec/prawn/graphics/transparency_spec.rb +0 -81
- data/spec/prawn/graphics_spec.rb +0 -837
- data/spec/prawn/graphics_stroke_styles_spec.rb +0 -229
- data/spec/prawn/image_handler_spec.rb +0 -53
- data/spec/prawn/images/jpg_spec.rb +0 -20
- data/spec/prawn/images/png_spec.rb +0 -283
- data/spec/prawn/images_spec.rb +0 -224
- data/spec/prawn/measurements_extensions_spec.rb +0 -24
- data/spec/prawn/outline_spec.rb +0 -412
- data/spec/prawn/repeater_spec.rb +0 -165
- data/spec/prawn/soft_mask_spec.rb +0 -74
- data/spec/prawn/stamp_spec.rb +0 -172
- data/spec/prawn/text/box_spec.rb +0 -1112
- data/spec/prawn/text/formatted/arranger_spec.rb +0 -466
- data/spec/prawn/text/formatted/box_spec.rb +0 -846
- data/spec/prawn/text/formatted/fragment_spec.rb +0 -343
- data/spec/prawn/text/formatted/line_wrap_spec.rb +0 -494
- data/spec/prawn/text/formatted/parser_spec.rb +0 -697
- data/spec/prawn/text_draw_text_spec.rb +0 -149
- data/spec/prawn/text_rendering_mode_spec.rb +0 -48
- data/spec/prawn/text_spacing_spec.rb +0 -95
- data/spec/prawn/text_spec.rb +0 -603
- data/spec/prawn/text_with_inline_formatting_spec.rb +0 -35
- data/spec/prawn/transformation_stack_spec.rb +0 -66
- data/spec/prawn/view_spec.rb +0 -63
- data/spec/prawn_manual_spec.rb +0 -35
- data/spec/spec_helper.rb +0 -48
data/spec/prawn/document_spec.rb
DELETED
@@ -1,802 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
require 'tempfile'
|
5
|
-
|
6
|
-
describe Prawn::Document do
|
7
|
-
let(:pdf) { create_pdf }
|
8
|
-
|
9
|
-
describe '.new' do
|
10
|
-
it 'does not modify its argument' do
|
11
|
-
options = { page_layout: :landscape }
|
12
|
-
described_class.new(options)
|
13
|
-
expect(options).to eq(page_layout: :landscape)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
describe 'The cursor' do
|
18
|
-
it 'equals pdf.y - bounds.absolute_bottom' do
|
19
|
-
pdf = described_class.new
|
20
|
-
expect(pdf.cursor).to eq(pdf.bounds.top)
|
21
|
-
|
22
|
-
pdf.y = 300
|
23
|
-
expect(pdf.cursor).to eq(pdf.y - pdf.bounds.absolute_bottom)
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'is able to move relative to the bottom margin' do
|
27
|
-
pdf = described_class.new
|
28
|
-
pdf.move_cursor_to(10)
|
29
|
-
|
30
|
-
expect(pdf.cursor).to eq(10)
|
31
|
-
expect(pdf.y).to eq(pdf.cursor + pdf.bounds.absolute_bottom)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
describe 'when generating a document with a custom text formatter' do
|
36
|
-
it 'uses the provided text formatter' do
|
37
|
-
text_formatter = Class.new do
|
38
|
-
def self.format(string)
|
39
|
-
[
|
40
|
-
{
|
41
|
-
text: string.gsub('Dr. Who?', "Just 'The Doctor'."),
|
42
|
-
styles: [],
|
43
|
-
color: nil,
|
44
|
-
link: nil,
|
45
|
-
anchor: nil,
|
46
|
-
local: nil,
|
47
|
-
font: nil,
|
48
|
-
size: nil,
|
49
|
-
character_spacing: nil
|
50
|
-
}
|
51
|
-
]
|
52
|
-
end
|
53
|
-
end
|
54
|
-
pdf = described_class.new text_formatter: text_formatter
|
55
|
-
pdf.text 'Dr. Who?', inline_format: true
|
56
|
-
text = PDF::Inspector::Text.analyze(pdf.render)
|
57
|
-
expect(text.strings.first).to eq("Just 'The Doctor'.")
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
describe 'when generating a document from a subclass' do
|
62
|
-
it 'is an instance of the subclass' do
|
63
|
-
custom_document = Class.new(described_class)
|
64
|
-
custom_document.generate(Tempfile.new('generate_test').path) do |e|
|
65
|
-
expect(e.class).to eq(custom_document)
|
66
|
-
expect(e).to be_a_kind_of(described_class)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'retains any extensions found on Prawn::Document' do
|
71
|
-
mod1 = Module.new { attr_reader :test_extensions1 }
|
72
|
-
mod2 = Module.new { attr_reader :test_extensions2 }
|
73
|
-
|
74
|
-
described_class.extensions << mod1 << mod2
|
75
|
-
|
76
|
-
custom_document = Class.new(described_class)
|
77
|
-
expect(custom_document.extensions).to eq([mod1, mod2])
|
78
|
-
|
79
|
-
# remove the extensions we added to prawn document
|
80
|
-
described_class.extensions.delete(mod1)
|
81
|
-
described_class.extensions.delete(mod2)
|
82
|
-
|
83
|
-
expect(described_class.new.respond_to?(:test_extensions1)).to eq false
|
84
|
-
expect(described_class.new.respond_to?(:test_extensions2)).to eq false
|
85
|
-
|
86
|
-
# verify these still exist on custom class
|
87
|
-
expect(custom_document.extensions).to eq([mod1, mod2])
|
88
|
-
|
89
|
-
expect(custom_document.new.respond_to?(:test_extensions1)).to eq true
|
90
|
-
expect(custom_document.new.respond_to?(:test_extensions2)).to eq true
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
describe 'When creating multi-page documents' do
|
95
|
-
it 'initializes with a single page' do
|
96
|
-
page_counter = PDF::Inspector::Page.analyze(pdf.render)
|
97
|
-
|
98
|
-
expect(page_counter.pages.size).to eq(1)
|
99
|
-
expect(pdf.page_count).to eq(1)
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'provides an accurate page_count' do
|
103
|
-
3.times { pdf.start_new_page }
|
104
|
-
page_counter = PDF::Inspector::Page.analyze(pdf.render)
|
105
|
-
|
106
|
-
expect(page_counter.pages.size).to eq(4)
|
107
|
-
expect(pdf.page_count).to eq(4)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
describe 'When beginning each new page' do
|
112
|
-
describe 'Background image feature' do
|
113
|
-
let(:filename) { "#{Prawn::DATADIR}/images/pigs.jpg" }
|
114
|
-
let(:pdf) { described_class.new(background: filename) }
|
115
|
-
|
116
|
-
it 'places a background image if it is in options block' do
|
117
|
-
output = pdf.render
|
118
|
-
images = PDF::Inspector::XObject.analyze(output)
|
119
|
-
# there should be 2 images in the page resources
|
120
|
-
expect(images.page_xobjects.first.size).to eq(1)
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'places a background image interntally if it is in options block' do
|
124
|
-
expect(pdf.instance_variable_defined?(:@background)).to eq(true)
|
125
|
-
expect(pdf.instance_variable_get(:@background)).to eq(filename)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
describe '#float' do
|
131
|
-
it 'restores the original y-position' do
|
132
|
-
orig_y = pdf.y
|
133
|
-
pdf.float { pdf.text 'Foo' }
|
134
|
-
expect(pdf.y).to eq(orig_y)
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'teleports across pages if necessary' do
|
138
|
-
pdf.float do
|
139
|
-
pdf.text 'Foo'
|
140
|
-
pdf.start_new_page
|
141
|
-
pdf.text 'Bar'
|
142
|
-
end
|
143
|
-
pdf.text 'Baz'
|
144
|
-
|
145
|
-
pages = PDF::Inspector::Page.analyze(pdf.render).pages
|
146
|
-
expect(pages.size).to eq(2)
|
147
|
-
expect(pages[0][:strings]).to eq(%w[Foo Baz])
|
148
|
-
expect(pages[1][:strings]).to eq(['Bar'])
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
describe '#start_new_page' do
|
153
|
-
it "doesn't modify the options hash" do
|
154
|
-
expect do
|
155
|
-
described_class.new.start_new_page({ margin: 0 }.freeze)
|
156
|
-
end.to_not raise_error
|
157
|
-
end
|
158
|
-
|
159
|
-
it 'sets individual page margins' do
|
160
|
-
doc = described_class.new
|
161
|
-
doc.start_new_page(top_margin: 42)
|
162
|
-
expect(doc.page.margins[:top]).to eq(42)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
describe '#delete_page(index)' do
|
167
|
-
before do
|
168
|
-
pdf.text 'Page one'
|
169
|
-
pdf.start_new_page
|
170
|
-
pdf.text 'Page two'
|
171
|
-
pdf.start_new_page
|
172
|
-
pdf.text 'Page three'
|
173
|
-
end
|
174
|
-
|
175
|
-
it 'destroy a specific page of the document' do
|
176
|
-
pdf.delete_page(1)
|
177
|
-
expect(pdf.page_number).to eq(2)
|
178
|
-
text_analysis = PDF::Inspector::Text.analyze(pdf.render)
|
179
|
-
expect(text_analysis.strings).to eq(['Page one', 'Page three'])
|
180
|
-
end
|
181
|
-
|
182
|
-
it 'destroy the last page of the document' do
|
183
|
-
pdf.delete_page(-1)
|
184
|
-
expect(pdf.page_number).to eq(2)
|
185
|
-
text_analysis = PDF::Inspector::Text.analyze(pdf.render)
|
186
|
-
expect(text_analysis.strings).to eq(['Page one', 'Page two'])
|
187
|
-
end
|
188
|
-
|
189
|
-
context 'with an invalid index' do
|
190
|
-
let(:expected_content) { ['Page one', 'Page two', 'Page three'] }
|
191
|
-
|
192
|
-
it 'does not destroy an invalid positve index' do
|
193
|
-
pdf.delete_page(42)
|
194
|
-
expect(pdf.page_number).to eq(3)
|
195
|
-
text_analysis = PDF::Inspector::Text.analyze(pdf.render)
|
196
|
-
expect(text_analysis.strings).to eq(expected_content)
|
197
|
-
end
|
198
|
-
|
199
|
-
it 'does not destroy an invalid negative index' do
|
200
|
-
pdf.delete_page(-42)
|
201
|
-
expect(pdf.page_number).to eq(3)
|
202
|
-
text_analysis = PDF::Inspector::Text.analyze(pdf.render)
|
203
|
-
expect(text_analysis.strings).to eq(expected_content)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
describe '#page_number' do
|
209
|
-
it 'is 1 for a new document' do
|
210
|
-
pdf = described_class.new
|
211
|
-
expect(pdf.page_number).to eq(1)
|
212
|
-
end
|
213
|
-
|
214
|
-
it 'is 0 for documents with no pages' do
|
215
|
-
pdf = described_class.new(skip_page_creation: true)
|
216
|
-
expect(pdf.page_number).to eq(0)
|
217
|
-
end
|
218
|
-
|
219
|
-
it 'is changed by go_to_page' do
|
220
|
-
pdf = described_class.new
|
221
|
-
10.times { pdf.start_new_page }
|
222
|
-
pdf.go_to_page 3
|
223
|
-
expect(pdf.page_number).to eq(3)
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
describe 'on_page_create callback' do
|
228
|
-
it 'is delegated from Document to renderer' do
|
229
|
-
expect(pdf.respond_to?(:on_page_create)).to eq true
|
230
|
-
end
|
231
|
-
|
232
|
-
it 'is invoked with document' do
|
233
|
-
called_with = nil
|
234
|
-
|
235
|
-
pdf.renderer.on_page_create { |*args| called_with = args }
|
236
|
-
|
237
|
-
pdf.start_new_page
|
238
|
-
|
239
|
-
expect(called_with).to eq([pdf])
|
240
|
-
end
|
241
|
-
|
242
|
-
it 'is invoked for each new page' do
|
243
|
-
trigger = instance_double('trigger')
|
244
|
-
allow(trigger).to receive(:fire)
|
245
|
-
|
246
|
-
pdf.renderer.on_page_create { trigger.fire }
|
247
|
-
|
248
|
-
5.times { pdf.start_new_page }
|
249
|
-
|
250
|
-
expect(trigger).to have_received(:fire).exactly(5).times
|
251
|
-
end
|
252
|
-
|
253
|
-
it 'is replaceable' do
|
254
|
-
trigger1 = instance_double('trigger 1')
|
255
|
-
allow(trigger1).to receive(:fire)
|
256
|
-
|
257
|
-
trigger2 = instance_double('trigger 2')
|
258
|
-
allow(trigger2).to receive(:fire)
|
259
|
-
|
260
|
-
pdf.renderer.on_page_create { trigger1.fire }
|
261
|
-
|
262
|
-
pdf.start_new_page
|
263
|
-
|
264
|
-
pdf.renderer.on_page_create { trigger2.fire }
|
265
|
-
|
266
|
-
pdf.start_new_page
|
267
|
-
|
268
|
-
expect(trigger1).to have_received(:fire).once
|
269
|
-
expect(trigger2).to have_received(:fire).once
|
270
|
-
end
|
271
|
-
|
272
|
-
it 'is clearable by calling on_page_create without a block' do
|
273
|
-
trigger = instance_double('trigger')
|
274
|
-
allow(trigger).to receive(:fire)
|
275
|
-
|
276
|
-
pdf.renderer.on_page_create { trigger.fire }
|
277
|
-
|
278
|
-
pdf.start_new_page
|
279
|
-
|
280
|
-
pdf.renderer.on_page_create
|
281
|
-
|
282
|
-
pdf.start_new_page
|
283
|
-
|
284
|
-
expect(trigger).to have_received(:fire).once
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
describe 'compression' do
|
289
|
-
it 'does not compress the page content stream if compression is disabled' do
|
290
|
-
pdf = described_class.new(compress: false)
|
291
|
-
allow(pdf.page.content.stream).to receive(:compress!).and_return(true)
|
292
|
-
|
293
|
-
pdf.text 'Hi There' * 20
|
294
|
-
pdf.render
|
295
|
-
|
296
|
-
expect(pdf.page.content.stream).to_not have_received(:compress!)
|
297
|
-
end
|
298
|
-
|
299
|
-
it 'compresses the page content stream if compression is enabled' do
|
300
|
-
pdf = described_class.new(compress: true)
|
301
|
-
allow(pdf.page.content.stream).to receive(:compress!).and_return(true)
|
302
|
-
|
303
|
-
pdf.text 'Hi There' * 20
|
304
|
-
pdf.render
|
305
|
-
|
306
|
-
expect(pdf.page.content.stream).to have_received(:compress!).once
|
307
|
-
end
|
308
|
-
|
309
|
-
it 'results in a smaller file size when compressed' do
|
310
|
-
doc_uncompressed = described_class.new
|
311
|
-
doc_compressed = described_class.new(compress: true)
|
312
|
-
[doc_compressed, doc_uncompressed].each do |pdf|
|
313
|
-
pdf.font "#{Prawn::DATADIR}/fonts/gkai00mp.ttf"
|
314
|
-
pdf.text '更可怕的是,同质化竞争对手可以按照URL中后面这个ID来遍历' * 10
|
315
|
-
end
|
316
|
-
|
317
|
-
expect(doc_compressed.render.length).to be <
|
318
|
-
doc_uncompressed.render.length
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
|
-
describe 'Dometadata' do
|
323
|
-
it 'outputs strings as UTF-16 with a byte order mark' do
|
324
|
-
pdf = described_class.new(info: { Author: 'Lóránt' })
|
325
|
-
expect(pdf.state.store.info.object).to match(
|
326
|
-
# UTF-16: BOM L ó r á n t
|
327
|
-
%r{/Author\s*<feff004c00f3007200e1006e0074>}i
|
328
|
-
)
|
329
|
-
end
|
330
|
-
end
|
331
|
-
|
332
|
-
describe 'When reopening pages' do
|
333
|
-
it 'modifies the content stream size' do
|
334
|
-
pdf = described_class.new do
|
335
|
-
text 'Page 1'
|
336
|
-
start_new_page
|
337
|
-
text 'Page 2'
|
338
|
-
go_to_page 1
|
339
|
-
text 'More for page 1'
|
340
|
-
end
|
341
|
-
|
342
|
-
# Indirectly verify that the actual length does not match dictionary
|
343
|
-
# length. If it isn't, a MalformedPDFError will be raised
|
344
|
-
PDF::Inspector::Page.analyze(pdf.render)
|
345
|
-
end
|
346
|
-
|
347
|
-
it 'inserts pages after the current page when calling start_new_page' do
|
348
|
-
pdf = described_class.new
|
349
|
-
3.times do |i|
|
350
|
-
pdf.text "Old page #{i + 1}"
|
351
|
-
pdf.start_new_page
|
352
|
-
end
|
353
|
-
|
354
|
-
pdf.go_to_page 1
|
355
|
-
pdf.start_new_page
|
356
|
-
pdf.text 'New page 2'
|
357
|
-
|
358
|
-
expect(pdf.page_number).to eq(2)
|
359
|
-
|
360
|
-
pages = PDF::Inspector::Page.analyze(pdf.render).pages
|
361
|
-
expect(pages.size).to eq(5)
|
362
|
-
expect(pages[1][:strings]).to eq(['New page 2'])
|
363
|
-
expect(pages[2][:strings]).to eq(['Old page 2'])
|
364
|
-
end
|
365
|
-
|
366
|
-
it 'restores the layout of the page' do
|
367
|
-
doc = described_class.new do
|
368
|
-
start_new_page layout: :landscape
|
369
|
-
end
|
370
|
-
|
371
|
-
lsize = [doc.bounds.width, doc.bounds.height]
|
372
|
-
|
373
|
-
expect([doc.bounds.width, doc.bounds.height]).to eq lsize
|
374
|
-
doc.go_to_page 1
|
375
|
-
expect([doc.bounds.width, doc.bounds.height]).to eq lsize.reverse
|
376
|
-
end
|
377
|
-
|
378
|
-
it 'restores the margin box of the page' do
|
379
|
-
doc = described_class.new(margin: [100, 100])
|
380
|
-
page1_bounds = doc.bounds
|
381
|
-
|
382
|
-
doc.start_new_page(margin: [200, 200])
|
383
|
-
|
384
|
-
expect([doc.bounds.width, doc.bounds.height]).to eq(
|
385
|
-
[page1_bounds.width - 200, page1_bounds.height - 200]
|
386
|
-
)
|
387
|
-
|
388
|
-
doc.go_to_page(1)
|
389
|
-
|
390
|
-
expect(doc.bounds.width).to eq page1_bounds.width
|
391
|
-
expect(doc.bounds.height).to eq page1_bounds.height
|
392
|
-
end
|
393
|
-
end
|
394
|
-
|
395
|
-
describe 'When setting page size' do
|
396
|
-
it 'defaults to LETTER' do
|
397
|
-
pdf = described_class.new
|
398
|
-
pages = PDF::Inspector::Page.analyze(pdf.render).pages
|
399
|
-
expect(pages.first[:size]).to eq(PDF::Core::PageGeometry::SIZES['LETTER'])
|
400
|
-
end
|
401
|
-
|
402
|
-
(PDF::Core::PageGeometry::SIZES.keys - ['LETTER']).each do |k|
|
403
|
-
it "provides #{k} geometry" do
|
404
|
-
pdf = described_class.new(page_size: k)
|
405
|
-
pages = PDF::Inspector::Page.analyze(pdf.render).pages
|
406
|
-
expect(pages.first[:size]).to eq(PDF::Core::PageGeometry::SIZES[k])
|
407
|
-
end
|
408
|
-
end
|
409
|
-
|
410
|
-
it 'allows custom page size' do
|
411
|
-
pdf = described_class.new(page_size: [1920, 1080])
|
412
|
-
pages = PDF::Inspector::Page.analyze(pdf.render).pages
|
413
|
-
expect(pages.first[:size]).to eq([1920, 1080])
|
414
|
-
end
|
415
|
-
|
416
|
-
it 'retains page size by default when starting a new page' do
|
417
|
-
pdf = described_class.new(page_size: 'LEGAL')
|
418
|
-
pdf.start_new_page
|
419
|
-
pages = PDF::Inspector::Page.analyze(pdf.render).pages
|
420
|
-
pages.each do |page|
|
421
|
-
expect(page[:size]).to eq(PDF::Core::PageGeometry::SIZES['LEGAL'])
|
422
|
-
end
|
423
|
-
end
|
424
|
-
end
|
425
|
-
|
426
|
-
describe 'When setting page layout' do
|
427
|
-
it 'reverses coordinates for landscape' do
|
428
|
-
pdf = described_class.new(page_size: 'A4', page_layout: :landscape)
|
429
|
-
pages = PDF::Inspector::Page.analyze(pdf.render).pages
|
430
|
-
expect(pages.first[:size]).to eq(
|
431
|
-
PDF::Core::PageGeometry::SIZES['A4'].reverse
|
432
|
-
)
|
433
|
-
end
|
434
|
-
|
435
|
-
it 'retains page layout by default when starting a new page' do
|
436
|
-
pdf = described_class.new(page_layout: :landscape)
|
437
|
-
pdf.start_new_page(trace: true)
|
438
|
-
pages = PDF::Inspector::Page.analyze(pdf.render).pages
|
439
|
-
pages.each do |page|
|
440
|
-
expect(page[:size]).to eq(
|
441
|
-
PDF::Core::PageGeometry::SIZES['LETTER'].reverse
|
442
|
-
)
|
443
|
-
end
|
444
|
-
end
|
445
|
-
|
446
|
-
it 'swaps the bounds when starting a new page with different layout' do
|
447
|
-
pdf = described_class.new
|
448
|
-
size = [pdf.bounds.width, pdf.bounds.height]
|
449
|
-
pdf.start_new_page(layout: :landscape)
|
450
|
-
expect([pdf.bounds.width, pdf.bounds.height]).to eq(size.reverse)
|
451
|
-
end
|
452
|
-
end
|
453
|
-
|
454
|
-
describe '#mask' do
|
455
|
-
it 'allows transactional restoration of attributes' do
|
456
|
-
pdf = described_class.new
|
457
|
-
y = pdf.y
|
458
|
-
line_width = pdf.line_width
|
459
|
-
pdf.mask(:y, :line_width) do
|
460
|
-
pdf.y = y + 1
|
461
|
-
pdf.line_width = line_width + 1
|
462
|
-
expect(pdf.y).to_not eq(y)
|
463
|
-
expect(pdf.line_width).to_not eq(line_width)
|
464
|
-
end
|
465
|
-
expect(pdf.y).to eq(y)
|
466
|
-
expect(pdf.line_width).to eq(line_width)
|
467
|
-
end
|
468
|
-
end
|
469
|
-
|
470
|
-
describe '#render' do
|
471
|
-
it 'returns a 8 bit encoded string on a m17n aware VM' do
|
472
|
-
pdf = described_class.new(page_size: 'A4', page_layout: :landscape)
|
473
|
-
pdf.line [100, 100], [200, 200]
|
474
|
-
str = pdf.render
|
475
|
-
expect(str.encoding.to_s).to eq('ASCII-8BIT')
|
476
|
-
end
|
477
|
-
|
478
|
-
it 'triggers before_render callbacks just before rendering' do
|
479
|
-
pdf = described_class.new
|
480
|
-
|
481
|
-
# Verify the order: finalize -> fire callbacks -> render body
|
482
|
-
allow(pdf.renderer).to receive(:finalize_all_page_contents)
|
483
|
-
.and_call_original
|
484
|
-
|
485
|
-
trigger = instance_double('trigger')
|
486
|
-
allow(trigger).to receive(:fire)
|
487
|
-
|
488
|
-
pdf.renderer.before_render { trigger.fire }
|
489
|
-
|
490
|
-
allow(pdf.renderer).to receive(:render_body).and_call_original
|
491
|
-
|
492
|
-
pdf.render(StringIO.new)
|
493
|
-
|
494
|
-
expect(pdf.renderer).to have_received(:finalize_all_page_contents)
|
495
|
-
.ordered
|
496
|
-
expect(trigger).to have_received(:fire).ordered
|
497
|
-
expect(pdf.renderer).to have_received(:render_body).ordered
|
498
|
-
end
|
499
|
-
|
500
|
-
it 'is idempotent' do
|
501
|
-
pdf = described_class.new
|
502
|
-
|
503
|
-
contents = pdf.render
|
504
|
-
contents2 = pdf.render
|
505
|
-
expect(contents2).to eq(contents)
|
506
|
-
end
|
507
|
-
end
|
508
|
-
|
509
|
-
describe 'PDF file versions' do
|
510
|
-
it 'defaults to 1.3' do
|
511
|
-
pdf = described_class.new
|
512
|
-
str = pdf.render
|
513
|
-
expect(str[0, 8]).to eq('%PDF-1.3')
|
514
|
-
end
|
515
|
-
|
516
|
-
it 'allows the default to be changed' do
|
517
|
-
pdf = described_class.new
|
518
|
-
pdf.renderer.min_version(1.4)
|
519
|
-
str = pdf.render
|
520
|
-
expect(str[0, 8]).to eq('%PDF-1.4')
|
521
|
-
end
|
522
|
-
end
|
523
|
-
|
524
|
-
describe '#go_to_page' do
|
525
|
-
it 'has 2 pages after calling start_new_page and go_to_page' do
|
526
|
-
pdf = described_class.new
|
527
|
-
pdf.text 'James'
|
528
|
-
pdf.start_new_page
|
529
|
-
pdf.text 'Anthony'
|
530
|
-
pdf.go_to_page(1)
|
531
|
-
pdf.text 'Healy'
|
532
|
-
|
533
|
-
page_counter = PDF::Inspector::Page.analyze(pdf.render)
|
534
|
-
expect(page_counter.pages.size).to eq(2)
|
535
|
-
end
|
536
|
-
|
537
|
-
it 'correctlies add text to pages' do
|
538
|
-
pdf = described_class.new
|
539
|
-
pdf.text 'James'
|
540
|
-
pdf.start_new_page
|
541
|
-
pdf.text 'Anthony'
|
542
|
-
pdf.go_to_page(1)
|
543
|
-
pdf.text 'Healy'
|
544
|
-
|
545
|
-
text = PDF::Inspector::Text.analyze(pdf.render)
|
546
|
-
|
547
|
-
expect(text.strings.size).to eq(3)
|
548
|
-
expect(text.strings.include?('James')).to eq(true)
|
549
|
-
expect(text.strings.include?('Anthony')).to eq(true)
|
550
|
-
expect(text.strings.include?('Healy')).to eq(true)
|
551
|
-
end
|
552
|
-
end
|
553
|
-
|
554
|
-
describe 'content stream characteristics' do
|
555
|
-
it 'has 1 single content stream for a single page PDF' do
|
556
|
-
pdf = described_class.new
|
557
|
-
pdf.text 'James'
|
558
|
-
output = StringIO.new(pdf.render)
|
559
|
-
hash = PDF::Reader::ObjectHash.new(output)
|
560
|
-
|
561
|
-
streams = hash.values.select { |obj| obj.is_a?(PDF::Reader::Stream) }
|
562
|
-
|
563
|
-
expect(streams.size).to eq(1)
|
564
|
-
end
|
565
|
-
|
566
|
-
it 'has 1 single content stream for a single page PDF, even if go_to_page '\
|
567
|
-
'is used' do
|
568
|
-
pdf = described_class.new
|
569
|
-
pdf.text 'James'
|
570
|
-
pdf.go_to_page(1)
|
571
|
-
pdf.text 'Healy'
|
572
|
-
output = StringIO.new(pdf.render)
|
573
|
-
hash = PDF::Reader::ObjectHash.new(output)
|
574
|
-
|
575
|
-
streams = hash.values.select { |obj| obj.is_a?(PDF::Reader::Stream) }
|
576
|
-
|
577
|
-
expect(streams.size).to eq(1)
|
578
|
-
end
|
579
|
-
end
|
580
|
-
|
581
|
-
describe '#number_pages' do
|
582
|
-
let(:pdf) { described_class.new(skip_page_creation: true) }
|
583
|
-
|
584
|
-
it "replaces the '<page>' string with the proper page number" do
|
585
|
-
pdf.start_new_page
|
586
|
-
allow(pdf).to receive(:text_box)
|
587
|
-
pdf.number_pages '<page>, test', page_filter: :all
|
588
|
-
expect(pdf).to have_received(:text_box).with('1, test', height: 50)
|
589
|
-
end
|
590
|
-
|
591
|
-
it "replaces the '<total>' string with the total page count" do
|
592
|
-
pdf.start_new_page
|
593
|
-
allow(pdf).to receive(:text_box)
|
594
|
-
pdf.number_pages 'test, <total>', page_filter: :all
|
595
|
-
expect(pdf).to have_received(:text_box).with('test, 1', height: 50)
|
596
|
-
end
|
597
|
-
|
598
|
-
it 'must print each page if given the :all page_filter' do
|
599
|
-
10.times { pdf.start_new_page }
|
600
|
-
allow(pdf).to receive(:text_box)
|
601
|
-
pdf.number_pages 'test', page_filter: :all
|
602
|
-
expect(pdf).to have_received(:text_box).exactly(10).times
|
603
|
-
end
|
604
|
-
|
605
|
-
it 'must print each page if no :page_filter is specified' do
|
606
|
-
10.times { pdf.start_new_page }
|
607
|
-
allow(pdf).to receive(:text_box)
|
608
|
-
pdf.number_pages 'test'
|
609
|
-
expect(pdf).to have_received(:text_box).exactly(10).times
|
610
|
-
end
|
611
|
-
|
612
|
-
it 'must not print the page number if given a nil filter' do
|
613
|
-
10.times { pdf.start_new_page }
|
614
|
-
allow(pdf).to receive(:text_box)
|
615
|
-
pdf.number_pages 'test', page_filter: nil
|
616
|
-
expect(pdf).to_not have_received(:text_box)
|
617
|
-
end
|
618
|
-
|
619
|
-
context 'with start_count_at option' do
|
620
|
-
[1, 2].each do |startat|
|
621
|
-
context "equal to #{startat}" do
|
622
|
-
it 'increments the pages' do
|
623
|
-
2.times { pdf.start_new_page }
|
624
|
-
options = { page_filter: :all, start_count_at: startat }
|
625
|
-
allow(pdf).to receive(:text_box)
|
626
|
-
pdf.number_pages '<page> <total>', options
|
627
|
-
|
628
|
-
expect(pdf).to have_received(:text_box)
|
629
|
-
.with("#{startat} 2", height: 50)
|
630
|
-
expect(pdf).to have_received(:text_box)
|
631
|
-
.with("#{startat + 1} 2", height: 50)
|
632
|
-
end
|
633
|
-
end
|
634
|
-
end
|
635
|
-
|
636
|
-
[0, nil].each do |val|
|
637
|
-
context "equal to #{val}" do
|
638
|
-
it 'defaults to start at page 1' do
|
639
|
-
3.times { pdf.start_new_page }
|
640
|
-
options = { page_filter: :all, start_count_at: val }
|
641
|
-
allow(pdf).to receive(:text_box)
|
642
|
-
pdf.number_pages '<page> <total>', options
|
643
|
-
|
644
|
-
expect(pdf).to have_received(:text_box).with('1 3', height: 50)
|
645
|
-
expect(pdf).to have_received(:text_box).with('2 3', height: 50)
|
646
|
-
expect(pdf).to have_received(:text_box).with('3 3', height: 50)
|
647
|
-
end
|
648
|
-
end
|
649
|
-
end
|
650
|
-
end
|
651
|
-
|
652
|
-
context 'with total_pages option' do
|
653
|
-
it 'allows the total pages count to be overridden' do
|
654
|
-
2.times { pdf.start_new_page }
|
655
|
-
allow(pdf).to receive(:text_box)
|
656
|
-
pdf.number_pages '<page> <total>', page_filter: :all, total_pages: 10
|
657
|
-
|
658
|
-
expect(pdf).to have_received(:text_box).with('1 10', height: 50)
|
659
|
-
expect(pdf).to have_received(:text_box).with('2 10', height: 50)
|
660
|
-
end
|
661
|
-
end
|
662
|
-
|
663
|
-
context 'with special page filter' do
|
664
|
-
describe 'such as :odd' do
|
665
|
-
it 'increments the pages' do
|
666
|
-
3.times { pdf.start_new_page }
|
667
|
-
allow(pdf).to receive(:text_box)
|
668
|
-
pdf.number_pages '<page> <total>', page_filter: :odd
|
669
|
-
|
670
|
-
expect(pdf).to have_received(:text_box).with('1 3', height: 50)
|
671
|
-
expect(pdf).to have_received(:text_box).with('3 3', height: 50)
|
672
|
-
expect(pdf).to_not have_received(:text_box).with('2 3', height: 50)
|
673
|
-
end
|
674
|
-
end
|
675
|
-
|
676
|
-
describe 'missing' do
|
677
|
-
it 'does not print any page numbers' do
|
678
|
-
3.times { pdf.start_new_page }
|
679
|
-
allow(pdf).to receive(:text_box)
|
680
|
-
pdf.number_pages '<page> <total>', page_filter: nil
|
681
|
-
|
682
|
-
expect(pdf).to_not have_received(:text_box)
|
683
|
-
end
|
684
|
-
end
|
685
|
-
end
|
686
|
-
|
687
|
-
context 'with both a special page filter and a start_count_at parameter' do
|
688
|
-
describe 'such as :odd and 7' do
|
689
|
-
it 'increments the pages' do
|
690
|
-
3.times { pdf.start_new_page }
|
691
|
-
allow(pdf).to receive(:text_box)
|
692
|
-
pdf.number_pages '<page> <total>',
|
693
|
-
page_filter: :odd,
|
694
|
-
start_count_at: 5
|
695
|
-
|
696
|
-
expect(pdf).to_not have_received(:text_box).with('1 3', height: 50)
|
697
|
-
# page 1
|
698
|
-
expect(pdf).to have_received(:text_box).with('5 3', height: 50)
|
699
|
-
|
700
|
-
# page 2
|
701
|
-
expect(pdf).to_not have_received(:text_box).with('6 3', height: 50)
|
702
|
-
|
703
|
-
# page 3
|
704
|
-
expect(pdf).to have_received(:text_box).with('7 3', height: 50)
|
705
|
-
end
|
706
|
-
end
|
707
|
-
|
708
|
-
context 'with some crazy proc and 2' do
|
709
|
-
it 'increments the pages' do
|
710
|
-
6.times { pdf.start_new_page }
|
711
|
-
options = {
|
712
|
-
page_filter: ->(p) { p != 2 && p != 5 },
|
713
|
-
start_count_at: 4
|
714
|
-
}
|
715
|
-
allow(pdf).to receive(:text_box)
|
716
|
-
pdf.number_pages '<page> <total>', options
|
717
|
-
|
718
|
-
# page 1
|
719
|
-
expect(pdf).to have_received(:text_box).with('4 6', height: 50)
|
720
|
-
|
721
|
-
# page 2
|
722
|
-
expect(pdf).to_not have_received(:text_box).with('5 6', height: 50)
|
723
|
-
|
724
|
-
# page 3
|
725
|
-
expect(pdf).to have_received(:text_box).with('6 6', height: 50)
|
726
|
-
|
727
|
-
# page 4
|
728
|
-
expect(pdf).to have_received(:text_box).with('7 6', height: 50)
|
729
|
-
|
730
|
-
# page 5
|
731
|
-
expect(pdf).to_not have_received(:text_box).with('8 6', height: 50)
|
732
|
-
|
733
|
-
# page 6
|
734
|
-
expect(pdf).to have_received(:text_box).with('9 6', height: 50)
|
735
|
-
end
|
736
|
-
end
|
737
|
-
end
|
738
|
-
|
739
|
-
describe 'height option' do
|
740
|
-
before do
|
741
|
-
pdf.start_new_page
|
742
|
-
end
|
743
|
-
|
744
|
-
it 'with 10 height' do
|
745
|
-
allow(pdf).to receive(:text_box)
|
746
|
-
pdf.number_pages '<page> <total>', height: 10
|
747
|
-
expect(pdf).to have_received(:text_box).with('1 1', height: 10)
|
748
|
-
end
|
749
|
-
|
750
|
-
it 'with nil height' do
|
751
|
-
allow(pdf).to receive(:text_box)
|
752
|
-
pdf.number_pages '<page> <total>', height: nil
|
753
|
-
expect(pdf).to have_received(:text_box).with('1 1', height: nil)
|
754
|
-
end
|
755
|
-
|
756
|
-
it 'with no height' do
|
757
|
-
allow(pdf).to receive(:text_box)
|
758
|
-
pdf.number_pages '<page> <total>'
|
759
|
-
expect(pdf).to have_received(:text_box).with('1 1', height: 50)
|
760
|
-
end
|
761
|
-
end
|
762
|
-
end
|
763
|
-
|
764
|
-
describe '#page_match?' do
|
765
|
-
let(:pdf) do
|
766
|
-
described_class.new(skip_page_creation: true) do |pdf|
|
767
|
-
10.times { pdf.start_new_page }
|
768
|
-
end
|
769
|
-
end
|
770
|
-
|
771
|
-
it 'returns nil given no filter' do
|
772
|
-
expect(pdf).to_not be_page_match(:nil, 1)
|
773
|
-
end
|
774
|
-
|
775
|
-
it 'must provide an :all filter' do
|
776
|
-
expect((1..pdf.page_count).all? { |i| pdf.page_match?(:all, i) })
|
777
|
-
.to eq true
|
778
|
-
end
|
779
|
-
|
780
|
-
it 'must provide an :odd filter' do
|
781
|
-
odd, even = (1..pdf.page_count).partition(&:odd?)
|
782
|
-
expect(odd.all? { |i| pdf.page_match?(:odd, i) }).to eq true
|
783
|
-
expect(even).to_not(be_any { |i| pdf.page_match?(:odd, i) })
|
784
|
-
end
|
785
|
-
|
786
|
-
it 'must be able to filter by an array of page numbers' do
|
787
|
-
fltr = [1, 2, 7]
|
788
|
-
expect((1..10).select { |i| pdf.page_match?(fltr, i) }).to eq([1, 2, 7])
|
789
|
-
end
|
790
|
-
|
791
|
-
it 'must be able to filter by a range of page numbers' do
|
792
|
-
fltr = 2..4
|
793
|
-
expect((1..10).select { |i| pdf.page_match?(fltr, i) }).to eq([2, 3, 4])
|
794
|
-
end
|
795
|
-
|
796
|
-
it 'must be able to filter by an arbitrary proc' do
|
797
|
-
fltr = ->(x) { x == 1 || (x % 3).zero? }
|
798
|
-
expect((1..10).select { |i| pdf.page_match?(fltr, i) })
|
799
|
-
.to eq([1, 3, 6, 9])
|
800
|
-
end
|
801
|
-
end
|
802
|
-
end
|