asciidoctor-pdf 2.1.1 → 2.1.4

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: bfcc8354e8152f540a4510dbddc39d38d577ee958aa51fbfb10b92d965abaa0c
4
- data.tar.gz: 68848a664ded97d88c45e2d8357f3880a5e10f4b6cc0f0c44b014cd85088d1ea
3
+ metadata.gz: eb8baebe850d75fcfc95460fbbdf89978867adb076acf572abaff0f51e18fb04
4
+ data.tar.gz: d4dbbaab4981db0666488ae108aee0f5851feb706e3846b13cd5cf46c341b5bc
5
5
  SHA512:
6
- metadata.gz: b1fb4074705e06fb70c188278e677c69f696e832d28d5ad49e6135b218ef36416abfaebfdedd980ff094579ae509d5006b59a52c57cf62374e9bdd69822b3714
7
- data.tar.gz: 07acff80d3d5c04e5ba8fbf591bbf3d952685bd0de605ac0e60645bbe478eafd1013451d4085abf8e2a41a996f5c4d8bba885377a1878a301ad75e144c0d2316
6
+ metadata.gz: 26b1c9830deeb0a39494e9cdb85fa5c2e2295efe8b3d527525b27c6dcf420a8ab94e06eeaca3431425e9cf547150d372bab49813af946cdd5ea0e155d6aad1f0
7
+ data.tar.gz: d584830d1eb1f76a005b48cf6a20030311d40184254d4ddfbd752f99a66c27feab85292c79012af0c9c4b7272a1727f402828f1c6d992228660ccbf78be44d2a
data/CHANGELOG.adoc CHANGED
@@ -5,6 +5,47 @@
5
5
  This document provides a high-level view of the changes to the {project-name} by release.
6
6
  For a detailed view of what has changed, refer to the {url-repo}/commits/main[commit history] on GitHub.
7
7
 
