prawn 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +2 -31
  5. data/lib/prawn.rb +1 -0
  6. data/lib/prawn/document.rb +20 -15
  7. data/lib/prawn/document/bounding_box.rb +10 -2
  8. data/lib/prawn/document/span.rb +2 -1
  9. data/lib/prawn/font.rb +6 -4
  10. data/lib/prawn/font_metric_cache.rb +7 -6
  11. data/lib/prawn/fonts/afm.rb +18 -16
  12. data/lib/prawn/fonts/ttf.rb +55 -29
  13. data/lib/prawn/graphics.rb +11 -11
  14. data/lib/prawn/graphics/color.rb +18 -16
  15. data/lib/prawn/graphics/join_style.rb +1 -1
  16. data/lib/prawn/graphics/patterns.rb +57 -49
  17. data/lib/prawn/graphics/transformation.rb +3 -3
  18. data/lib/prawn/grid.rb +36 -1
  19. data/lib/prawn/images.rb +29 -27
  20. data/lib/prawn/images/jpg.rb +4 -1
  21. data/lib/prawn/images/png.rb +2 -1
  22. data/lib/prawn/outline.rb +6 -5
  23. data/lib/prawn/repeater.rb +1 -1
  24. data/lib/prawn/security.rb +39 -36
  25. data/lib/prawn/text.rb +18 -18
  26. data/lib/prawn/text/box.rb +10 -9
  27. data/lib/prawn/text/formatted/arranger.rb +38 -19
  28. data/lib/prawn/text/formatted/box.rb +20 -15
  29. data/lib/prawn/text/formatted/line_wrap.rb +18 -16
  30. data/lib/prawn/text/formatted/parser.rb +28 -26
  31. data/lib/prawn/text/formatted/wrap.rb +15 -11
  32. data/lib/prawn/version.rb +1 -1
  33. data/lib/prawn/view.rb +2 -2
  34. data/manual/basic_concepts/measurement.rb +1 -1
  35. data/manual/bounding_box/canvas.rb +3 -3
  36. data/manual/bounding_box/nesting.rb +1 -1
  37. data/manual/document_and_page_options/background.rb +6 -2
  38. data/manual/document_and_page_options/document_and_page_options.rb +3 -3
  39. data/manual/document_and_page_options/print_scaling.rb +2 -1
  40. data/manual/graphics/common_lines.rb +1 -1
  41. data/manual/graphics/fill_and_stroke.rb +1 -1
  42. data/manual/graphics/fill_rules.rb +4 -3
  43. data/manual/graphics/helper.rb +11 -4
  44. data/manual/graphics/lines_and_curves.rb +1 -1
  45. data/manual/graphics/stroke_dash.rb +5 -5
  46. data/manual/graphics/translate.rb +2 -1
  47. data/manual/images/horizontal.rb +2 -2
  48. data/manual/images/scale.rb +3 -3
  49. data/manual/images/vertical.rb +6 -3
  50. data/manual/images/width_and_height.rb +3 -3
  51. data/manual/layout/content.rb +2 -2
  52. data/manual/outline/outline.rb +1 -1
  53. data/manual/security/permissions.rb +4 -2
  54. data/manual/security/security.rb +1 -1
  55. data/manual/text/alignment.rb +2 -2
  56. data/manual/text/column_box.rb +2 -2
  57. data/manual/text/font_style.rb +5 -2
  58. data/manual/text/formatted_callbacks.rb +17 -12
  59. data/manual/text/formatted_text.rb +7 -4
  60. data/manual/text/free_flowing_text.rb +3 -3
  61. data/manual/text/kerning_and_character_spacing.rb +4 -4
  62. data/manual/text/paragraph_indentation.rb +4 -5
  63. data/manual/text/rendering_and_color.rb +1 -1
  64. data/manual/text/right_to_left_text.rb +6 -6
  65. data/manual/text/rotation.rb +8 -3
  66. data/manual/text/text_box_extensions.rb +1 -1
  67. data/manual/text/text_box_overflow.rb +11 -9
  68. data/manual/text/win_ansi_charset.rb +9 -9
  69. data/prawn.gemspec +4 -10
  70. data/spec/prawn/document/bounding_box_spec.rb +82 -78
  71. data/spec/prawn/document/security_spec.rb +1 -1
  72. data/spec/prawn/document_span_spec.rb +14 -6
  73. data/spec/prawn/document_spec.rb +29 -26
  74. data/spec/prawn/font_spec.rb +16 -14
  75. data/spec/prawn/graphics_spec.rb +79 -44
  76. data/spec/prawn/images_spec.rb +13 -8
  77. data/spec/prawn/outline_spec.rb +127 -27
  78. data/spec/prawn/repeater_spec.rb +9 -8
  79. data/spec/prawn/soft_mask_spec.rb +1 -1
  80. data/spec/prawn/stamp_spec.rb +3 -2
  81. data/spec/prawn/text/box_spec.rb +57 -59
  82. data/spec/prawn/text/formatted/arranger_spec.rb +10 -10
  83. data/spec/prawn/text/formatted/box_spec.rb +8 -5
  84. data/spec/prawn/text/formatted/line_wrap_spec.rb +2 -1
  85. data/spec/prawn/text_draw_text_spec.rb +9 -8
  86. data/spec/prawn/text_spacing_spec.rb +2 -2
  87. data/spec/prawn/text_spec.rb +9 -9
  88. data/spec/prawn/text_with_inline_formatting_spec.rb +1 -1
  89. data/spec/prawn_manual_spec.rb +4 -4
  90. metadata +14 -98
  91. metadata.gz.sig +0 -0
