asciidoctor-pdf 2.1.6 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 626c05cc96837efcf9f6fd0b96f0f31e8791188f27db387609a6a2d6a1345e94
4
- data.tar.gz: 311afcb050d8063c6878166b8ce89e2e7bd1986af9b212ee9ee9202d87ba3a53
3
+ metadata.gz: 5dbb3a6c2c5b664510e19714de969553f3943994b4be273238c646e41274885f
4
+ data.tar.gz: f6495e965c651113bbc61383d82a18db4fb78a7df64644801bd10fba1c6ed078
5
5
  SHA512:
6
- metadata.gz: a82a51068e74bf9ea3bdb89c11a8075a27e58c49fdc84bfdce9066030e7f6688a99a6956bbbd8a1739aa5d2de3eaf5943a9e6ec234ecfce0bc5bc938d0ffc91a
7
- data.tar.gz: bad6ea4168ef017bec92534f657ec54208851cb224ae2c4e2c37fe329946192bab9d0e5519c8d2d19cf3c1184185664402523fe7175b4fb496465a3ebed41b01
6
+ metadata.gz: 0b93162e6b69d1c32cf3365c08f78457f80cb1588a98c847b0ddfa6946074ba1c7c163009434243d9c78d87e6982c84b2c74eb06fbb72003f003854fbadea926
7
+ data.tar.gz: 2cc9d0d4d64ac4ae889e54cf272339019ec91a812ba38f22f28b81abb8daa6af086941e8b50bb95a70f1f1028dd06879952fd51da4219fc46db523f4757ca774
data/CHANGELOG.adoc CHANGED
@@ -5,15 +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.6 (2022-07-19) - @mojavelinux
8
+ == 2.2.0 (2022-07-22) - @mojavelinux
9
+
10
+ Enhancements::
11
+
12
+ * allow page background image to be specified per layout using `+{page-layout}+` attribute reference in path (#1739)
13
+ * allow page margin for rotated page to be configured independently using `page-margin-rotated` theme key or `pdf-page-margin-rotated` document attribute (#1719)
14
+ * allow orphan detection to be enabled for all section titles and discrete headings by setting `heading-min-height-after` to `auto` in theme (#2268)
15
+ * set `docimagesdir` attribute when attribute substitutions are applied to value from theme (#2278)
16
+ * start page numbering and running content on empty verso page before first chapter of prepress book if `start-at` value is 0 (#2252)
17
+ * don't force page break after TOC with automatic placement in article if `title-page` attribute is set and value of `toc-break-after` theme key is `auto` (#1768)
18
+ * add `--theme` option to CLI as shorthand for `-a pdf-theme` (#2250)
19
+ * add `--sourcemap` option to CLI to enable `:sourcemap` option on processor (#2265)
20
+ * broaden support for relative font sizes in theme to more than just inline elements; document support for relative font sizes
21
+ * allow theme to control font properties of marker for ordered list using `olist-marker` category (#2279)
22
+ * allow theme to control font style of marker (per marker or all markers) for unordered list
23
+
24
+ Improvements::
25
+
26
+ * add internal `Document#attr_unspecified?` method to simplify check for an attribute which has not been set or unset
9
27
 
10
28
  Bug Fixes::
11
29
 
12
- * resolve font size for monospaced cell when font size value on `codespan` key in theme is relative (#2281)
30
+ * always set `imagesdir` attribute to value of `themesdir` when resolving images from theme
31
+ * allow `top` keys in `title-page` theme category to accept a fixed value (e.g., `1in`) (#2269)
32
+ * prevent orphan detection for heading (section title or discrete heading) from modifying document state (#2288)
33
+
34
+ Compliance::
35
+
36
+ * configure table borders in way that is compatible with prawn-table > 0.2.2
37
+ * don't coerce font size < 1 to relative font size; relative font size should be specified in units
13
38
 
14
39
  === Details
15
40
 
16
- {url-repo}/releases/tag/v2.1.6[git tag] | {url-repo}/compare/v2.1.5\...v2.1.6[full diff]
41
+ {url-repo}/releases/tag/v2.2.0[git tag] | {url-repo}/compare/v2.1.6\...v2.2.0[full diff]
42
+
43
+ == 2.1.6 (2022-07-19) - @mojavelinux
44
+
45
+ Bug Fixes::
46
+
47
+ * resolve font size for monospaced cell when font size value on `codespan` key in theme is relative (#2281)
17
48
 
18
49
  == 2.1.5 (2022-07-10) - @mojavelinux
19
50
 
@@ -22,10 +53,6 @@ Bug Fixes::
22
53
  * fix position of background color on caption with outside margin (#2271)
23
54
  * don't allow font scale to compound when entering nested table (#2276)
24
55
 
25
- === Details
26
-
27
- {url-repo}/releases/tag/v2.1.5[git tag] | {url-repo}/compare/v2.1.4\...v2.1.5[full diff]
28
-
29
56
  == 2.1.4 (2022-06-26) - @mojavelinux
30
57
 
31
58
  Improvements::
@@ -35,13 +62,9 @@ Improvements::
35
62
  Bug Fixes::
36
63
 
37
64
  * allow alt text for block image, video, and audio to wrap to next line on same page (#2258)
38
- * apply `text-transform` from custom role on phrase after attributes have been resolved (#2263)
65
+ * apply text-tranform from custom role on phrase after attributes have been resolved (#2263)
39
66
  * make URL check more strict so image target containing a colon is not mistaken as a URL
40
67
 
41
- === Details
42
-
43
- {url-repo}/releases/tag/v2.1.4[git tag] | {url-repo}/compare/v2.1.3\...v2.1.4[full diff]
44
-
45
68
  == 2.1.3 (2022-06-23) - @mojavelinux
46
69
 
47
70
  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.6, 2022-07-19
3
+ v2.2.0, 2022-07-22
4
4
  // Settings:
5
5
  :experimental:
6
6
  :idprefix:
data/bin/asciidoctor-pdf CHANGED
@@ -8,17 +8,36 @@ else
8
8
  end
9
9
  require 'asciidoctor/cli'
10
10
 
11
- options = Asciidoctor::Cli::Options.new backend: 'pdf', header_footer: true
11
+ # FIXME: provide an API in Asciidoctor for sub-projects to prepend version information
12
+ options = (Asciidoctor::Cli::Options.new backend: 'pdf', header_footer: true).extend (Module.new do
13
+ def print_version os = $stdout
14
+ os.write %(Asciidoctor PDF #{Asciidoctor::PDF::VERSION} using )
15
+ super
16
+ end
17
+ end)
12
18
 
13
- # FIXME: provide an API in Asciidoctor for sub-components to print version information
14
- unless ARGV != ['-v'] && (ARGV & ['-V', '--version']).empty?
15
- $stdout.write %(Asciidoctor PDF #{Asciidoctor::PDF::VERSION} using )
16
- options.print_version
17
- exit 0
19
+ args = ARGV.dup
20
+
21
+ if (theme_idx = args.index {|it| it == '--theme' || (it.start_with? '--theme=') })
22
+ if (theme_arg = args[theme_idx]).length > 7
23
+ args[theme_idx..theme_idx] = ['-a', %(pdf#{theme_arg.slice 1, theme_arg.length})]
24
+ elsif (val = args[theme_idx + 1]) && !(val.start_with? '-')
25
+ args[theme_idx] = '-a'
26
+ args[theme_idx + 1] = %(pdf-theme=#{val})
27
+ end
28
+ end
29
+
30
+ if (Gem::Version.new Asciidoctor::VERSION) < (Gem::Version.new '2.1.0') && (args.include? '--sourcemap')
31
+ args.delete '--sourcemap'
32
+ Asciidoctor::Extensions.register do
33
+ preprocessor do
34
+ process {|doc| (doc.sourcemap = true) && nil }
35
+ end
36
+ end
18
37
  end
19
38
 
20
39
  # FIXME: This is a really bizarre API. Please make me simpler.
21
- case (result = options.parse! ARGV)
40
+ case (result = options.parse! args)
22
41
  when Integer
23
42
  exit result
24
43
  else
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- optimizer = File.absolute_path '../lib/asciidoctor/pdf/optimizer.rb', __dir__
5
- if File.exist? optimizer
4
+ if File.file? (optimizer = File.join (File.dirname __dir__), 'lib/asciidoctor/pdf/optimizer.rb')
6
5
  require optimizer
7
6
  else
8
7
  require 'asciidoctor/pdf/optimizer'
@@ -160,11 +160,11 @@ module Asciidoctor
160
160
  doc.promote_preface_block
161
161
  init_pdf doc
162
162
  # set default value for outline, outline-title, and pagenums attributes if not otherwise set
163
- doc.attributes['outline'] = '' unless (doc.attribute_locked? 'outline') || ((doc.instance_variable_get :@attributes_modified).include? 'outline')
164
- doc.attributes['outline-title'] = '' unless (doc.attribute_locked? 'outline-title') || ((doc.instance_variable_get :@attributes_modified).include? 'outline-title')
165
- doc.attributes['pagenums'] = '' unless (doc.attribute_locked? 'pagenums') || ((doc.instance_variable_get :@attributes_modified).include? 'pagenums')
163
+ doc.attributes['outline'] = '' if doc.attr_unspecified? 'outline'
164
+ doc.attributes['outline-title'] = '' if doc.attr_unspecified? 'outline-title'
165
+ doc.attributes['pagenums'] = '' if doc.attr_unspecified? 'pagenums'
166
166
 
167
- on_page_create(&(method :init_page))
167
+ on_page_create(&(method :init_page).curry[doc])
168
168
 
169
169
  marked_page_number = page_number
170
170
  # NOTE: a new page will already be started (page_number = 2) if the front cover image is a PDF
@@ -179,7 +179,7 @@ module Asciidoctor
179
179
  end
180
180
  start_new_page
181
181
  else
182
- @page_margin_by_side[:cover] = @page_margin_by_side[:recto] if @media == 'prepress' && page_number == 0
182
+ @page_margin[:cover] = @page_margin[page.layout][:recto] if @media == 'prepress' && page_number == 0
183
183
  start_new_page unless page&.empty? # rubocop:disable Lint/SafeNavigationWithEmpty
184
184
  # NOTE: the base font must be set before any content is written to the main or scratch document
185
185
  # this method is called inside ink_title_page if the title page is active
@@ -200,19 +200,24 @@ module Asciidoctor
200
200
  if (insert_toc = (doc.attr? 'toc') && !((toc_placement = doc.attr 'toc-placement') == 'macro' || toc_placement == 'preamble') && !(get_entries_for_toc doc).empty?)
201
201
  start_new_page if @ppbook && verso_page?
202
202
  add_dest_for_block doc, id: 'toc', y: (at_page_top? ? page_height : nil)
203
- @toc_extent = allocate_toc doc, toc_num_levels, cursor, title_page_on
203
+ @toc_extent = allocate_toc doc, toc_num_levels, cursor, (title_page_on && theme.toc_break_after != 'auto')
204
204
  else
205
205
  @toc_extent = nil
206
206
  end
207
207
 
208
- start_new_page if @ppbook && verso_page? && !(((next_block = doc.first_child)&.context == :preamble ? next_block.first_child : next_block)&.option? 'nonfacing')
208
+ if @ppbook && verso_page? && !(((next_block = doc.first_child)&.context == :preamble ? next_block.first_child : next_block)&.option? 'nonfacing')
209
+ min_start_at = 0
210
+ start_new_page
211
+ else
212
+ min_start_at = 1
213
+ end
209
214
 
210
215
  if title_page_on
211
216
  zero_page_offset = has_front_cover ? 1 : 0
212
217
  first_page_offset = has_title_page ? zero_page_offset.next : zero_page_offset
213
218
  body_offset = (body_start_page_number = page_number) - 1
214
219
  if ::Integer === (running_content_start_at = @theme.running_content_start_at)
215
- running_content_body_offset = body_offset + [running_content_start_at.pred, 0].max
220
+ running_content_body_offset = body_offset + [running_content_start_at.pred, min_start_at.pred].max
216
221
  running_content_start_at = 'body'
217
222
  else
218
223
  running_content_body_offset = body_offset
@@ -226,7 +231,7 @@ module Asciidoctor
226
231
  end
227
232
  end
228
233
  if ::Integer === (page_numbering_start_at = @theme.page_numbering_start_at)
229
- page_numbering_body_offset = body_offset + [page_numbering_start_at.pred, 0].max
234
+ page_numbering_body_offset = body_offset + [page_numbering_start_at.pred, min_start_at.pred].max
230
235
  page_numbering_start_at = 'body'
231
236
  else
232
237
  page_numbering_body_offset = body_offset
@@ -351,7 +356,6 @@ module Asciidoctor
351
356
  @cache_uri = doc.attr? 'cache-uri'
352
357
  @jail_dir = doc.safe < ::Asciidoctor::SafeMode::SAFE ? nil : doc.base_dir
353
358
  @media ||= doc.attr 'media', 'screen'
354
- @page_margin_by_side = { recto: (page_margin_recto = page_margin), verso: (page_margin_verso = page_margin), cover: page_margin }
355
359
  case doc.attr 'pdf-folio-placement', (@media == 'prepress' ? 'physical' : 'virtual')
356
360
  when 'physical'
357
361
  @folio_placement = { basis: :physical }
@@ -362,6 +366,13 @@ module Asciidoctor
362
366
  else
363
367
  @folio_placement = { basis: :virtual }
364
368
  end
369
+ @page_margin = { cover: page_margin }
370
+ @page_margin[:portrait] = @page_margin[:landscape] = { recto: (page_margin_recto = page_margin), verso: (page_margin_verso = page_margin) }
371
+ if (rotated_page_margin = resolve_page_margin (doc.attr 'pdf-page-margin-rotated') || theme.page_margin_rotated)
372
+ rotated_page_margin = expand_margin_value rotated_page_margin
373
+ @edge_shorthand_cache = nil
374
+ @page_margin[PageLayouts[(PageLayouts.index page.layout) - 1]] = { recto: rotated_page_margin, verso: rotated_page_margin.dup }
375
+ end
365
376
  if @media == 'prepress'
366
377
  @ppbook = doc.doctype == 'book'
367
378
  if (page_margin_outer = theme.page_margin_outer)
@@ -373,17 +384,7 @@ module Asciidoctor
373
384
  else
374
385
  @ppbook = nil
375
386
  end
376
- if (bg_image = resolve_background_image doc, theme, 'page-background-image')&.first
377
- @page_bg_image = { verso: bg_image, recto: bg_image }
378
- else
379
- @page_bg_image = { verso: nil, recto: nil }
380
- end
381
- if (bg_image = resolve_background_image doc, theme, 'page-background-image-verso')
382
- @page_bg_image[:verso] = bg_image[0] && bg_image
383
- end
384
- if (bg_image = resolve_background_image doc, theme, 'page-background-image-recto')
385
- @page_bg_image[:recto] = bg_image[0] && bg_image
386
- end
387
+ @page_bg_image = {}
387
388
  @page_bg_color = resolve_theme_color :page_background_color, 'FFFFFF'
388
389
  # QUESTION: should ThemeLoader handle registering fonts instead?
389
390
  register_fonts theme.font_catalog, ((doc.attr 'pdf-fontsdir')&.sub '{docdir}', (doc.attr 'docdir')) || 'GEM_FONTS_DIR'
@@ -396,8 +397,7 @@ module Asciidoctor
396
397
  @base_text_align = (text_align = doc.attr 'text-align') && (TextAlignmentNames.include? text_align) ? text_align : theme.base_text_align
397
398
  @base_line_height = theme.base_line_height
398
399
  @cjk_line_breaks = doc.attr? 'scripts', 'cjk'
399
- if (hyphen_lang = (doc.attr 'hyphens') ||
400
- (((doc.attribute_locked? 'hyphens') || ((doc.instance_variable_get :@attributes_modified).include? 'hyphens')) ? nil : @theme.base_hyphens)) &&
400
+ if (hyphen_lang = (doc.attr 'hyphens') || ((doc.attr_unspecified? 'hyphens') ? @theme.base_hyphens : nil)) &&
401
401
  ((defined? ::Text::Hyphen::VERSION) || !(Helpers.require_library 'text/hyphen', 'text-hyphen', :warn).nil?)
402
402
  hyphen_lang = doc.attr 'lang' if !(::String === hyphen_lang) || hyphen_lang.empty?
403
403
  hyphen_lang = 'en_us' if hyphen_lang.nil_or_empty? || hyphen_lang == 'en'
@@ -435,34 +435,7 @@ module Asciidoctor
435
435
  end
436
436
 
437
437
  def build_pdf_options doc, theme
438
- case (page_margin = (doc.attr 'pdf-page-margin') || theme.page_margin)
439
- when ::Array
440
- if page_margin.empty?
441
- page_margin = nil
442
- else
443
- page_margin = page_margin.slice 0, 4 if page_margin.length > 4
444
- page_margin = page_margin.map {|v| ::Numeric === v ? v : (str_to_pt v.to_s) }
445
- end
446
- when ::Numeric
447
- page_margin = [page_margin]
448
- when ::String
449
- if page_margin.empty?
450
- page_margin = nil
451
- elsif (page_margin.start_with? '[') && (page_margin.end_with? ']')
452
- if (page_margin = (page_margin.slice 1, page_margin.length - 2).rstrip).empty?
453
- page_margin = nil
454
- else
455
- if (page_margin = page_margin.split ',', -1).length > 4
456
- page_margin = page_margin.slice 0, 4
457
- end
458
- page_margin = page_margin.map {|v| str_to_pt v.rstrip }
459
- end
460
- else
461
- page_margin = [(str_to_pt page_margin)]
462
- end
463
- else
464
- page_margin = nil
465
- end
438
+ page_margin = resolve_page_margin (doc.attr 'pdf-page-margin') || theme.page_margin
466
439
 
467
440
  if (doc.attr? 'pdf-page-size') && PageSizeRx =~ (doc.attr 'pdf-page-size')
468
441
  # e.g, [8.5in, 11in]
@@ -915,7 +888,7 @@ module Asciidoctor
915
888
  label_width = label_min_width || (icon_size * 1.5)
916
889
  elsif (icon_path = has_icon || !(icon_path = (@theme[%(admonition_icon_#{type})] || {})[:image]) ?
917
890
  (get_icon_image_path node, type) :
918
- (ThemeLoader.resolve_theme_asset (apply_subs_discretely doc, icon_path, subs: [:attributes]), @themesdir)) &&
891
+ (ThemeLoader.resolve_theme_asset (apply_subs_discretely doc, icon_path, subs: [:attributes], imagesdir: @themesdir), @themesdir)) &&
919
892
  (::File.readable? icon_path)
920
893
  icons = true
921
894
  # TODO: introduce @theme.admonition_image_width? or use size key from admonition_icon_<name>?
@@ -1462,7 +1435,8 @@ module Asciidoctor
1462
1435
  end
1463
1436
  max_term_width += (term_padding[1] + term_padding[3])
1464
1437
  term_column_width = [max_term_width, bounds.width * 0.5].min
1465
- table table_data, position: :left, cell_style: { border_width: 0 }, column_widths: [term_column_width] do
1438
+ table table_data, position: :left, column_widths: [term_column_width] do
1439
+ cells.style border_width: 0
1466
1440
  @pdf.ink_table_caption node if node.title?
1467
1441
  end
1468
1442
  theme_margin :prose, :bottom, (next_enclosed_block actual_node) #unless actual_node.nested?
@@ -1631,6 +1605,9 @@ module Asciidoctor
1631
1605
  marker = node.parent.style == 'decimal' && index.abs < 10 ? %(#{index < 0 ? '-' : ''}0#{index.abs}.) : %(#{index}.)
1632
1606
  dir = (node.parent.option? 'reversed') ? :pred : :next
1633
1607
  @list_numerals << (index.public_send dir)
1608
+ [:font_color, :font_family, :font_size, :font_style, :line_height].each do |prop|
1609
+ marker_style[prop] = @theme[%(olist_marker_#{prop})] || marker_style[prop]
1610
+ end
1634
1611
  end
1635
1612
  end
1636
1613
  else # :ulist
@@ -1645,7 +1622,7 @@ module Asciidoctor
1645
1622
  else
1646
1623
  marker = @theme[%(ulist_marker_#{marker_type}_content)] || Bullets[marker_type]
1647
1624
  end
1648
- [:font_color, :font_family, :font_size, :line_height].each do |prop|
1625
+ [:font_color, :font_family, :font_size, :font_style, :line_height].each do |prop|
1649
1626
  marker_style[prop] = @theme[%(ulist_marker_#{marker_type}_#{prop})] || @theme[%(ulist_marker_#{prop})] || marker_style[prop]
1650
1627
  end if marker
1651
1628
  end
@@ -1656,8 +1633,9 @@ module Asciidoctor
1656
1633
  log :info, 'deprecated fa icon set found in theme; use fas, far, or fab instead'
1657
1634
  marker_style[:font_family] = FontAwesomeIconSets.find {|candidate| (icon_font_data candidate).yaml[candidate].value? marker } || 'fas'
1658
1635
  end
1636
+ marker_style[:font_style] &&= marker_style[:font_style].to_sym
1659
1637
  marker_gap = rendered_width_of_char 'x'
1660
- font marker_style[:font_family], marker_style[:font_size] do
1638
+ font marker_style[:font_family], size: marker_style[:font_size], style: marker_style[:font_style] do
1661
1639
  marker_width = rendered_width_of_string marker
1662
1640
  # NOTE: compensate if character_spacing is not applied to first character
1663
1641
  # see https://github.com/prawnpdf/prawn/commit/c61c5d48841910aa11b9e3d6f0e01b68ce435329
@@ -1676,6 +1654,7 @@ module Asciidoctor
1676
1654
  color: marker_style[:font_color],
1677
1655
  inline_format: false,
1678
1656
  line_height: marker_style[:line_height],
1657
+ style: marker_style[:font_style],
1679
1658
  margin: 0,
1680
1659
  normalize: false,
1681
1660
  single_line: true
@@ -1940,10 +1919,10 @@ module Asciidoctor
1940
1919
  if at_page_top?
1941
1920
  if page_layout && page_layout != page.layout && page.empty?
1942
1921
  delete_current_page
1943
- advance_page layout: page_layout
1922
+ advance_page layout: page_layout, margin: @page_margin[page_layout][page_side nil, @folio_placement[:inverted]]
1944
1923
  end
1945
1924
  elsif page_layout
1946
- advance_page layout: page_layout
1925
+ advance_page layout: page_layout, margin: @page_margin[page_layout][page_side nil, @folio_placement[:inverted]]
1947
1926
  else
1948
1927
  advance_page
1949
1928
  end
@@ -2104,15 +2083,10 @@ module Asciidoctor
2104
2083
  when :monospaced
2105
2084
  cell_data.delete :font_style
2106
2085
  cell_line_height = @base_line_height
2107
- current_font_size = @font_size
2108
2086
  theme_font :codespan do
2109
2087
  mono_cell_font_info = font_info
2110
2088
  cell_data[:font] = mono_cell_font_info[:family]
2111
- if ::String === @font_size || @font_size < 1
2112
- @font_size = current_font_size
2113
- font_size mono_cell_font_info[:size]
2114
- end
2115
- cell_data[:size] = @font_size
2089
+ cell_data[:size] = mono_cell_font_info[:size]
2116
2090
  cell_data[:text_color] = @font_color
2117
2091
  cell_line_metrics = calc_line_metrics cell_line_height
2118
2092
  end
@@ -2244,10 +2218,10 @@ module Asciidoctor
2244
2218
  # NOTE: position is handled by this method
2245
2219
  position: :left,
2246
2220
  # NOTE: the border color, style, and width of the outer frame is set in the table callback block
2247
- cell_style: { border_color: grid_color.values, border_lines: grid_style.values, border_width: grid_width.values },
2248
2221
  width: table_width,
2249
2222
  column_widths: column_widths,
2250
2223
  }
2224
+ cell_style = { border_color: grid_color.values, border_lines: grid_style.values, border_width: grid_width.values }
2251
2225
 
2252
2226
  # QUESTION: should we support nth; should we support sequence of roles?
2253
2227
  case node.attr 'stripes', nil, 'table-stripes'
@@ -2263,6 +2237,8 @@ module Asciidoctor
2263
2237
 
2264
2238
  left_padding = right_padding = nil
2265
2239
  table table_data, table_settings do
2240
+ # NOTE: cell_style must be applied manually to be compatible with both prawn-table 0.2.2 and prawn-table 0.2.3
2241
+ cells.style cell_style
2266
2242
  @column_widths = column_widths unless column_widths.empty?
2267
2243
  # NOTE: call width to capture resolved table width
2268
2244
  table_width = width
@@ -2434,7 +2410,7 @@ module Asciidoctor
2434
2410
  # QUESTION: should we insert breakable chars into URI when building fragment instead?
2435
2411
  %(#{anchor}<a href="#{target}"#{attrs.join}>#{breakable_uri text}</a>)
2436
2412
  # NOTE: @media may not be initialized if method is called before convert phase
2437
- elsif (doc.attr? 'show-link-uri') || !(@media == 'screen' || (doc.attribute_locked? 'show-link-uri') || ((doc.instance_variable_get :@attributes_modified).include? 'show-link-uri'))
2413
+ elsif (doc.attr? 'show-link-uri') || (@media != 'screen' && (doc.attr_unspecified? 'show-link-uri'))
2438
2414
  # QUESTION: should we insert breakable chars into URI when building fragment instead?
2439
2415
  # TODO: allow style of printed link to be controlled by theme
2440
2416
  %(#{anchor}<a href="#{target}"#{attrs.join}>#{text}</a> [<font size="0.85em">#{breakable_uri bare_target}</font>&#93;)
@@ -2798,6 +2774,11 @@ module Asciidoctor
2798
2774
  if (imagesdir = opts[:imagesdir])
2799
2775
  imagesdir_to_restore = doc.attr 'imagesdir'
2800
2776
  doc.set_attr 'imagesdir', imagesdir
2777
+ remove_docimagesdir = doc.set_attr 'docimagesdir', (::File.absolute_path imagesdir_to_restore.to_s, (doc.attr 'docdir', '')), false
2778
+ end
2779
+ if (page_layout = opts[:page_layout])
2780
+ page_layout_to_restore = doc.attr 'page-layout'
2781
+ doc.set_attr 'page-layout', page.layout.to_s
2801
2782
  end
2802
2783
  # FIXME: get sub_attributes to handle drop-line w/o a warning
2803
2784
  doc.set_attr 'attribute-missing', 'skip' unless (attribute_missing = doc.attr 'attribute-missing') == 'skip'
@@ -2806,20 +2787,26 @@ module Asciidoctor
2806
2787
  value = (value.split LF).delete_if {|line| SimpleAttributeRefRx.match? line }.join LF if opts[:drop_lines_with_unresolved_attributes] && (value.include? '{')
2807
2788
  value = value.gsub '\{', '{' if escaped_attr_ref
2808
2789
  doc.set_attr 'attribute-missing', attribute_missing unless attribute_missing == 'skip'
2809
- imagesdir_to_restore ? (doc.set_attr 'imagesdir', imagesdir_to_restore) : (doc.remove_attr 'imagesdir') if imagesdir
2790
+ page_layout_to_restore ? (doc.set_attr 'page-layout', page_layout_to_restore) : (doc.remove_attr 'page-layout') if page_layout
2791
+ if imagesdir
2792
+ imagesdir_to_restore ? (doc.set_attr 'imagesdir', imagesdir_to_restore) : (doc.remove_attr 'imagesdir')
2793
+ doc.remove_attr 'docimagesdir' if remove_docimagesdir
2794
+ end
2810
2795
  value
2811
2796
  end
2812
2797
 
2813
2798
  # Position the cursor for where to ink the specified section title or discrete heading node.
2814
2799
  #
2815
- # This method computes whether there is enough room on the page to prevent the specified node
2816
- # from being orphaned. If there is not enough room, the method will advance the cursor to
2800
+ # This method computes whether there's enough room on the page to prevent the specified node
2801
+ # from being orphaned. If there's not enough room, the method will advance the cursor to
2817
2802
  # the next page. This method is not called if the cursor is already at the top of the page or
2818
2803
  # whether this node has no node that follows it in document order.
2819
2804
  def arrange_heading node, title, opts
2820
- if node.option? 'breakable'
2805
+ if (min_height_after = @theme.heading_min_height_after) == 'auto' || (node.option? 'breakable')
2821
2806
  orphaned = nil
2807
+ doc = node.document
2822
2808
  dry_run single_page: true do
2809
+ push_scratch doc
2823
2810
  start_page = page
2824
2811
  theme_font :heading, level: opts[:level] do
2825
2812
  if opts[:part]
@@ -2834,6 +2821,8 @@ module Asciidoctor
2834
2821
  page.tare_content_stream
2835
2822
  orphaned = stop_if_first_page_empty { node.context == :section ? (traverse node) : (convert node.next_sibling) }
2836
2823
  end
2824
+ ensure
2825
+ pop_scratch doc
2837
2826
  end
2838
2827
  advance_page if orphaned
2839
2828
  else
@@ -2844,9 +2833,7 @@ module Asciidoctor
2844
2833
  heading_h = (height_of_typeset_text title) +
2845
2834
  (@theme[%(heading_h#{hlevel}_margin_top)] || @theme.heading_margin_top) +
2846
2835
  (@theme[%(heading_h#{hlevel}_margin_bottom)] || @theme.heading_margin_bottom) + h_padding_t + h_padding_b
2847
- if (min_height_after = @theme.heading_min_height_after) && (node.context == :section ? node.blocks? : !node.last_child?)
2848
- heading_h += min_height_after
2849
- end
2836
+ heading_h += min_height_after if min_height_after && (node.context == :section ? node.blocks? : !node.last_child?)
2850
2837
  cursor >= heading_h
2851
2838
  end
2852
2839
  advance_page unless h_fits
@@ -3148,7 +3135,7 @@ module Asciidoctor
3148
3135
  open_graphics_state if face == :front
3149
3136
  return
3150
3137
  elsif image_path == '~'
3151
- @page_margin_by_side[:cover] = @page_margin_by_side[:recto] if @media == 'prepress'
3138
+ @page_margin[:cover] = @page_margin[page.layout][:recto] if @media == 'prepress'
3152
3139
  return
3153
3140
  end
3154
3141
 
@@ -3279,7 +3266,7 @@ module Asciidoctor
3279
3266
 
3280
3267
  def allocate_running_content_layout doc, page, periphery, cache
3281
3268
  cache[layout = page.layout] ||= begin
3282
- page_margin_recto = @page_margin_by_side[:recto]
3269
+ page_margin_recto = @page_margin[layout][:recto]
3283
3270
  trim_margin_recto = @theme[%(#{periphery}_recto_margin)] || @theme[%(#{periphery}_margin)] || [0, 'inherit', 0, 'inherit']
3284
3271
  trim_margin_recto = (expand_margin_value trim_margin_recto).map.with_index {|v, i| i.odd? && v == 'inherit' ? page_margin_recto[i] : v.to_f }
3285
3272
  trim_content_margin_recto = @theme[%(#{periphery}_recto_content_margin)] || @theme[%(#{periphery}_content_margin)] || [0, 'inherit', 0, 'inherit']
@@ -3289,7 +3276,7 @@ module Asciidoctor
3289
3276
  else
3290
3277
  trim_padding_recto = trim_content_margin_recto
3291
3278
  end
3292
- page_margin_verso = @page_margin_by_side[:verso]
3279
+ page_margin_verso = @page_margin[layout][:verso]
3293
3280
  trim_margin_verso = @theme[%(#{periphery}_verso_margin)] || @theme[%(#{periphery}_margin)] || [0, 'inherit', 0, 'inherit']
3294
3281
  trim_margin_verso = (expand_margin_value trim_margin_verso).map.with_index {|v, i| i.odd? && v == 'inherit' ? page_margin_verso[i] : v.to_f }
3295
3282
  trim_content_margin_verso = @theme[%(#{periphery}_verso_content_margin)] || @theme[%(#{periphery}_content_margin)] || [0, 'inherit', 0, 'inherit']
@@ -3684,7 +3671,7 @@ module Asciidoctor
3684
3671
  logo_image_attrs = (AttributeList.new $2).parse %w(alt width height)
3685
3672
  if logo_image_from_theme
3686
3673
  relative_to_imagesdir = false
3687
- logo_image_path = apply_subs_discretely doc, $1, subs: [:attributes]
3674
+ logo_image_path = apply_subs_discretely doc, $1, subs: [:attributes], imagesdir: @themesdir
3688
3675
  logo_image_path = ThemeLoader.resolve_theme_asset logo_image_path, @themesdir unless doc.is_uri? logo_image_path
3689
3676
  else
3690
3677
  relative_to_imagesdir = true
@@ -3694,7 +3681,7 @@ module Asciidoctor
3694
3681
  logo_image_attrs = {}
3695
3682
  relative_to_imagesdir = false
3696
3683
  if logo_image_from_theme
3697
- logo_image_path = apply_subs_discretely doc, logo_image_path, subs: [:attributes]
3684
+ logo_image_path = apply_subs_discretely doc, logo_image_path, subs: [:attributes], imagesdir: @themesdir
3698
3685
  logo_image_path = ThemeLoader.resolve_theme_asset logo_image_path, @themesdir unless doc.is_uri? logo_image_path
3699
3686
  end
3700
3687
  end
@@ -3780,12 +3767,12 @@ module Asciidoctor
3780
3767
  end
3781
3768
  end
3782
3769
 
3783
- def allocate_toc doc, toc_num_levels, toc_start_cursor, title_page_on
3770
+ def allocate_toc doc, toc_num_levels, toc_start_cursor, break_after_toc
3784
3771
  toc_start_page_number = page_number
3785
3772
  to_page = nil
3786
3773
  extent = dry_run onto: self do
3787
3774
  to_page = (ink_toc doc, toc_num_levels, toc_start_page_number, toc_start_cursor).end
3788
- theme_margin :block, :bottom unless title_page_on
3775
+ theme_margin :block, :bottom unless break_after_toc
3789
3776
  end
3790
3777
  # NOTE: patch for custom converters that allocate extra TOC pages without actually creating them
3791
3778
  if to_page > extent.to.page
@@ -3793,7 +3780,7 @@ module Asciidoctor
3793
3780
  extent.to.cursor = bounds.height
3794
3781
  end
3795
3782
  # NOTE: reserve pages for the toc; leaves cursor on page after last page in toc
3796
- if title_page_on
3783
+ if break_after_toc
3797
3784
  extent.each_page { start_new_page }
3798
3785
  else
3799
3786
  extent.each_page {|first_page| start_new_page unless first_page }
@@ -4064,18 +4051,14 @@ module Asciidoctor
4064
4051
  return []
4065
4052
  elsif (image_path.include? ':') && image_path =~ ImageAttributeValueRx
4066
4053
  image_attrs = (AttributeList.new $2).parse %w(alt width)
4067
- if from_theme
4068
- image_path = apply_subs_discretely doc, $1, subs: [:attributes]
4069
- image_relative_to = @themesdir
4070
- else
4071
- image_path = $1
4072
- image_relative_to = true
4073
- end
4074
- elsif from_theme
4075
- image_path = apply_subs_discretely doc, image_path, subs: [:attributes]
4076
- image_relative_to = @themesdir
4054
+ image_path = $1
4055
+ image_relative_to = true
4056
+ end
4057
+ if from_theme
4058
+ image_path = apply_subs_discretely doc, image_path, subs: [:attributes], imagesdir: (image_relative_to = @themesdir), page_layout: page.layout.to_s
4059
+ elsif image_path.include? '{page-layout}'
4060
+ image_path = image_path.sub '{page-layout}', page.layout.to_s
4077
4061
  end
4078
-
4079
4062
  image_path, image_format = ::Asciidoctor::Image.target_and_format image_path, image_attrs
4080
4063
  image_path = resolve_image_path doc, image_path, image_format, image_relative_to
4081
4064
 
@@ -4289,6 +4272,27 @@ module Asciidoctor
4289
4272
  end
4290
4273
  end
4291
4274
 
4275
+ def resolve_page_margin value
4276
+ return if value.nil_or_empty?
4277
+ case value
4278
+ when ::Array
4279
+ value = value.slice 0, 4 if value.length > 4
4280
+ value.map {|v| ::Numeric === v ? v : (str_to_pt v.to_s) }
4281
+ when ::Numeric
4282
+ [value]
4283
+ when ::String
4284
+ if (value.start_with? '[') && (value.end_with? ']')
4285
+ return if (value = (value.slice 1, value.length - 2).rstrip).empty?
4286
+ if (value = value.split ',', -1).length > 4
4287
+ value = value.slice 0, 4
4288
+ end
4289
+ value.map {|v| str_to_pt v.rstrip }
4290
+ else
4291
+ [(str_to_pt value)]
4292
+ end
4293
+ end
4294
+ end
4295
+
4292
4296
  def resolve_text_align_from_role roles, query_theme: false, remove_predefined: false
4293
4297
  if (align_role = roles.reverse.find {|r| TextAlignmentRoles.include? r })
4294
4298
  roles.replace roles - TextAlignmentRoles if remove_predefined
@@ -4341,17 +4345,17 @@ module Asciidoctor
4341
4345
  elsif @ppbook && page_number > 0 && recto_page?
4342
4346
  start_new_page
4343
4347
  end
4344
- side = page_side (recycle ? nil : page_number + 1), @folio_placement[:inverted]
4345
- prev_bg_image = @page_bg_image[side]
4346
- prev_bg_color = @page_bg_color
4347
4348
  if (bg_image = resolve_background_image doc, @theme, 'title-page-background-image')
4348
- @page_bg_image[side] = bg_image[0] && bg_image
4349
+ side = page_side (recycle ? nil : page_number + 1), @folio_placement[:inverted]
4350
+ prev_bg_image = get_page_bg_image doc, @theme, (layout = page.layout), side
4351
+ @page_bg_image[layout][side] = bg_image[0] && bg_image
4349
4352
  end
4350
4353
  if (bg_color = resolve_theme_color :title_page_background_color)
4354
+ prev_bg_color = @page_bg_color
4351
4355
  @page_bg_color = bg_color
4352
4356
  end
4353
- recycle ? float { init_page self } : start_new_page
4354
- @page_bg_image[side] = prev_bg_image if bg_image
4357
+ recycle ? float { init_page doc, self } : start_new_page
4358
+ @page_bg_image[layout][side] = prev_bg_image if bg_image
4355
4359
  @page_bg_color = prev_bg_color if bg_color
4356
4360
  true
4357
4361
  end
@@ -4438,7 +4442,12 @@ module Asciidoctor
4438
4442
  if opts.key? :level
4439
4443
  hlevel_category = %(#{category}_h#{opts[:level]})
4440
4444
  family = @theme[%(#{hlevel_category}_font_family)] || @theme[%(#{category}_font_family)] || @theme.base_font_family || font_family
4441
- size = (@theme[%(#{hlevel_category}_font_size)] || @theme[%(#{category}_font_size)] || @root_font_size) * @font_scale
4445
+ if (size = @theme[%(#{hlevel_category}_font_size)] || @theme[%(#{category}_font_size)])
4446
+ scale = @font_scale unless ::String === size
4447
+ else
4448
+ scale = @font_scale
4449
+ size = @root_font_size
4450
+ end
4442
4451
  style = @theme[%(#{hlevel_category}_font_style)] || @theme[%(#{category}_font_style)]
4443
4452
  color = @theme[%(#{hlevel_category}_font_color)] || @theme[%(#{category}_font_color)]
4444
4453
  kerning = resolve_font_kerning @theme[%(#{hlevel_category}_font_kerning)] || @theme[%(#{category}_font_kerning)]
@@ -4448,7 +4457,11 @@ module Asciidoctor
4448
4457
  else
4449
4458
  inherited_font = font_info
4450
4459
  family = @theme[%(#{category}_font_family)] || inherited_font[:family]
4451
- size = (size = @theme[%(#{category}_font_size)]) ? size * @font_scale : inherited_font[:size]
4460
+ if (size = @theme[%(#{category}_font_size)])
4461
+ scale = @font_scale unless ::String === size
4462
+ else
4463
+ size = inherited_font[:size]
4464
+ end
4452
4465
  style = @theme[%(#{category}_font_style)] || inherited_font[:style]
4453
4466
  color = @theme[%(#{category}_font_color)]
4454
4467
  kerning = resolve_font_kerning @theme[%(#{category}_font_kerning)]
@@ -4464,6 +4477,7 @@ module Asciidoctor
4464
4477
 
4465
4478
  result = nil
4466
4479
  font family, size: size, style: style&.to_sym do
4480
+ @font_size *= scale if scale
4467
4481
  result = yield
4468
4482
  ensure
4469
4483
  @font_color = prev_color if color
@@ -4800,6 +4814,23 @@ module Asciidoctor
4800
4814
  (code.start_with? '\u') ? ([((code.slice 2, code.length).to_i 16)].pack 'U1') : code
4801
4815
  end
4802
4816
 
4817
+ def get_page_bg_image doc, theme_, layout, side
4818
+ (@page_bg_image[layout] ||= begin
4819
+ if (bg_image = resolve_background_image doc, theme_, 'page-background-image')&.first
4820
+ val = { verso: bg_image, recto: bg_image }
4821
+ else
4822
+ val = { verso: nil, recto: nil }
4823
+ end
4824
+ if (bg_image = resolve_background_image doc, theme_, 'page-background-image-verso')
4825
+ val[:verso] = bg_image[0] && bg_image
4826
+ end
4827
+ if (bg_image = resolve_background_image doc, theme_, 'page-background-image-recto')
4828
+ val[:recto] = bg_image[0] && bg_image
4829
+ end
4830
+ val
4831
+ end)[side]
4832
+ end
4833
+
4803
4834
  def get_icon_image_path node, type, resolve = true
4804
4835
  doc = node.document
4805
4836
  doc.remove_attr 'data-uri' if (data_uri_enabled = doc.attr? 'data-uri')
@@ -4823,18 +4854,17 @@ module Asciidoctor
4823
4854
  @float_box = { page: page_number, top: box_t, right: box_r, bottom: box_b, left: box_l, width: box_w, height: box_h, gap: gap }
4824
4855
  end
4825
4856
 
4826
- # NOTE: init_page is called within a float context; this will suppress prawn-svg messing with the cursor
4827
4857
  # NOTE: init_page is not called for imported pages, cover pages, image pages, and pages in the scratch document
4828
- def init_page *_args
4858
+ def init_page doc, _self
4829
4859
  next_page_side = page_side nil, @folio_placement[:inverted]
4830
- if @media == 'prepress' && (next_page_margin = @page_margin_by_side[page_number == 1 ? :cover : next_page_side]) != page_margin
4860
+ if @media == 'prepress' && (next_page_margin = page_number == 1 ? @page_margin[:cover] : @page_margin[page.layout][next_page_side]) != page_margin
4831
4861
  set_page_margin next_page_margin
4832
4862
  end
4833
4863
  unless @page_bg_color == 'FFFFFF'
4834
4864
  fill_absolute_bounds @page_bg_color
4835
4865
  tare = true
4836
4866
  end
4837
- if (bg_image_path, bg_image_opts = @page_bg_image[next_page_side])
4867
+ if (bg_image_path, bg_image_opts = get_page_bg_image doc, @theme, (layout = page.layout), next_page_side)
4838
4868
  begin
4839
4869
  if bg_image_opts[:format] == 'pdf'
4840
4870
  # NOTE: pages that use PDF for the background do not support a background color or running content
@@ -4845,9 +4875,10 @@ module Asciidoctor
4845
4875
  end
4846
4876
  tare = true
4847
4877
  rescue
4848
- facing_page_side = (PageSides - [next_page_side])[0]
4849
- @page_bg_image[facing_page_side] = nil if @page_bg_image[facing_page_side] == @page_bg_image[next_page_side]
4850
- @page_bg_image[next_page_side] = nil
4878
+ facing_page_side = PageSides[(PageSides.index next_page_side) - 1]
4879
+ bg_image_by_side = @page_bg_image[layout]
4880
+ bg_image_by_side[facing_page_side] = nil if bg_image_by_side[facing_page_side] == bg_image_by_side[next_page_side]
4881
+ bg_image_by_side[next_page_side] = nil
4851
4882
  log :warn, %(could not embed page background image: #{bg_image_path}; #{$!.message})
4852
4883
  end
4853
4884
  end
@@ -5018,7 +5049,9 @@ module Asciidoctor
5018
5049
  end
5019
5050
 
5020
5051
  def resolve_top val
5021
- if val.end_with? 'vh'
5052
+ if ::Numeric === val
5053
+ @y - val
5054
+ elsif val.end_with? 'vh'
5022
5055
  page_height * (1 - (val.to_f / 100))
5023
5056
  elsif val.end_with? '%'
5024
5057
  @y - effective_page_height * (val.to_f / 100)
@@ -5110,20 +5143,17 @@ module Asciidoctor
5110
5143
  @label = :scratch
5111
5144
  @save_state = nil
5112
5145
  @scratch_depth = 0
5113
- # NOTE: don't need background image in scratch document; can cause marshal error anyway
5114
- saved_page_bg_image, @page_bg_image = @page_bg_image, { verso: nil, recto: nil }
5115
5146
  # NOTE: pdfmark has a reference to the Asciidoctor::Document, which we don't want to serialize
5116
5147
  saved_pdfmark, @pdfmark = @pdfmark, nil
5117
5148
  # IMPORTANT: don't set font before using marshal as it causes serialization to fail
5118
5149
  result = yield
5119
5150
  @pdfmark = saved_pdfmark
5120
- @page_bg_image = saved_page_bg_image
5121
5151
  @label = :primary
5122
5152
  result
5123
5153
  end
5124
5154
 
5125
5155
  def init_scratch originator
5126
- if @media == 'prepress' && page_margin != (page_margin_recto = @page_margin_by_side[:recto])
5156
+ if @media == 'prepress' && page_margin != (page_margin_recto = @page_margin[page.layout][:recto])
5127
5157
  # NOTE: prepare scratch document to use page margin from recto side (which has same width as verso side)
5128
5158
  set_page_margin page_margin_recto
5129
5159
  end
@@ -23,4 +23,9 @@ class Asciidoctor::Document
23
23
  end
24
24
  nil
25
25
  end
26
+
27
+ # Internal: Returns whether the specified attribute has never been set and is not locked.
28
+ def attr_unspecified? name
29
+ !((attribute_locked? name) || (@attributes_modified.include? name))
30
+ end
26
31
  end
@@ -371,14 +371,16 @@ module Asciidoctor
371
371
  else
372
372
  super points.to_f
373
373
  end
374
- # NOTE: assume em value (since a font size of 1 is extremely unlikely)
375
- elsif points <= 1
376
- super @font_size * points
377
374
  else
378
375
  super points
379
376
  end
380
377
  end
381
378
 
379
+ def set_font font, size = nil
380
+ @font = font
381
+ font_size size if size
382
+ end
383
+
382
384
  def resolve_font_style styles
383
385
  if styles.include? :bold
384
386
  (styles.include? :italic) ? :bold_italic : :bold
@@ -1121,6 +1123,10 @@ module Asciidoctor
1121
1123
  # Note that if the block has content that itself requires a dry run, that nested dry run will
1122
1124
  # be performed in a separate scratch document.
1123
1125
  #
1126
+ # The block passed to dry run should take steps to avoid leaving the document state modified.
1127
+ # This can be done by calling `push_scratch doc` at the start of the block and `pop_scratch`
1128
+ # in the ensure clause of the block.
1129
+ #
1124
1130
  # options - A Hash of options that configure the dry run computation:
1125
1131
  # :keep_together - A Boolean indicating whether an attempt should be made to keep
1126
1132
  # the content on the same page (optional, default: false).
@@ -1133,7 +1139,7 @@ module Asciidoctor
1133
1139
  #
1134
1140
  # Returns an Extent or ScratchExtent object that describes the bounds of the content block.
1135
1141
  def dry_run keep_together: nil, pages_advanced: 0, single_page: nil, onto: nil, &block
1136
- (scratch_pdf = scratch).start_new_page layout: page.layout
1142
+ (scratch_pdf = scratch).start_new_page layout: page.layout, margin: page_margin
1137
1143
  saved_bounds = scratch_pdf.bounds
1138
1144
  scratch_pdf.bounds = bounds.dup.tap do |bounds_copy|
1139
1145
  bounds_copy.instance_variable_set :@document, scratch_pdf
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Asciidoctor
4
4
  module PDF
5
- VERSION = '2.1.6'
5
+ VERSION = '2.2.0'
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.6
4
+ version: 2.2.0
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-07-19 00:00:00.000000000 Z
12
+ date: 2022-07-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: asciidoctor