8
+ == 2.1.4 (2022-06-26) - @mojavelinux
9
+
10
+ Improvements::
11
+
12
+ * include source location in warning message for truncated table cell if sourcemap is enabled (#2261)
13
+
14
+ Bug Fixes::
15
+
16
+ * allow alt text for block image, video, and audio to wrap to next line on same page (#2258)
17
+ * apply text-tranform from custom role on phrase after attributes have been resolved (#2263)
18
+ * make URL check more strict so image target containing a colon is not mistaken as a URL
19
+
20
+ === Details
21
+
22
+ {url-repo}/releases/tag/v2.1.4[git tag] | {url-repo}/compare/v2.1.3\...v2.1.4[full diff]
23
+
24
+ == 2.1.3 (2022-06-23) - @mojavelinux
25
+
26
+ Bug Fixes::
27
+
28
+ * interpret `start-at` theme keys with value `1` correctly (as `1` instead of `2`) (#2255)
29
+ * restore column layout after importing page(s) from PDF (#2253)
30
+ * fix crash when border color is transparent (`thematic-break-border-color`, `admonition-column-rule`, `quote-border-color`, `verse-border-color`)
31
+ * ensure page margin is restored after imported page
32
+
33
+ === Details
34
+
35
+ {url-repo}/releases/tag/v2.1.3[git tag] | {url-repo}/compare/v2.1.2\...v2.1.3[full diff]
36
+
37
+ == 2.1.2 (2022-06-17) - @mojavelinux
38
+
39
+ Bug Fixes::
40
+
41
+ * apply page layout from main document to new page in scratch document (#2248)
42
+ * use correct logic to insert page before TOC with automatic placement when doctype=book and media=prepress
43
+ * use `get_entries_for_toc` to determine if the TOC is non-empty rather than `Document#sections?`
44
+
45
+ === Details
46
+
47
+ {url-repo}/releases/tag/v2.1.2[git tag] | {url-repo}/compare/v2.1.1\...v2.1.2[full diff]
48
+
8
49
  == 2.1.1 (2022-06-15) - @mojavelinux
9
50
 
10
51
  Improvements::
data/README.adoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = Asciidoctor PDF: A native PDF converter for AsciiDoc
2
2
  Dan Allen <https://github.com/mojavelinux[@mojavelinux]>; Sarah White <https://github.com/graphitefriction[@graphitefriction]>
3
- v2.1.1, 2022-06-15
3
+ v2.1.4, 2022-06-26
4
4
  // Settings:
5
5
  :experimental:
6
6
  :idprefix:
@@ -22,8 +22,6 @@ endif::[]
22
22
  // Aliases:
23
23
  :project-name: Asciidoctor PDF
24
24
  :project-handle: asciidoctor-pdf
25
- // Variables:
26
- :release-line: 2.1.x
27
25
  // URLs:
28
26
  :url-gem: https://rubygems.org/gems/asciidoctor-pdf
29
27
  :url-project: https://github.com/asciidoctor/asciidoctor-pdf
@@ -114,6 +114,7 @@ module Asciidoctor
114
114
  UriBreakCharsRx = %r((?:/|\?|&amp;|#)(?!$))
115
115
  UriBreakCharRepl = %(\\&#{ZeroWidthSpace})
116
116
  UriSchemeBoundaryRx = %r((?<=://))
117
+ UrlSniffRx = %r(^\p{Alpha}[\p{Alnum}+.-]*://)
117
118
  LineScanRx = /\n|.+/
118
119
  BlankLineRx = /\n{2,}/
119
120
  CjkLineBreakRx = /(?=[\u3000\u30a0-\u30ff\u3040-\u309f\p{Han}\uff00-\uffef])/
@@ -198,8 +199,8 @@ module Asciidoctor
198
199
 
199
200
  indent_section do
200
201
  toc_num_levels = (doc.attr 'toclevels', 2).to_i
201
- if (insert_toc = (doc.attr? 'toc') && !((toc_placement = doc.attr 'toc-placement') == 'macro' || toc_placement == 'preamble') && doc.sections?)
202
- start_toc_page doc, toc_placement if title_page_on
202
+ if (insert_toc = (doc.attr? 'toc') && !((toc_placement = doc.attr 'toc-placement') == 'macro' || toc_placement == 'preamble') && !(get_entries_for_toc doc).empty?)
203
+ start_new_page if @ppbook && verso_page?
203
204
  add_dest_for_block doc, id: 'toc', y: (at_page_top? ? page_height : nil)
204
205
  @toc_extent = allocate_toc doc, toc_num_levels, cursor, title_page_on
205
206
  else
@@ -213,7 +214,7 @@ module Asciidoctor
213
214
  first_page_offset = has_title_page ? zero_page_offset.next : zero_page_offset
214
215
  body_offset = (body_start_page_number = page_number) - 1
215
216
  if ::Integer === (running_content_start_at = @theme.running_content_start_at)
216
- running_content_body_offset = body_offset + [running_content_start_at.pred, 1].max
217
+ running_content_body_offset = body_offset + [running_content_start_at.pred, 0].max
217
218
  running_content_start_at = 'body'
218
219
  else
219
220
  running_content_body_offset = body_offset
@@ -227,7 +228,7 @@ module Asciidoctor
227
228
  end
228
229
  end
229
230
  if ::Integer === (page_numbering_start_at = @theme.page_numbering_start_at)
230
- page_numbering_body_offset = body_offset + [page_numbering_start_at.pred, 1].max
231
+ page_numbering_body_offset = body_offset + [page_numbering_start_at.pred, 0].max
231
232
  page_numbering_start_at = 'body'
232
233
  else
233
234
  page_numbering_body_offset = body_offset
@@ -263,12 +264,12 @@ module Asciidoctor
263
264
  else
264
265
  body_offset = body_start_page_number - 1
265
266
  if ::Integer === (running_content_start_at = @theme.running_content_start_at)
266
- running_content_body_offset = body_offset + [running_content_start_at.pred, 1].max
267
+ running_content_body_offset = body_offset + [running_content_start_at.pred, 0].max
267
268
  else
268
269
  running_content_body_offset = body_offset
269
270
  end
270
271
  if ::Integer === (page_numbering_start_at = @theme.page_numbering_start_at)
271
- page_numbering_body_offset = body_offset + [page_numbering_start_at.pred, 1].max
272
+ page_numbering_body_offset = body_offset + [page_numbering_start_at.pred, 0].max
272
273
  elsif page_numbering_start_at == 'cover' && has_front_cover
273
274
  page_numbering_body_offset = 0
274
275
  else
@@ -371,8 +372,6 @@ module Asciidoctor
371
372
  if (page_margin_inner = theme.page_margin_inner)
372
373
  page_margin_recto[3] = page_margin_verso[1] = page_margin_inner
373
374
  end
374
- # NOTE: prepare scratch document to use page margin from recto side (which has same width as verso side)
375
- set_page_margin page_margin_recto unless page_margin_recto == page_margin
376
375
  else
377
376
  @ppbook = nil
378
377
  end
@@ -581,6 +580,7 @@ module Asciidoctor
581
580
  end
582
581
 
583
582
  def prepare_theme theme
583
+ theme.base_border_color = nil if theme.base_border_color == 'transparent'
584
584
  theme.base_font_color ||= '000000'
585
585
  theme.base_font_size ||= 12
586
586
  theme.base_font_style = theme.base_font_style&.to_sym || :normal
@@ -943,7 +943,7 @@ module Asciidoctor
943
943
  if extent
944
944
  label_height = extent.single_page_height || cursor
945
945
  if (rule_width = @theme.admonition_column_rule_width || 0) > 0 &&
946
- (rule_color = @theme.admonition_column_rule_color || @theme.base_border_color)
946
+ (rule_color = resolve_theme_color :admonition_column_rule_color, @theme.base_border_color, nil)
947
947
  rule_style = @theme.admonition_column_rule_style&.to_sym || :solid
948
948
  float do
949
949
  extent.each_page do |first_page, last_page|
@@ -1273,7 +1273,7 @@ module Asciidoctor
1273
1273
  category = node.context == :quote ? :quote : :verse
1274
1274
  # NOTE: b_width and b_left_width are mutually exclusive
1275
1275
  if (b_left_width = @theme[%(#{category}_border_left_width)]) && b_left_width > 0
1276
- b_color = @theme[%(#{category}_border_color)] || @theme.base_border_color
1276
+ b_left_width = nil unless (b_color = resolve_theme_color %(#{category}_border_color), @theme.base_border_color, nil)
1277
1277
  else
1278
1278
  b_left_width = nil
1279
1279
  b_width = nil if (b_width = @theme[%(#{category}_border_width)]) == 0
@@ -1887,7 +1887,7 @@ module Asciidoctor
1887
1887
  add_dest_for_block node if node.id
1888
1888
  audio_path = node.media_uri node.attr 'target'
1889
1889
  play_symbol = (node.document.attr? 'icons', 'font') ? %(<font name="fas">#{(icon_font_data 'fas').unicode 'play'}</font>) : RightPointer
1890
- ink_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{audio_path}">#{audio_path}</a> <em>(audio)</em>), normalize: false, margin: 0, single_line: true
1890
+ ink_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{audio_path}">#{audio_path}</a> <em>(audio)</em>), normalize: false, margin: 0
1891
1891
  ink_caption node, labeled: false, end: :bottom if node.title?
1892
1892
  theme_margin :block, :bottom, (next_enclosed_block node)
1893
1893
  end
@@ -1915,7 +1915,7 @@ module Asciidoctor
1915
1915
  if poster.nil_or_empty?
1916
1916
  add_dest_for_block node if node.id
1917
1917
  play_symbol = (node.document.attr? 'icons', 'font') ? %(<font name="fas">#{(icon_font_data 'fas').unicode 'play'}</font>) : RightPointer
1918
- ink_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{video_path}">#{video_path}</a> <em>(#{type})</em>), normalize: false, margin: 0, single_line: true
1918
+ ink_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{video_path}">#{video_path}</a> <em>(#{type})</em>), normalize: false, margin: 0
1919
1919
  ink_caption node, labeled: false, end: :bottom if node.title?
1920
1920
  theme_margin :block, :bottom, (next_enclosed_block node)
1921
1921
  else
@@ -2054,7 +2054,8 @@ module Asciidoctor
2054
2054
  content: cell_text,
2055
2055
  colspan: cell.colspan || 1,
2056
2056
  align: (cell.attr 'halign').to_sym,
2057
- valign: (val = cell.attr 'valign') == 'middle' ? :center : val.to_sym
2057
+ valign: (val = cell.attr 'valign') == 'middle' ? :center : val.to_sym,
2058
+ source_location: cell.source_location
2058
2059
  end)
2059
2060
  end
2060
2061
  end unless head_rows.empty?
@@ -2073,7 +2074,8 @@ module Asciidoctor
2073
2074
  colspan: cell.colspan || 1,
2074
2075
  rowspan: cell.rowspan || 1,
2075
2076
  align: (cell.attr 'halign').to_sym,
2076
- valign: (val = cell.attr 'valign') == 'middle' ? :center : val.to_sym
2077
+ valign: (val = cell.attr 'valign') == 'middle' ? :center : val.to_sym,
2078
+ source_location: cell.source_location
2077
2079
  cell_line_metrics = body_cell_line_metrics
2078
2080
  case cell.style
2079
2081
  when :emphasis
@@ -2134,7 +2136,7 @@ module Asciidoctor
2134
2136
  # NOTE: line metrics get applied when AsciiDoc content is converted
2135
2137
  cell_line_metrics = nil
2136
2138
  asciidoc_cell = ::Prawn::Table::Cell::AsciiDoc.new self, (cell_data.merge content: cell.inner_document, padding: body_cell_padding)
2137
- cell_data = { content: asciidoc_cell }
2139
+ cell_data = { content: asciidoc_cell, source_location: cell.source_location }
2138
2140
  end
2139
2141
  if cell_line_metrics
2140
2142
  cell_padding = body_cell_padding.dup
@@ -2341,9 +2343,11 @@ module Asciidoctor
2341
2343
 
2342
2344
  def convert_thematic_break node
2343
2345
  pad_box @theme.thematic_break_padding || [@theme.thematic_break_margin_top, 0] do
2344
- stroke_horizontal_rule @theme.thematic_break_border_color,
2345
- line_width: @theme.thematic_break_border_width,
2346
- line_style: (@theme.thematic_break_border_style&.to_sym || :solid)
2346
+ if (b_color = resolve_theme_color :thematic_break_border_color)
2347
+ stroke_horizontal_rule b_color,
2348
+ line_width: @theme.thematic_break_border_width,
2349
+ line_style: (@theme.thematic_break_border_style&.to_sym || :solid)
2350
+ end
2347
2351
  end
2348
2352
  conceal_page_top { theme_margin :block, :bottom, (next_enclosed_block node) }
2349
2353
  end
@@ -2352,7 +2356,7 @@ module Asciidoctor
2352
2356
  # NOTE: only allow document to have a single managed toc
2353
2357
  return if @toc_extent
2354
2358
  is_macro = (placement = opts[:placement] || 'macro') == 'macro'
2355
- if ((doc = node.document).attr? 'toc-placement', placement) && (doc.attr? 'toc') && doc.sections?
2359
+ if ((doc = node.document).attr? 'toc-placement', placement) && (doc.attr? 'toc') && !(get_entries_for_toc doc).empty?
2356
2360
  start_toc_page node, placement if (is_book = doc.doctype == 'book')
2357
2361
  add_dest_for_block node, id: (node.id || 'toc') if is_macro
2358
2362
  toc_extent = @toc_extent = allocate_toc doc, (doc.attr 'toclevels', 2).to_i, cursor, (title_page_on = is_book || (doc.attr? 'title-page'))
@@ -2684,13 +2688,7 @@ module Asciidoctor
2684
2688
  end
2685
2689
 
2686
2690
  if (roles = node.role)
2687
- theme = load_theme node.document
2688
- roles.split.each do |role|
2689
- if (text_transform = theme[%(role_#{role}_text_transform)])
2690
- inner_text = transform_text inner_text, text_transform
2691
- end
2692
- inner_text = inner_text.gsub DoubleSpaceRx, ' ' + ZeroWidthSpace if role == 'pre-wrap' && (inner_text.include? DoubleSpace)
2693
- end
2691
+ inner_text = inner_text.gsub DoubleSpaceRx, ' ' + ZeroWidthSpace if (node.has_role? 'pre-wrap') && (inner_text.include? DoubleSpace)
2694
2692
  quoted_text = is_tag ? %(#{open.chop} class="#{roles}">#{inner_text}#{close}) : %(<span class="#{roles}">#{open}#{inner_text}#{close}</span>)
2695
2693
  else
2696
2694
  quoted_text = %(#{open}#{inner_text}#{close})
@@ -2802,13 +2800,7 @@ module Asciidoctor
2802
2800
  value = (value.split LF).delete_if {|line| SimpleAttributeRefRx.match? line }.join LF if opts[:drop_lines_with_unresolved_attributes] && (value.include? '{')
2803
2801
  value = value.gsub '\{', '{' if escaped_attr_ref
2804
2802
  doc.set_attr 'attribute-missing', attribute_missing unless attribute_missing == 'skip'
2805
- if imagesdir
2806
- if imagesdir_to_restore
2807
- doc.set_attr 'imagesdir', imagesdir_to_restore
2808
- else
2809
- doc.remove_attr 'imagesdir'
2810
- end
2811
- end
2803
+ imagesdir_to_restore ? (doc.set_attr 'imagesdir', imagesdir_to_restore) : (doc.remove_attr 'imagesdir') if imagesdir
2812
2804
  value
2813
2805
  end
2814
2806
 
@@ -3246,7 +3238,8 @@ module Asciidoctor
3246
3238
  end
3247
3239
  end
3248
3240
 
3249
- # NOTE: inline_format is true by default
3241
+ # NOTE: inline_format option is true by default
3242
+ # NOTE: single_line option is not compatible with this method
3250
3243
  def ink_prose string, opts = {}
3251
3244
  top_margin = (margin = (opts.delete :margin)) || (opts.delete :margin_top) || 0
3252
3245
  bot_margin = margin || (opts.delete :margin_bottom) || @theme.prose_margin_bottom
@@ -4260,10 +4253,10 @@ module Asciidoctor
4260
4253
  # NOTE: this will catch a classloader resource path on JRuby (e.g., uri:classloader:/path/to/image)
4261
4254
  elsif ::File.absolute_path? image_path
4262
4255
  ::File.absolute_path image_path
4263
- elsif !(is_uri = node.is_uri? image_path) && imagesdir && (::File.absolute_path? imagesdir)
4256
+ elsif !(is_url = url? image_path) && imagesdir && (::File.absolute_path? imagesdir)
4264
4257
  ::File.absolute_path image_path, imagesdir
4265
4258
  # handle case when image is a URI
4266
- elsif is_uri || (imagesdir && (node.is_uri? imagesdir) && (image_path = node.normalize_web_path image_path, imagesdir, false))
4259
+ elsif is_url || (imagesdir && (url? imagesdir) && (image_path = node.normalize_web_path image_path, imagesdir, false))
4267
4260
  if !allow_uri_read
4268
4261
  log :warn, %(cannot embed remote image: #{image_path} (allow-uri-read attribute not enabled))
4269
4262
  return
@@ -4501,6 +4494,7 @@ module Asciidoctor
4501
4494
  end
4502
4495
 
4503
4496
  # TODO: document me, esp the first line formatting functionality
4497
+ # NOTE: single_line option should only be used if height option is specified
4504
4498
  def typeset_text string, line_metrics, opts = {}
4505
4499
  opts = { leading: line_metrics.leading, final_gap: line_metrics.final_gap }.merge opts
4506
4500
  string = string.gsub CjkLineBreakRx, ZeroWidthSpace if @cjk_line_breaks
@@ -4823,18 +4817,17 @@ module Asciidoctor
4823
4817
  end
4824
4818
 
4825
4819
  # NOTE: init_page is called within a float context; this will suppress prawn-svg messing with the cursor
4826
- # NOTE: init_page is not called for imported pages, front and back cover pages, and other image pages
4820
+ # NOTE: init_page is not called for imported pages, cover pages, image pages, and pages in the scratch document
4827
4821
  def init_page *_args
4828
4822
  next_page_side = page_side nil, @folio_placement[:inverted]
4829
4823
  if @media == 'prepress' && (next_page_margin = @page_margin_by_side[page_number == 1 ? :cover : next_page_side]) != page_margin
4830
4824
  set_page_margin next_page_margin
4831
4825
  end
4832
4826
  unless @page_bg_color == 'FFFFFF'
4833
- tare = true
4834
4827
  fill_absolute_bounds @page_bg_color
4828
+ tare = true
4835
4829
  end
4836
4830
  if (bg_image_path, bg_image_opts = @page_bg_image[next_page_side])
4837
- tare = true
4838
4831
  begin
4839
4832
  if bg_image_opts[:format] == 'pdf'
4840
4833
  # NOTE: pages that use PDF for the background do not support a background color or running content
@@ -4843,6 +4836,7 @@ module Asciidoctor
4843
4836
  else
4844
4837
  canvas { image bg_image_path, ({ position: :center, vposition: :center }.merge bg_image_opts) }
4845
4838
  end
4839
+ tare = true
4846
4840
  rescue
4847
4841
  facing_page_side = (PageSides - [next_page_side])[0]
4848
4842
  @page_bg_image[facing_page_side] = nil if @page_bg_image[facing_page_side] == @page_bg_image[next_page_side]
@@ -4955,7 +4949,7 @@ module Asciidoctor
4955
4949
  alt_text_vars[:'/link'] = ''
4956
4950
  end
4957
4951
  theme_font :image_alt do
4958
- ink_prose alt_text_template % alt_text_vars, align: opts[:align], margin: 0, normalize: false, single_line: true
4952
+ ink_prose alt_text_template % alt_text_vars, align: opts[:align], margin: 0, normalize: false
4959
4953
  end
4960
4954
  ink_caption node, category: :image, end: :bottom if node.title?
4961
4955
  theme_margin :block, :bottom, (next_enclosed_block node) unless opts[:pinned]
@@ -5037,10 +5031,8 @@ module Asciidoctor
5037
5031
  # QUESTION: should we pass a category as an argument?
5038
5032
  # QUESTION: should we make this a method on the theme ostruct? (e.g., @theme.resolve_color key, fallback)
5039
5033
  def resolve_theme_color key, fallback_color = nil, transparent_color = fallback_color
5040
- if (color = @theme[key])
5034
+ if (color = @theme[key] || fallback_color)
5041
5035
  color == 'transparent' ? transparent_color : color
5042
- else
5043
- fallback_color
5044
5036
  end
5045
5037
  end
5046
5038
 
@@ -5052,6 +5044,10 @@ module Asciidoctor
5052
5044
  false
5053
5045
  end
5054
5046
 
5047
+ def url? str
5048
+ (str.include? ':/') && (UrlSniffRx.match? str)
5049
+ end
5050
+
5055
5051
  # Calculate the width that is needed to print all the
5056
5052
  # fragments without wrapping any lines.
5057
5053
  #
@@ -5120,6 +5116,10 @@ module Asciidoctor
5120
5116
  end
5121
5117
 
5122
5118
  def init_scratch originator
5119
+ if @media == 'prepress' && page_margin != (page_margin_recto = @page_margin_by_side[:recto])
5120
+ # NOTE: prepare scratch document to use page margin from recto side (which has same width as verso side)
5121
+ set_page_margin page_margin_recto
5122
+ end
5123
5123
  @scratch_prototype = originator.instance_variable_get :@scratch_prototype
5124
5124
  @tmp_files = originator.instance_variable_get :@tmp_files
5125
5125
  text_formatter.scratch = true
@@ -6,20 +6,23 @@ Prawn::Document::ColumnBox.prepend (Module.new do
6
6
  def move_past_bottom
7
7
  (doc = @document).y = @y
8
8
  return if (@current_column = (@current_column + 1) % @columns) > 0
9
- par = @parent
10
- if (reset_y = @reflow_margins) && (reset_y == true || reset_y > doc.page_number)
11
- @y = par.absolute_top
12
- @height = par.height unless stretchy?
13
- end
9
+ parent_ = @parent
10
+ reset_top parent_ if (reflow_at = @reflow_margins) && (reflow_at == true || reflow_at > doc.page_number)
14
11
  initial_margins = doc.page.margins
15
- par.move_past_bottom
12
+ parent_.move_past_bottom
16
13
  if doc.page.margins != initial_margins
17
- doc.bounds = self.class.new doc, par, [(margin_box = doc.margin_box).absolute_left, @y],
14
+ doc.bounds = self.class.new doc, parent_, [(margin_box = doc.margin_box).absolute_left, @y],
18
15
  columns: @columns, reflow_margins: @reflow_margins, spacer: @spacer, width: margin_box.width, height: @height
19
16
  end
20
17
  nil
21
18
  end
22
19
 
20
+ def reset_top parent_ = @parent
21
+ @current_column = 0
22
+ @height = parent_.height unless stretchy?
23
+ @y = parent_.absolute_top
24
+ end
25
+
23
26
  # Rearranges the column box into a single column, where the original columns are in a single file. Used
24
27
  # for the purpose of computing the extent of content in a scratch document.
25
28
  def single_file
@@ -528,29 +528,6 @@ module Asciidoctor
528
528
  end
529
529
  end
530
530
 
531
- # Apply the text transform to the specified text.
532
- #
533
- # Supported transform values are "uppercase", "lowercase", or "none" (passed
534
- # as either a String or a Symbol). When the uppercase transform is applied to
535
- # the text, it correctly uppercases visible text while leaving markup and
536
- # named character entities unchanged. The none transform returns the text
537
- # unmodified.
538
- #
539
- def transform_text text, transform
540
- case transform
541
- when :uppercase, 'uppercase'
542
- uppercase_pcdata text
543
- when :lowercase, 'lowercase'
544
- lowercase_pcdata text
545
- when :capitalize, 'capitalize'
546
- capitalize_words_pcdata text
547
- when :smallcaps, 'smallcaps'
548
- smallcaps_pcdata text
549
- else
550
- text
551
- end
552
- end
553
-
554
531
  def hyphenate_text text, hyphenator
555
532
  hyphenate_words_pcdata text, hyphenator
556
533
  end
@@ -924,6 +901,8 @@ module Asciidoctor
924
901
  def import_page file, options = {}
925
902
  prev_page_layout = page.layout
926
903
  prev_page_size = page.size
904
+ prev_page_margin = page_margin
905
+ prev_bounds = bounds
927
906
  state.compress = false if state.compress # can't use compression if using template
928
907
  prev_text_rendering_mode = (defined? @text_rendering_mode) ? @text_rendering_mode : nil
929
908
  delete_current_page if options[:replace]
@@ -936,11 +915,15 @@ module Asciidoctor
936
915
  # NOTE: set page size & layout explicitly in case imported page differs
937
916
  # I'm not sure it's right to start a new page here, but unfortunately there's no other
938
917
  # way atm to prevent the size & layout of the imported page from affecting subsequent pages
939
- advance_page size: prev_page_size, layout: prev_page_layout if options.fetch :advance, true
918
+ if options.fetch :advance, true
919
+ advance_page layout: prev_page_layout, margin: prev_page_margin, size: prev_page_size
920
+ (@bounding_box = prev_bounds).reset_top if ColumnBox === prev_bounds
921
+ end
940
922
  elsif options.fetch :advance_if_missing, true
941
923
  delete_current_page
942
924
  # NOTE: see previous comment
943
- advance_page size: prev_page_size, layout: prev_page_layout
925
+ advance_page layout: prev_page_layout, margin: prev_page_margin, size: prev_page_size
926
+ @y = (@bounding_box = prev_bounds).reset_top if ColumnBox === prev_bounds
944
927
  else
945
928
  delete_current_page
946
929
  end
@@ -1112,7 +1095,8 @@ module Asciidoctor
1112
1095
  # This method performs all work in a scratch document (or documents). It begins by starting a
1113
1096
  # new page in the scratch document, first creating the scratch document if necessary. It then
1114
1097
  # applies all the settings from the main document to the scratch document that impact
1115
- # rendering. This includes the bounds, the cursor position, and the font settings.
1098
+ # rendering. This includes the bounds, the cursor position, and the font settings. This method
1099
+ # assumes that the content area remains constant when content flows from one page to the next.
1116
1100
  #
1117
1101
  # From this point, the number of attempts the method makes is determined by the value of the
1118
1102
  # keep_together keyword parameter. If the value is true (or the parent document is inhibiting
@@ -1149,7 +1133,7 @@ module Asciidoctor
1149
1133
  #
1150
1134
  # Returns an Extent or ScratchExtent object that describes the bounds of the content block.
1151
1135
  def dry_run keep_together: nil, pages_advanced: 0, single_page: nil, onto: nil, &block
1152
- (scratch_pdf = scratch).start_new_page
1136
+ (scratch_pdf = scratch).start_new_page layout: page.layout
1153
1137
  saved_bounds = scratch_pdf.bounds
1154
1138
  scratch_pdf.bounds = bounds.dup.tap do |bounds_copy|
1155
1139
  bounds_copy.instance_variable_set :@document, scratch_pdf
@@ -91,7 +91,9 @@ module Prawn
91
91
  # TODO: apply horizontal alignment; currently it is necessary to specify alignment on content blocks
92
92
  apply_font_properties { pdf.traverse content }
93
93
  if (extra_pages = pdf.page_number - start_page) > 0
94
- logger.error %(the table cell on page #{start_page} has been truncated; Asciidoctor PDF does not support table cell content that exceeds the height of a single page) unless extra_pages == 1 && pdf.page.empty?
94
+ unless extra_pages == 1 && pdf.page.empty?
95
+ logger.error message_with_context %(the table cell on page #{start_page} has been truncated; Asciidoctor PDF does not support table cell content that exceeds the height of a single page), source_location: @source_location
96
+ end
95
97
  extra_pages.times { pdf.delete_current_page }
96
98
  end
97
99
  nil
@@ -16,7 +16,9 @@ class Prawn::Table::Cell::Text
16
16
  height: spanned_content_height + FPTolerance,
17
17
  at: [0, @pdf.cursor]).render
18
18
  end
19
- logger.error %(the table cell on page #{@pdf.page_number} has been truncated; Asciidoctor PDF does not support table cell content that exceeds the height of a single page) unless remaining_text.empty? || @pdf.scratch?
19
+ unless remaining_text.empty? || @pdf.scratch?
20
+ logger.error message_with_context %(the table cell on page #{@pdf.page_number} has been truncated; Asciidoctor PDF does not support table cell content that exceeds the height of a single page), source_location: @source_location
21
+ end
20
22
  end
21
23
  end
22
24
 
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Prawn::Table::Cell.prepend (Module.new do
4
+ attr_writer :source_location
5
+
4
6
  def border_color= color
5
7
  color = [color, color] if Asciidoctor::PDF::ThemeLoader::CMYKColorValue === color
6
8
  super
@@ -4,6 +4,8 @@ module Asciidoctor
4
4
  module PDF
5
5
  module FormattedText
6
6
  class Transform
7
+ include TextTransformer
8
+
7
9
  LF = ?\n
8
10
  ZeroWidthSpace = ?\u200b
9
11
  CharEntityTable = { amp: '&', apos: ?', gt: '>', lt: '<', nbsp: ?\u00a0, quot: '"' }
@@ -21,8 +23,8 @@ module Asciidoctor
21
23
  'font_size' => :size,
22
24
  'text_decoration_color' => :text_decoration_color,
23
25
  'text_decoration_width' => :text_decoration_width,
26
+ 'text_transform' => :text_transform,
24
27
  }
25
- #DummyText = ?\u0000
26
28
 
27
29
  def initialize options = {}
28
30
  @merge_adjacent_text_nodes = options[:merge_adjacent_text_nodes]
@@ -96,7 +98,7 @@ module Asciidoctor
96
98
  }.compact,
97
99
  }
98
100
  @theme_settings.tap do |accum|
99
- revise_roles = [].to_set
101
+ roles_with_styles = [].to_set
100
102
  theme.each_pair do |key, val|
101
103
  next unless (key = key.to_s).start_with? 'role_'
102
104
  role, key = (key.slice 5, key.length).split '_', 2
@@ -110,10 +112,10 @@ module Asciidoctor
110
112
  # (accum[role] ||= {})[:kerning] = resolved_val
111
113
  # end
112
114
  elsif key == 'font_style' || key == 'text_decoration'
113
- revise_roles << role
115
+ roles_with_styles << role
114
116
  end
115
117
  end
116
- revise_roles.each do |role|
118
+ roles_with_styles.each do |role|
117
119
  (accum[role] ||= {})[:styles] = to_styles theme[%(role_#{role}_font_style)], theme[%(role_#{role}_text_decoration)]
118
120
  end
119
121
  end
@@ -172,6 +174,11 @@ module Asciidoctor
172
174
  previous_fragment_is_text && ((previous_fragment_text = fragments[-1][:text]).end_with? ' ')
173
175
  fragments[-1][:text] = previous_fragment_text.chop
174
176
  end
177
+ if (text_transform = fragment.delete :text_transform)
178
+ text = (text_chunks = extract_text pcdata).join
179
+ text_io = StringIO.new transform_text text, text_transform
180
+ restore_text pcdata, text_chunks.each_with_object([]) {|chunk, accum| accum << (text_io.read chunk.length) }
181
+ end
175
182
  # NOTE: decorate child fragments with inherited properties from this element
176
183
  apply pcdata, fragments, fragment
177
184
  previous_fragment_is_text = false
@@ -251,6 +258,8 @@ module Asciidoctor
251
258
  fragments
252
259
  end
253
260
 
261
+ private
262
+
254
263
  def build_fragment fragment, tag_name, attrs
255
264
  styles = (fragment[:styles] ||= ::Set.new)
256
265
  case tag_name
@@ -324,7 +333,6 @@ module Asciidoctor
324
333
  # NOTE: spaces in style value are superfluous for our purpose; split drops record after trailing ;
325
334
  attrs[:style].tr(' ', '').split(';').each do |style|
326
335
  pname, pvalue = style.split ':', 2
327
- # TODO: text-transform
328
336
  case pname
329
337
  when 'color' # color needed to support syntax highlighters
330
338
  fragment[:color] = pvalue.length == 7 ? (pvalue.slice 1, 6) : (pvalue.slice 1, 3).each_char.map {|c| c * 2 }.join if (pvalue.start_with? '#') && (HexColorRx.match? pvalue)
@@ -409,6 +417,29 @@ module Asciidoctor
409
417
  end
410
418
  end
411
419
  end
420
+
421
+ def extract_text pcdata
422
+ pcdata.reduce [] do |accum, it|
423
+ case it[:type]
424
+ when :text
425
+ accum << it[:value]
426
+ when :element
427
+ accum += (extract_text it[:pcdata]) if it.key? :pcdata
428
+ end
429
+ accum
430
+ end
431
+ end
432
+
433
+ def restore_text pcdata, text_chunks
434
+ pcdata.each do |it|
435
+ case it[:type]
436
+ when :text
437
+ it[:value] = text_chunks.shift
438
+ when :element
439
+ restore_text it[:pcdata], text_chunks if it.key? :pcdata
440
+ end
441
+ end
442
+ end
412
443
  end
413
444
  end
414
445
  end
@@ -3,7 +3,7 @@
3
3
  module Asciidoctor
4
4
  module PDF
5
5
  class IndexCatalog
6
- include ::Asciidoctor::PDF::TextTransformer
6
+ include TextTransformer
7
7
 
8
8
  LeadingAlphaRx = /^\p{Alpha}/
9
9
 
@@ -64,6 +64,29 @@ module Asciidoctor
64
64
  string.tr LowerAlphaChars, SmallCapsChars
65
65
  end
66
66
  end
67
+
68
+ # Apply the text transform to the specified text.
69
+ #
70
+ # Supported transform values are "uppercase", "lowercase", or "none" (passed
71
+ # as either a String or a Symbol). When the uppercase transform is applied to
72
+ # the text, it correctly uppercases visible text while leaving markup and
73
+ # named character entities unchanged. The none transform returns the text
74
+ # unmodified.
75
+ #
76
+ def transform_text text, transform
77
+ case transform
78
+ when :uppercase, 'uppercase'
79
+ uppercase_pcdata text
80
+ when :lowercase, 'lowercase'
81
+ lowercase_pcdata text
82
+ when :capitalize, 'capitalize'
83
+ capitalize_words_pcdata text
84
+ when :smallcaps, 'smallcaps'
85
+ smallcaps_pcdata text
86
+ else
87
+ text
88
+ end
89
+ end
67
90
  end
68
91
  end
69
92
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Asciidoctor
4
4
  module PDF
5
- VERSION = '2.1.1'
5
+ VERSION = '2.1.4'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-pdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Allen
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-06-15 00:00:00.000000000 Z
12
+ date: 2022-06-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: asciidoctor