@@ -264,11 +264,12 @@ module Prawn
264
264
  counting_parent = parent
265
265
  while counting_parent
266
266
  counting_parent.data.count += 1
267
- counting_parent = if counting_parent == root
268
- nil
269
- else
270
- counting_parent.data.parent
271
- end
267
+ counting_parent =
268
+ if counting_parent == root
269
+ nil
270
+ else
271
+ counting_parent.data.parent
272
+ end
272
273
  end
273
274
  end
274
275
 
@@ -115,7 +115,7 @@ module Prawn
115
115
  @document.stamp(@stamp_name) if match?(page_number)
116
116
  elsif @block && match?(page_number)
117
117
  @document.save_graphics_state(@graphic_state) do
118
- @document.send(:freeze_stamp_graphics)
118
+ @document.__send__(:freeze_stamp_graphics)
119
119
  @block.call
120
120
  end
121
121
  end
@@ -124,8 +124,8 @@ module Prawn
124
124
  def encryption_dictionary
125
125
  {
126
126
  Filter: :Standard, # default PDF security handler
127
- V: 1, # "Algorithm 3.1", PDF reference 1.3
128
- R: 2, # Revision 2 of the algorithm
127
+ V: 1, # "Algorithm 3.1", PDF reference 1.3
128
+ R: 2, # Revision 2 of the algorithm
129
129
  O: PDF::Core::ByteString.new(owner_password_hash),
130
130
  U: PDF::Core::ByteString.new(user_password_hash),
131
131
  P: permissions_value
@@ -181,21 +181,23 @@ module Prawn
181
181
  end
182
182
 
183
183
  def user_encryption_key
184
- @user_encryption_key ||= begin
185
- md5 = Digest::MD5.new
186
- md5 << pad_password(@user_password)
187
- md5 << owner_password_hash
188
- md5 << [permissions_value].pack('V')
189
- md5.digest[0, 5]
190
- end
184
+ @user_encryption_key ||=
185
+ begin
186
+ md5 = Digest::MD5.new
187
+ md5 << pad_password(@user_password)
188
+ md5 << owner_password_hash
189
+ md5 << [permissions_value].pack('V')
190
+ md5.digest[0, 5]
191
+ end
191
192
  end
192
193
 
193
194
  # The O (owner) value in the encryption dictionary. Algorithm 3.3.
194
195
  def owner_password_hash
195
- @owner_password_hash ||= begin
196
- key = Digest::MD5.digest(pad_password(@owner_password))[0, 5]
197
- Arcfour.new(key).encrypt(pad_password(@user_password))
198
- end
196
+ @owner_password_hash ||=
197
+ begin
198
+ key = Digest::MD5.digest(pad_password(@owner_password))[0, 5]
199
+ Arcfour.new(key).encrypt(pad_password(@user_password))
200
+ end
199
201
  end
200
202
 
201
203
  # The U (user) value in the encryption dictionary. Algorithm 3.4.
@@ -219,19 +221,22 @@ module PDF
219
221
  def encrypted_pdf_object(obj, key, id, gen, in_content_stream = false)
220
222
  case obj
221
223
  when Array
222
- '[' + obj.map do |e|
224
+ array_content = obj.map do |e|
223
225
  encrypted_pdf_object(e, key, id, gen, in_content_stream)
224
- end.join(' ') + ']'
226
+ end.join(' ')
227
+ "[#{array_content}]"
225
228
  when LiteralString
226
- obj = ByteString.new(
227
- Prawn::Document::Security.encrypt_string(obj, key, id, gen)
228
- ).gsub(/[\\\n\(\)]/) { |m| "\\#{m}" }
229
+ obj =
230
+ ByteString.new(
231
+ Prawn::Document::Security.encrypt_string(obj, key, id, gen)
232
+ ).gsub(/[\\\n()]/) { |m| "\\#{m}" }
229
233
  "(#{obj})"
230
234
  when Time
231
- obj = obj.strftime('D:%Y%m%d%H%M%S%z').chop.chop + "'00'"
232
- obj = ByteString.new(
233
- Prawn::Document::Security.encrypt_string(obj, key, id, gen)
234
- ).gsub(/[\\\n\(\)]/) { |m| "\\#{m}" }
235
+ obj = "#{obj.strftime('D:%Y%m%d%H%M%S%z').chop.chop}'00'"
236
+ obj =
237
+ ByteString.new(
238
+ Prawn::Document::Security.encrypt_string(obj, key, id, gen)
239
+ ).gsub(/[\\\n()]/) { |m| "\\#{m}" }
235
240
  "(#{obj})"
236
241
  when String
237
242
  pdf_object(
@@ -241,19 +246,16 @@ module PDF
241
246
  in_content_stream
242
247
  )
243
248
  when ::Hash
244
- '<< ' +
245
- obj.map do |k, v|
246
- unless k.is_a?(String) || k.is_a?(Symbol)
247
- raise PDF::Core::Errors::FailedObjectConversion,
248
- 'A PDF Dictionary must be keyed by names'
249
- end
250
- pdf_object(k.to_sym, in_content_stream) + ' ' +
251
- encrypted_pdf_object(v, key, id, gen, in_content_stream) + "\n"
252
- end.join('') +
253
- '>>'
249
+ hash_content = obj.map do |k, v|
250
+ unless k.is_a?(String) || k.is_a?(Symbol)
251
+ raise PDF::Core::Errors::FailedObjectConversion,
252
+ 'A PDF Dictionary must be keyed by names'
253
+ end
254
+ "#{pdf_object(k.to_sym, in_content_stream)} #{encrypted_pdf_object(v, key, id, gen, in_content_stream)}\n"
255
+ end.join('')
256
+ "<< #{hash_content}>>"
254
257
  when NameTree::Value
255
- pdf_object(obj.name) + ' ' +
256
- encrypted_pdf_object(obj.value, key, id, gen, in_content_stream)
258
+ "#{pdf_object(obj.name)} #{encrypted_pdf_object(obj.value, key, id, gen, in_content_stream)}"
257
259
  when PDF::Core::OutlineRoot, PDF::Core::OutlineItem
258
260
  encrypted_pdf_object(obj.to_hash, key, id, gen, in_content_stream)
259
261
  else # delegate back to pdf_object
@@ -265,10 +267,11 @@ module PDF
265
267
  class Stream
266
268
  def encrypted_object(key, id, gen)
267
269
  if filtered_stream
268
- "stream\n" +
270
+ "stream\n#{
269
271
  Prawn::Document::Security.encrypt_string(
270
272
  filtered_stream, key, id, gen
271
- ) + "\nendstream\n"
273
+ )
274
+ }\nendstream\n"
272
275
  else
