asciidoctor-pdf 2.1.2 → 2.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2109e7ec140c759820252d4c7f0f155c2d7bf4adfcad9d34fddb8cf4bc81a260
4
- data.tar.gz: c18e3fb15231f968d907fc05693f6c4d7f9fbedfd29e368b0dc355f44d2e4254
3
+ metadata.gz: 0cacde45fb257acbe2644ae3da1673e0a9fe9cd42f4b97de92a3ae2d97400fdb
4
+ data.tar.gz: e4e01d9fa4e923e598277c5db822632a5dc3fe67e51ebbea26d744f8d30e7315
5
5
  SHA512:
6
- metadata.gz: 4e51a465c863440441cae24e429bbf84d9fb782e2c711958d5b72dfa585ba4b1b7c9c94b92d8155b2cea0d72eec276fac6e4669ea8a50c175ff8ed82ab91eb8d
7
- data.tar.gz: a62b653261f3194d51a738cc4b1cf46f4a78a6ba0c1687fbeb06bf5049ecc9d65a20edd7acc463a2f4b473d1248795ce39902b214b87b019cbc8485d394a32f3
6
+ metadata.gz: 2fadd03cc382136bf1387867d83d68396f58c4182a51616254562c1d6460e28e0555781e9c5c51d372cd6d3fee29f80b7c06d9fc0d6e055a2839cf63491bf92d
7
+ data.tar.gz: 6fa97a16ff15ac5b0dee3789d33aa2760595139299ae41eb4e0104b4346c8569ffb8f1377fd0844f2c98ec831a08156258754e2a54f25c9fb10972a681f0c592
data/CHANGELOG.adoc CHANGED
@@ -5,6 +5,46 @@
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.5 (2022-07-10) - @mojavelinux
9
+
10
+ Bug Fixes::
11
+
12
+ * fix position of background color on caption with outside margin (#2271)
13
+ * don't allow font scale to compound when entering nested table (#2276)
14
+
15
+ === Details
16
+
17
+ {url-repo}/releases/tag/v2.1.5[git tag] | {url-repo}/compare/v2.1.4\...v2.1.5[full diff]
18
+
19
+ == 2.1.4 (2022-06-26) - @mojavelinux
20
+
21
+ Improvements::
22
+
23
+ * include source location in warning message for truncated table cell if sourcemap is enabled (#2261)
24
+
25
+ Bug Fixes::
26
+
27
+ * allow alt text for block image, video, and audio to wrap to next line on same page (#2258)
28
+ * apply text-tranform from custom role on phrase after attributes have been resolved (#2263)
29
+ * make URL check more strict so image target containing a colon is not mistaken as a URL
30
+
31
+ === Details
32
+
33
+ {url-repo}/releases/tag/v2.1.4[git tag] | {url-repo}/compare/v2.1.3\...v2.1.4[full diff]
34
+
35
+ == 2.1.3 (2022-06-23) - @mojavelinux
36
+
37
+ Bug Fixes::
38
+
39
+ * interpret `start-at` theme keys with value `1` correctly (as `1` instead of `2`) (#2255)
40
+ * restore column layout after importing page(s) from PDF (#2253)
41
+ * fix crash when border color is transparent (`thematic-break-border-color`, `admonition-column-rule`, `quote-border-color`, `verse-border-color`)
42
+ * ensure page margin is restored after imported page
43
+
44
+ === Details
45
+
46
+ {url-repo}/releases/tag/v2.1.3[git tag] | {url-repo}/compare/v2.1.2\...v2.1.3[full diff]
47
+
8
48
  == 2.1.2 (2022-06-17) - @mojavelinux
9
49
 
10
50
  Bug Fixes::
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.2, 2022-06-17
3
+ v2.1.5, 2022-07-10
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
data/bin/asciidoctor-pdf CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- if File.file?(asciidoctor_pdf = (File.expand_path '../../lib/asciidoctor/pdf.rb', __FILE__))
4
+ if File.file? (asciidoctor_pdf = File.join (File.dirname __dir__), 'lib/asciidoctor/pdf.rb')
5
5
  require asciidoctor_pdf
6
6
  else
7
7
  require 'asciidoctor/pdf'
@@ -10,14 +10,14 @@ require 'asciidoctor/cli'
10
10
 
11
11
  options = Asciidoctor::Cli::Options.new backend: 'pdf', header_footer: true
12
12
 
13
- # FIXME provide an API in Asciidoctor for sub-components to print version information
13
+ # FIXME: provide an API in Asciidoctor for sub-components to print version information
14
14
  unless ARGV != ['-v'] && (ARGV & ['-V', '--version']).empty?
15
15
  $stdout.write %(Asciidoctor PDF #{Asciidoctor::PDF::VERSION} using )
16
16
  options.print_version
17
17
  exit 0
18
18
  end
19
19
 
20
- # FIXME This is a really bizarre API. Please make me simpler.
20
+ # FIXME: This is a really bizarre API. Please make me simpler.
21
21
  case (result = options.parse! ARGV)
22
22
  when Integer
23
23
  exit result
@@ -27,8 +27,6 @@ module Asciidoctor
27
27
 
28
28
  attr_accessor :font_scale
29
29
 
30
- attr_reader :root_font_size
31
-
32
30
  attr_reader :index
33
31
 
34
32
  attr_reader :theme
@@ -114,6 +112,7 @@ module Asciidoctor
114
112
  UriBreakCharsRx = %r((?:/|\?|&amp;|#)(?!$))
115
113
  UriBreakCharRepl = %(\\&#{ZeroWidthSpace})
116
114
  UriSchemeBoundaryRx = %r((?<=://))
115
+ UrlSniffRx = %r(^\p{Alpha}[\p{Alnum}+.-]*://)
117
116
  LineScanRx = /\n|.+/
118
117
  BlankLineRx = /\n{2,}/
119
118
  CjkLineBreakRx = /(?=[\u3000\u30a0-\u30ff\u3040-\u309f\p{Han}\uff00-\uffef])/
@@ -213,7 +212,7 @@ module Asciidoctor
213
212
  first_page_offset = has_title_page ? zero_page_offset.next : zero_page_offset
214
213
  body_offset = (body_start_page_number = page_number) - 1
215
214
  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
215
+ running_content_body_offset = body_offset + [running_content_start_at.pred, 0].max
217
216
  running_content_start_at = 'body'
218
217
  else
219
218
  running_content_body_offset = body_offset
@@ -227,7 +226,7 @@ module Asciidoctor
227
226
  end
228
227
  end
229
228
  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
229
+ page_numbering_body_offset = body_offset + [page_numbering_start_at.pred, 0].max
231
230
  page_numbering_start_at = 'body'
232
231
  else
233
232
  page_numbering_body_offset = body_offset
@@ -263,12 +262,12 @@ module Asciidoctor
263
262
  else
264
263
  body_offset = body_start_page_number - 1
265
264
  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
265
+ running_content_body_offset = body_offset + [running_content_start_at.pred, 0].max
267
266
  else
268
267
  running_content_body_offset = body_offset
269
268
  end
270
269
  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
270
+ page_numbering_body_offset = body_offset + [page_numbering_start_at.pred, 0].max
272
271
  elsif page_numbering_start_at == 'cover' && has_front_cover
273
272
  page_numbering_body_offset = 0
274
273
  else
@@ -371,8 +370,6 @@ module Asciidoctor
371
370
  if (page_margin_inner = theme.page_margin_inner)
372
371
  page_margin_recto[3] = page_margin_verso[1] = page_margin_inner
373
372
  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
373
  else
377
374
  @ppbook = nil
378
375
  end
@@ -581,6 +578,7 @@ module Asciidoctor
581
578
  end
582
579
 
583
580
  def prepare_theme theme
581
+ theme.base_border_color = nil if theme.base_border_color == 'transparent'
584
582
  theme.base_font_color ||= '000000'
585
583
  theme.base_font_size ||= 12
586
584
  theme.base_font_style = theme.base_font_style&.to_sym || :normal
@@ -943,7 +941,7 @@ module Asciidoctor
943
941
  if extent
944
942
  label_height = extent.single_page_height || cursor
945
943
  if (rule_width = @theme.admonition_column_rule_width || 0) > 0 &&
946
- (rule_color = @theme.admonition_column_rule_color || @theme.base_border_color)
944
+ (rule_color = resolve_theme_color :admonition_column_rule_color, @theme.base_border_color, nil)
947
945
  rule_style = @theme.admonition_column_rule_style&.to_sym || :solid
948
946
  float do
949
947
  extent.each_page do |first_page, last_page|
@@ -1273,7 +1271,7 @@ module Asciidoctor
1273
1271
  category = node.context == :quote ? :quote : :verse
1274
1272
  # NOTE: b_width and b_left_width are mutually exclusive
1275
1273
  if (b_left_width = @theme[%(#{category}_border_left_width)]) && b_left_width > 0
1276
- b_color = @theme[%(#{category}_border_color)] || @theme.base_border_color
1274
+ b_left_width = nil unless (b_color = resolve_theme_color %(#{category}_border_color), @theme.base_border_color, nil)
1277
1275
  else
1278
1276
  b_left_width = nil
1279
1277
  b_width = nil if (b_width = @theme[%(#{category}_border_width)]) == 0
@@ -1887,7 +1885,7 @@ module Asciidoctor
1887
1885
  add_dest_for_block node if node.id
1888
1886
  audio_path = node.media_uri node.attr 'target'
1889
1887
  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
1888
+ ink_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{audio_path}">#{audio_path}</a> <em>(audio)</em>), normalize: false, margin: 0
1891
1889
  ink_caption node, labeled: false, end: :bottom if node.title?
1892
1890
  theme_margin :block, :bottom, (next_enclosed_block node)
1893
1891
  end
@@ -1915,7 +1913,7 @@ module Asciidoctor
1915
1913
  if poster.nil_or_empty?
1916
1914
  add_dest_for_block node if node.id
1917
1915
  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
1916
+ ink_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{video_path}">#{video_path}</a> <em>(#{type})</em>), normalize: false, margin: 0
1919
1917
  ink_caption node, labeled: false, end: :bottom if node.title?
1920
1918
  theme_margin :block, :bottom, (next_enclosed_block node)
1921
1919
  else
@@ -1996,6 +1994,7 @@ module Asciidoctor
1996
1994
  num_cols = node.columns.size
1997
1995
  table_header_size = false
1998
1996
  theme = @theme
1997
+ prev_font_scale, @font_scale = @font_scale, 1 if node.document.nested?
1999
1998
 
2000
1999
  tbl_bg_color = resolve_theme_color :table_background_color
2001
2000
  # QUESTION: should we fallback to page background color? (which is never transparent)
@@ -2054,7 +2053,8 @@ module Asciidoctor
2054
2053
  content: cell_text,
2055
2054
  colspan: cell.colspan || 1,
2056
2055
  align: (cell.attr 'halign').to_sym,
2057
- valign: (val = cell.attr 'valign') == 'middle' ? :center : val.to_sym
2056
+ valign: (val = cell.attr 'valign') == 'middle' ? :center : val.to_sym,
2057
+ source_location: cell.source_location
2058
2058
  end)
2059
2059
  end
2060
2060
  end unless head_rows.empty?
@@ -2073,7 +2073,8 @@ module Asciidoctor
2073
2073
  colspan: cell.colspan || 1,
2074
2074
  rowspan: cell.rowspan || 1,
2075
2075
  align: (cell.attr 'halign').to_sym,
2076
- valign: (val = cell.attr 'valign') == 'middle' ? :center : val.to_sym
2076
+ valign: (val = cell.attr 'valign') == 'middle' ? :center : val.to_sym,
2077
+ source_location: cell.source_location
2077
2078
  cell_line_metrics = body_cell_line_metrics
2078
2079
  case cell.style
2079
2080
  when :emphasis
@@ -2133,8 +2134,8 @@ module Asciidoctor
2133
2134
  end
2134
2135
  # NOTE: line metrics get applied when AsciiDoc content is converted
2135
2136
  cell_line_metrics = nil
2136
- 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 }
2137
+ asciidoc_cell = ::Prawn::Table::Cell::AsciiDoc.new self, (cell_data.merge content: cell.inner_document, padding: body_cell_padding, root_font_size: @root_font_size)
2138
+ cell_data = { content: asciidoc_cell, source_location: cell.source_location }
2138
2139
  end
2139
2140
  if cell_line_metrics
2140
2141
  cell_padding = body_cell_padding.dup
@@ -2337,13 +2338,17 @@ module Asciidoctor
2337
2338
  theme_margin :block, :bottom, (next_enclosed_block node)
2338
2339
  rescue ::Prawn::Errors::CannotFit
2339
2340
  log :error, (message_with_context 'cannot fit contents of table cell into specified column width', source_location: node.source_location)
2341
+ ensure
2342
+ @font_scale = prev_font_scale if prev_font_scale
2340
2343
  end
2341
2344
 
2342
2345
  def convert_thematic_break node
2343
2346
  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)
2347
+ if (b_color = resolve_theme_color :thematic_break_border_color)
2348
+ stroke_horizontal_rule b_color,
2349
+ line_width: @theme.thematic_break_border_width,
2350
+ line_style: (@theme.thematic_break_border_style&.to_sym || :solid)
2351
+ end
2347
2352
  end
2348
2353
  conceal_page_top { theme_margin :block, :bottom, (next_enclosed_block node) }
2349
2354
  end
@@ -2684,13 +2689,7 @@ module Asciidoctor
2684
2689
  end
2685
2690
 
2686
2691
  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
2692
+ inner_text = inner_text.gsub DoubleSpaceRx, ' ' + ZeroWidthSpace if (node.has_role? 'pre-wrap') && (inner_text.include? DoubleSpace)
2694
2693
  quoted_text = is_tag ? %(#{open.chop} class="#{roles}">#{inner_text}#{close}) : %(<span class="#{roles}">#{open}#{inner_text}#{close}</span>)
2695
2694
  else
2696
2695
  quoted_text = %(#{open}#{inner_text}#{close})
@@ -3105,7 +3104,8 @@ module Asciidoctor
3105
3104
  end
3106
3105
  unless scratch? || !(bg_color = @theme[%(#{category_caption}_background_color)] || @theme.caption_background_color)
3107
3106
  caption_height = height_of_typeset_text string
3108
- fill_at = [bounds.left, cursor + (margin[:top] || 0)]
3107
+ fill_at = [bounds.left, cursor]
3108
+ fill_at[1] -= (margin[:top] || 0) unless at_page_top?
3109
3109
  float { bounding_box(fill_at, width: container_width, height: caption_height) { fill_bounds bg_color } }
3110
3110
  end
3111
3111
  indent(*indent_by) do
@@ -3240,7 +3240,8 @@ module Asciidoctor
3240
3240
  end
3241
3241
  end
3242
3242
 
3243
- # NOTE: inline_format is true by default
3243
+ # NOTE: inline_format option is true by default
3244
+ # NOTE: single_line option is not compatible with this method
3244
3245
  def ink_prose string, opts = {}
3245
3246
  top_margin = (margin = (opts.delete :margin)) || (opts.delete :margin_top) || 0
3246
3247
  bot_margin = margin || (opts.delete :margin_bottom) || @theme.prose_margin_bottom
@@ -4254,10 +4255,10 @@ module Asciidoctor
4254
4255
  # NOTE: this will catch a classloader resource path on JRuby (e.g., uri:classloader:/path/to/image)
4255
4256
  elsif ::File.absolute_path? image_path
4256
4257
  ::File.absolute_path image_path
4257
- elsif !(is_uri = node.is_uri? image_path) && imagesdir && (::File.absolute_path? imagesdir)
4258
+ elsif !(is_url = url? image_path) && imagesdir && (::File.absolute_path? imagesdir)
4258
4259
  ::File.absolute_path image_path, imagesdir
4259
4260
  # handle case when image is a URI
4260
- elsif is_uri || (imagesdir && (node.is_uri? imagesdir) && (image_path = node.normalize_web_path image_path, imagesdir, false))
4261
+ elsif is_url || (imagesdir && (url? imagesdir) && (image_path = node.normalize_web_path image_path, imagesdir, false))
4261
4262
  if !allow_uri_read
4262
4263
  log :warn, %(cannot embed remote image: #{image_path} (allow-uri-read attribute not enabled))
4263
4264
  return
@@ -4495,6 +4496,7 @@ module Asciidoctor
4495
4496
  end
4496
4497
 
4497
4498
  # TODO: document me, esp the first line formatting functionality
4499
+ # NOTE: single_line option should only be used if height option is specified
4498
4500
  def typeset_text string, line_metrics, opts = {}
4499
4501
  opts = { leading: line_metrics.leading, final_gap: line_metrics.final_gap }.merge opts
4500
4502
  string = string.gsub CjkLineBreakRx, ZeroWidthSpace if @cjk_line_breaks
@@ -4817,18 +4819,17 @@ module Asciidoctor
4817
4819
  end
4818
4820
 
4819
4821
  # NOTE: init_page is called within a float context; this will suppress prawn-svg messing with the cursor
4820
- # NOTE: init_page is not called for imported pages, front and back cover pages, and other image pages
4822
+ # NOTE: init_page is not called for imported pages, cover pages, image pages, and pages in the scratch document
4821
4823
  def init_page *_args
4822
4824
  next_page_side = page_side nil, @folio_placement[:inverted]
4823
4825
  if @media == 'prepress' && (next_page_margin = @page_margin_by_side[page_number == 1 ? :cover : next_page_side]) != page_margin
4824
4826
  set_page_margin next_page_margin
4825
4827
  end
4826
4828
  unless @page_bg_color == 'FFFFFF'
4827
- tare = true
4828
4829
  fill_absolute_bounds @page_bg_color
4830
+ tare = true
4829
4831
  end
4830
4832
  if (bg_image_path, bg_image_opts = @page_bg_image[next_page_side])
4831
- tare = true
4832
4833
  begin
4833
4834
  if bg_image_opts[:format] == 'pdf'
4834
4835
  # NOTE: pages that use PDF for the background do not support a background color or running content
@@ -4837,6 +4838,7 @@ module Asciidoctor
4837
4838
  else
4838
4839
  canvas { image bg_image_path, ({ position: :center, vposition: :center }.merge bg_image_opts) }
4839
4840
  end
4841
+ tare = true
4840
4842
  rescue
4841
4843
  facing_page_side = (PageSides - [next_page_side])[0]
4842
4844
  @page_bg_image[facing_page_side] = nil if @page_bg_image[facing_page_side] == @page_bg_image[next_page_side]
@@ -4949,7 +4951,7 @@ module Asciidoctor
4949
4951
  alt_text_vars[:'/link'] = ''
4950
4952
  end
4951
4953
  theme_font :image_alt do
4952
- ink_prose alt_text_template % alt_text_vars, align: opts[:align], margin: 0, normalize: false, single_line: true
4954
+ ink_prose alt_text_template % alt_text_vars, align: opts[:align], margin: 0, normalize: false
4953
4955
  end
4954
4956
  ink_caption node, category: :image, end: :bottom if node.title?
4955
4957
  theme_margin :block, :bottom, (next_enclosed_block node) unless opts[:pinned]
@@ -5031,10 +5033,8 @@ module Asciidoctor
5031
5033
  # QUESTION: should we pass a category as an argument?
5032
5034
  # QUESTION: should we make this a method on the theme ostruct? (e.g., @theme.resolve_color key, fallback)
5033
5035
  def resolve_theme_color key, fallback_color = nil, transparent_color = fallback_color
5034
- if (color = @theme[key])
5036
+ if (color = @theme[key] || fallback_color)
5035
5037
  color == 'transparent' ? transparent_color : color
5036
- else
5037
- fallback_color
5038
5038
  end
5039
5039
  end
5040
5040
 
@@ -5046,6 +5046,10 @@ module Asciidoctor
5046
5046
  false
5047
5047
  end
5048
5048
 
5049
+ def url? str
5050
+ (str.include? ':/') && (UrlSniffRx.match? str)
5051
+ end
5052
+
5049
5053
  # Calculate the width that is needed to print all the
5050
5054
  # fragments without wrapping any lines.
5051
5055
  #
@@ -5114,6 +5118,10 @@ module Asciidoctor
5114
5118
  end
5115
5119
 
5116
5120
  def init_scratch originator
5121
+ if @media == 'prepress' && page_margin != (page_margin_recto = @page_margin_by_side[:recto])
5122
+ # NOTE: prepare scratch document to use page margin from recto side (which has same width as verso side)
5123
+ set_page_margin page_margin_recto
5124
+ end
5117
5125
  @scratch_prototype = originator.instance_variable_get :@scratch_prototype
5118
5126
  @tmp_files = originator.instance_variable_get :@tmp_files
5119
5127
  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
@@ -7,6 +7,7 @@ module Prawn
7
7
  include ::Asciidoctor::Logging
8
8
 
9
9
  attr_accessor :align
10
+ attr_accessor :root_font_size
10
11
  attr_accessor :valign
11
12
 
12
13
  def initialize pdf, opts = {}
@@ -91,7 +92,9 @@ module Prawn
91
92
  # TODO: apply horizontal alignment; currently it is necessary to specify alignment on content blocks
92
93
  apply_font_properties { pdf.traverse content }
93
94
  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?
95
+ unless extra_pages == 1 && pdf.page.empty?
96
+ 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
97
+ end
95
98
  extra_pages.times { pdf.delete_current_page }
96
99
  end
97
100
  nil
@@ -107,7 +110,7 @@ module Prawn
107
110
  prev_font_color, pdf.font_color = pdf.font_color, font_color if font_color
108
111
  font_family ||= font_info[:family]
109
112
  if font_size
110
- prev_font_scale, pdf.font_scale = pdf.font_scale, (font_size.to_f / @pdf.root_font_size)
113
+ prev_font_scale, pdf.font_scale = pdf.font_scale, (font_size.to_f / @root_font_size)
111
114
  else
112
115
  font_size = font_info[:size]
113
116
  end
@@ -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]
@@ -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.2'
5
+ VERSION = '2.1.5'
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.2
4
+ version: 2.1.5
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-17 00:00:00.000000000 Z
12
+ date: 2022-07-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: asciidoctor