asciidoctor-pdf 2.0.0.alpha.3 → 2.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +28 -1
- data/README.adoc +31 -13
- data/data/fonts/ABOUT-mplus1p-subset +1 -0
- data/data/fonts/ABOUT-notosans-subset +1 -0
- data/data/fonts/ABOUT-notoserif-subset +1 -0
- data/data/fonts/mplus1mn-bold-subset.ttf +0 -0
- data/data/fonts/mplus1mn-bold_italic-subset.ttf +0 -0
- data/data/fonts/mplus1mn-italic-subset.ttf +0 -0
- data/data/fonts/mplus1mn-regular-subset.ttf +0 -0
- data/data/fonts/mplus1p-regular-fallback.ttf +0 -0
- data/data/fonts/notosans-bold-subset.ttf +0 -0
- data/data/fonts/notosans-bold_italic-subset.ttf +0 -0
- data/data/fonts/notosans-italic-subset.ttf +0 -0
- data/data/fonts/notosans-regular-subset.ttf +0 -0
- data/data/fonts/notoserif-bold-subset.ttf +0 -0
- data/data/fonts/notoserif-bold_italic-subset.ttf +0 -0
- data/data/fonts/notoserif-italic-subset.ttf +0 -0
- data/data/fonts/notoserif-regular-subset.ttf +0 -0
- data/data/themes/base-theme.yml +7 -16
- data/docs/theming-guide.adoc +4 -3
- data/lib/asciidoctor/pdf/converter.rb +127 -88
- data/lib/asciidoctor/pdf/ext/pdf-core/page.rb +8 -0
- data/lib/asciidoctor/pdf/ext/prawn/extensions.rb +22 -6
- data/lib/asciidoctor/pdf/ext/prawn-table/cell/asciidoc.rb +1 -1
- data/lib/asciidoctor/pdf/nopngmagick.rb +3 -0
- data/lib/asciidoctor/pdf/optimizer.rb +12 -5
- data/lib/asciidoctor/pdf/text_transformer.rb +14 -0
- data/lib/asciidoctor/pdf/theme_loader.rb +3 -3
- data/lib/asciidoctor/pdf/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3c96a0b756ccd22c3aec10c571e5ef0280a0003398f48a86287037c52d13a85
|
4
|
+
data.tar.gz: c611aec1ecafd132c9415babfc193929bbe52879b6282cc752d6def346ce9d56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 517791afccee6a976f59244b08ffdd062f09d2153d04917a61b969ef525752eee70d8118586932757e3f6fd175880f899a60d768cfc4b8e8ef6cabdad5f5f239
|
7
|
+
data.tar.gz: 3ae8abd3251302def2b2305a4c9aebe940235735d0c0204891c909e383ac8622eb21b158d3d844a49b60dab5f1c5d82e8252961c1f2247b6158a7975d9d7c50b
|
data/CHANGELOG.adoc
CHANGED
@@ -5,6 +5,33 @@
|
|
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 {uri-repo}/commits/main[commit history] on GitHub.
|
7
7
|
|
8
|
+
== 2.0.0.beta.1 (2022-05-04) - @mojavelinux
|
9
|
+
|
10
|
+
Enhancements::
|
11
|
+
|
12
|
+
* introduce `index-pagenum-sequence-style` document attribute to control style of sequential page numbers in index when media=screen (#1656)
|
13
|
+
* allow entry for document in outline to be controlled using `outline-title` attribute (#1789)
|
14
|
+
* allow extended converter to insert or filter toc entries by overriding `get_entries_for_toc` method (#2097)
|
15
|
+
* add `asciidoctor/pdf/nopngmagick` script to unregister Gmagick handler for PNG images only (#1687)
|
16
|
+
* allow theme to configure which end the caption is placed for a block image (#2115)
|
17
|
+
* add `Page#imported` method to mark page as imported (which suppresses running contennt)
|
18
|
+
* add support for `smallcaps` text transform by replacing lowercase letters with small capital variants (#1192)
|
19
|
+
* use `base-border-color` as default border color; control appearance of border using `border-width` value alone (#2134)
|
20
|
+
* remove border colors in base theme so all border colors can be controlled using `base-border-color` when extending theme
|
21
|
+
* enable running footer when using base theme
|
22
|
+
|
23
|
+
Bug Fixes::
|
24
|
+
|
25
|
+
* allow border width of block image to be specified as an array (1, 2, or 4 values) (#2119)
|
26
|
+
* rename `delete_page` extension method to `delete_current_page` to avoid conflict with incompatible method on `Prawn::Document`
|
27
|
+
* remap `table-caption-side` theme key to `table-caption-end` (#2125)
|
28
|
+
* add missing glyph for `ÿ` in built-in fonts
|
29
|
+
* remove use of deprecated keys in chronicles-dark-theme.yml
|
30
|
+
|
31
|
+
=== Details
|
32
|
+
|
33
|
+
{url-repo}/releases/tag/v2.0.0.beta.1[git tag] | {url-repo}/compare/v2.0.0.alpha.3\...v2.0.0.beta.1[full diff]
|
34
|
+
|
8
35
|
== 2.0.0.alpha.3 (2022-05-01) - @mojavelinux
|
9
36
|
|
10
37
|
Enhancements::
|
@@ -44,7 +71,7 @@ Enhancements::
|
|
44
71
|
* pass the `part` and `chapterlike` options to the `arrange_section` method for convenience
|
45
72
|
* add support for `background-color` property on caption (#1995)
|
46
73
|
* add support for image-based icons, resolved from `iconsdir` and having the `icontype` file extension (#1770)
|
47
|
-
* add `asciidoctor/pdf/nogmagick` script to prevent
|
74
|
+
* add `asciidoctor/pdf/nogmagick` script to prevent loading prawn-gmagick gem (#1687)
|
48
75
|
* change name of `untitled` option on special section to `notitle`
|
49
76
|
* allow the title of any section to be hidden using the `notitle` option
|
50
77
|
* allow imported PDF page to be referenced in TOC by enclosing in parent section with `notitle` option (#1213)
|
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.0.0.
|
3
|
+
v2.0.0.beta.1, 2022-05-04
|
4
4
|
// Settings:
|
5
5
|
:experimental:
|
6
6
|
:idprefix:
|
@@ -24,7 +24,7 @@ endif::[]
|
|
24
24
|
:project-handle: asciidoctor-pdf
|
25
25
|
// Variables:
|
26
26
|
:release-line: 2.0.x
|
27
|
-
:release-version: 2.0.0.
|
27
|
+
:release-version: 2.0.0.beta.1
|
28
28
|
// URIs:
|
29
29
|
:url-asciidoctor: http://asciidoctor.org
|
30
30
|
:url-gem: http://rubygems.org/gems/asciidoctor-pdf
|
@@ -713,23 +713,41 @@ If you're using fonts in your SVG, and you want those fonts to be preserved, tho
|
|
713
713
|
|
714
714
|
== Supporting Additional Image File Formats
|
715
715
|
|
716
|
-
In order to embed an image into a PDF, Asciidoctor PDF must understand how to
|
716
|
+
In order to embed an image into a PDF, Asciidoctor PDF must understand how to decode it.
|
717
717
|
To perform this work, Asciidoctor delegates to the underlying libraries.
|
718
|
-
{url-prawn}[Prawn] provides support for
|
719
|
-
{url-prawn-svg}[prawn-svg] brings support for SVG images.
|
720
|
-
Without any additional libraries, those are the only
|
718
|
+
{url-prawn}[Prawn] provides support for decoding JPG and PNG images.
|
719
|
+
{url-prawn-svg}[prawn-svg] brings support for translating SVG images to PDF commands.
|
720
|
+
Without any additional libraries, those are the only image file formats supported by Asciidoctor PDF.
|
721
721
|
|
722
|
-
If you need support for additional image formats, such as GIF, TIFF, or interlaced PNG--and you don't want to convert those images to a supported format--you must install the {url-prawn-gmagick}[prawn-gmagick] (>= 0.0.9) Ruby gem.
|
723
|
-
prawn-gmagick is an extension for Prawn
|
724
|
-
|
722
|
+
If you need support for additional image formats, such as GIF, TIFF, WebP, or interlaced PNG--and you don't want to convert those images to a supported format like JPG--you must install the {url-prawn-gmagick}[prawn-gmagick] (>= 0.0.9) Ruby gem.
|
723
|
+
prawn-gmagick is an extension for Prawn that delegates image decoding to {url-graphicsmagick}[GraphicsMagick] to add support for all image formats recognized by that library.
|
724
|
+
|
725
|
+
prawn-gmagick has the additional benefit of *significantly* reducing the processing time, power, and memory necessary to generate a PDF that contains a lot of PNG images.
|
726
|
+
For large books (such as Pro Git), you might see the conversion time drop by as much as half.
|
727
|
+
Decoding PNG images requires a lot of mathematical computation, a task Ruby is not particularly efficient at performing.
|
728
|
+
That's why adding the prawn-gmagick gem to the converter makes such a substantial difference.
|
729
|
+
|
730
|
+
As an alternative to using prawn-gmagick, you could optimize the images you pass into Asciidoctor PDF, either by scaling them down or converting them to an uncompressed format like JPG.
|
725
731
|
|
726
732
|
The prawn-gmagick gem uses native extensions to compile against GraphicsMagick.
|
727
|
-
This system prerequisite limits installation to Linux and
|
733
|
+
This system prerequisite limits installation to C Ruby running on Linux and macOS.
|
728
734
|
Please refer to the {url-prawn-gmagick}[README for prawn-gmagick] to learn how to install it.
|
729
735
|
|
730
|
-
|
731
|
-
|
732
|
-
|
736
|
+
$ gem install prawn-gmagick
|
737
|
+
|
738
|
+
When this gem is installed, Asciidoctor automatically detects and loads it, then delegates all image decoding to GraphicsMagick by way of the bridge it provides.
|
739
|
+
We highly recommend using this gem with Asciidoctor PDF if you're able to install it.
|
740
|
+
|
741
|
+
The one downside of delegating to GraphicsMagick is that it can mangle certain PNG images.
|
742
|
+
If this happens, you can instruct Asciidoctor PDF to not delegate to GraphicsMagick to load PNG images by requiring `asciidoctor/pdf/nopngmagick` when calling Asciidoctor PDF, as follows:
|
743
|
+
|
744
|
+
$ asciidoctor-pdf -r asciidoctor/pdf/nopngmagick doc.adoc
|
745
|
+
|
746
|
+
You can also tell Asciidoctor PDF not to use prawn-gmagick at all by requiring `asciidoctor/pdf/nogmagick` when calling Asciidoctor PDF, as follows:
|
747
|
+
|
748
|
+
$ asciidoctor-pdf -r asciidoctor/pdf/nogmagick doc.adoc
|
749
|
+
|
750
|
+
Granted, bypassing prawn-gmagick means you no longer get support for additional image formats that Prawn cannot handle or the PNG acceleration.
|
733
751
|
|
734
752
|
== Importing PDF Pages
|
735
753
|
|
@@ -17,6 +17,7 @@ The following changes were made using fontforge to produce mplus1p-regular-fallb
|
|
17
17
|
** General Punctuation (U+2000–U203a)
|
18
18
|
** Geometric Shapes (U+25a0–U25ff)
|
19
19
|
** Assorted Symbols (U+20ac, U+2122, U+21d0–U+21d5, U+2190–U+2195, U+2610–U+2611, U+2713–U+2714)
|
20
|
+
** Latin Small Capital Letters (U+1D00, U+0299, U+1D04, U+1D05, U+1D07, U+A730, U+0262, U+029C, U+026A, U+1D0A, U+1D0B, U+029F, U+1D0D, U+0274, U+1D0F, U+1D18, U+A7AF (missing), U+0280, U+A731, U+1D1B, U+1D1C, U+1D20, U+1D21, U+028F, U+1D22)
|
20
21
|
** .notdef glyph
|
21
22
|
* Added BOM (U+feff), hair space (U+200a), zero-width space (U+200b) and line feed (U+000a) characters (from blank)
|
22
23
|
* Manually added non-breaking hyphen (U+2011) from hyphen (U+002d)
|
@@ -17,6 +17,7 @@ The following changes were made using fontforge to produce the notosans-*-subset
|
|
17
17
|
** General Punctuation (U+2000–U203a)
|
18
18
|
** Geometric Shapes (U+25a0–U25ff)
|
19
19
|
** Assorted Symbols (U+20ac, U+2122, U+21d0, U+21d2, U+2190, U+2192)
|
20
|
+
** Latin Small Capital Letters (U+1D00, U+0299, U+1D04, U+1D05, U+1D07, U+A730 (missing), U+0262, U+029C, U+026A, U+1D0A, U+1D0B, U+029F, U+1D0D, U+0274, U+1D0F, U+1D18, U+A7AF (missing), U+0280, U+A731 (missing), U+1D1B, U+1D1C, U+1D20, U+1D21, U+028F, U+1D22, U+01EB)
|
20
21
|
** .notdef glyph
|
21
22
|
* Imported ballot boxes from Font Awesome (U+2610, U+2611) (Noto Serif Regular only)
|
22
23
|
* Added line feed character (U+000a)
|
@@ -17,6 +17,7 @@ The following changes were made using fontforge to produce the notoserif-*-subse
|
|
17
17
|
** General Punctuation (U+2000–U203a)
|
18
18
|
** Geometric Shapes (U+25a0–U25ff)
|
19
19
|
** Assorted Symbols (U+20ac, U+2122, U+21d0, U+21d2, U+2190, U+2192)
|
20
|
+
** Latin Small Capital Letters (U+1D00, U+0299, U+1D04, U+1D05, U+1D07, U+A730 (missing), U+0262, U+029C, U+026A, U+1D0A, U+1D0B, U+029F, U+1D0D, U+0274, U+1D0F, U+1D18, U+A7AF (missing), U+0280, U+A731 (missing), U+1D1B, U+1D1C, U+1D20, U+1D21, U+028F, U+1D22, U+01EB)
|
20
21
|
** .notdef glyph
|
21
22
|
* Imported ballot boxes from Font Awesome (U+2610, U+2611) (Noto Serif Regular only)
|
22
23
|
* Added line feed character (U+000a)
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/data/themes/base-theme.yml
CHANGED
@@ -1,24 +1,19 @@
|
|
1
|
-
# NOTE file is read "as is"; variables are not parsed; key layout must be flat
|
1
|
+
# NOTE: file is read "as is"; variables are not parsed; key layout must be flat
|
2
2
|
page_background_color: 'FFFFFF'
|
3
3
|
page_layout: portrait
|
4
4
|
page_initial_zoom: FitH
|
5
|
-
# 36 is
|
6
|
-
page_margin: 36
|
5
|
+
page_margin: 36 # 36 is 0.5in
|
7
6
|
page_margin_inner: 48
|
8
7
|
page_margin_outer: 24
|
9
8
|
page_size: A4
|
10
9
|
base_text_align: left
|
11
|
-
#base_font_color: '333333'
|
12
10
|
base_font_color: '000000'
|
13
|
-
#base_font_family: Times-Roman
|
14
11
|
base_font_family: Helvetica
|
15
12
|
base_font_size: 12
|
16
|
-
# QUESTION should we rename to min_font_size?
|
17
13
|
base_font_size_min: 6
|
18
14
|
base_font_style: normal
|
19
15
|
base_line_height: 1.15
|
20
|
-
base_border_color: '
|
21
|
-
base_border_width: 0.5
|
16
|
+
base_border_color: '000000'
|
22
17
|
role_lead_font_size: 13.5
|
23
18
|
role_line-through_text_decoration: line-through
|
24
19
|
role_underline_text_decoration: underline
|
@@ -47,7 +42,6 @@ heading_margin_top: 4
|
|
47
42
|
heading_margin_bottom: 12
|
48
43
|
heading_min_height_after: 20
|
49
44
|
title_page_text_align: center
|
50
|
-
title_page_line_height: 1.15
|
51
45
|
title_page_logo_top: 10%
|
52
46
|
title_page_title_top: 40%
|
53
47
|
title_page_title_font_size: 18
|
@@ -69,43 +63,37 @@ abstract_line_height: 1.4
|
|
69
63
|
abstract_padding: 0
|
70
64
|
abstract_title_align: center
|
71
65
|
abstract_title_font_style: bold
|
72
|
-
admonition_column_rule_color: 'EEEEEE'
|
73
66
|
admonition_column_rule_width: 0.5
|
74
67
|
admonition_padding: [4, 12, 4, 12]
|
75
68
|
admonition_label_font_style: bold
|
76
69
|
admonition_label_text_transform: uppercase
|
77
|
-
quote_border_color: 'EEEEEE'
|
78
70
|
quote_border_left_width: 4
|
79
71
|
quote_padding: [3, 12, 3, 14]
|
80
|
-
verse_border_color: 'EEEEEE'
|
81
72
|
verse_border_left_width: 4
|
82
73
|
verse_padding: [3, 12, 3, 14]
|
83
74
|
code_font_family: Courier
|
84
75
|
code_font_size: 10.8
|
85
76
|
code_line_height: 1.2
|
86
77
|
code_padding: 9
|
87
|
-
code_border_color: 'EEEEEE'
|
88
78
|
code_border_width: 0.5
|
89
79
|
conum_line_height: 1.15
|
90
80
|
conum_glyphs: circled
|
91
81
|
example_background_color: 'FFFFFF'
|
92
|
-
example_border_color: 'EEEEEE'
|
93
82
|
example_border_width: 0.5
|
94
83
|
example_padding: 12
|
95
84
|
image_align: left
|
96
85
|
prose_margin_bottom: 12
|
97
86
|
sidebar_background_color: 'EEEEEE'
|
87
|
+
sidebar_border_width: 0.5
|
98
88
|
sidebar_padding: 12
|
99
89
|
sidebar_title_align: center
|
100
90
|
sidebar_title_font_style: bold
|
101
|
-
table_border_color: '000000'
|
102
91
|
table_border_style: solid
|
103
92
|
table_border_width: 0.5
|
104
93
|
table_cell_padding: 2
|
105
94
|
table_head_font_style: bold
|
106
95
|
table_head_border_bottom_width: 1.25
|
107
96
|
table_body_stripe_background_color: 'EEEEEE'
|
108
|
-
thematic_break_border_color: 'EEEEEE'
|
109
97
|
thematic_break_border_style: solid
|
110
98
|
thematic_break_border_width: 0.5
|
111
99
|
thematic_break_margin_bottom: 12
|
@@ -113,5 +101,8 @@ toc_indent: 15
|
|
113
101
|
toc_line_height: 1.4
|
114
102
|
footnotes_font_size: 9
|
115
103
|
footnotes_item_spacing: 3
|
104
|
+
footer_border_width: 0.5
|
105
|
+
footer_font_size: 10
|
106
|
+
footer_height: 30
|
116
107
|
footer_recto_right_content: '{page-number}'
|
117
108
|
footer_verso_left_content: '{page-number}'
|
data/docs/theming-guide.adoc
CHANGED
@@ -4223,11 +4223,12 @@ The keys in this category control the arrangement and style of tables and table
|
|
4223
4223
|
caption:
|
4224
4224
|
text-align: left
|
4225
4225
|
|
4226
|
-
|caption-
|
4226
|
+
|caption-end
|
4227
4227
|
|top {vbar} bottom +
|
4228
4228
|
(default: top)
|
4229
4229
|
|table:
|
4230
|
-
caption
|
4230
|
+
caption:
|
4231
|
+
end: bottom
|
4231
4232
|
|
4232
4233
|
|caption-max-width
|
4233
4234
|
|fit-content {vbar} fit-content(percentage) {vbar} none {vbar} <<measurement-units,Measurement>> +
|
@@ -5921,7 +5922,7 @@ def ink_part_title node, title, opts = {}
|
|
5921
5922
|
fill_absolute_bounds 'E64C3D'
|
5922
5923
|
move_down 20
|
5923
5924
|
typeset_text title, (calc_line_metrics 1.5), color: 'FFFFFF', inline_format: true, align: :center, size: 42
|
5924
|
-
page.
|
5925
|
+
page.imported
|
5925
5926
|
end
|
5926
5927
|
----
|
5927
5928
|
|
@@ -139,6 +139,7 @@ module Asciidoctor
|
|
139
139
|
# NOTE: enabling data-uri forces Asciidoctor Diagram to produce absolute image paths
|
140
140
|
doc.attributes['data-uri'] = (doc.instance_variable_get :@attribute_overrides)['data-uri'] = ''
|
141
141
|
end
|
142
|
+
@label = :primary
|
142
143
|
@initial_instance_variables = [:@initial_instance_variables] + instance_variables
|
143
144
|
end
|
144
145
|
|
@@ -181,8 +182,9 @@ module Asciidoctor
|
|
181
182
|
def convert_document doc
|
182
183
|
doc.promote_preface_block
|
183
184
|
init_pdf doc
|
184
|
-
# set default value for outline,
|
185
|
+
# set default value for outline, outline-title, and pagenums attributes if not otherwise set
|
185
186
|
doc.attributes['outline'] = '' unless (doc.attribute_locked? 'outline') || ((doc.instance_variable_get :@attributes_modified).include? 'outline')
|
187
|
+
doc.attributes['outline-title'] = '' unless (doc.attribute_locked? 'outline-title') || ((doc.instance_variable_get :@attributes_modified).include? 'outline-title')
|
186
188
|
doc.attributes['pagenums'] = '' unless (doc.attribute_locked? 'pagenums') || ((doc.instance_variable_get :@attributes_modified).include? 'pagenums')
|
187
189
|
#assign_missing_section_ids doc
|
188
190
|
|
@@ -216,7 +218,7 @@ module Asciidoctor
|
|
216
218
|
if (insert_toc = (doc.attr? 'toc') && !((toc_placement = doc.attr 'toc-placement') == 'macro' || toc_placement == 'preamble') && doc.sections?)
|
217
219
|
start_new_page if @ppbook && verso_page?
|
218
220
|
add_dest_for_block doc, id: 'toc', y: (at_page_top? ? page_height : nil)
|
219
|
-
allocate_toc doc, toc_num_levels, cursor, title_page_on
|
221
|
+
@toc_extent = allocate_toc doc, toc_num_levels, cursor, title_page_on
|
220
222
|
else
|
221
223
|
@toc_extent = nil
|
222
224
|
end
|
@@ -303,19 +305,19 @@ module Asciidoctor
|
|
303
305
|
# NOTE: for a book, these are leftover footnotes; for an article this is everything
|
304
306
|
outdent_section { ink_footnotes doc }
|
305
307
|
|
306
|
-
if @toc_extent
|
308
|
+
if (toc_extent = @toc_extent)
|
307
309
|
if title_page_on && !insert_toc
|
308
|
-
num_front_matter_pages[0] =
|
309
|
-
num_front_matter_pages[1] =
|
310
|
+
num_front_matter_pages[0] = toc_extent.to.page if @theme.running_content_start_at == 'after-toc'
|
311
|
+
num_front_matter_pages[1] = toc_extent.to.page if @theme.page_numbering_start_at == 'after-toc'
|
310
312
|
end
|
311
|
-
toc_page_nums = ink_toc doc, toc_num_levels,
|
313
|
+
toc_page_nums = ink_toc doc, toc_num_levels, toc_extent.from.page, toc_extent.from.cursor, num_front_matter_pages[1]
|
312
314
|
else
|
313
315
|
toc_page_nums = []
|
314
316
|
end
|
315
317
|
|
316
318
|
# NOTE: delete orphaned page (a page was created but there was no additional content)
|
317
319
|
# QUESTION: should we delete page if document is empty? (leaving no pages?)
|
318
|
-
|
320
|
+
delete_current_page if page_count > 1 && page.empty?
|
319
321
|
end
|
320
322
|
|
321
323
|
unless page_count < body_start_page_number
|
@@ -461,8 +463,6 @@ module Asciidoctor
|
|
461
463
|
end
|
462
464
|
|
463
465
|
def prepare_theme theme
|
464
|
-
theme.base_border_color ||= '000000'
|
465
|
-
theme.base_border_width ||= 0
|
466
466
|
theme.base_font_color ||= '000000'
|
467
467
|
theme.base_font_size ||= 12
|
468
468
|
theme.base_font_style = theme.base_font_style&.to_sym || :normal
|
@@ -479,7 +479,9 @@ module Asciidoctor
|
|
479
479
|
theme.list_item_spacing ||= 0
|
480
480
|
theme.description_list_term_spacing ||= 0
|
481
481
|
theme.description_list_description_indent ||= 0
|
482
|
+
theme.table_border_color ||= (theme.base_border_color || '000000')
|
482
483
|
theme.table_border_width ||= 0.5
|
484
|
+
theme.thematic_break_border_color ||= (theme.base_border_color || '000000')
|
483
485
|
theme.image_border_width ||= 0
|
484
486
|
theme.code_linenum_font_color ||= '999999'
|
485
487
|
theme.callout_list_margin_top_after_code ||= 0
|
@@ -902,8 +904,8 @@ module Asciidoctor
|
|
902
904
|
pad_box [0, cpad[1], 0, lpad[3]] do
|
903
905
|
if extent
|
904
906
|
label_height = extent.single_page_height || cursor
|
905
|
-
if (
|
906
|
-
(
|
907
|
+
if (rule_width = @theme.admonition_column_rule_width || 0) > 0 &&
|
908
|
+
(rule_color = @theme.admonition_column_rule_color || @theme.base_border_color)
|
907
909
|
rule_style = @theme.admonition_column_rule_style&.to_sym || :solid
|
908
910
|
float do
|
909
911
|
extent.each_page do |first_page, last_page|
|
@@ -1057,7 +1059,7 @@ module Asciidoctor
|
|
1057
1059
|
category = node.context == :quote ? :quote : :verse
|
1058
1060
|
# NOTE: b_width and b_left_width are mutually exclusive
|
1059
1061
|
if (b_left_width = @theme[%(#{category}_border_left_width)]) && b_left_width > 0
|
1060
|
-
b_color = @theme[%(#{category}_border_color)]
|
1062
|
+
b_color = @theme[%(#{category}_border_color)] || @theme.base_border_color
|
1061
1063
|
else
|
1062
1064
|
b_left_width = nil
|
1063
1065
|
b_width = nil if (b_width = @theme[%(#{category}_border_width)]) == 0
|
@@ -1559,8 +1561,10 @@ module Asciidoctor
|
|
1559
1561
|
# TODO: add `to_pt page_width` method to ViewportWidth type
|
1560
1562
|
width = (width.to_f / 100) * page_width if ViewportWidth === width
|
1561
1563
|
|
1564
|
+
caption_end = @theme.image_caption_end&.to_sym || :bottom
|
1565
|
+
caption_max_width = @theme.image_caption_max_width
|
1562
1566
|
# NOTE: if width is not set explicitly and max-width is fit-content, caption height may not be accurate
|
1563
|
-
caption_h = node.title? ? (ink_caption node, category: :image,
|
1567
|
+
caption_h = node.title? ? (ink_caption node, category: :image, end: caption_end, block_align: alignment, block_width: width, max_width: caption_max_width, dry_run: true, force_top_margin: caption_end == :bottom) : 0
|
1564
1568
|
|
1565
1569
|
align_to_page = node.option? 'align-to-page'
|
1566
1570
|
pinned = opts[:pinned]
|
@@ -1596,14 +1600,14 @@ module Asciidoctor
|
|
1596
1600
|
end
|
1597
1601
|
rendered_w = (svg_obj.resize height: (rendered_h = available_h)).output_width if rendered_h > available_h
|
1598
1602
|
end
|
1599
|
-
image_y = y
|
1600
|
-
image_cursor = cursor
|
1601
1603
|
add_dest_for_block node if node.id
|
1602
1604
|
# NOTE: workaround to fix Prawn not adding fill and stroke commands on page that only has an image;
|
1603
1605
|
# breakage occurs when running content (stamps) are added to page
|
1604
1606
|
update_colors if graphic_state.color_space.empty?
|
1605
|
-
|
1606
|
-
|
1607
|
+
ink_caption node, category: :image, end: :top, block_align: alignment, block_width: rendered_w, max_width: caption_max_width if caption_end == :top && node.title?
|
1608
|
+
image_y = y
|
1609
|
+
image_cursor = cursor
|
1610
|
+
svg_obj.draw # NOTE: cursor advances automatically
|
1607
1611
|
svg_obj.document.warnings.each do |img_warning|
|
1608
1612
|
log :warn, %(problem encountered in image: #{image_path}; #{img_warning})
|
1609
1613
|
end unless scratch?
|
@@ -1627,12 +1631,13 @@ module Asciidoctor
|
|
1627
1631
|
end
|
1628
1632
|
rendered_w, rendered_h = image_info.calc_image_dimensions height: available_h if rendered_h > available_h
|
1629
1633
|
end
|
1630
|
-
image_y = y
|
1631
|
-
image_cursor = cursor
|
1632
1634
|
add_dest_for_block node if node.id
|
1633
1635
|
# NOTE: workaround to fix Prawn not adding fill and stroke commands on page that only has an image;
|
1634
1636
|
# breakage occurs when running content (stamps) are added to page
|
1635
1637
|
update_colors if graphic_state.color_space.empty?
|
1638
|
+
ink_caption node, category: :image, end: :top, block_align: alignment, block_width: rendered_w, max_width: caption_max_width if caption_end == :top && node.title?
|
1639
|
+
image_y = y
|
1640
|
+
image_cursor = cursor
|
1636
1641
|
# NOTE: specify both width and height to avoid recalculation
|
1637
1642
|
embed_image image_obj, image_info, width: rendered_w, height: rendered_h, position: alignment
|
1638
1643
|
draw_image_border image_cursor, rendered_w, rendered_h, alignment unless node.role? && (node.has_role? 'noborder')
|
@@ -1643,7 +1648,7 @@ module Asciidoctor
|
|
1643
1648
|
move_down rendered_h if y == image_y
|
1644
1649
|
end
|
1645
1650
|
end
|
1646
|
-
ink_caption node, category: :image,
|
1651
|
+
ink_caption node, category: :image, end: :bottom, block_align: alignment, block_width: rendered_w, max_width: caption_max_width if caption_end == :bottom && node.title?
|
1647
1652
|
theme_margin :block, :bottom, (next_enclosed_block node) unless pinned
|
1648
1653
|
rescue => e
|
1649
1654
|
raise if ::StopIteration === e
|
@@ -1652,7 +1657,7 @@ module Asciidoctor
|
|
1652
1657
|
end
|
1653
1658
|
|
1654
1659
|
def draw_image_border top, w, h, alignment
|
1655
|
-
if @theme.image_border_width
|
1660
|
+
if (Array @theme.image_border_width).any? {|it| it&.> 0 } && (@theme.image_border_color || @theme.base_border_color)
|
1656
1661
|
if (@theme.image_border_fit || 'content') == 'auto'
|
1657
1662
|
bb_width = bounds.width
|
1658
1663
|
elsif alignment == :center
|
@@ -1685,7 +1690,7 @@ module Asciidoctor
|
|
1685
1690
|
(resolve_alignment_from_role node.roles) || (@theme.image_align&.to_sym || :left)
|
1686
1691
|
ink_prose alt_text_template % alt_text_vars, align: alignment, margin: 0, normalize: false, single_line: true
|
1687
1692
|
end
|
1688
|
-
ink_caption node, category: :image,
|
1693
|
+
ink_caption node, category: :image, end: :bottom if node.title?
|
1689
1694
|
theme_margin :block, :bottom, (next_enclosed_block node) unless opts[:pinned]
|
1690
1695
|
nil
|
1691
1696
|
end
|
@@ -1695,7 +1700,7 @@ module Asciidoctor
|
|
1695
1700
|
audio_path = node.media_uri node.attr 'target'
|
1696
1701
|
play_symbol = (node.document.attr? 'icons', 'font') ? %(<font name="fas">#{(icon_font_data 'fas').unicode 'play'}</font>) : RightPointer
|
1697
1702
|
ink_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{audio_path}">#{audio_path}</a> <em>(audio)</em>), normalize: false, margin: 0, single_line: true
|
1698
|
-
ink_caption node, labeled: false,
|
1703
|
+
ink_caption node, labeled: false, end: :bottom if node.title?
|
1699
1704
|
theme_margin :block, :bottom, (next_enclosed_block node)
|
1700
1705
|
end
|
1701
1706
|
|
@@ -1723,7 +1728,7 @@ module Asciidoctor
|
|
1723
1728
|
add_dest_for_block node if node.id
|
1724
1729
|
play_symbol = (node.document.attr? 'icons', 'font') ? %(<font name="fas">#{(icon_font_data 'fas').unicode 'play'}</font>) : RightPointer
|
1725
1730
|
ink_prose %(#{play_symbol}#{NoBreakSpace}<a href="#{video_path}">#{video_path}</a> <em>(#{type})</em>), normalize: false, margin: 0, single_line: true
|
1726
|
-
ink_caption node, labeled: false,
|
1731
|
+
ink_caption node, labeled: false, end: :bottom if node.title?
|
1727
1732
|
theme_margin :block, :bottom, (next_enclosed_block node)
|
1728
1733
|
else
|
1729
1734
|
original_attributes = node.attributes.dup
|
@@ -2188,12 +2193,12 @@ module Asciidoctor
|
|
2188
2193
|
|
2189
2194
|
rect_side_names = [:top, :right, :bottom, :left]
|
2190
2195
|
grid_axis_names = [:rows, :cols]
|
2191
|
-
border_color = (rect_side_names.zip expand_rect_values theme.table_border_color,
|
2196
|
+
border_color = (rect_side_names.zip expand_rect_values theme.table_border_color, 'transparent').to_h
|
2192
2197
|
border_style = (rect_side_names.zip (expand_rect_values theme.table_border_style, :solid).map(&:to_sym)).to_h
|
2193
|
-
border_width = (rect_side_names.zip expand_rect_values theme.table_border_width,
|
2194
|
-
grid_color = (grid_axis_names.zip expand_grid_values (theme.table_grid_color || [border_color[:top], border_color[:left]]),
|
2198
|
+
border_width = (rect_side_names.zip expand_rect_values theme.table_border_width, 0).to_h
|
2199
|
+
grid_color = (grid_axis_names.zip expand_grid_values (theme.table_grid_color || [border_color[:top], border_color[:left]]), 'transparent').to_h
|
2195
2200
|
grid_style = (grid_axis_names.zip (expand_grid_values (theme.table_grid_style || [border_style[:top], border_style[:left]]), :solid).map(&:to_sym)).to_h
|
2196
|
-
grid_width = (grid_axis_names.zip expand_grid_values (theme.table_grid_width || [border_width[:top], border_width[:left]]),
|
2201
|
+
grid_width = (grid_axis_names.zip expand_grid_values (theme.table_grid_width || [border_width[:top], border_width[:left]]), 0).to_h
|
2197
2202
|
|
2198
2203
|
if table_header_size
|
2199
2204
|
head_border_bottom_color = theme.table_head_border_bottom_color || grid_color[:rows]
|
@@ -2239,7 +2244,7 @@ module Asciidoctor
|
|
2239
2244
|
alignment = theme.table_align&.to_sym || :left
|
2240
2245
|
end
|
2241
2246
|
|
2242
|
-
|
2247
|
+
caption_end = theme.table_caption_end&.to_sym || :top
|
2243
2248
|
caption_max_width = theme.table_caption_max_width || 'fit-content'
|
2244
2249
|
|
2245
2250
|
table_settings = {
|
@@ -2268,7 +2273,7 @@ module Asciidoctor
|
|
2268
2273
|
table table_data, table_settings do
|
2269
2274
|
# NOTE: call width to capture resolved table width
|
2270
2275
|
table_width = width
|
2271
|
-
@pdf.ink_table_caption node, alignment, table_width, caption_max_width if node.title? &&
|
2276
|
+
@pdf.ink_table_caption node, alignment, table_width, caption_max_width if node.title? && caption_end == :top
|
2272
2277
|
# NOTE: align using padding instead of bounding_box as prawn-table does
|
2273
2278
|
# using a bounding_box across pages mangles the margin box of subsequent pages
|
2274
2279
|
if alignment != :left && table_width != (this_bounds = @pdf.bounds).width
|
@@ -2341,7 +2346,7 @@ module Asciidoctor
|
|
2341
2346
|
bounds.subtract_left_padding left_padding
|
2342
2347
|
bounds.subtract_right_padding right_padding if right_padding
|
2343
2348
|
end
|
2344
|
-
ink_table_caption node, alignment, table_width, caption_max_width,
|
2349
|
+
ink_table_caption node, alignment, table_width, caption_max_width, caption_end if node.title? && caption_end == :bottom
|
2345
2350
|
theme_margin :block, :bottom, (next_enclosed_block node)
|
2346
2351
|
rescue ::Prawn::Errors::CannotFit
|
2347
2352
|
log :error, (message_with_context 'cannot fit contents of table cell into specified column width', source_location: node.source_location)
|
@@ -2349,12 +2354,14 @@ module Asciidoctor
|
|
2349
2354
|
|
2350
2355
|
def convert_thematic_break node
|
2351
2356
|
theme_margin :thematic_break, :top
|
2352
|
-
stroke_horizontal_rule @theme.thematic_break_border_color,
|
2357
|
+
stroke_horizontal_rule @theme.thematic_break_border_color,
|
2358
|
+
line_width: @theme.thematic_break_border_width,
|
2359
|
+
line_style: (@theme.thematic_break_border_style&.to_sym || :solid)
|
2353
2360
|
theme_margin :thematic_break, ((block_next = next_enclosed_block node) ? :bottom : :top), block_next || true
|
2354
2361
|
end
|
2355
2362
|
|
2356
2363
|
def convert_toc node, opts = {}
|
2357
|
-
# NOTE: only allow document to have a single toc
|
2364
|
+
# NOTE: only allow document to have a single managed toc
|
2358
2365
|
return if @toc_extent
|
2359
2366
|
is_macro = (placement = opts[:placement] || 'macro') == 'macro'
|
2360
2367
|
if ((doc = node.document).attr? 'toc-placement', placement) && (doc.attr? 'toc') && doc.sections?
|
@@ -2363,11 +2370,11 @@ module Asciidoctor
|
|
2363
2370
|
start_new_page if @ppbook && verso_page? && !(is_macro && (node.option? 'nonfacing'))
|
2364
2371
|
end
|
2365
2372
|
add_dest_for_block node, id: (node.id || 'toc') if is_macro
|
2366
|
-
allocate_toc doc, (doc.attr 'toclevels', 2).to_i, cursor, (title_page_on = is_book || (doc.attr? 'title-page'))
|
2367
|
-
@index.start_page_number =
|
2373
|
+
toc_extent = @toc_extent = allocate_toc doc, (doc.attr 'toclevels', 2).to_i, cursor, (title_page_on = is_book || (doc.attr? 'title-page'))
|
2374
|
+
@index.start_page_number = toc_extent.to.page + 1 if title_page_on && @theme.page_numbering_start_at == 'after-toc'
|
2368
2375
|
if is_macro
|
2369
|
-
@disable_running_content[:header] +=
|
2370
|
-
@disable_running_content[:footer] +=
|
2376
|
+
@disable_running_content[:header] += toc_extent.page_range if node.option? 'noheader'
|
2377
|
+
@disable_running_content[:footer] += toc_extent.page_range if node.option? 'nofooter'
|
2371
2378
|
end
|
2372
2379
|
end
|
2373
2380
|
nil
|
@@ -2385,7 +2392,7 @@ module Asciidoctor
|
|
2385
2392
|
|
2386
2393
|
if at_page_top?
|
2387
2394
|
if page_layout && page_layout != page.layout && page.empty?
|
2388
|
-
|
2395
|
+
delete_current_page
|
2389
2396
|
advance_page layout: page_layout
|
2390
2397
|
end
|
2391
2398
|
elsif page_layout
|
@@ -2395,8 +2402,9 @@ module Asciidoctor
|
|
2395
2402
|
end
|
2396
2403
|
end
|
2397
2404
|
|
2398
|
-
def convert_index_section
|
2405
|
+
def convert_index_section node
|
2399
2406
|
space_needed_for_category = @theme.description_list_term_spacing + (2 * (height_of_typeset_text 'A'))
|
2407
|
+
pagenum_sequence_style = node.document.attr 'index-pagenum-sequence-style'
|
2400
2408
|
column_box [0, cursor], columns: @theme.index_columns, width: bounds.width, reflow_margins: true do
|
2401
2409
|
def @bounding_box.move_past_bottom *args # rubocop:disable Lint/NestedMethodDefinition
|
2402
2410
|
super(*args)
|
@@ -2409,8 +2417,8 @@ module Asciidoctor
|
|
2409
2417
|
align: :left,
|
2410
2418
|
inline_format: false,
|
2411
2419
|
margin_bottom: @theme.description_list_term_spacing,
|
2412
|
-
style: @theme.description_list_term_font_style
|
2413
|
-
category.terms.each {|term| convert_index_list_item term }
|
2420
|
+
style: @theme.description_list_term_font_style&.to_sym
|
2421
|
+
category.terms.each {|term| convert_index_list_item term, pagenum_sequence_style }
|
2414
2422
|
# NOTE: see previous note for why we can't use margin_bottom method
|
2415
2423
|
if @theme.prose_margin_bottom > y - reference_bounds.absolute_bottom
|
2416
2424
|
bounds.move_past_bottom
|
@@ -2422,13 +2430,24 @@ module Asciidoctor
|
|
2422
2430
|
nil
|
2423
2431
|
end
|
2424
2432
|
|
2425
|
-
def convert_index_list_item term
|
2433
|
+
def convert_index_list_item term, pagenum_sequence_style = nil
|
2426
2434
|
text = escape_xml term.name
|
2427
2435
|
unless term.container?
|
2428
2436
|
if @media == 'screen'
|
2429
|
-
|
2437
|
+
case pagenum_sequence_style
|
2438
|
+
when 'page'
|
2439
|
+
pagenums = term.dests.uniq {|dest| dest[:page] }.map {|dest| %(<a anchor="#{dest[:anchor]}">#{dest[:page]}</a>) }
|
2440
|
+
when 'range'
|
2441
|
+
first_anchor_per_page = term.dests.each_with_object({}) {|dest, accum| accum[dest[:page]] ||= dest[:anchor] }
|
2442
|
+
pagenums = (consolidate_ranges first_anchor_per_page.keys).map do |range|
|
2443
|
+
anchor = first_anchor_per_page[(range.include? '-') ? (range.partition '-')[0] : range]
|
2444
|
+
%(<a anchor="#{anchor}">#{range}</a>)
|
2445
|
+
end
|
2446
|
+
else # term
|
2447
|
+
pagenums = term.dests.map {|dest| %(<a anchor="#{dest[:anchor]}">#{dest[:page]}</a>) }
|
2448
|
+
end
|
2430
2449
|
else
|
2431
|
-
pagenums = consolidate_ranges term.dests.
|
2450
|
+
pagenums = consolidate_ranges term.dests.map {|dest| dest[:page] }.uniq
|
2432
2451
|
end
|
2433
2452
|
text = %(#{text}, #{pagenums.join ', '})
|
2434
2453
|
end
|
@@ -2436,7 +2455,7 @@ module Asciidoctor
|
|
2436
2455
|
ink_prose text, align: :left, margin: 0, hanging_indent: subterm_indent * 2
|
2437
2456
|
indent subterm_indent do
|
2438
2457
|
term.subterms.each do |subterm|
|
2439
|
-
convert_index_list_item subterm
|
2458
|
+
convert_index_list_item subterm, pagenum_sequence_style
|
2440
2459
|
end
|
2441
2460
|
end unless term.leaf?
|
2442
2461
|
end
|
@@ -2991,7 +3010,7 @@ module Asciidoctor
|
|
2991
3010
|
}.merge(opts)
|
2992
3011
|
end
|
2993
3012
|
if h_category && @theme[%(#{h_category}_border_width)] &&
|
2994
|
-
@theme[%(#{h_category}_border_color)] && page_number == start_page_number
|
3013
|
+
(@theme[%(#{h_category}_border_color)] || @theme.base_border_color) && page_number == start_page_number
|
2995
3014
|
float do
|
2996
3015
|
bounding_box [bounds.left, start_cursor], width: bounds.width, height: start_cursor - cursor do
|
2997
3016
|
theme_fill_and_stroke_bounds h_category
|
@@ -3112,7 +3131,7 @@ module Asciidoctor
|
|
3112
3131
|
end
|
3113
3132
|
end
|
3114
3133
|
theme_font_cascade [:caption, category_caption] do
|
3115
|
-
if ((opts.delete :side) || :top) == :top
|
3134
|
+
if ((opts.delete :end) || (opts.delete :side) || :top) == :top
|
3116
3135
|
margin = { top: caption_margin_outside, bottom: caption_margin_inside }
|
3117
3136
|
else
|
3118
3137
|
margin = { top: caption_margin_inside, bottom: caption_margin_outside }
|
@@ -3140,8 +3159,8 @@ module Asciidoctor
|
|
3140
3159
|
end
|
3141
3160
|
|
3142
3161
|
# Render the caption for a table and return the height of the rendered content
|
3143
|
-
def ink_table_caption node, table_alignment = :left, table_width = nil, max_width = nil,
|
3144
|
-
ink_caption node, category: :table,
|
3162
|
+
def ink_table_caption node, table_alignment = :left, table_width = nil, max_width = nil, end_ = :top
|
3163
|
+
ink_caption node, category: :table, end: end_, block_align: table_alignment, block_width: table_width, max_width: max_width
|
3145
3164
|
end
|
3146
3165
|
|
3147
3166
|
def allocate_toc doc, toc_num_levels, toc_start_cursor, title_page_on
|
@@ -3163,7 +3182,11 @@ module Asciidoctor
|
|
3163
3182
|
extent.each_page {|first_page| start_new_page unless first_page }
|
3164
3183
|
move_cursor_to extent.to.cursor
|
3165
3184
|
end
|
3166
|
-
|
3185
|
+
extent
|
3186
|
+
end
|
3187
|
+
|
3188
|
+
def get_entries_for_toc node
|
3189
|
+
node.sections
|
3167
3190
|
end
|
3168
3191
|
|
3169
3192
|
# NOTE: num_front_matter_pages not used during a dry run
|
@@ -3199,7 +3222,7 @@ module Asciidoctor
|
|
3199
3222
|
}
|
3200
3223
|
end
|
3201
3224
|
theme_margin :toc, :top
|
3202
|
-
ink_toc_level doc
|
3225
|
+
ink_toc_level (get_entries_for_toc doc), num_levels, dot_leader, num_front_matter_pages
|
3203
3226
|
end
|
3204
3227
|
# NOTE: range must be calculated relative to toc_page_number; absolute page number in scratch document is arbitrary
|
3205
3228
|
toc_page_numbers = (toc_page_number..(toc_page_number + (page_number - start_page_number)))
|
@@ -3207,38 +3230,48 @@ module Asciidoctor
|
|
3207
3230
|
toc_page_numbers
|
3208
3231
|
end
|
3209
3232
|
|
3210
|
-
def ink_toc_level
|
3233
|
+
def ink_toc_level entries, num_levels, dot_leader, num_front_matter_pages
|
3211
3234
|
# NOTE: font options aren't always reliable, so store size separately
|
3212
3235
|
toc_font_info = theme_font :toc do
|
3213
3236
|
{ font: font, size: @font_size }
|
3214
3237
|
end
|
3215
3238
|
hanging_indent = @theme.toc_hanging_indent
|
3216
|
-
|
3217
|
-
next if (
|
3218
|
-
theme_font :toc, level:
|
3219
|
-
|
3220
|
-
|
3239
|
+
entries.each do |entry|
|
3240
|
+
next if (num_levels_for_entry = (entry.attr 'toclevels', num_levels).to_i) < (entry_level = entry.level + 1).pred
|
3241
|
+
theme_font :toc, level: entry_level do
|
3242
|
+
next unless (entry_anchor = (entry.attr 'pdf-anchor') || entry.id)
|
3243
|
+
entry_title = entry.context == :section ? entry.numbered_title : (entry.title? ? entry.title : (entry.xreftext 'basic'))
|
3244
|
+
next if entry_title.empty?
|
3245
|
+
entry_title = transform_text entry_title, @text_transform if @text_transform
|
3221
3246
|
pgnum_label_placeholder_width = rendered_width_of_string '0' * @toc_max_pagenum_digits
|
3222
|
-
# NOTE: only write
|
3247
|
+
# NOTE: only write title (excluding dots and page number) if this is a dry run
|
3223
3248
|
if scratch?
|
3224
3249
|
indent 0, pgnum_label_placeholder_width do
|
3225
3250
|
# NOTE: must wrap title in empty anchor element in case links are styled with different font family / size
|
3226
|
-
ink_prose
|
3251
|
+
ink_prose entry_title, anchor: true, normalize: false, hanging_indent: hanging_indent, normalize_line_height: true, margin: 0
|
3227
3252
|
end
|
3228
3253
|
else
|
3229
|
-
physical_pgnum =
|
3230
|
-
|
3231
|
-
|
3254
|
+
if !(physical_pgnum = entry.attr 'pdf-page-start') &&
|
3255
|
+
(target_page_ref = (get_dest entry_anchor)&.first) &&
|
3256
|
+
(target_page_idx = state.pages.index {|candidate| candidate.dictionary == target_page_ref })
|
3257
|
+
physical_pgnum = target_page_idx + 1
|
3258
|
+
end
|
3259
|
+
if physical_pgnum
|
3260
|
+
virtual_pgnum = physical_pgnum - num_front_matter_pages
|
3261
|
+
pgnum_label = (virtual_pgnum < 1 ? (RomanNumeral.new physical_pgnum, :lower) : virtual_pgnum).to_s
|
3262
|
+
else
|
3263
|
+
pgnum_label = '?'
|
3264
|
+
end
|
3232
3265
|
start_page_number = page_number
|
3233
3266
|
start_cursor = cursor
|
3234
3267
|
start_dots = nil
|
3235
|
-
|
3268
|
+
entry_title_inherited = (apply_text_decoration ::Set.new, :toc, entry_level).merge anchor: entry_anchor, color: @font_color
|
3236
3269
|
# NOTE: use text formatter to add anchor overlay to avoid using inline format with synthetic anchor tag
|
3237
|
-
|
3270
|
+
entry_title_fragments = text_formatter.format entry_title, inherited: entry_title_inherited
|
3238
3271
|
line_metrics = calc_line_metrics @base_line_height
|
3239
3272
|
indent 0, pgnum_label_placeholder_width do
|
3240
|
-
(
|
3241
|
-
typeset_formatted_text
|
3273
|
+
(entry_title_fragments[-1][:callback] ||= []) << (last_fragment_pos = ::Asciidoctor::PDF::FormattedText::FragmentPositionRenderer.new)
|
3274
|
+
typeset_formatted_text entry_title_fragments, line_metrics, hanging_indent: hanging_indent, normalize_line_height: true
|
3242
3275
|
start_dots = last_fragment_pos.right + hanging_indent
|
3243
3276
|
last_fragment_cursor = last_fragment_pos.top + line_metrics.padding_top
|
3244
3277
|
start_cursor = last_fragment_cursor if last_fragment_pos.page_number > start_page_number || (start_cursor - last_fragment_cursor) > line_metrics.height
|
@@ -3246,7 +3279,7 @@ module Asciidoctor
|
|
3246
3279
|
end_cursor = cursor
|
3247
3280
|
move_cursor_to start_cursor
|
3248
3281
|
# NOTE: we're guaranteed to be on the same page as the final line of the entry
|
3249
|
-
if dot_leader[:width] > 0 && (dot_leader[:levels].include?
|
3282
|
+
if dot_leader[:width] > 0 && (dot_leader[:levels].include? entry_level.pred)
|
3250
3283
|
pgnum_label_width = rendered_width_of_string pgnum_label
|
3251
3284
|
pgnum_label_font_settings = { color: @font_color, font: font_family, size: @font_size, styles: font_styles }
|
3252
3285
|
save_font do
|
@@ -3258,18 +3291,18 @@ module Asciidoctor
|
|
3258
3291
|
typeset_formatted_text [
|
3259
3292
|
{ text: dot_leader[:text] * num_dots, color: dot_leader[:font_color] },
|
3260
3293
|
dot_leader[:spacer],
|
3261
|
-
({ text: pgnum_label, anchor:
|
3294
|
+
({ text: pgnum_label, anchor: entry_anchor }.merge pgnum_label_font_settings),
|
3262
3295
|
], line_metrics, align: :right
|
3263
3296
|
end
|
3264
3297
|
else
|
3265
|
-
typeset_formatted_text [{ text: pgnum_label, color: @font_color, anchor:
|
3298
|
+
typeset_formatted_text [{ text: pgnum_label, color: @font_color, anchor: entry_anchor }], line_metrics, align: :right
|
3266
3299
|
end
|
3267
3300
|
move_cursor_to end_cursor
|
3268
3301
|
end
|
3269
3302
|
end
|
3270
3303
|
indent @theme.toc_indent do
|
3271
|
-
ink_toc_level
|
3272
|
-
end if
|
3304
|
+
ink_toc_level (get_entries_for_toc entry), num_levels_for_entry, dot_leader, num_front_matter_pages
|
3305
|
+
end if num_levels_for_entry >= entry_level
|
3273
3306
|
end
|
3274
3307
|
end
|
3275
3308
|
|
@@ -3437,7 +3470,7 @@ module Asciidoctor
|
|
3437
3470
|
theme_font periphery do
|
3438
3471
|
canvas do
|
3439
3472
|
bounding_box [trim_styles[:content_left][side], trim_styles[:top][side]], width: trim_styles[:content_width][side], height: trim_styles[:height] do
|
3440
|
-
if (trim_column_rule_width = trim_styles[:column_rule_width]) > 0
|
3473
|
+
if trim_styles[:column_rule_color] && (trim_column_rule_width = trim_styles[:column_rule_width]) > 0
|
3441
3474
|
trim_column_rule_spacing = trim_styles[:column_rule_spacing]
|
3442
3475
|
else
|
3443
3476
|
trim_column_rule_width = nil
|
@@ -3545,12 +3578,12 @@ module Asciidoctor
|
|
3545
3578
|
# NOTE: we've already verified this property is set
|
3546
3579
|
height: (trim_height = @theme[%(#{periphery}_height)]),
|
3547
3580
|
bg_color: (resolve_theme_color %(#{periphery}_background_color).to_sym),
|
3548
|
-
|
3581
|
+
border_width: (trim_border_width = @theme[%(#{periphery}_border_width)] || 0),
|
3582
|
+
border_color: trim_border_width > 0 ? (resolve_theme_color %(#{periphery}_border_color).to_sym, @theme.base_border_color) : nil,
|
3549
3583
|
border_style: (@theme[%(#{periphery}_border_style)]&.to_sym || :solid),
|
3550
|
-
|
3551
|
-
column_rule_color:
|
3584
|
+
column_rule_width: (trim_column_rule_width = @theme[%(#{periphery}_column_rule_width)] || 0),
|
3585
|
+
column_rule_color: trim_column_rule_width > 0 ? (resolve_theme_color %(#{periphery}_column_rule_color).to_sym) : nil,
|
3552
3586
|
column_rule_style: (@theme[%(#{periphery}_column_rule_style)]&.to_sym || :solid),
|
3553
|
-
column_rule_width: (trim_column_rule_color ? @theme[%(#{periphery}_column_rule_width)] || 0 : 0),
|
3554
3587
|
column_rule_spacing: (@theme[%(#{periphery}_column_rule_spacing)] || 0),
|
3555
3588
|
valign: valign_offset ? [valign, valign_offset] : valign,
|
3556
3589
|
img_valign: @theme[%(#{periphery}_image_vertical_align)],
|
@@ -3718,8 +3751,9 @@ module Asciidoctor
|
|
3718
3751
|
outline.define do
|
3719
3752
|
initial_pagenum = has_front_cover ? 2 : 1
|
3720
3753
|
# FIXME: use sanitize: :plain_text on Document#doctitle once available
|
3721
|
-
if document.page_count >= initial_pagenum && (
|
3722
|
-
|
3754
|
+
if document.page_count >= initial_pagenum && (outline_title = doc.attr 'outline-title') &&
|
3755
|
+
(outline_title.empty? ? (outline_title = document.resolve_doctitle doc) : outline_title)
|
3756
|
+
page title: (document.sanitize outline_title), destination: (document.dest_top initial_pagenum)
|
3723
3757
|
end
|
3724
3758
|
# QUESTION: is there any way to get add_outline_level to invoke in the context of the outline?
|
3725
3759
|
document.add_outline_level self, doc.sections, num_levels, expand_levels
|
@@ -3781,7 +3815,14 @@ module Asciidoctor
|
|
3781
3815
|
pdf_doc.render_file target
|
3782
3816
|
# QUESTION: restore attributes first?
|
3783
3817
|
@pdfmark&.generate_file target
|
3784
|
-
(
|
3818
|
+
if (quality = @optimize)
|
3819
|
+
if quality.include? ','
|
3820
|
+
quality, compliance = quality.split ',', 2
|
3821
|
+
elsif quality.include? '/'
|
3822
|
+
quality, compliance = nil, quality
|
3823
|
+
end
|
3824
|
+
(Optimizer.new quality, pdf_doc.min_version, compliance).optimize_file target
|
3825
|
+
end
|
3785
3826
|
to_file = true
|
3786
3827
|
end
|
3787
3828
|
if !ENV['KEEP_ARTIFACTS']
|
@@ -3833,7 +3874,7 @@ module Asciidoctor
|
|
3833
3874
|
end
|
3834
3875
|
|
3835
3876
|
def resolve_text_transform key, use_fallback = true
|
3836
|
-
if (transform = ::Hash === key ? (key.delete :text_transform) : @theme[key
|
3877
|
+
if (transform = ::Hash === key ? (key.delete :text_transform) : @theme[key])
|
3837
3878
|
transform == 'none' ? nil : transform
|
3838
3879
|
elsif use_fallback
|
3839
3880
|
@text_transform
|
@@ -3842,9 +3883,9 @@ module Asciidoctor
|
|
3842
3883
|
|
3843
3884
|
# QUESTION: should we pass a category as an argument?
|
3844
3885
|
# QUESTION: should we make this a method on the theme ostruct? (e.g., @theme.resolve_color key, fallback)
|
3845
|
-
def resolve_theme_color key, fallback_color = nil
|
3846
|
-
if (color = @theme[key
|
3847
|
-
color
|
3886
|
+
def resolve_theme_color key, fallback_color = nil, transparent_color = fallback_color
|
3887
|
+
if (color = @theme[key])
|
3888
|
+
color == 'transparent' ? transparent_color : color
|
3848
3889
|
else
|
3849
3890
|
fallback_color
|
3850
3891
|
end
|
@@ -3855,7 +3896,7 @@ module Asciidoctor
|
|
3855
3896
|
end
|
3856
3897
|
|
3857
3898
|
def theme_fill_and_stroke_bounds category, opts = {}
|
3858
|
-
fill_and_stroke_bounds opts[:background_color], @theme[%(#{category}_border_color)],
|
3899
|
+
fill_and_stroke_bounds opts[:background_color], @theme[%(#{category}_border_color)] || @theme.base_border_color,
|
3859
3900
|
line_width: @theme[%(#{category}_border_width)],
|
3860
3901
|
line_style: (@theme[%(#{category}_border_style)]&.to_sym || :solid),
|
3861
3902
|
radius: @theme[%(#{category}_border_radius)]
|
@@ -3881,11 +3922,9 @@ module Asciidoctor
|
|
3881
3922
|
ink_caption node_with_caption, category: category if node_with_caption
|
3882
3923
|
return
|
3883
3924
|
end
|
3884
|
-
|
3885
|
-
b_color = @page_bg_color
|
3886
|
-
end
|
3925
|
+
b_color = resolve_theme_color %(#{category}_border_color).to_sym, @theme.base_border_color, @page_bg_color
|
3887
3926
|
b_radius ||= (@theme[%(#{category}_border_radius)] || 0) + (b_width || 0)
|
3888
|
-
if b_width
|
3927
|
+
if b_width
|
3889
3928
|
if b_color == @page_bg_color # let page background cut into block background
|
3890
3929
|
b_gap_color, b_shift = @page_bg_color, (b_width * 0.5)
|
3891
3930
|
elsif (b_gap_color = bg_color) && b_gap_color != b_color
|
@@ -14,6 +14,14 @@ class PDF::Core::Page
|
|
14
14
|
content.stream.filtered_stream == (@tare_content_stream ||= InitialPageContent) && document.page_number > 0
|
15
15
|
end
|
16
16
|
|
17
|
+
# Flags this page as imported.
|
18
|
+
#
|
19
|
+
def imported
|
20
|
+
@imported_page = true
|
21
|
+
end
|
22
|
+
|
23
|
+
alias imported_page imported
|
24
|
+
|
17
25
|
# Reset the content of the page.
|
18
26
|
# Note that this method may leave behind an orphaned background image.
|
19
27
|
def reset_content
|
@@ -103,7 +103,7 @@ module Asciidoctor
|
|
103
103
|
NewPageRequiredError = ::Class.new ::StopIteration
|
104
104
|
|
105
105
|
InhibitNewPageProc = proc do |pdf|
|
106
|
-
pdf.
|
106
|
+
pdf.delete_current_page
|
107
107
|
raise NewPageRequiredError
|
108
108
|
end
|
109
109
|
|
@@ -111,7 +111,7 @@ module Asciidoctor
|
|
111
111
|
|
112
112
|
DetectEmptyFirstPageProc = proc do |delegate, pdf|
|
113
113
|
if pdf.state.pages[pdf.page_number - 2].empty?
|
114
|
-
pdf.
|
114
|
+
pdf.delete_current_page
|
115
115
|
raise NewPageRequiredError
|
116
116
|
end
|
117
117
|
delegate.call pdf if (pdf.state.on_page_create_callback = delegate)
|
@@ -269,6 +269,20 @@ module Asciidoctor
|
|
269
269
|
dest_xyz 0, page_height, nil, (page_num ? state.pages[page_num - 1] : page)
|
270
270
|
end
|
271
271
|
|
272
|
+
# Gets the destination registered for the specified name. The return value
|
273
|
+
# matches that which was passed to the add_dest method.
|
274
|
+
#
|
275
|
+
def get_dest name, node = dests.data
|
276
|
+
node.children.each do |child|
|
277
|
+
if ::PDF::Core::NameTree::Value === child
|
278
|
+
return child.value.data if child.name == name
|
279
|
+
elsif (found = get_dest name, child)
|
280
|
+
return found
|
281
|
+
end
|
282
|
+
end
|
283
|
+
nil
|
284
|
+
end
|
285
|
+
|
272
286
|
# Fonts
|
273
287
|
|
274
288
|
# Registers a new custom font described in the data parameter
|
@@ -495,6 +509,8 @@ module Asciidoctor
|
|
495
509
|
lowercase_pcdata text
|
496
510
|
when :capitalize, 'capitalize'
|
497
511
|
capitalize_words_pcdata text
|
512
|
+
when :smallcaps, 'smallcaps'
|
513
|
+
smallcaps_pcdata text
|
498
514
|
else
|
499
515
|
text
|
500
516
|
end
|
@@ -823,7 +839,7 @@ module Asciidoctor
|
|
823
839
|
|
824
840
|
# Deletes the current page and move the cursor
|
825
841
|
# to the previous page.
|
826
|
-
def
|
842
|
+
def delete_current_page
|
827
843
|
pg = page_number
|
828
844
|
pdf_store = state.store
|
829
845
|
content_id = page.content.identifier
|
@@ -857,7 +873,7 @@ module Asciidoctor
|
|
857
873
|
prev_page_size = page.size
|
858
874
|
state.compress = false if state.compress # can't use compression if using template
|
859
875
|
prev_text_rendering_mode = (defined? @text_rendering_mode) ? @text_rendering_mode : nil
|
860
|
-
|
876
|
+
delete_current_page if options[:replace]
|
861
877
|
# NOTE: use functionality provided by prawn-templates
|
862
878
|
start_new_page_discretely template: file, template_page: options[:page]
|
863
879
|
# prawn-templates sets text_rendering_mode to :unknown, which breaks running content; revert
|
@@ -869,11 +885,11 @@ module Asciidoctor
|
|
869
885
|
# way atm to prevent the size & layout of the imported page from affecting subsequent pages
|
870
886
|
advance_page size: prev_page_size, layout: prev_page_layout if options.fetch :advance, true
|
871
887
|
elsif options.fetch :advance_if_missing, true
|
872
|
-
|
888
|
+
delete_current_page
|
873
889
|
# NOTE: see previous comment
|
874
890
|
advance_page size: prev_page_size, layout: prev_page_layout
|
875
891
|
else
|
876
|
-
|
892
|
+
delete_current_page
|
877
893
|
end
|
878
894
|
nil
|
879
895
|
end
|
@@ -99,7 +99,7 @@ module Prawn
|
|
99
99
|
apply_font_properties { pdf.traverse content }
|
100
100
|
if (extra_pages = pdf.page_number - start_page) > 0
|
101
101
|
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?
|
102
|
-
extra_pages.times { pdf.
|
102
|
+
extra_pages.times { pdf.delete_current_page }
|
103
103
|
end
|
104
104
|
nil
|
105
105
|
end
|
@@ -40,9 +40,10 @@ module Asciidoctor
|
|
40
40
|
attr_reader :quality
|
41
41
|
attr_reader :compatibility_level
|
42
42
|
|
43
|
-
def initialize quality = 'default', compatibility_level = '1.4'
|
43
|
+
def initialize quality = 'default', compatibility_level = '1.4', compliance = 'PDF'
|
44
44
|
@quality = QUALITY_NAMES[quality]
|
45
45
|
@compatibility_level = compatibility_level
|
46
|
+
@compliance = compliance
|
46
47
|
if (gs_path = ::ENV['GS'])
|
47
48
|
::RGhost::Config::GS[:path] = gs_path
|
48
49
|
end
|
@@ -57,10 +58,16 @@ module Asciidoctor
|
|
57
58
|
else
|
58
59
|
inputs = target
|
59
60
|
end
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
d:
|
61
|
+
d = { Printed: false, CannotEmbedFontPolicy: '/Warning', CompatibilityLevel: @compatibility_level }
|
62
|
+
case @compliance
|
63
|
+
when 'PDF/A', 'PDF/A-1', 'PDF/A-2', 'PDF/A-3'
|
64
|
+
d[:PDFA] = ((@compliance.split '-', 2)[1] || 1).to_i
|
65
|
+
d[:ShowAnnots] = false
|
66
|
+
when 'PDF/X', 'PDF/X-1', 'PDF/X-3'
|
67
|
+
d[:PDFX] = true
|
68
|
+
d[:ShowAnnots] = false
|
69
|
+
end
|
70
|
+
(::RGhost::Convert.new inputs).to :pdf, filename: filename_tmp.to_s, quality: @quality, d: d
|
64
71
|
filename_o.binwrite filename_tmp.binread
|
65
72
|
end
|
66
73
|
nil
|
@@ -10,6 +10,12 @@ module Asciidoctor
|
|
10
10
|
WordRx = /\p{Word}+/
|
11
11
|
Hyphen = '-'
|
12
12
|
SoftHyphen = ?\u00ad
|
13
|
+
LowerAlphaChars = 'a-z'
|
14
|
+
# NOTE: use more widely-supported ғ instead of ꜰ as replacement for F
|
15
|
+
# NOTE: use more widely-supported ǫ instead of ꞯ as replacement for Q
|
16
|
+
# NOTE: use more widely-supported s (lowercase latin "s") instead of ꜱ as replacement for S
|
17
|
+
# NOTE: in small caps, x (lowercase latin "x") remains unchanged
|
18
|
+
SmallCapsChars = 'ᴀʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴoᴘǫʀsᴛᴜᴠᴡxʏᴢ'
|
13
19
|
|
14
20
|
def capitalize_words_pcdata string
|
15
21
|
if XMLMarkupRx.match? string
|
@@ -50,6 +56,14 @@ module Asciidoctor
|
|
50
56
|
string.upcase
|
51
57
|
end
|
52
58
|
end
|
59
|
+
|
60
|
+
def smallcaps_pcdata string
|
61
|
+
if XMLMarkupRx.match? string
|
62
|
+
string.gsub(PCDATAFilterRx) { $2 ? ($2.tr LowerAlphaChars, SmallCapsChars) : $1 }
|
63
|
+
else
|
64
|
+
string.tr LowerAlphaChars, SmallCapsChars
|
65
|
+
end
|
66
|
+
end
|
53
67
|
end
|
54
68
|
end
|
55
69
|
end
|
@@ -15,7 +15,7 @@ module Asciidoctor
|
|
15
15
|
BaseThemePath = ::File.join ThemesDir, 'base-theme.yml'
|
16
16
|
BundledThemeNames = (::Dir.children ThemesDir).map {|it| it.slice 0, it.length - 10 }
|
17
17
|
DeprecatedCategoryKeys = { 'blockquote' => 'quote', 'key' => 'kbd', 'literal' => 'codespan', 'outline_list' => 'list' }
|
18
|
-
|
18
|
+
DeprecatedKeys = %w(base heading heading_h1 heading_h2 heading_h3 heading_h4 heading_h5 heading_h6 title_page abstract abstract_title admonition_label sidebar_title toc_title).each_with_object({ 'table_caption_side' => 'table_caption_end' }) do |prefix, accum|
|
19
19
|
accum[%(#{prefix}_align)] = %(#{prefix}_text_align)
|
20
20
|
end
|
21
21
|
PaddingBottomHackKeys = %w(example_padding quote_padding sidebar_padding verse_padding)
|
@@ -171,7 +171,7 @@ module Asciidoctor
|
|
171
171
|
val.each do |subkey, subval|
|
172
172
|
process_entry %(#{key}_#{key == 'role' || !(subkey.include? '-') ? subkey : (subkey.tr '-', '_')}), subval, data
|
173
173
|
end
|
174
|
-
elsif (rekey =
|
174
|
+
elsif (rekey = DeprecatedKeys[key]) ||
|
175
175
|
((key.start_with? 'role_') && (key.end_with? '_align') && (rekey = key.sub RoleAlignKeyRx, '_text_align'))
|
176
176
|
data[rekey] = evaluate val, data
|
177
177
|
elsif PaddingBottomHackKeys.include? key
|
@@ -222,7 +222,7 @@ module Asciidoctor
|
|
222
222
|
var = var.tr '-', '_' if var.include? '-'
|
223
223
|
if (vars.respond_to? var) ||
|
224
224
|
DeprecatedCategoryKeys.any? {|old, new| (var.start_with? old + '_') && (vars.respond_to? (replace = new + (var.slice old.length, var.length))) && (var = replace) } ||
|
225
|
-
((replace =
|
225
|
+
((replace = DeprecatedKeys[var]) && (vars.respond_to? replace) && (var = replace))
|
226
226
|
vars[var]
|
227
227
|
else
|
228
228
|
logger.warn %(unknown variable reference in PDF theme: #{ref})
|
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.0.0.
|
4
|
+
version: 2.0.0.beta.1
|
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-05-
|
12
|
+
date: 2022-05-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: asciidoctor
|
@@ -291,6 +291,7 @@ files:
|
|
291
291
|
- lib/asciidoctor/pdf/index_catalog.rb
|
292
292
|
- lib/asciidoctor/pdf/measurements.rb
|
293
293
|
- lib/asciidoctor/pdf/nogmagick.rb
|
294
|
+
- lib/asciidoctor/pdf/nopngmagick.rb
|
294
295
|
- lib/asciidoctor/pdf/optimizer.rb
|
295
296
|
- lib/asciidoctor/pdf/pdfmark.rb
|
296
297
|
- lib/asciidoctor/pdf/roman_numeral.rb
|