273
276
  ''
274
277
  end
@@ -192,21 +192,19 @@ module Prawn
192
192
 
193
193
  color = options.delete(:color)
194
194
  if color
195
- array = array.map do |fragment|
196
- fragment[:color] ? fragment : fragment.merge(color: color)
197
- end
195
+ array =
196
+ array.map do |fragment|
197
+ fragment[:color] ? fragment : fragment.merge(color: color)
198
+ end
198
199
  end
199
200
 
200
201
  if @indent_paragraphs
201
202
  text_formatter.array_paragraphs(array).each do |paragraph|
202
203
  remaining_text = draw_indented_formatted_line(paragraph, options)
203
204
 
204
- if @no_text_printed
205
- # unless this paragraph was an empty line
206
- unless @all_text_printed
207
- @bounding_box.move_past_bottom
208
- remaining_text = draw_indented_formatted_line(paragraph, options)
209
- end
205
+ if @no_text_printed && !@all_text_printed
206
+ @bounding_box.move_past_bottom
207
+ remaining_text = draw_indented_formatted_line(paragraph, options)
210
208
  end
211
209
 
212
210
  unless @all_text_printed
@@ -337,8 +335,8 @@ module Prawn
337
335
  #
338
336
  def height_of_formatted(array, options = {})
339
337
  if options[:indent_paragraphs]
