asciidoctor-pdf 2.0.0.alpha.1 → 2.0.0.beta.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 +94 -1
- data/README.adoc +32 -14
- 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 +11 -20
- data/data/themes/default-theme.yml +8 -7
- data/docs/theming-guide.adoc +11 -10
- data/lib/asciidoctor/pdf/converter.rb +445 -305
- data/lib/asciidoctor/pdf/ext/asciidoctor/document.rb +4 -0
- data/lib/asciidoctor/pdf/ext/pdf-core/page.rb +8 -0
- data/lib/asciidoctor/pdf/ext/prawn/extensions.rb +117 -38
- data/lib/asciidoctor/pdf/ext/prawn/formatted_text/box.rb +5 -0
- data/lib/asciidoctor/pdf/ext/prawn/formatted_text/protect_bottom_gutter.rb +13 -0
- data/lib/asciidoctor/pdf/ext/prawn/images.rb +6 -2
- data/lib/asciidoctor/pdf/ext/prawn-table/cell/asciidoc.rb +1 -1
- data/lib/asciidoctor/pdf/ext/prawn.rb +1 -0
- data/lib/asciidoctor/pdf/formatted_text/transform.rb +7 -2
- data/lib/asciidoctor/pdf/nogmagick.rb +6 -0
- 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 +19 -3
- data/lib/asciidoctor/pdf/version.rb +1 -1
- metadata +5 -2
@@ -11,6 +11,10 @@ class Asciidoctor::Document
|
|
11
11
|
preface.sectname = 'preface'
|
12
12
|
preface.title = blk0.instance_variable_get :@title
|
13
13
|
preface.id = preface.generate_id
|
14
|
+
if (first_child = blk0.blocks[0])&.option? 'notitle'
|
15
|
+
preface.set_option 'notitle'
|
16
|
+
first_child.role = 'lead' if first_child.context == :paragraph && !first_child.role?
|
17
|
+
end
|
14
18
|
preface.blocks.replace (blk0.blocks.map do |b|
|
15
19
|
b.parent = preface
|
16
20
|
b
|
@@ -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
|
@@ -538,25 +554,34 @@ module Asciidoctor
|
|
538
554
|
# Example:
|
539
555
|
#
|
540
556
|
# pad_box 20 do
|
541
|
-
# text 'A paragraph inside a blox with even padding
|
557
|
+
# text 'A paragraph inside a blox with even padding from all edges.'
|
558
|
+
# end
|
559
|
+
#
|
560
|
+
# pad_box [10, 5] do
|
561
|
+
# text 'A paragraph inside a box with different padding from ends and sides.'
|
542
562
|
# end
|
543
563
|
#
|
544
|
-
# pad_box [
|
545
|
-
# text '
|
564
|
+
# pad_box [5, 10, 15, 20] do
|
565
|
+
# text 'A paragraph inside a box with different padding from each edge.'
|
546
566
|
# end
|
547
567
|
#
|
548
|
-
def pad_box padding
|
568
|
+
def pad_box padding, node = nil
|
549
569
|
if padding
|
550
|
-
|
551
|
-
|
570
|
+
p_top, p_right, p_bottom, p_left = expand_padding_value padding
|
571
|
+
# logic is intentionally inlined
|
552
572
|
begin
|
553
|
-
|
573
|
+
if node && ((last_block = node).content_model != :compound || (last_block = node.blocks[-1])&.context == :paragraph)
|
574
|
+
@bottom_gutters << { last_block => p_bottom }
|
575
|
+
else
|
576
|
+
@bottom_gutters << {}
|
577
|
+
end
|
554
578
|
move_down p_top
|
555
579
|
bounds.add_left_padding p_left
|
556
580
|
bounds.add_right_padding p_right
|
557
581
|
yield
|
558
|
-
cursor > p_bottom ? (move_down p_bottom) : reference_bounds.move_past_bottom unless at_page_top?
|
559
582
|
ensure
|
583
|
+
cursor > p_bottom ? (move_down p_bottom) : reference_bounds.move_past_bottom unless at_page_top?
|
584
|
+
@bottom_gutters.pop
|
560
585
|
bounds.subtract_left_padding p_left
|
561
586
|
bounds.subtract_right_padding p_right
|
562
587
|
end
|
@@ -570,30 +595,73 @@ module Asciidoctor
|
|
570
595
|
end
|
571
596
|
|
572
597
|
def expand_padding_value shorthand
|
573
|
-
|
574
|
-
if ::Array ===
|
575
|
-
case
|
598
|
+
(@edge_shorthand_cache ||= ::Hash.new do |store, key|
|
599
|
+
if ::Array === key
|
600
|
+
case key.size
|
576
601
|
when 1
|
577
|
-
|
602
|
+
value = [(value0 = key[0] || 0), value0, value0, value0]
|
578
603
|
when 2
|
579
|
-
|
604
|
+
value = [(value0 = key[0] || 0), (value1 = key[1] || 0), value0, value1]
|
580
605
|
when 3
|
581
|
-
|
606
|
+
value = [key[0] || 0, (value1 = key[1] || 0), key[2] || 0, value1]
|
582
607
|
when 4
|
583
|
-
|
608
|
+
value = key.map {|it| it || 0 }
|
584
609
|
else
|
585
|
-
|
610
|
+
value = (key.slice 0, 4).map {|it| it || 0 }
|
586
611
|
end
|
587
612
|
else
|
588
|
-
|
613
|
+
value = [(value0 = key || 0), value0, value0, value0]
|
589
614
|
end
|
590
|
-
|
591
|
-
end
|
592
|
-
padding.dup
|
615
|
+
store[key] = value
|
616
|
+
end)[shorthand]
|
593
617
|
end
|
594
618
|
|
595
619
|
alias expand_margin_value expand_padding_value
|
596
620
|
|
621
|
+
def expand_grid_values shorthand, default = nil
|
622
|
+
if ::Array === shorthand
|
623
|
+
case shorthand.size
|
624
|
+
when 1
|
625
|
+
[(value0 = shorthand[0] || default), value0]
|
626
|
+
when 2
|
627
|
+
shorthand.map {|it| it || default }
|
628
|
+
when 4
|
629
|
+
if Asciidoctor::PDF::ThemeLoader::CMYKColorValue === shorthand
|
630
|
+
[shorthand, shorthand]
|
631
|
+
else
|
632
|
+
(shorthand.slice 0, 2).map {|it| it || default }
|
633
|
+
end
|
634
|
+
else
|
635
|
+
(shorthand.slice 0, 2).map {|it| it || default }
|
636
|
+
end
|
637
|
+
else
|
638
|
+
[(value0 = shorthand || default), value0]
|
639
|
+
end
|
640
|
+
end
|
641
|
+
|
642
|
+
def expand_rect_values shorthand, default = nil
|
643
|
+
if ::Array === shorthand
|
644
|
+
case shorthand.size
|
645
|
+
when 1
|
646
|
+
[(value0 = shorthand[0] || default), value0, value0, value0]
|
647
|
+
when 2
|
648
|
+
[(value0 = shorthand[0] || default), (value1 = shorthand[1] || default), value0, value1]
|
649
|
+
when 3
|
650
|
+
[shorthand[0] || default, (value1 = shorthand[1] || default), shorthand[2] || default, value1]
|
651
|
+
when 4
|
652
|
+
if Asciidoctor::PDF::ThemeLoader::CMYKColorValue === shorthand
|
653
|
+
[shorthand, shorthand, shorthand, shorthand]
|
654
|
+
else
|
655
|
+
shorthand.map {|it| it || default }
|
656
|
+
end
|
657
|
+
else
|
658
|
+
(shorthand.slice 0, 4).map {|it| it || default }
|
659
|
+
end
|
660
|
+
else
|
661
|
+
[(value0 = shorthand || default), value0, value0, value0]
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
597
665
|
# Stretch the current bounds to the left and right edges of the current page
|
598
666
|
# while yielding the specified block if the verdict argument is true.
|
599
667
|
# Otherwise, simply yield the specified block.
|
@@ -650,7 +718,8 @@ module Asciidoctor
|
|
650
718
|
def fill_and_stroke_bounds f_color = fill_color, s_color = stroke_color, options = {}
|
651
719
|
no_fill = !f_color || f_color == 'transparent'
|
652
720
|
if ::Array === (s_width = options[:line_width] || 0)
|
653
|
-
|
721
|
+
s_width = [s_width[0], s_width[1], s_width[0], s_width[1]] if s_width.size == 2
|
722
|
+
s_width_max = (s_width = s_width.map {|it| it || 0 }).max
|
654
723
|
radius = 0
|
655
724
|
else
|
656
725
|
radius = options[:radius] || 0
|
@@ -668,13 +737,19 @@ module Asciidoctor
|
|
668
737
|
|
669
738
|
# stroke
|
670
739
|
if s_width_max
|
671
|
-
|
672
|
-
|
673
|
-
|
740
|
+
s_width_top, s_width_right, s_width_bottom, s_width_left = s_width
|
741
|
+
projection_top, projection_right, projection_bottom, projection_left = s_width.map {|it| it * 0.5 }
|
742
|
+
if s_width_top > 0
|
743
|
+
stroke_horizontal_rule s_color, line_width: s_width_top, line_style: options[:line_style], left_projection: projection_left, right_projection: projection_right
|
744
|
+
end
|
745
|
+
if s_width_right > 0
|
746
|
+
stroke_vertical_rule s_color, line_width: s_width_right, line_style: options[:line_style], at: bounds.width, top_projection: projection_top, bottom_projection: projection_bottom
|
747
|
+
end
|
748
|
+
if s_width_bottom > 0
|
749
|
+
stroke_horizontal_rule s_color, line_width: s_width_bottom, line_style: options[:line_style], at: bounds.height, left_projection: projection_left, right_projection: projection_right
|
674
750
|
end
|
675
|
-
if
|
676
|
-
stroke_vertical_rule s_color, line_width:
|
677
|
-
stroke_vertical_rule s_color, line_width: s_width_side, line_style: options[:line_style], at: bounds.width
|
751
|
+
if s_width_left > 0
|
752
|
+
stroke_vertical_rule s_color, line_width: s_width_left, line_style: options[:line_style], top_projection: projection_top, bottom_projection: projection_bottom
|
678
753
|
end
|
679
754
|
else
|
680
755
|
stroke_color s_color
|
@@ -709,8 +784,8 @@ module Asciidoctor
|
|
709
784
|
rule_y = cursor - (options[:at] || 0)
|
710
785
|
rule_style = options[:line_style]
|
711
786
|
rule_width = options[:line_width] || 0.5
|
712
|
-
rule_x_start = bounds.left
|
713
|
-
rule_x_end = bounds.right
|
787
|
+
rule_x_start = bounds.left - (options[:left_projection] || 0)
|
788
|
+
rule_x_end = bounds.right - (options[:right_projection] || 0)
|
714
789
|
save_graphics_state do
|
715
790
|
stroke_color rule_color
|
716
791
|
case rule_style
|
@@ -740,8 +815,8 @@ module Asciidoctor
|
|
740
815
|
#
|
741
816
|
def stroke_vertical_rule rule_color = stroke_color, options = {}
|
742
817
|
rule_x = options[:at] || 0
|
743
|
-
rule_y_from = bounds.top
|
744
|
-
rule_y_to = bounds.bottom
|
818
|
+
rule_y_from = bounds.top + (options[:top_projection] || 0)
|
819
|
+
rule_y_to = bounds.bottom - (options[:bottom_projection] || 0)
|
745
820
|
rule_style = options[:line_style]
|
746
821
|
rule_width = options[:line_width] || 0.5
|
747
822
|
save_graphics_state do
|
@@ -764,10 +839,15 @@ module Asciidoctor
|
|
764
839
|
|
765
840
|
# Deletes the current page and move the cursor
|
766
841
|
# to the previous page.
|
767
|
-
def
|
842
|
+
def delete_current_page
|
768
843
|
pg = page_number
|
769
844
|
pdf_store = state.store
|
770
845
|
content_id = page.content.identifier
|
846
|
+
page_ref = page.dictionary
|
847
|
+
(prune_dests = proc do |node|
|
848
|
+
node.children.delete_if {|it| ::PDF::Core::NameTree::Node === it ? prune_dests[it] : it.value.data[0] == page_ref }
|
849
|
+
false
|
850
|
+
end)[dests.data]
|
771
851
|
# NOTE: cannot delete objects and IDs, otherwise references get corrupted; so just reset the value
|
772
852
|
(pdf_store.instance_variable_get :@objects)[content_id] = ::PDF::Core::Reference.new content_id, {}
|
773
853
|
pdf_store.pages.data[:Kids].pop
|
@@ -793,7 +873,7 @@ module Asciidoctor
|
|
793
873
|
prev_page_size = page.size
|
794
874
|
state.compress = false if state.compress # can't use compression if using template
|
795
875
|
prev_text_rendering_mode = (defined? @text_rendering_mode) ? @text_rendering_mode : nil
|
796
|
-
|
876
|
+
delete_current_page if options[:replace]
|
797
877
|
# NOTE: use functionality provided by prawn-templates
|
798
878
|
start_new_page_discretely template: file, template_page: options[:page]
|
799
879
|
# prawn-templates sets text_rendering_mode to :unknown, which breaks running content; revert
|
@@ -805,11 +885,11 @@ module Asciidoctor
|
|
805
885
|
# way atm to prevent the size & layout of the imported page from affecting subsequent pages
|
806
886
|
advance_page size: prev_page_size, layout: prev_page_layout if options.fetch :advance, true
|
807
887
|
elsif options.fetch :advance_if_missing, true
|
808
|
-
|
888
|
+
delete_current_page
|
809
889
|
# NOTE: see previous comment
|
810
890
|
advance_page size: prev_page_size, layout: prev_page_layout
|
811
891
|
else
|
812
|
-
|
892
|
+
delete_current_page
|
813
893
|
end
|
814
894
|
nil
|
815
895
|
end
|
@@ -866,7 +946,6 @@ module Asciidoctor
|
|
866
946
|
def scratch?
|
867
947
|
@label == :scratch
|
868
948
|
end
|
869
|
-
alias is_scratch? scratch?
|
870
949
|
|
871
950
|
def with_dry_run &block
|
872
951
|
yield dry_run(&block).position_onto self, cursor
|
@@ -6,6 +6,11 @@ Prawn::Text::Formatted::Box.prepend (Module.new do
|
|
6
6
|
def initialize formatted_text, options = {}
|
7
7
|
super
|
8
8
|
formatted_text[0][:normalize_line_height] = true if options[:normalize_line_height] && !formatted_text.empty?
|
9
|
+
options[:extensions]&.each {|extension| extend extension }
|
10
|
+
if (bottom_gutter = options[:bottom_gutter]) && bottom_gutter > 0
|
11
|
+
@bottom_gutter = bottom_gutter
|
12
|
+
extend Prawn::Text::Formatted::ProtectBottomGutter
|
13
|
+
end
|
9
14
|
end
|
10
15
|
|
11
16
|
def draw_fragment_overlay_styles fragment
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Prawn::Text::Formatted::ProtectBottomGutter
|
4
|
+
def enough_height_for_this_line?
|
5
|
+
return super unless @arranger.finished?
|
6
|
+
begin
|
7
|
+
@height -= @bottom_gutter
|
8
|
+
super
|
9
|
+
ensure
|
10
|
+
@height += @bottom_gutter
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -13,14 +13,18 @@ module Asciidoctor
|
|
13
13
|
#opts[:cache_images] = cache_uri if !(opts.key? :cache_images) && (respond_to? :cache_uri)
|
14
14
|
#opts[:fallback_font_name] = fallback_svg_font_name if !(opts.key? :fallback_font_name) && (respond_to? :fallback_svg_font_name)
|
15
15
|
if (fit = opts.delete :fit) && !(opts[:width] || opts[:height])
|
16
|
-
svg (::File.read file, mode: 'r:UTF-8'), opts do |svg_doc|
|
16
|
+
image_info = svg (::File.read file, mode: 'r:UTF-8'), opts do |svg_doc|
|
17
17
|
# NOTE: fit to specified width, then reduce size if height exceeds bounds
|
18
18
|
svg_doc.calculate_sizing requested_width: fit[0] if svg_doc.sizing.output_width != fit[0]
|
19
19
|
svg_doc.calculate_sizing requested_height: fit[1] if svg_doc.sizing.output_height > fit[1]
|
20
20
|
end
|
21
21
|
else
|
22
|
-
svg (::File.read file, mode: 'r:UTF-8'), opts
|
22
|
+
image_info = svg (::File.read file, mode: 'r:UTF-8'), opts
|
23
23
|
end
|
24
|
+
if ::Asciidoctor::Logging === self && !scratch? && !(warnings = image_info[:warnings]).empty?
|
25
|
+
warnings.each {|warning| log :warn, %(problem encountered in image: #{file}; #{warning}) }
|
26
|
+
end
|
27
|
+
image_info
|
24
28
|
else
|
25
29
|
::File.open(file, 'rb') {|fd| super fd, opts }
|
26
30
|
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
|
@@ -7,4 +7,5 @@ require_relative 'prawn/images'
|
|
7
7
|
require_relative 'prawn/formatted_text/arranger'
|
8
8
|
require_relative 'prawn/formatted_text/box'
|
9
9
|
require_relative 'prawn/formatted_text/fragment'
|
10
|
+
require_relative 'prawn/formatted_text/protect_bottom_gutter'
|
10
11
|
require_relative 'prawn/extensions'
|
@@ -156,14 +156,19 @@ module Asciidoctor
|
|
156
156
|
if (pcdata = node[:pcdata]).empty?
|
157
157
|
# QUESTION: should this be handled by the formatter after the transform is complete?
|
158
158
|
if previous_fragment_is_text && ((previous_fragment_text = fragments[-1][:text]).end_with? ' ')
|
159
|
-
fragments[-1][:text] = previous_fragment_text.
|
159
|
+
fragments[-1][:text] = previous_fragment_text.chop
|
160
160
|
end
|
161
161
|
else
|
162
162
|
tag_name = node[:name]
|
163
163
|
attributes = node[:attributes]
|
164
164
|
parent = clone_fragment inherited
|
165
|
+
fragment = build_fragment parent, tag_name, attributes
|
166
|
+
if tag_name == :a && fragment[:type] == :indexterm && !attributes[:visible] &&
|
167
|
+
previous_fragment_is_text && ((previous_fragment_text = fragments[-1][:text]).end_with? ' ')
|
168
|
+
fragments[-1][:text] = previous_fragment_text.chop
|
169
|
+
end
|
165
170
|
# NOTE: decorate child fragments with inherited properties from this element
|
166
|
-
apply pcdata, fragments,
|
171
|
+
apply pcdata, fragments, fragment
|
167
172
|
previous_fragment_is_text = false
|
168
173
|
end
|
169
174
|
# case 2: void element
|
@@ -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,6 +15,10 @@ 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
|
+
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
|
+
accum[%(#{prefix}_align)] = %(#{prefix}_text_align)
|
20
|
+
end
|
21
|
+
PaddingBottomHackKeys = %w(example_padding quote_padding sidebar_padding verse_padding)
|
18
22
|
|
19
23
|
VariableRx = /\$([a-z0-9_-]+)/
|
20
24
|
LoneVariableRx = /^\$([a-z0-9_-]+)$/
|
@@ -22,6 +26,7 @@ module Asciidoctor
|
|
22
26
|
MultiplyDivideOpRx = %r((-?\d+(?:\.\d+)?) +([*/^]) +(-?\d+(?:\.\d+)?))
|
23
27
|
AddSubtractOpRx = /(-?\d+(?:\.\d+)?) +([+\-]) +(-?\d+(?:\.\d+)?)/
|
24
28
|
PrecisionFuncRx = /^(round|floor|ceil)\(/
|
29
|
+
RoleAlignKeyRx = /(?:_text)?_align$/
|
25
30
|
|
26
31
|
module ColorValue; end
|
27
32
|
|
@@ -77,7 +82,7 @@ module Asciidoctor
|
|
77
82
|
else
|
78
83
|
theme_data = load_file theme_path, nil, theme_dir
|
79
84
|
unless (::File.dirname theme_path) == ThemesDir
|
80
|
-
theme_data.
|
85
|
+
theme_data.base_text_align ||= 'left'
|
81
86
|
theme_data.base_line_height ||= 1
|
82
87
|
theme_data.base_font_color ||= '000000'
|
83
88
|
theme_data.code_font_family ||= (theme_data.codespan_font_family || 'Courier')
|
@@ -166,9 +171,19 @@ module Asciidoctor
|
|
166
171
|
val.each do |subkey, subval|
|
167
172
|
process_entry %(#{key}_#{key == 'role' || !(subkey.include? '-') ? subkey : (subkey.tr '-', '_')}), subval, data
|
168
173
|
end
|
174
|
+
elsif (rekey = DeprecatedKeys[key]) ||
|
175
|
+
((key.start_with? 'role_') && (key.end_with? '_align') && (rekey = key.sub RoleAlignKeyRx, '_text_align'))
|
176
|
+
data[rekey] = evaluate val, data
|
177
|
+
elsif PaddingBottomHackKeys.include? key
|
178
|
+
val = evaluate val, data
|
179
|
+
# normalize padding hacks for themes designed before the converter had smart margins
|
180
|
+
val[2] = val[0] if ::Array === val && val[0].to_f >= 0 && val[2].to_f <= 0
|
181
|
+
data[key] = val
|
169
182
|
# QUESTION: do we really need to evaluate_math in this case?
|
170
183
|
elsif key.end_with? '_color'
|
171
|
-
if key == '
|
184
|
+
if key == 'table_border_color'
|
185
|
+
data[key] = ::Array === val ? val.map {|it| to_color evaluate it, data } : (to_color evaluate val, data)
|
186
|
+
elsif key == 'table_grid_color' && ::Array === val && val.size == 2
|
172
187
|
data[key] = val.map {|it| to_color evaluate it, data }
|
173
188
|
else
|
174
189
|
data[key] = to_color evaluate val, data
|
@@ -206,7 +221,8 @@ module Asciidoctor
|
|
206
221
|
def resolve_var vars, ref, var
|
207
222
|
var = var.tr '-', '_' if var.include? '-'
|
208
223
|
if (vars.respond_to? var) ||
|
209
|
-
DeprecatedCategoryKeys.any? {|old, new| (var.start_with? old + '_') && (vars.respond_to? (replace = new + (var.slice old.length, var.length))) && (var = replace) }
|
224
|
+
DeprecatedCategoryKeys.any? {|old, new| (var.start_with? old + '_') && (vars.respond_to? (replace = new + (var.slice old.length, var.length))) && (var = replace) } ||
|
225
|
+
((replace = DeprecatedKeys[var]) && (vars.respond_to? replace) && (var = replace))
|
210
226
|
vars[var]
|
211
227
|
else
|
212
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-04
|
12
|
+
date: 2022-05-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: asciidoctor
|
@@ -270,6 +270,7 @@ files:
|
|
270
270
|
- lib/asciidoctor/pdf/ext/prawn/formatted_text/arranger.rb
|
271
271
|
- lib/asciidoctor/pdf/ext/prawn/formatted_text/box.rb
|
272
272
|
- lib/asciidoctor/pdf/ext/prawn/formatted_text/fragment.rb
|
273
|
+
- lib/asciidoctor/pdf/ext/prawn/formatted_text/protect_bottom_gutter.rb
|
273
274
|
- lib/asciidoctor/pdf/ext/prawn/images.rb
|
274
275
|
- lib/asciidoctor/pdf/ext/pygments.rb
|
275
276
|
- lib/asciidoctor/pdf/ext/rouge.rb
|
@@ -289,6 +290,8 @@ files:
|
|
289
290
|
- lib/asciidoctor/pdf/formatted_text/transform.rb
|
290
291
|
- lib/asciidoctor/pdf/index_catalog.rb
|
291
292
|
- lib/asciidoctor/pdf/measurements.rb
|
293
|
+
- lib/asciidoctor/pdf/nogmagick.rb
|
294
|
+
- lib/asciidoctor/pdf/nopngmagick.rb
|
292
295
|
- lib/asciidoctor/pdf/optimizer.rb
|
293
296
|
- lib/asciidoctor/pdf/pdfmark.rb
|
294
297
|
- lib/asciidoctor/pdf/roman_numeral.rb
|