asciidoctor-pdf 1.5.2 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +68 -1
- data/{LICENSE.adoc → LICENSE} +3 -4
- data/NOTICE.adoc +4 -6
- data/README.adoc +139 -46
- data/asciidoctor-pdf.gemspec +11 -14
- data/bin/asciidoctor-pdf-optimize +1 -1
- data/docs/theming-guide.adoc +26 -22
- data/lib/asciidoctor/pdf/converter.rb +88 -78
- data/lib/asciidoctor/pdf/ext/asciidoctor/section.rb +3 -2
- data/lib/asciidoctor/pdf/ext/core/file.rb +4 -5
- data/lib/asciidoctor/pdf/ext/core.rb +0 -1
- data/lib/asciidoctor/pdf/ext/pdf-core/pdf_object.rb +1 -1
- data/lib/asciidoctor/pdf/ext/pdf-core.rb +15 -0
- data/lib/asciidoctor/pdf/ext/prawn/coderay_encoder.rb +4 -13
- data/lib/asciidoctor/pdf/ext/prawn/extensions.rb +28 -2
- data/lib/asciidoctor/pdf/ext/prawn/font_metric_cache.rb +1 -1
- data/lib/asciidoctor/pdf/ext/prawn/formatted_text/arranger.rb +15 -0
- data/lib/asciidoctor/pdf/ext/prawn/formatted_text/box.rb +28 -7
- data/lib/asciidoctor/pdf/ext/prawn-svg.rb +0 -1
- data/lib/asciidoctor/pdf/ext/prawn.rb +1 -0
- data/lib/asciidoctor/pdf/ext/pygments.rb +11 -9
- data/lib/asciidoctor/pdf/ext.rb +0 -1
- data/lib/asciidoctor/pdf/formatted_text/fragment_position_renderer.rb +5 -1
- data/lib/asciidoctor/pdf/formatted_text/inline_image_arranger.rb +9 -2
- data/lib/asciidoctor/pdf/formatted_text/transform.rb +6 -4
- data/lib/asciidoctor/pdf/index_catalog.rb +1 -1
- data/lib/asciidoctor/pdf/optimizer.rb +40 -12
- data/lib/asciidoctor/pdf/pdfmark.rb +1 -2
- data/lib/asciidoctor/pdf/text_transformer.rb +10 -71
- data/lib/asciidoctor/pdf/theme_loader.rb +1 -1
- data/lib/asciidoctor/pdf/version.rb +1 -1
- data/lib/asciidoctor/pdf.rb +3 -0
- metadata +21 -63
- data/lib/asciidoctor/pdf/ext/core/numeric.rb +0 -26
- data/lib/asciidoctor/pdf/ext/prawn-svg/interface.rb +0 -14
- data/lib/asciidoctor/pdf/ext/prawn-templates.rb +0 -7
data/asciidoctor-pdf.gemspec
CHANGED
@@ -14,10 +14,10 @@ Gem::Specification.new do |s|
|
|
14
14
|
s.homepage = 'https://asciidoctor.org/docs/asciidoctor-pdf'
|
15
15
|
s.license = 'MIT'
|
16
16
|
# NOTE required ruby version is informational only; it's not enforced since it can't be overridden and can cause builds to break
|
17
|
-
#s.required_ruby_version = '>= 2.
|
17
|
+
#s.required_ruby_version = '>= 2.5.0'
|
18
18
|
s.metadata = {
|
19
19
|
'bug_tracker_uri' => 'https://github.com/asciidoctor/asciidoctor-pdf/issues',
|
20
|
-
'changelog_uri' => 'https://github.com/asciidoctor/asciidoctor-pdf/blob/
|
20
|
+
'changelog_uri' => 'https://github.com/asciidoctor/asciidoctor-pdf/blob/main/CHANGELOG.adoc',
|
21
21
|
'mailing_list_uri' => 'http://discuss.asciidoctor.org',
|
22
22
|
'source_code_uri' => 'https://github.com/asciidoctor/asciidoctor-pdf'
|
23
23
|
}
|
@@ -28,30 +28,27 @@ Gem::Specification.new do |s|
|
|
28
28
|
rescue
|
29
29
|
files = Dir['**/*']
|
30
30
|
end
|
31
|
-
s.files = files.grep %r/^(?:(?:data|lib)\/.+|docs\/theming-guide\.adoc|(?:CHANGELOG|
|
31
|
+
s.files = files.grep %r/^(?:(?:data|lib)\/.+|docs\/theming-guide\.adoc|LICENSE|(?:CHANGELOG|NOTICE|README)\.adoc|\.yardopts|#{s.name}\.gemspec)$/
|
32
32
|
s.executables = (files.grep %r/^bin\//).map {|f| File.basename f }
|
33
33
|
s.require_paths = ['lib']
|
34
34
|
#s.test_files = files.grep %r/^(?:test|spec|feature)\/.*$/
|
35
35
|
|
36
|
-
s.add_runtime_dependency 'asciidoctor', '
|
37
|
-
s.add_runtime_dependency 'prawn', '~> 2.
|
38
|
-
# NOTE
|
39
|
-
s.add_runtime_dependency 'ttfunk', ['~> 1.5.0'], ['>= 1.5.1']
|
40
|
-
# NOTE must use prawn-table from master branch (defined in Gemfile) for full functionality
|
36
|
+
s.add_runtime_dependency 'asciidoctor', '~> 2.0'
|
37
|
+
s.add_runtime_dependency 'prawn', '~> 2.4.0'
|
38
|
+
# NOTE must use prawn-table from head (defined in Gemfile) for full functionality
|
41
39
|
s.add_runtime_dependency 'prawn-table', '~> 0.2.0'
|
42
40
|
s.add_runtime_dependency 'prawn-templates', '~> 0.1.0'
|
43
|
-
s.add_runtime_dependency 'prawn-svg', '~> 0.
|
44
|
-
s.add_runtime_dependency 'prawn-icon', '~>
|
41
|
+
s.add_runtime_dependency 'prawn-svg', '~> 0.32.0'
|
42
|
+
s.add_runtime_dependency 'prawn-icon', '~> 3.0.0'
|
45
43
|
s.add_runtime_dependency 'safe_yaml', '~> 1.0.0'
|
46
|
-
s.add_runtime_dependency '
|
47
|
-
s.add_runtime_dependency 'concurrent-ruby', '~> 1.1.0'
|
44
|
+
s.add_runtime_dependency 'concurrent-ruby', '~> 1.1'
|
48
45
|
s.add_runtime_dependency 'treetop', '~> 1.6.0'
|
49
46
|
|
50
47
|
s.add_development_dependency 'rake', '~> 13.0.0'
|
51
|
-
s.add_development_dependency 'rspec', '~> 3.
|
48
|
+
s.add_development_dependency 'rspec', '~> 3.10.0'
|
52
49
|
s.add_development_dependency 'pdf-inspector', '~> 1.3.0'
|
53
50
|
# Asciidoctor PDF supports Rouge >= 2 (verified in CI build using 2.0.0)
|
54
51
|
s.add_development_dependency 'rouge', '~> 3.0'
|
55
52
|
s.add_development_dependency 'coderay', '~> 1.1.0'
|
56
|
-
s.add_development_dependency 'chunky_png', '~> 1.
|
53
|
+
s.add_development_dependency 'chunky_png', '~> 1.4.0'
|
57
54
|
end
|
data/docs/theming-guide.adoc
CHANGED
@@ -141,7 +141,7 @@ Otherwise, Asciidoctor PDF will use built-in AFM fonts, which can result in miss
|
|
141
141
|
|
142
142
|
[TIP]
|
143
143
|
====
|
144
|
-
Instead of creating a theme from scratch, another option is to download the https://github.com/asciidoctor/asciidoctor-pdf/blob/
|
144
|
+
Instead of creating a theme from scratch, another option is to download the https://github.com/asciidoctor/asciidoctor-pdf/blob/main/data/themes/default-theme.yml[default-theme.yml] file from the source repository.
|
145
145
|
Save the file using a unique name (e.g., _custom-theme.yml_) and start hacking on it.
|
146
146
|
|
147
147
|
Alternatively, you can snag the file from your local installation using the following command:
|
@@ -752,8 +752,9 @@ A sans-serif font that provides a very complete set of Unicode glyphs.
|
|
752
752
|
Cannot be styled as italic, bold or bold_italic.
|
753
753
|
Used as the fallback font in the `default-with-fallback-font` theme.
|
754
754
|
|
755
|
-
TIP:
|
756
|
-
|
755
|
+
TIP: The default themes in 1.5.x do not include the `GEM_FONTS_DIR` prefix in the path of the bundled font files.
|
756
|
+
Therefore, if you want to specify the location of custom fonts using the `pdf-fontsdir` attribute, yet still be able to use the bundled fonts, you need to refer to the bundled fonts using the `GEM_FONTS_DIR` token.
|
757
|
+
To do so, you can either a) redeclare the bundle fonts in your theme and prefix the path with the segment `GEM_FONTS_DIR` (e.g., `GEM_FONTS_DIR/mplus1p-regular-fallback.ttf`, or b) include `GEM_FONT_DIR` in the value of the `pdf-fontsdir` attribute separated by the location of your custom fonts using a semi-colon (e.g., `"path/to/your/fonts;GEM_FONTS_DIR"`).
|
757
758
|
|
758
759
|
=== Custom Fonts
|
759
760
|
|
@@ -963,9 +964,9 @@ This nested structure is for organizational purposes only.
|
|
963
964
|
All keys are flatted when the theme is loaded (e.g., `align` nested under `base` becomes `base-align`).
|
964
965
|
|
965
966
|
The converter uses the values of these keys to control how most elements are arranged and styled in the PDF.
|
966
|
-
The default values listed in this section get inherited from the https://github.com/asciidoctor/asciidoctor-pdf/blob/
|
967
|
+
The default values listed in this section get inherited from the https://github.com/asciidoctor/asciidoctor-pdf/blob/main/data/themes/base-theme.yml[base theme].
|
967
968
|
|
968
|
-
IMPORTANT: The https://github.com/asciidoctor/asciidoctor-pdf/blob/
|
969
|
+
IMPORTANT: The https://github.com/asciidoctor/asciidoctor-pdf/blob/main/data/themes/default-theme.yml[default theme] has a different set of values which are not shown in this guide.
|
969
970
|
|
970
971
|
When creating a theme, all keys are optional.
|
971
972
|
Required keys are provided by the base theme.
|
@@ -1256,7 +1257,8 @@ To disable the image, use the value `none`.
|
|
1256
1257
|
These margins and used when the value `prepress` is assigned to the `media` document attribute.
|
1257
1258
|
If no cover is specified, the recto margin is not applied to the title page.
|
1258
1259
|
To apply the recto margin to the title page, but not include a cover, assign the value `~` to the `front-cover-image` attribute.
|
1259
|
-
.
|
1260
|
+
. Only works if the document uses a title page (i.e., doctype is book or `title-page` attribute is set)
|
1261
|
+
The `toc` value only applies if the toc is in the default location (before the first page of the body).
|
1260
1262
|
If the toc macro is used to position the toc, the start-at behavior is the same as if the toc is not enabled.
|
1261
1263
|
If value is an integer, page numbering will start at the specified page of the body (i.e., 1 is first page, 2 is second page, etc.)
|
1262
1264
|
|
@@ -3363,7 +3365,7 @@ The keys in this category control the arrangement of block images.
|
|
3363
3365
|
|font-style
|
3364
3366
|
|<<font-styles,Font style>> +
|
3365
3367
|
(default: normal)
|
3366
|
-
|
|
3368
|
+
|image:
|
3367
3369
|
alt:
|
3368
3370
|
font-style: italic
|
3369
3371
|
|
@@ -3382,8 +3384,9 @@ The keys in this category control the arrangement of block images.
|
|
3382
3384
|
max-width: fit-content
|
3383
3385
|
|===
|
3384
3386
|
|
3385
|
-
. Only applies to block images.
|
3386
|
-
If specified, this value takes precedence over the value of the `width` attribute on the image macro, but not over the value of the `pdfwidth`
|
3387
|
+
. Only applies to block images that don't have either a `pdfwidth` or `scaledwidth` attribute on the image macro.
|
3388
|
+
If specified, this value takes precedence over the value of the `width` attribute on the image macro, but not over the value of the `pdfwidth` or `scaledwidth` attributes.
|
3389
|
+
This key accepts the same values as the `pdfwidth` attribute.
|
3387
3390
|
. The border is only used if a border color is specified, the border width is specified, the border width is greater than 0, and the `noborder` role is not present.
|
3388
3391
|
The border is drawn above the image on the inside of the box reserved for the image.
|
3389
3392
|
. The value `auto` means the border should expand to fit the width of the container (i.e., full width) instead of the image.
|
@@ -3639,8 +3642,8 @@ The subject stop can be customized using the `subject-stop` attribute.
|
|
3639
3642
|
[source,asciidoc]
|
3640
3643
|
----
|
3641
3644
|
[unordered]
|
3642
|
-
|
3643
|
-
|
3645
|
+
alpha:: partially complete and unstable
|
3646
|
+
beta:: feature complete and undergoing testing
|
3644
3647
|
----
|
3645
3648
|
====
|
3646
3649
|
|
@@ -4135,7 +4138,7 @@ Since Asciidoctor 2, table stripes are not enabled by default (e.g., `stripes=no
|
|
4135
4138
|
[#keys-footnotes]
|
4136
4139
|
=== Footnotes
|
4137
4140
|
|
4138
|
-
The keys in this
|
4141
|
+
The keys in this category control the style of the footnotes list at the end of the chapter (book) or document (otherwise).
|
4139
4142
|
If the `footnotes-title` attribute is specified, it is styled as a block caption.
|
4140
4143
|
The styling of the links is controlled by the global link styles.
|
4141
4144
|
|
@@ -4678,7 +4681,8 @@ To avoid this problem, reduce the height of the running content periphery or mak
|
|
4678
4681
|
The `columns` key can also be defined one level up (on `header` or `footer`), in which case the setting will be inherited.
|
4679
4682
|
Where the page sides fall in relation to the physical or printed page number is controlled using the `pdf-folio-placement` attribute (except when `media=prepress`, which implies `physical`).
|
4680
4683
|
. `<position>` can be `left`, `center` or `right`.
|
4681
|
-
.
|
4684
|
+
. Only works if the document uses a title page (i.e., doctype is book or `title-page` attribute is set)
|
4685
|
+
The `toc` value only applies if the toc is in the default location (before the first page of the body).
|
4682
4686
|
If the toc macro is used to position the toc, the start-at behavior is the same as if the toc is not enabled.
|
4683
4687
|
If value is an integer, the running content will start at the specified page of the body (i.e., 1 is first page, 2 is second page, etc.)
|
4684
4688
|
|
@@ -4741,7 +4745,7 @@ footer:
|
|
4741
4745
|
----
|
4742
4746
|
|
4743
4747
|
The `&shared_footer` assigns an ID to the YAML subtree under the `recto` key and the `*shared_footer` outputs a copy of it under the `verso` key.
|
4744
|
-
This technique can be used
|
4748
|
+
This technique can be used throughout the theme file as it's a core feature of YAML.
|
4745
4749
|
|
4746
4750
|
==== Attribute References
|
4747
4751
|
|
@@ -4762,7 +4766,7 @@ This feature allows you to have alternate lines that are selected when all the a
|
|
4762
4766
|
One case where this is useful is when referencing the `page-number` attribute.
|
4763
4767
|
If you unset the `pagenums` attribute on the document, any line in the running content that makes reference to `\{page-number}` will be dropped.
|
4764
4768
|
|
4765
|
-
You can also built-in AsciiDoc text replacements like `+(C)+`, numeric character references like `+©+`,
|
4769
|
+
You can also use built-in AsciiDoc text replacements like `+(C)+`, numeric character references like `+©+`, hexadecimal character references like `+€+`, and inline formatting (e.g., bold, italic, monospace).
|
4766
4770
|
|
4767
4771
|
Here's an example that shows how attributes and replacements can be used in the running footer:
|
4768
4772
|
|
@@ -4836,7 +4840,7 @@ header:
|
|
4836
4840
|
center:
|
4837
4841
|
content: $header-recto-center-content
|
4838
4842
|
----
|
4839
|
-
<1> You can use the `image-vertical-align` key to
|
4843
|
+
<1> You can use the `image-vertical-align` key to slightly nudge the image up or down.
|
4840
4844
|
|
4841
4845
|
CAUTION: By default, the image must fit in the allotted space for the running header or footer.
|
4842
4846
|
Otherwise, you will run into layout issues.
|
@@ -5159,7 +5163,7 @@ Each style declaration accepts the following properties:
|
|
5159
5163
|
* `inline_block` - fill the background color to the height of the line (Asciidoctor PDF only)
|
5160
5164
|
* `extend` - extend the background color to the end of the line for a line-oriented match (Asciidoctor PDF only)
|
5161
5165
|
|
5162
|
-
Colors are defined using
|
5166
|
+
Colors are defined using hexadecimal format (e.g., #ff0000 for red).
|
5163
5167
|
|
5164
5168
|
Use the `Text` token to set the background color of the source block and the default text color.
|
5165
5169
|
|
@@ -5219,7 +5223,7 @@ When you override an inline element, you return pseudo-HTML, which is then parse
|
|
5219
5223
|
|
5220
5224
|
The pseudo-HTML in Asciidoctor PDF evolved from the inline formatting in Prawn, now supporting the following elements: a, br, button, code, color, del, em, font, img, key, mark, span, strong, sub, sup.
|
5221
5225
|
All decimal and hexadecimal character references are supported, as well as the named entities amp, apos, gt, lt, nbsp, and quot (e.g., `\'`).
|
5222
|
-
You can change the font color using `rgb`
|
5226
|
+
You can change the font color using the `rgb` attribute on the `color` element (e.g., `<color rgb="#ff0000">`) and the font family and size using the `name` and `size` attributes on the `font` element, respectively (e.g., `<font name="sans" size="12">`).
|
5223
5227
|
You can also use the `style` attribute on `span` to control the font color, weight, and style using the relevant CSS property names.
|
5224
5228
|
The pseudo-HTML in Asciidoctor PDF also supports the `class` attribute on any element for applying roles from the theme.
|
5225
5229
|
(Though not recommended, you can pass this pseudo-HTML straight through to Prawn using an inline passthrough in AsciiDoc).
|
@@ -5239,7 +5243,7 @@ end
|
|
5239
5243
|
----
|
5240
5244
|
|
5241
5245
|
As it stands, the converter doesn't do anything differently than the primary converter because we haven't yet overridden any of its methods.
|
5242
|
-
Let's do that now, starting by overriding the thematic break (aka
|
5246
|
+
Let's do that now, starting by overriding the thematic break (aka horizontal rule) to make it render like a ribbon:
|
5243
5247
|
|
5244
5248
|
[source,ruby]
|
5245
5249
|
----
|
@@ -5405,12 +5409,12 @@ You may need to scale the glyph so it fits properly in the art box.
|
|
5405
5409
|
IMPORTANT: If you're copying a non-visible character, be sure to set the width to 0 using menu:Metrics[Set Width...], enter 0 into *Set Width To*, then click btn:[OK].
|
5406
5410
|
|
5407
5411
|
When you're done, save the font with the old-style kern table enabled.
|
5408
|
-
To do so, select menu:File[Generate Fonts...], click btn:[Options],
|
5412
|
+
To do so, select menu:File[Generate Fonts...], select *TrueType*, click btn:[Options], make sure _only_ the following options are checked (equivalent to the flags 0x90 + 0x08):
|
5409
5413
|
|
5410
5414
|
* [x] OpenType
|
5411
5415
|
** [x] Old style 'kern'
|
5412
5416
|
|
5413
|
-
Then click btn:[Generate] to generate and save the font.
|
5417
|
+
Then click btn:[OK], then uncheck *Validate Before Saving*, and finally click btn:[Generate] to generate and save the font.
|
5414
5418
|
|
5415
5419
|
Your font file is now ready to be used with Asciidoctor PDF.
|
5416
5420
|
|
@@ -5420,5 +5424,5 @@ Performing all this font modification manually can be tedious (not to mention ha
|
|
5420
5424
|
Fortunately, FontForge provides a {url-fontforge-scripting}[scripting interface], which you can use to automate the process.
|
5421
5425
|
|
5422
5426
|
In fact, that's what we use to prepare the fonts that are bundled with Asciidoctor PDF.
|
5423
|
-
You can find that FontForge script, the Bash script that calls it, and the Docker image in which it is run in the https://github.com/asciidoctor/asciidoctor-pdf/tree/
|
5427
|
+
You can find that FontForge script, the Bash script that calls it, and the Docker image in which it is run in the https://github.com/asciidoctor/asciidoctor-pdf/tree/main/scripts[scripts directory] of this project.
|
5424
5428
|
You can use that script as a starting point or reference for your own font preparation / modification script.
|
@@ -32,7 +32,7 @@ module Asciidoctor
|
|
32
32
|
PygmentsRequirePath = ::File.join __dir__, 'ext/pygments'
|
33
33
|
OptimizerRequirePath = ::File.join __dir__, 'optimizer'
|
34
34
|
|
35
|
-
AsciidoctorVersion = ::Gem::Version.
|
35
|
+
AsciidoctorVersion = ::Gem::Version.new ::Asciidoctor::VERSION
|
36
36
|
AdmonitionIcons = {
|
37
37
|
caution: { name: 'fas-fire', stroke_color: 'BF3400', size: 24 },
|
38
38
|
important: { name: 'fas-exclamation-circle', stroke_color: 'BF0000', size: 24 },
|
@@ -92,7 +92,7 @@ module Asciidoctor
|
|
92
92
|
'circled' => (?\u2460..?\u2473).to_a,
|
93
93
|
'filled' => (?\u2776..?\u277f).to_a + (?\u24eb..?\u24f4).to_a,
|
94
94
|
}
|
95
|
-
SimpleAttributeRefRx = /(?<!\\)\{\w+(
|
95
|
+
SimpleAttributeRefRx = /(?<!\\)\{\w+(?:-\w+)*\}/
|
96
96
|
MeasurementRxt = '\\d+(?:\\.\\d+)?(?:in|cm|mm|p[txc])?'
|
97
97
|
MeasurementPartsRx = /^(\d+(?:\.\d+)?)(in|mm|cm|p[txc])?$/
|
98
98
|
PageSizeRx = /^(?:\[(#{MeasurementRxt}), ?(#{MeasurementRxt})\]|(#{MeasurementRxt})(?: x |x)(#{MeasurementRxt})|\S+)$/
|
@@ -108,6 +108,7 @@ module Asciidoctor
|
|
108
108
|
WhitespaceChars = ' ' + TAB + LF
|
109
109
|
ValueSeparatorRx = /;|,/
|
110
110
|
HexColorRx = /^#[a-fA-F0-9]{6}$/
|
111
|
+
VimeoThumbnailRx = /<thumbnail_url>(.*?)<\/thumbnail_url>/
|
111
112
|
SourceHighlighters = %w(coderay pygments rouge).to_set
|
112
113
|
ViewportWidth = ::Module.new
|
113
114
|
(TitleStyles = {
|
@@ -125,10 +126,6 @@ module Asciidoctor
|
|
125
126
|
# NOTE enabling data-uri forces Asciidoctor Diagram to produce absolute image paths
|
126
127
|
doc.attributes['data-uri'] = ((doc.instance_variable_get :@attribute_overrides) || {})['data-uri'] = ''
|
127
128
|
end
|
128
|
-
@capabilities = {
|
129
|
-
special_sectnums: AsciidoctorVersion >= (::Gem::Version.create '1.5.7'),
|
130
|
-
syntax_highlighter: AsciidoctorVersion >= (::Gem::Version.create '2.0.0'),
|
131
|
-
}
|
132
129
|
@initial_instance_variables = [:@initial_instance_variables] + instance_variables
|
133
130
|
end
|
134
131
|
|
@@ -164,9 +161,6 @@ module Asciidoctor
|
|
164
161
|
init_pdf doc
|
165
162
|
# set default value for pagenums if not otherwise set
|
166
163
|
doc.attributes['pagenums'] = '' unless (doc.attribute_locked? 'pagenums') || ((doc.instance_variable_get :@attributes_modified).include? 'pagenums')
|
167
|
-
if (idx_sect = doc.sections.find {|candidate| candidate.sectname == 'index' }) && idx_sect.numbered
|
168
|
-
idx_sect.numbered = false
|
169
|
-
end unless @capabilities[:special_sectnums]
|
170
164
|
#assign_missing_section_ids doc
|
171
165
|
|
172
166
|
# promote anonymous preface (defined using preamble block) to preface section
|
@@ -333,7 +327,7 @@ module Asciidoctor
|
|
333
327
|
# QUESTION should ThemeLoader handle registering fonts instead?
|
334
328
|
register_fonts theme.font_catalog, (doc.attr 'pdf-fontsdir', 'GEM_FONTS_DIR')
|
335
329
|
default_kerning theme.base_font_kerning != 'none'
|
336
|
-
@fallback_fonts =
|
330
|
+
@fallback_fonts = Array theme.font_fallbacks
|
337
331
|
@allow_uri_read = doc.attr? 'allow-uri-read'
|
338
332
|
@cache_uri = doc.attr? 'cache-uri'
|
339
333
|
@tmp_files = {}
|
@@ -374,7 +368,10 @@ module Asciidoctor
|
|
374
368
|
@index = IndexCatalog.new
|
375
369
|
# NOTE: we have to init Pdfmark class here while we have reference to the doc
|
376
370
|
@pdfmark = (doc.attr? 'pdfmark') ? (Pdfmark.new doc) : nil
|
377
|
-
|
371
|
+
# NOTE: defer instantiating optimizer until we know min pdf version
|
372
|
+
if (@optimize = doc.attr 'optimize')
|
373
|
+
@optimize = nil unless (defined? ::Asciidoctor::PDF::Optimizer) || !(Helpers.require_library OptimizerRequirePath, 'rghost', :warn).nil?
|
374
|
+
end
|
378
375
|
init_scratch_prototype
|
379
376
|
self
|
380
377
|
end
|
@@ -571,9 +568,10 @@ module Asciidoctor
|
|
571
568
|
# NOTE: section must have pdf-anchor in order to be listed in the TOC
|
572
569
|
sect.set_attr 'pdf-anchor', (sect_anchor = derive_anchor_from_id sect.id, %(#{start_pgnum}-#{y.ceil}))
|
573
570
|
add_dest_for_block sect, sect_anchor
|
574
|
-
|
571
|
+
case type
|
572
|
+
when :part
|
575
573
|
layout_part_title sect, title, align: align, level: hlevel
|
576
|
-
|
574
|
+
when :chapter
|
577
575
|
layout_chapter_title sect, title, align: align, level: hlevel
|
578
576
|
else
|
579
577
|
layout_heading title, align: align, level: hlevel, outdent: true
|
@@ -609,13 +607,18 @@ module Asciidoctor
|
|
609
607
|
def layout_footnotes node
|
610
608
|
return if (fns = (doc = node.document).footnotes - @footnotes).empty?
|
611
609
|
theme_margin :footnotes, :top
|
612
|
-
|
613
|
-
(
|
614
|
-
|
615
|
-
|
616
|
-
|
610
|
+
with_dry_run do |box_height = nil|
|
611
|
+
if box_height && (delta = cursor - box_height) > 0
|
612
|
+
move_down delta
|
613
|
+
end
|
614
|
+
theme_font :footnotes do
|
615
|
+
(title = doc.attr 'footnotes-title') && (layout_caption title, category: :footnotes)
|
616
|
+
item_spacing = @theme.footnotes_item_spacing
|
617
|
+
fns.each do |fn|
|
618
|
+
layout_prose %(<a id="_footnotedef_#{index = fn.index}">#{DummyText}</a>[<a anchor="_footnoteref_#{index}">#{index}</a>] #{fn.text}), margin_bottom: item_spacing, hyphenate: true
|
619
|
+
end
|
620
|
+
@footnotes += fns unless scratch?
|
617
621
|
end
|
618
|
-
@footnotes += fns
|
619
622
|
end
|
620
623
|
nil
|
621
624
|
end
|
@@ -1077,7 +1080,7 @@ module Asciidoctor
|
|
1077
1080
|
stack_subject = node.has_role? 'stack'
|
1078
1081
|
subject_stop = node.attr 'subject-stop', (stack_subject ? nil : ':'), false
|
1079
1082
|
node.items.each do |subjects, dd|
|
1080
|
-
subject =
|
1083
|
+
subject = (Array subjects).first.text
|
1081
1084
|
list_item_text = %(+++<strong>#{subject}#{(StopPunctRx.match? sanitize subject) ? '' : subject_stop}</strong>#{dd.text? ? "#{stack_subject ? '<br>' : ' '}#{dd.text}" : ''}+++)
|
1082
1085
|
list_item = ListItem.new list, list_item_text
|
1083
1086
|
dd.blocks.each {|it| list_item << it }
|
@@ -1333,8 +1336,14 @@ module Asciidoctor
|
|
1333
1336
|
marker_gap = rendered_width_of_char 'x'
|
1334
1337
|
font marker_style[:font_family], size: marker_style[:font_size] do
|
1335
1338
|
marker_width = rendered_width_of_string marker
|
1339
|
+
# NOTE compensate if character_spacing is not applied to first character
|
1340
|
+
# see https://github.com/prawnpdf/prawn/commit/c61c5d48841910aa11b9e3d6f0e01b68ce435329
|
1341
|
+
character_spacing_correction = 0
|
1342
|
+
character_spacing(-0.5) do
|
1343
|
+
character_spacing_correction = 0.5 if (rendered_width_of_char 'x', character_spacing: -0.5) == marker_gap
|
1344
|
+
end
|
1336
1345
|
marker_height = height_of_typeset_text marker, line_height: marker_style[:line_height], single_line: true
|
1337
|
-
start_position = -marker_width + -marker_gap
|
1346
|
+
start_position = -marker_width + -marker_gap + character_spacing_correction
|
1338
1347
|
float do
|
1339
1348
|
start_new_page if @media == 'prepress' && cursor < marker_height
|
1340
1349
|
flow_bounding_box start_position, width: marker_width do
|
@@ -1527,7 +1536,7 @@ module Asciidoctor
|
|
1527
1536
|
layout_caption node, category: :image, side: :bottom, block_align: alignment, block_width: rendered_w, max_width: @theme.image_caption_max_width if node.title?
|
1528
1537
|
theme_margin :block, :bottom unless pinned
|
1529
1538
|
rescue
|
1530
|
-
on_image_error :exception, node, target, (opts.merge message: %(could not embed image: #{image_path}; #{$!.message}#{::Prawn::Errors::UnsupportedImageType === $! ? '; install prawn-gmagick gem to add support' : ''}))
|
1539
|
+
on_image_error :exception, node, target, (opts.merge message: %(could not embed image: #{image_path}; #{$!.message}#{::Prawn::Errors::UnsupportedImageType === $! && !(defined? ::GMagick::Image) ? '; install prawn-gmagick gem to add support' : ''}))
|
1531
1540
|
end
|
1532
1541
|
end
|
1533
1542
|
|
@@ -1591,14 +1600,9 @@ module Asciidoctor
|
|
1591
1600
|
when 'vimeo'
|
1592
1601
|
video_path = %(https://vimeo.com/#{video_id = node.attr 'target'})
|
1593
1602
|
if allow_uri_read
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
::OpenURI
|
1598
|
-
end
|
1599
|
-
poster = ::OpenURI.open_uri %(http://vimeo.com/api/v2/video/#{video_id}.xml), 'r' do |f|
|
1600
|
-
/<thumbnail_large>(.*?)<\/thumbnail_large>/ =~ f.read && $1
|
1601
|
-
end
|
1603
|
+
poster = load_open_uri.open_uri(%(https://vimeo.com/api/oembed.xml?url=https%3A//vimeo.com/#{video_id}&width=1280), 'r') {|f| (VimeoThumbnailRx.match f.read)[1] } rescue nil
|
1604
|
+
else
|
1605
|
+
poster = nil
|
1602
1606
|
end
|
1603
1607
|
type = 'Vimeo video'
|
1604
1608
|
else
|
@@ -1630,9 +1634,7 @@ module Asciidoctor
|
|
1630
1634
|
add_dest_for_block node if node.id
|
1631
1635
|
|
1632
1636
|
# HACK: disable built-in syntax highlighter; must be done before calling node.content!
|
1633
|
-
if node.style == 'source' && (highlighter =
|
1634
|
-
(syntax_hl = node.document.syntax_highlighter) && syntax_hl.highlight? && syntax_hl.name :
|
1635
|
-
(highlighter = node.document.attributes['source-highlighter']) && (SourceHighlighters.include? highlighter) && highlighter)
|
1637
|
+
if node.style == 'source' && (highlighter = (syntax_hl = node.document.syntax_highlighter)&.highlight? && syntax_hl.name)
|
1636
1638
|
case highlighter
|
1637
1639
|
when 'coderay'
|
1638
1640
|
unless defined? ::Asciidoctor::Prawn::CodeRayEncoder
|
@@ -1702,7 +1704,7 @@ module Asciidoctor
|
|
1702
1704
|
# NOTE: highlight can return nil if something goes wrong; fallback to encoded source string if this happens
|
1703
1705
|
result = (lexer.highlight source_string, options: lexer_opts) || (node.apply_subs source_string, [:specialcharacters])
|
1704
1706
|
if node.attr? 'highlight', nil, false
|
1705
|
-
if (highlight_lines = (node.method :resolve_lines_to_highlight).arity > 1 ?
|
1707
|
+
if (highlight_lines = (node.method :resolve_lines_to_highlight).arity.abs > 1 ?
|
1706
1708
|
(node.resolve_lines_to_highlight source_string, (node.attr 'highlight')) :
|
1707
1709
|
(node.resolve_lines_to_highlight node.attr 'highlight')).empty?
|
1708
1710
|
highlight_lines = nil
|
@@ -1750,7 +1752,7 @@ module Asciidoctor
|
|
1750
1752
|
lexer ||= ::Rouge::Lexers::PlainText
|
1751
1753
|
source_string, conum_mapping = extract_conums source_string
|
1752
1754
|
if node.attr? 'highlight', nil, false
|
1753
|
-
unless (hl_lines = (node.method :resolve_lines_to_highlight).arity > 1 ?
|
1755
|
+
unless (hl_lines = (node.method :resolve_lines_to_highlight).arity.abs > 1 ?
|
1754
1756
|
(node.resolve_lines_to_highlight source_string, (node.attr 'highlight')) :
|
1755
1757
|
(node.resolve_lines_to_highlight node.attr 'highlight')).empty?
|
1756
1758
|
formatter_opts[:highlight_lines] = hl_lines.map {|linenum| [linenum, true] }.to_h
|
@@ -1853,7 +1855,10 @@ module Asciidoctor
|
|
1853
1855
|
line << fragment
|
1854
1856
|
end
|
1855
1857
|
end
|
1856
|
-
|
1858
|
+
conum_font_color = @theme.conum_font_color
|
1859
|
+
if (conum_font_name = @theme.conum_font_family) == font_name
|
1860
|
+
conum_font_name = nil
|
1861
|
+
end
|
1857
1862
|
last_line_num = lines.size - 1
|
1858
1863
|
if linenums
|
1859
1864
|
pad_size = (last_line_num + 1).to_s.length
|
@@ -1870,7 +1875,10 @@ module Asciidoctor
|
|
1870
1875
|
if conum_mapping && (conums = conum_mapping.delete cur_line_num)
|
1871
1876
|
line << { text: conums.shift } if ::String === conums[0]
|
1872
1877
|
conum_text = conums.map {|num| conum_glyph num }.join ' '
|
1873
|
-
|
1878
|
+
conum_fragment = { text: conum_text }
|
1879
|
+
conum_fragment[:color] = conum_font_color if conum_font_color
|
1880
|
+
conum_fragment[:font] = conum_font_name if conum_font_name
|
1881
|
+
line << conum_fragment
|
1874
1882
|
end
|
1875
1883
|
line << { text: LF } unless last_line
|
1876
1884
|
line
|
@@ -2040,7 +2048,7 @@ module Asciidoctor
|
|
2040
2048
|
end
|
2041
2049
|
unless cell_data.key? :content
|
2042
2050
|
cell_text = cell.text.strip
|
2043
|
-
cell_text = transform_text cell_text if cell_transform
|
2051
|
+
cell_text = transform_text cell_text, cell_transform if cell_transform
|
2044
2052
|
cell_text = hyphenate_text cell_text, @hyphenator if defined? @hyphenator
|
2045
2053
|
cell_text = cell_text.gsub CjkLineBreakRx, ZeroWidthSpace if @cjk_line_breaks
|
2046
2054
|
if cell_text.include? LF
|
@@ -2115,10 +2123,6 @@ module Asciidoctor
|
|
2115
2123
|
else
|
2116
2124
|
table_width = bounds.width * ((node.attr 'tablepcwidth') / 100.0)
|
2117
2125
|
column_widths = node.columns.map {|col| ((col.attr 'colpcwidth') * table_width) / 100.0 }
|
2118
|
-
# NOTE: until Asciidoctor 1.5.4, colpcwidth values didn't always add up to 100%; use last column to compensate
|
2119
|
-
unless column_widths.empty? || (width_delta = table_width - column_widths.sum) == 0
|
2120
|
-
column_widths[-1] += width_delta
|
2121
|
-
end
|
2122
2126
|
end
|
2123
2127
|
|
2124
2128
|
if ((alignment = node.attr 'align', nil, false) && (BlockAlignmentNames.include? alignment)) ||
|
@@ -2349,7 +2353,7 @@ module Asciidoctor
|
|
2349
2353
|
bare_target = target
|
2350
2354
|
text = node.text
|
2351
2355
|
end
|
2352
|
-
if (role = node.attr 'role', nil, false) && (role == 'bare' || (
|
2356
|
+
if (role = node.attr 'role', nil, false) && (role == 'bare' || (role.split.include? 'bare'))
|
2353
2357
|
# QUESTION should we insert breakable chars into URI when building fragment instead?
|
2354
2358
|
%(<a href="#{target}"#{attrs.join}>#{breakable_uri text}</a>)
|
2355
2359
|
# NOTE @media may not be initialized if method is called before convert phase
|
@@ -2368,13 +2372,8 @@ module Asciidoctor
|
|
2368
2372
|
%(<a href="#{target}">#{node.text || path}</a>)
|
2369
2373
|
elsif (refid = node.attributes['refid'])
|
2370
2374
|
unless (text = node.text)
|
2371
|
-
if (
|
2372
|
-
|
2373
|
-
text = ref.xreftext node.attr 'xrefstyle', nil, true
|
2374
|
-
end
|
2375
|
-
else
|
2376
|
-
# Asciidoctor < 1.5.6
|
2377
|
-
text = doc.catalog[:ids][refid]
|
2375
|
+
if ::Asciidoctor::AbstractNode === (ref = doc.catalog[:refs][refid])
|
2376
|
+
text = ref.xreftext node.attr 'xrefstyle', nil, true
|
2378
2377
|
end
|
2379
2378
|
end
|
2380
2379
|
%(<a anchor="#{derive_anchor_from_id refid}">#{text || "[#{refid}]"}</a>).gsub ']', ']'
|
@@ -2410,12 +2409,16 @@ module Asciidoctor
|
|
2410
2409
|
end
|
2411
2410
|
|
2412
2411
|
def convert_inline_callout node
|
2413
|
-
if (
|
2414
|
-
|
2415
|
-
%(<color rgb="#{conum_color}">#{conum_glyph node.text.to_i}</color>)
|
2412
|
+
if (conum_font_family = @theme.conum_font_family) == font_name
|
2413
|
+
result = conum_glyph node.text.to_i
|
2416
2414
|
else
|
2417
|
-
conum_glyph node.text.to_i
|
2415
|
+
result = %(<font name="#{conum_font_family}">#{conum_glyph node.text.to_i}</font>)
|
2418
2416
|
end
|
2417
|
+
if (conum_font_color = @theme.conum_font_color)
|
2418
|
+
# NOTE CMYK value gets flattened here, but is restored by formatted text parser
|
2419
|
+
result = %(<color rgb="#{conum_font_color}">#{result}</font>)
|
2420
|
+
end
|
2421
|
+
result
|
2419
2422
|
end
|
2420
2423
|
|
2421
2424
|
def convert_inline_footnote node
|
@@ -2501,7 +2504,7 @@ module Asciidoctor
|
|
2501
2504
|
if ::File.readable? image_path
|
2502
2505
|
width_attr = (width = preresolve_explicit_width node.attributes) ? %( width="#{width}") : ''
|
2503
2506
|
fit_attr = (fit = node.attr 'fit', nil, false) ? %( fit="#{fit}") : ''
|
2504
|
-
img = %(<img src="#{image_path}" format="#{image_format}" alt="
|
2507
|
+
img = %(<img src="#{image_path}" format="#{image_format}" alt="#{encode_quotes node.attr 'alt'}"#{width_attr}#{fit_attr}>)
|
2505
2508
|
else
|
2506
2509
|
logger.warn %(image to embed not found or not readable: #{image_path}) unless scratch?
|
2507
2510
|
img = %([#{node.attr 'alt'}])
|
@@ -2889,8 +2892,8 @@ module Asciidoctor
|
|
2889
2892
|
if opts.delete :dry_run
|
2890
2893
|
height = nil
|
2891
2894
|
dry_run do
|
2892
|
-
move_down
|
2893
|
-
height =
|
2895
|
+
move_down 0.001 # HACK: force top margin to be applied
|
2896
|
+
height = layout_caption subject, opts
|
2894
2897
|
end
|
2895
2898
|
return height
|
2896
2899
|
end
|
@@ -3421,12 +3424,12 @@ module Asciidoctor
|
|
3421
3424
|
end
|
3422
3425
|
tot_width = 0
|
3423
3426
|
side_colspecs = colspecs.map {|col, spec|
|
3424
|
-
if (alignment_char = spec.chr).to_i.to_s
|
3425
|
-
alignment = AlignmentTable[alignment_char] || :left
|
3426
|
-
rel_width = (spec.slice 1, spec.length).to_f
|
3427
|
-
else
|
3427
|
+
if (alignment_char = spec.chr).to_i.to_s == alignment_char
|
3428
3428
|
alignment = :left
|
3429
3429
|
rel_width = spec.to_f
|
3430
|
+
else
|
3431
|
+
alignment = AlignmentTable[alignment_char] || :left
|
3432
|
+
rel_width = (spec.slice 1, spec.length).to_f
|
3430
3433
|
end
|
3431
3434
|
tot_width += rel_width
|
3432
3435
|
[col, { align: alignment, width: rel_width, x: 0 }]
|
@@ -3583,13 +3586,13 @@ module Asciidoctor
|
|
3583
3586
|
|
3584
3587
|
def write pdf_doc, target
|
3585
3588
|
if target.respond_to? :write
|
3586
|
-
target = ::QuantifiableStdout.new
|
3589
|
+
target = ::QuantifiableStdout.new $stdout if target == $stdout
|
3587
3590
|
pdf_doc.render target
|
3588
3591
|
else
|
3589
3592
|
pdf_doc.render_file target
|
3590
3593
|
# QUESTION restore attributes first?
|
3591
3594
|
@pdfmark&.generate_file target
|
3592
|
-
(Optimizer.new @optimize, pdf_doc.min_version).
|
3595
|
+
(Optimizer.new @optimize, pdf_doc.min_version).optimize_file target if @optimize
|
3593
3596
|
end
|
3594
3597
|
# write scratch document if debug is enabled (or perhaps DEBUG_STEPS env)
|
3595
3598
|
#get_scratch_document.render_file 'scratch.pdf'
|
@@ -3694,7 +3697,7 @@ module Asciidoctor
|
|
3694
3697
|
end
|
3695
3698
|
# FIXME: due to the calculation error logged in #789, we must advance page even when content is split across pages
|
3696
3699
|
advance_page if (opts.fetch :split_from_top, true) && block_height > cursor && !at_page_top?
|
3697
|
-
caption_height = (node = opts[:caption_node]) && node.title? ? (layout_caption node, category: category)
|
3700
|
+
caption_height = (node = opts[:caption_node]) && node.title? ? (layout_caption node, category: category) : 0
|
3698
3701
|
float do
|
3699
3702
|
remaining_height = block_height - caption_height
|
3700
3703
|
initial_page = true
|
@@ -4081,24 +4084,22 @@ module Asciidoctor
|
|
4081
4084
|
unlink_tmp_file tmp_image.path
|
4082
4085
|
nil
|
4083
4086
|
end
|
4084
|
-
#
|
4085
|
-
elsif
|
4086
|
-
|
4087
|
-
|
4087
|
+
# NOTE: this will catch a classloader resource path on JRuby (e.g., uri:classloader:/path/to/image)
|
4088
|
+
elsif ::File.absolute_path? image_path
|
4089
|
+
::File.absolute_path image_path
|
4090
|
+
elsif !(is_uri = node.is_uri? image_path) && imagesdir && (::File.absolute_path? imagesdir)
|
4091
|
+
::File.absolute_path image_path, imagesdir
|
4092
|
+
elsif is_uri || (imagesdir && (node.is_uri? imagesdir) && (image_path = node.normalize_web_path image_path, imagesdir, false))
|
4093
|
+
if !allow_uri_read
|
4088
4094
|
logger.warn %(allow-uri-read is not enabled; cannot embed remote image: #{image_path}) unless scratch?
|
4089
4095
|
return
|
4090
|
-
|
4091
|
-
if @tmp_files.key? image_path
|
4096
|
+
elsif @tmp_files.key? image_path
|
4092
4097
|
return @tmp_files[image_path]
|
4093
|
-
elsif cache_uri
|
4094
|
-
Helpers.require_library 'open-uri/cached', 'open-uri-cached' unless defined? ::OpenURI::Cache
|
4095
|
-
else
|
4096
|
-
::OpenURI
|
4097
4098
|
end
|
4098
4099
|
tmp_image = ::Tempfile.create ['image-', image_format && %(.#{image_format})]
|
4099
4100
|
tmp_image.binmode if (binary = image_format != 'svg')
|
4100
4101
|
begin
|
4101
|
-
|
4102
|
+
load_open_uri.open_uri(image_path, (binary ? 'rb' : 'r')) {|fd| tmp_image.write fd.read }
|
4102
4103
|
tmp_image.close
|
4103
4104
|
@tmp_files[image_path] = tmp_image.path
|
4104
4105
|
rescue
|
@@ -4285,11 +4286,12 @@ module Asciidoctor
|
|
4285
4286
|
result = {}
|
4286
4287
|
center = nil
|
4287
4288
|
(value.split ' ', 2).each do |keyword|
|
4288
|
-
|
4289
|
+
case keyword
|
4290
|
+
when 'left', 'right'
|
4289
4291
|
result[:position] = keyword.to_sym
|
4290
|
-
|
4292
|
+
when 'top', 'bottom'
|
4291
4293
|
result[:vposition] = keyword.to_sym
|
4292
|
-
|
4294
|
+
when 'center'
|
4293
4295
|
center = true
|
4294
4296
|
end
|
4295
4297
|
end
|
@@ -4348,6 +4350,14 @@ module Asciidoctor
|
|
4348
4350
|
link_annotation [image_x, (image_y - image_height), (image_x + image_width), image_y], Border: [0, 0, 0], A: { Type: :Action, S: :URI, URI: uri.as_pdf }
|
4349
4351
|
end
|
4350
4352
|
|
4353
|
+
def load_open_uri
|
4354
|
+
if @cache_uri && !(defined? ::OpenURI::Cache)
|
4355
|
+
# disable URI caching if library fails to load
|
4356
|
+
@cache_uri = false if (Helpers.require_library 'open-uri/cached', 'open-uri-cached', :warn).nil?
|
4357
|
+
end
|
4358
|
+
::OpenURI
|
4359
|
+
end
|
4360
|
+
|
4351
4361
|
def remove_tmp_files
|
4352
4362
|
@tmp_files.reject! {|_, path| path ? (unlink_tmp_file path) : true }
|
4353
4363
|
end
|