340
- raise NotImplementedError, ':indent_paragraphs option not available' \
341
- 'with height_of'
338
+ raise NotImplementedError,
339
+ ':indent_paragraphs option not available with height_of'
342
340
  end
343
341
  process_final_gap_option(options)
344
342
  box = Text::Formatted::Box.new(
@@ -364,11 +362,12 @@ module Prawn
364
362
  end
365
363
 
366
364
  def draw_indented_formatted_line(string, options)
367
- gap = if options.fetch(:direction, text_direction) == :ltr
368
- [@indent_paragraphs, 0]
369
- else
370
- [0, @indent_paragraphs]
371
- end
365
+ gap =
366
+ if options.fetch(:direction, text_direction) == :ltr
367
+ [@indent_paragraphs, 0]
368
+ else
369
+ [0, @indent_paragraphs]
370
+ end
372
371
 
373
372
  indent(*gap) do
374
373
  fill_formatted_text_box(string, options.dup.merge(single_line: true))
@@ -421,8 +420,9 @@ module Prawn
421
420
 
422
421
  def inspect_options_for_text(options)
423
422
  if options[:at]
424
- raise ArgumentError, ':at is no longer a valid option with text.' \
425
- 'use draw_text or text_box instead'
423
+ raise ArgumentError,
424
+ ':at is no longer a valid option with text.' \
425
+ 'use draw_text or text_box instead'
426
426
  end
427
427
  process_final_gap_option(options)
428
428
  process_indent_paragraphs_option(options)
@@ -107,14 +107,15 @@ module Prawn
107
107
  options = options.dup
108
108
  options[:document] = self
109
109
 
110
- box = if options[:inline_format]
111
- p = options.delete(:inline_format)
112
- p = [] unless p.is_a?(Array)
113
- array = text_formatter.format(string, *p)
114
- Text::Formatted::Box.new(array, options)
115
- else
116
- Text::Box.new(string, options)
117
- end
110
+ box =
111
+ if options[:inline_format]
112
+ p = options.delete(:inline_format)
113
+ p = [] unless p.is_a?(Array)
114
+ array = text_formatter.format(string, *p)
115
+ Text::Formatted::Box.new(array, options)
116
+ else
117
+ Text::Box.new(string, options)
118
+ end
118
119
 
119
120
  box.render
120
121
  end
@@ -134,7 +135,7 @@ module Prawn
134
135
 
135
136
  def render(flags = {})
136
137
  leftover = super(flags)
137
- leftover.collect { |hash| hash[:text] }.join
138
+ leftover.map { |hash| hash[:text] }.join
138
139
  end
139
140
  end
140
141
  end
@@ -13,6 +13,25 @@ module Prawn
13
13
  # @private
14
14
 
15
15
  class Arranger #:nodoc:
16
+ class NotFinalized < StandardError
17
+ DEFAULT_MESSAGE = 'Lines must be finalized'
18
+ MESSAGE_WITH_METHOD = 'Lines must be finalized before calling #%<method>s'
19
+
20
+ def initialize(message = DEFAULT_MESSAGE, method: nil)
21
+ if method && message == DEFAULT_MESSAGE
22
+ super format(MESSAGE_WITH_METHOD, method: method)
23
+ else
24
+ super message
25
+ end
26
+ end
27
+ end
28
+
29
+ class BadFontFamily < StandardError
30
+ def initialize(message = 'Bad font family')
31
+ super
32
+ end
33
+ end
34
+
16
35
  attr_reader :max_line_height
17
36
  attr_reader :max_descender
18
37
  attr_reader :max_ascender
@@ -33,30 +52,30 @@ module Prawn
33
52
 
34
53
  def space_count
35
54
  unless finalized
36
- raise 'Lines must be finalized before calling #space_count'
55
+ raise NotFinalized.new(method: 'space_count')
37
56
  end
38
57
 
39
- @fragments.inject(0) do |sum, fragment|
58
+ @fragments.reduce(0) do |sum, fragment|
40
59
  sum + fragment.space_count
41
60
  end
42
61
  end
43
62
 
44
63
  def line_width
45
64
  unless finalized
46
- raise 'Lines must be finalized before calling #line_width'
65
+ raise raise NotFinalized.new(method: 'line_width')
47
66
  end
48
67
 
49
- @fragments.inject(0) do |sum, fragment|
68
+ @fragments.reduce(0) do |sum, fragment|
50
69
  sum + fragment.width
51
70
  end
52
71
  end
53
72
 
54
73
  def line
55
74
  unless finalized
56
- raise 'Lines must be finalized before calling #line'
75
+ raise NotFinalized.new(method: 'line')
57
76
  end
58
77
 
59
- @fragments.collect do |fragment|
78
+ @fragments.map do |fragment|
60
79
  fragment.text.dup.encode(::Encoding::UTF_8)
61
80
  rescue ::Encoding::InvalidByteSequenceError,
62
81
  ::Encoding::UndefinedConversionError
@@ -110,7 +129,7 @@ module Prawn
110
129
 
111
130
  def next_string
112
131
  if finalized
113
- raise 'Lines must not be finalized when calling #next_string'
132
+ raise NotFinalized.new(method: 'next_string')
114
133
  end
115
134
 
116
135
  next_unconsumed_hash = @unconsumed.shift
@@ -163,7 +182,7 @@ module Prawn
163
182
 
164
183
  @document.character_spacing(character_spacing) do
165
184
  if font || font_style != :normal
166
- raise 'Bad font family' unless @document.font.family
185
+ raise BadFontFamily unless @document.font.family
167
186
 
168
187
  @document.font(
169
188
  font || @document.font.family, style: font_style
@@ -197,7 +216,7 @@ module Prawn
197
216
 
198
217
  def retrieve_fragment
199
218
  unless finalized
200
- raise 'Lines must be finalized before fragments can be retrieved'
219
+ raise NotFinalized, 'Lines must be finalized before fragments can be retrieved'
201
220
  end
202
221
 
203
222
  @fragments.shift
@@ -215,9 +234,8 @@ module Prawn
215
234
  end
216
235
 
217
236
  def font_style(styles)
218
- if styles.nil?
219
- :normal
220
- elsif styles.include?(:bold) && styles.include?(:italic)
237
+ styles = Array(styles)
238
+ if styles.include?(:bold) && styles.include?(:italic)
221
239
  :bold_italic
222
240
  elsif styles.include?(:bold)
223
241
  :bold
@@ -240,19 +258,20 @@ module Prawn
240
258
  end
241
259
  end
242
260
 
243
- def apply_font_size(size, styles)
261
+ def apply_font_size(size, styles, &block)
244
262
  if subscript?(styles) || superscript?(styles)
245
263
  relative_size = 0.583
246
- size = if size.nil?
247
- @document.font_size * relative_size
248
- else
249
- size * relative_size
250
- end
264
+ size =
265
+ if size.nil?
266
+ @document.font_size * relative_size
267
+ else
268
+ size * relative_size
269
+ end
251
270
  end
252
271
  if size.nil?
253
272
  yield
254
273
  else
255
- @document.font_size(size) { yield }
274
+ @document.font_size(size, &block)
256
275
  end
257
276
  end
258
277
 
@@ -222,11 +222,12 @@ module Prawn
222
222
  shrink_to_fit(text) if @overflow == :shrink_to_fit
223
223
  process_vertical_alignment(text)
224
224
  @inked = true unless flags[:dry_run]
225
- unprinted_text = if @rotate != 0 && @inked
226
- render_rotated(text)
227
- else
228
- wrap(text)
229
- end
225
+ unprinted_text =
226
+ if @rotate != 0 && @inked
227
+ render_rotated(text)
228
+ else
229
+ wrap(text)
230
+ end
230
231
  @inked = false
231
232
  end
232
233
  end
@@ -265,11 +266,12 @@ module Prawn
265
266
  when :right
266
267
  x = @at[0] + @width - line_width
267
268
  when :justify
268
- x = if @direction == :ltr
269
- @at[0]
270
- else
271
- @at[0] + @width - line_width
272
- end
269
+ x =
270
+ if @direction == :ltr
271
+ @at[0]
272
+ else
273
+ @at[0] + @width - line_width
274
+ end
273
275
  else
274
276
  raise ArgumentError,
275
277
  'align must be one of :left, :right, :center or :justify symbols'
@@ -290,13 +292,15 @@ module Prawn
290
292
  @document.word_spacing(word_spacing) do
291
293
  if @draw_text_callback
292
294
  @draw_text_callback.call(
293
- fragment.text, at: [x, y],
294
- kerning: @kerning
295
+ fragment.text,
296
+ at: [x, y],
297
+ kerning: @kerning
295
298
  )
296
299
  else
297
300
  @document.draw_text!(
298
- fragment.text, at: [x, y],
299
- kerning: @kerning
301
+ fragment.text,
302
+ at: [x, y],
303
+ kerning: @kerning
300
304
  )
301
305
  end
302
306
  end
@@ -340,6 +344,7 @@ module Prawn
340
344
 
341
345
  # @private
342
346
  def self.inherited(base)
347
+ super
343
348
  extensions.each { |e| base.extensions << e }
344
349
  end
345
350
 
@@ -371,7 +376,7 @@ module Prawn
371
376
  end
372
377
 
373
378
  def original_text
374
- @original_array.collect(&:dup)
379
+ @original_array.map(&:dup)
375
380
  end
376
381
 
377
382
  def original_text=(formatted_text)
@@ -86,18 +86,20 @@ module Prawn
86
86
  # the line
87
87
  #
88
88
  def add_fragment_to_line(fragment)
89
- if fragment == ''
89
+ case fragment
90
+ when ''
90
91
  true
91
- elsif fragment == "\n"
92
+ when "\n"
92
93
  @newline_encountered = true
93
94
  false
94
95
  else
95
96
  tokenize(fragment).each do |segment|
96
- segment_width = if segment == zero_width_space(segment.encoding)
97
- 0
98
- else
99
- @document.width_of(segment, kerning: @kerning)
100
- end
97
+ segment_width =
98
+ if segment == zero_width_space(segment.encoding)
99
+ 0
100
+ else
101
+ @document.width_of(segment, kerning: @kerning)
102
+ end
101
103
 
102
104
  if @accumulated_width + segment_width <= @width
103
105
  @accumulated_width += segment_width
@@ -151,9 +153,10 @@ module Prawn
151
153
  # word breaking is needed
152
154
  #
153
155
  def word_division_scan_pattern(encoding = ::Encoding::UTF_8)
154
- common_whitespaces = ["\t", "\n", "\v", "\r", ' '].map do |c|
155
- c.encode(encoding)
156
- end
156
+ common_whitespaces =
157
+ ["\t", "\n", "\v", "\r", ' '].map do |c|
158
+ c.encode(encoding)
159
+ end
157
160
 
158
161
  Regexp.union(
159
162
  common_whitespaces +
@@ -254,12 +257,11 @@ module Prawn
254
257
 
255
258
  def pull_preceding_fragment_to_join_this_one?(current_fragment)
256
259
  if @fragment_output.empty? && !current_fragment.empty? &&
257
- @line_contains_more_than_one_word
258
- unless previous_fragment_ended_with_breakable? ||
259
- fragment_begins_with_breakable?(current_fragment)
260
- @fragment_output = @previous_fragment_output_without_last_word
261
- update_output_based_on_last_fragment(@previous_fragment)
262
- end
260
+ @line_contains_more_than_one_word &&
261
+ !(previous_fragment_ended_with_breakable? ||
262
+ fragment_begins_with_breakable?(current_fragment))
263
+ @fragment_output = @previous_fragment_output_without_last_word
264
+ update_output_based_on_last_fragment(@previous_fragment)
263
265
  end
264
266
  end
265
267