asciidoctor-pdf 1.5.0.alpha.16 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +12 -0
  3. data/CHANGELOG.adoc +415 -1
  4. data/LICENSE.adoc +1 -1
  5. data/NOTICE.adoc +14 -11
  6. data/README.adoc +647 -222
  7. data/asciidoctor-pdf.gemspec +47 -44
  8. data/bin/asciidoctor-pdf +5 -9
  9. data/bin/asciidoctor-pdf-optimize +20 -0
  10. data/data/fonts/ABOUT-mplus1mn-subset +26 -0
  11. data/data/fonts/ABOUT-mplus1p-subset +26 -0
  12. data/data/fonts/ABOUT-notoemoji-subset +3 -0
  13. data/data/fonts/ABOUT-notoserif-subset +26 -0
  14. data/data/fonts/{LICENSE-mplus-testflight-58 → LICENSE-mplus} +2 -2
  15. data/data/fonts/{LICENSE-noto-2015-06-05 → LICENSE-notoserif} +0 -0
  16. data/data/fonts/mplus1mn-bold-ascii.ttf +0 -0
  17. data/data/fonts/mplus1mn-bold-subset.ttf +0 -0
  18. data/data/fonts/mplus1mn-bold_italic-ascii.ttf +0 -0
  19. data/data/fonts/mplus1mn-bold_italic-subset.ttf +0 -0
  20. data/data/fonts/mplus1mn-italic-ascii.ttf +0 -0
  21. data/data/fonts/mplus1mn-italic-subset.ttf +0 -0
  22. data/data/fonts/mplus1mn-regular-ascii-conums.ttf +0 -0
  23. data/data/fonts/mplus1mn-regular-subset.ttf +0 -0
  24. data/data/fonts/mplus1p-regular-fallback.ttf +0 -0
  25. data/data/fonts/notoemoji-subset.ttf +0 -0
  26. data/data/fonts/notoserif-bold-subset.ttf +0 -0
  27. data/data/fonts/notoserif-bold_italic-subset.ttf +0 -0
  28. data/data/fonts/notoserif-italic-subset.ttf +0 -0
  29. data/data/fonts/notoserif-regular-subset.ttf +0 -0
  30. data/data/themes/base-theme.yml +26 -4
  31. data/data/themes/default-theme.yml +76 -60
  32. data/data/themes/default-with-fallback-font-theme.yml +9 -0
  33. data/docs/theming-guide.adoc +2731 -922
  34. data/lib/asciidoctor/pdf/converter.rb +4489 -0
  35. data/lib/asciidoctor/pdf/ext/asciidoctor/abstract_block.rb +7 -0
  36. data/lib/asciidoctor/pdf/ext/asciidoctor/abstract_node.rb +7 -0
  37. data/lib/asciidoctor/pdf/ext/asciidoctor/document.rb +5 -0
  38. data/lib/asciidoctor/pdf/ext/asciidoctor/image.rb +35 -0
  39. data/lib/{asciidoctor-pdf/asciidoctor_ext → asciidoctor/pdf/ext/asciidoctor}/list.rb +4 -2
  40. data/lib/{asciidoctor-pdf/asciidoctor_ext → asciidoctor/pdf/ext/asciidoctor}/list_item.rb +3 -1
  41. data/lib/asciidoctor/pdf/ext/asciidoctor/logging_shim.rb +33 -0
  42. data/lib/asciidoctor/pdf/ext/asciidoctor/section.rb +45 -0
  43. data/lib/asciidoctor/pdf/ext/asciidoctor.rb +11 -0
  44. data/lib/{asciidoctor-pdf/core_ext → asciidoctor/pdf/ext/core}/array.rb +6 -6
  45. data/lib/asciidoctor/pdf/ext/core/file.rb +9 -0
  46. data/lib/asciidoctor/pdf/ext/core/hash.rb +7 -0
  47. data/lib/asciidoctor/pdf/ext/core/numeric.rb +26 -0
  48. data/lib/{asciidoctor-pdf/core_ext → asciidoctor/pdf/ext/core}/object.rb +3 -1
  49. data/lib/{asciidoctor-pdf/core_ext → asciidoctor/pdf/ext/core}/quantifiable_stdout.rb +9 -1
  50. data/lib/asciidoctor/pdf/ext/core/regexp.rb +5 -0
  51. data/lib/{asciidoctor-pdf/core_ext → asciidoctor/pdf/ext/core}/string.rb +9 -13
  52. data/lib/asciidoctor/pdf/ext/core.rb +10 -0
  53. data/lib/asciidoctor/pdf/ext/pdf-core/page.rb +54 -0
  54. data/lib/asciidoctor/pdf/ext/pdf-core/pdf_object.rb +8 -0
  55. data/lib/asciidoctor/pdf/ext/pdf-core.rb +4 -0
  56. data/lib/asciidoctor/pdf/ext/prawn/coderay_encoder.rb +117 -0
  57. data/lib/asciidoctor/pdf/ext/prawn/extensions.rb +922 -0
  58. data/lib/{asciidoctor-pdf/prawn_ext → asciidoctor/pdf/ext/prawn}/font/afm.rb +14 -10
  59. data/lib/asciidoctor/pdf/ext/prawn/font_metric_cache.rb +9 -0
  60. data/lib/asciidoctor/pdf/ext/prawn/formatted_text/box.rb +66 -0
  61. data/lib/{asciidoctor-pdf/prawn_ext → asciidoctor/pdf/ext/prawn}/formatted_text/fragment.rb +21 -18
  62. data/lib/asciidoctor/pdf/ext/prawn/images.rb +54 -0
  63. data/lib/asciidoctor/pdf/ext/prawn-svg/interface.rb +14 -0
  64. data/lib/asciidoctor/pdf/ext/prawn-svg.rb +6 -0
  65. data/lib/asciidoctor/pdf/ext/prawn-table/cell/asciidoc.rb +76 -0
  66. data/lib/{asciidoctor-pdf/prawn-table_ext → asciidoctor/pdf/ext/prawn-table}/cell/text.rb +6 -3
  67. data/lib/asciidoctor/pdf/ext/prawn-table/cell.rb +60 -0
  68. data/lib/asciidoctor/pdf/ext/prawn-table.rb +6 -0
  69. data/lib/{asciidoctor-pdf/prawn-templates_ext.rb → asciidoctor/pdf/ext/prawn-templates.rb} +2 -0
  70. data/lib/asciidoctor/pdf/ext/prawn.rb +9 -0
  71. data/lib/asciidoctor/pdf/ext/pygments.rb +34 -0
  72. data/lib/asciidoctor/pdf/ext/rouge/formatters/prawn.rb +208 -0
  73. data/lib/{asciidoctor-pdf/rouge_ext/themes/pastie.rb → asciidoctor/pdf/ext/rouge/themes/asciidoctor_pdf_default.rb} +7 -5
  74. data/lib/asciidoctor/pdf/ext/rouge.rb +5 -0
  75. data/lib/asciidoctor/pdf/ext.rb +9 -0
  76. data/lib/asciidoctor/pdf/formatted_text/formatter.rb +43 -0
  77. data/lib/asciidoctor/pdf/formatted_text/fragment_position_renderer.rb +14 -0
  78. data/lib/asciidoctor/pdf/formatted_text/inline_destination_marker.rb +21 -0
  79. data/lib/asciidoctor/pdf/formatted_text/inline_image_arranger.rb +134 -0
  80. data/lib/asciidoctor/pdf/formatted_text/inline_image_renderer.rb +51 -0
  81. data/lib/asciidoctor/pdf/formatted_text/inline_text_aligner.rb +22 -0
  82. data/lib/{asciidoctor-pdf → asciidoctor/pdf}/formatted_text/parser.rb +175 -53
  83. data/lib/{asciidoctor-pdf → asciidoctor/pdf}/formatted_text/parser.treetop +20 -14
  84. data/lib/asciidoctor/pdf/formatted_text/source_wrap.rb +43 -0
  85. data/lib/asciidoctor/pdf/formatted_text/text_background_and_border_renderer.rb +55 -0
  86. data/lib/asciidoctor/pdf/formatted_text/transform.rb +394 -0
  87. data/lib/{asciidoctor-pdf → asciidoctor/pdf}/formatted_text.rb +6 -0
  88. data/lib/asciidoctor/pdf/index_catalog.rb +133 -0
  89. data/lib/asciidoctor/pdf/measurements.rb +62 -0
  90. data/lib/asciidoctor/pdf/optimizer.rb +44 -0
  91. data/lib/asciidoctor/pdf/pdfmark.rb +41 -0
  92. data/lib/asciidoctor/pdf/roman_numeral.rb +128 -0
  93. data/lib/asciidoctor/pdf/sanitizer.rb +45 -0
  94. data/lib/asciidoctor/pdf/text_transformer.rb +116 -0
  95. data/lib/asciidoctor/pdf/theme_loader.rb +305 -0
  96. data/lib/asciidoctor/pdf/version.rb +8 -0
  97. data/lib/asciidoctor/pdf.rb +15 -0
  98. data/lib/asciidoctor-pdf/converter.rb +2 -3343
  99. data/lib/asciidoctor-pdf/version.rb +3 -5
  100. data/lib/asciidoctor-pdf.rb +3 -3
  101. metadata +242 -128
  102. data/Gemfile +0 -22
  103. data/Rakefile +0 -81
  104. data/lib/asciidoctor-pdf/asciidoctor_ext/image.rb +0 -24
  105. data/lib/asciidoctor-pdf/asciidoctor_ext/section.rb +0 -34
  106. data/lib/asciidoctor-pdf/asciidoctor_ext.rb +0 -5
  107. data/lib/asciidoctor-pdf/core_ext/numeric.rb +0 -15
  108. data/lib/asciidoctor-pdf/core_ext/ostruct.rb +0 -17
  109. data/lib/asciidoctor-pdf/core_ext.rb +0 -4
  110. data/lib/asciidoctor-pdf/formatted_text/formatter.rb +0 -27
  111. data/lib/asciidoctor-pdf/formatted_text/inline_destination_marker.rb +0 -21
  112. data/lib/asciidoctor-pdf/formatted_text/inline_image_arranger.rb +0 -172
  113. data/lib/asciidoctor-pdf/formatted_text/inline_image_renderer.rb +0 -46
  114. data/lib/asciidoctor-pdf/formatted_text/transform.rb +0 -261
  115. data/lib/asciidoctor-pdf/implicit_header_processor.rb +0 -63
  116. data/lib/asciidoctor-pdf/index_catalog.rb +0 -119
  117. data/lib/asciidoctor-pdf/measurements.rb +0 -58
  118. data/lib/asciidoctor-pdf/pdf-core_ext/page.rb +0 -25
  119. data/lib/asciidoctor-pdf/pdf-core_ext/pdf_object.rb +0 -6
  120. data/lib/asciidoctor-pdf/pdf-core_ext.rb +0 -2
  121. data/lib/asciidoctor-pdf/pdfmark.rb +0 -33
  122. data/lib/asciidoctor-pdf/prawn-svg_ext/interface.rb +0 -10
  123. data/lib/asciidoctor-pdf/prawn-svg_ext.rb +0 -4
  124. data/lib/asciidoctor-pdf/prawn-table_ext/cell/asciidoc.rb +0 -69
  125. data/lib/asciidoctor-pdf/prawn-table_ext.rb +0 -3
  126. data/lib/asciidoctor-pdf/prawn_ext/coderay_encoder.rb +0 -115
  127. data/lib/asciidoctor-pdf/prawn_ext/extensions.rb +0 -863
  128. data/lib/asciidoctor-pdf/prawn_ext/images.rb +0 -40
  129. data/lib/asciidoctor-pdf/prawn_ext.rb +0 -5
  130. data/lib/asciidoctor-pdf/roman_numeral.rb +0 -114
  131. data/lib/asciidoctor-pdf/rouge_ext/css_theme.rb +0 -15
  132. data/lib/asciidoctor-pdf/rouge_ext/formatters/prawn.rb +0 -164
  133. data/lib/asciidoctor-pdf/rouge_ext.rb +0 -4
  134. data/lib/asciidoctor-pdf/sanitizer.rb +0 -88
  135. data/lib/asciidoctor-pdf/temporary_path.rb +0 -13
  136. data/lib/asciidoctor-pdf/theme_loader.rb +0 -247
  137. data/lib/asciidoctor-pdf/ttfunk_ext.rb +0 -8
@@ -1,40 +0,0 @@
1
- module Asciidoctor
2
- module Prawn
3
- module Images
4
- class << self
5
- def extended base
6
- base.class.__send__ :alias_method, :_initial_image, :image
7
- end
8
- end
9
-
10
- # Dispatch to suitable image method in Prawn based on file extension.
11
- def image file, opts = {}
12
- # FIXME handle case when SVG is a File or IO object
13
- if ::String === file && (file.downcase.end_with? '.svg')
14
- opts[:fallback_font_name] ||= default_svg_font if respond_to? :default_svg_font
15
- svg((::IO.read file), opts)
16
- else
17
- _initial_image file, opts
18
- end
19
- end
20
-
21
- # Retrieve the intrinsic image dimensions for the specified path.
22
- #
23
- # Returns a Hash containing :width and :height keys that map to the image's
24
- # intrinsic width and height values (in pixels)
25
- def intrinsic_image_dimensions path
26
- if path.end_with? '.svg'
27
- img_obj = ::Prawn::Svg::Interface.new ::IO.read(path), self, {}
28
- img_size = img_obj.document.sizing
29
- { width: img_size.output_width, height: img_size.output_height }
30
- else
31
- # NOTE build_image_object caches image data previously loaded
32
- _, img_size = ::File.open(path, 'rb') {|fd| build_image_object fd }
33
- { width: img_size.width, height: img_size.height }
34
- end
35
- end
36
- end
37
-
38
- ::Prawn::Document.extensions << Images
39
- end
40
- end
@@ -1,5 +0,0 @@
1
- # the following are organized under the Asciidoctor::Prawn namespace
2
- require_relative 'prawn_ext/font/afm'
3
- require_relative 'prawn_ext/images'
4
- require_relative 'prawn_ext/formatted_text/fragment'
5
- require_relative 'prawn_ext/extensions'
@@ -1,114 +0,0 @@
1
- ########################################################################
2
- #
3
- # This file was copied from roman-numerals and modified for use with
4
- # Asciidoctor PDF.
5
- #
6
- # Permission is hereby granted, free of charge, to any person obtaining
7
- # a copy of this software and associated documentation files (the
8
- # "Software"), to deal in the Software without restriction, including
9
- # without limitation the rights to use, copy, modify, merge, publish,
10
- # distribute, sublicense, and/or sell copies of the Software, and to
11
- # permit persons to whom the Software is furnished to do so, subject to
12
- # the following conditions:
13
- #
14
- # The above copyright notice and this permission notice shall be
15
- # included in all copies or substantial portions of the Software.
16
- #
17
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
- #
25
- # Copyright (c) 2011 Andrew Vos
26
- # Copyright (c) 2014 OpenDevice, Inc.
27
- #
28
- ########################################################################
29
-
30
- module Asciidoctor
31
- module Pdf
32
- class RomanNumeral
33
- BaseDigits = {
34
- 1 => 'I',
35
- 4 => 'IV',
36
- 5 => 'V',
37
- 9 => 'IX',
38
- 10 => 'X',
39
- 40 => 'XL',
40
- 50 => 'L',
41
- 90 => 'XC',
42
- 100 => 'C',
43
- 400 => 'CD',
44
- 500 => 'D',
45
- 900 => 'CM',
46
- 1000 => 'M'
47
- }
48
-
49
- def initialize initial_value, letter_case = nil
50
- initial_value ||= 1
51
- if ::Integer === initial_value
52
- @integer_value = initial_value
53
- else
54
- @integer_value = RomanNumeral.roman_to_int initial_value
55
- letter_case = :lower if letter_case.nil? && initial_value.upcase != initial_value
56
- end
57
- @letter_case = letter_case.nil? ? :upper : letter_case
58
- end
59
-
60
- def to_s
61
- to_r
62
- end
63
-
64
- def to_r
65
- if (int = @integer_value) < 1
66
- return int.to_s
67
- end
68
- roman = RomanNumeral.int_to_roman int
69
- @letter_case == :lower ? roman.downcase : roman
70
- end
71
-
72
- def to_i
73
- @integer_value
74
- end
75
-
76
- def next
77
- RomanNumeral.new @integer_value + 1, @letter_case
78
- end
79
-
80
- def next!
81
- @integer_value += 1
82
- self
83
- end
84
-
85
- def pred
86
- RomanNumeral.new @integer_value - 1, @letter_case
87
- end
88
-
89
- def self.int_to_roman value
90
- result = []
91
- BaseDigits.keys.reverse.each do |ival|
92
- while value >= ival
93
- value -= ival
94
- result << BaseDigits[ival]
95
- end
96
- end
97
- result.join
98
- end
99
-
100
- def self.roman_to_int value
101
- value = value.upcase
102
- result = 0
103
- BaseDigits.values.reverse.each do |rval|
104
- while value.start_with? rval
105
- offset = rval.length
106
- value = value[offset..offset]
107
- result += BaseDigits.key rval
108
- end
109
- end
110
- result
111
- end
112
- end
113
- end
114
- end
@@ -1,15 +0,0 @@
1
- module Rouge
2
- class CSSTheme
3
- # Patch style_for to return most specific style first
4
- # See https://github.com/jneen/rouge/issues/280
5
- # Fixed as of rouge v1.10.0
6
- def style_for token
7
- token.token_chain.reverse_each do |t|
8
- if (s = styles[t])
9
- return s
10
- end
11
- end
12
- nil
13
- end
14
- end
15
- end if (Gem::Version.new Rouge.version) < (Gem::Version.new '1.10.0')
@@ -1,164 +0,0 @@
1
- module Rouge
2
- module Formatters
3
- # Transforms a token stream into an array of
4
- # formatted text fragments for use with Prawn.
5
- class Prawn < Formatter
6
- tag 'prawn'
7
-
8
- Tokens = ::Rouge::Token::Tokens
9
-
10
- LF = %(\n)
11
- NoBreakSpace = %(\u00a0)
12
- InnerIndent = %(\n )
13
- GuardedIndent = %(\u00a0)
14
- GuardedInnerIndent = %(\n\u00a0)
15
- BoldStyle = [:bold].to_set
16
- ItalicStyle = [:italic].to_set
17
- BoldItalicStyle = [:bold, :italic].to_set
18
- UnderlineStyle = [:underline].to_set
19
-
20
- def initialize opts = {}
21
- unless ::Rouge::Theme === (theme = opts[:theme])
22
- unless theme && (theme = ::Rouge::Theme.find theme)
23
- theme = ::Rouge::Themes::Pastie
24
- end
25
- theme = theme.new
26
- end
27
- @theme = theme
28
- @normalized_colors = {}
29
- @background_colorizer = BackgroundColorizer.new line_gap: opts[:line_gap]
30
- @linenum_fragment_base = (create_fragment Tokens::Generic::Lineno).merge linenum: true
31
- end
32
-
33
- def background_color
34
- @background_color ||= normalize_color((@theme.style_for Tokens::Text).bg)
35
- end
36
-
37
- # Override format method so fragments don't get flatted to a string
38
- # and to add an options Hash.
39
- def format tokens, opts = {}
40
- stream tokens, opts
41
- end
42
-
43
- def stream tokens, opts = {}
44
- if opts[:line_numbers]
45
- if (linenum = opts[:start_line]) > 0
46
- linenum -= 1
47
- else
48
- linenum = 0
49
- end
50
- fragments = []
51
- fragments << (create_linenum_fragment linenum += 1)
52
- tokens.each do |tok, val|
53
- if val == LF
54
- fragments << { text: LF }
55
- fragments << (create_linenum_fragment linenum += 1)
56
- elsif val.include? LF
57
- # NOTE we assume if the fragment ends in a line feed, the intention was to match a line-oriented form
58
- line_oriented = val.end_with? LF
59
- base_fragment = create_fragment tok, val
60
- val.each_line do |line|
61
- fragments << (line_oriented ? (base_fragment.merge text: line, line_oriented: true) : (base_fragment.merge text: line))
62
- # NOTE append linenum fragment if there's a next line; only works if source doesn't have trailing endline
63
- fragments << (create_linenum_fragment linenum += 1) if line.end_with? LF
64
- end
65
- else
66
- fragments << (create_fragment tok, val)
67
- end
68
- end
69
- # NOTE drop orphaned linenum fragment (due to trailing endline in source)
70
- fragments.pop if (last_fragment = fragments[-1]) && last_fragment[:linenum]
71
- # NOTE pad numbers that have less digits than the largest line number
72
- if (linenum_w = linenum.to_s.length) > 1
73
- # NOTE extra column is the trailing space after the line number
74
- linenum_w += 1
75
- fragments.each do |fragment|
76
- fragment[:text] = %(#{fragment[:text].rjust linenum_w, NoBreakSpace}) if fragment[:linenum]
77
- end
78
- end
79
- fragments
80
- else
81
- start_of_line = true
82
- tokens.map do |tok, val|
83
- # match one or more consecutive endlines
84
- if val == LF || (val == (LF * val.length))
85
- start_of_line = true
86
- { text: val }
87
- else
88
- val[0] = GuardedIndent if start_of_line && (val.start_with? ' ')
89
- val.gsub! InnerIndent, GuardedInnerIndent if val.include? InnerIndent
90
- # QUESTION do we need the call to create_fragment if val contains only spaces? consider bg
91
- #fragment = create_fragment tok, val
92
- fragment = val.rstrip.empty? ? { text: val } : (create_fragment tok, val)
93
- # NOTE we assume if the fragment ends in a line feed, the intention was to match a line-oriented form
94
- fragment[:line_oriented] = true if (start_of_line = val.end_with? LF)
95
- fragment
96
- end
97
- end
98
- # QUESTION should we strip trailing newline?
99
- end
100
- end
101
-
102
- # TODO method could still be optimized (for instance, check if val is LF or empty)
103
- def create_fragment tok, val = nil
104
- fragment = val ? { text: val } : {}
105
- if (style_rules = @theme.style_for tok)
106
- if (bg = normalize_color style_rules.bg) && bg != @background_color
107
- fragment[:background_color] = bg
108
- fragment[:callback] = @background_colorizer
109
- fragment[:inline_block] = true if style_rules[:inline_block]
110
- fragment[:extend] = true if style_rules[:extend]
111
- end
112
- if (fg = normalize_color style_rules.fg)
113
- fragment[:color] = fg
114
- end
115
- if style_rules[:bold]
116
- fragment[:styles] = style_rules[:italic] ? BoldItalicStyle.dup : BoldStyle.dup
117
- elsif style_rules[:italic]
118
- fragment[:styles] = ItalicStyle.dup
119
- end
120
- if style_rules[:underline]
121
- if fragment.key? :styles
122
- fragment[:styles] << UnderlineStyle[0]
123
- else
124
- fragment[:styles] = UnderlineStyle.dup
125
- end
126
- end
127
- end
128
- fragment
129
- end
130
-
131
- def create_linenum_fragment linenum
132
- @linenum_fragment_base.merge text: %(#{linenum} )
133
- end
134
-
135
- def normalize_color raw
136
- return unless raw
137
- if (normalized = @normalized_colors[raw])
138
- normalized
139
- else
140
- normalized = (raw.start_with? '#') ? raw[1..-1] : raw
141
- normalized = normalized.each_char.map {|c| c * 2 }.join if normalized.length == 3
142
- @normalized_colors[raw] = normalized
143
- end
144
- end
145
- end
146
-
147
- class BackgroundColorizer
148
- def initialize opts = {}
149
- @line_gap = opts[:line_gap] || 0
150
- end
151
-
152
- def render_behind fragment
153
- pdf = fragment.document
154
- data = fragment.format_state
155
- prev_fill_color = pdf.fill_color
156
- pdf.fill_color data[:background_color]
157
- v_gap = data[:inline_block] ? @line_gap : 0
158
- fragment_width = data[:line_oriented] && data[:extend] ? (pdf.bounds.width - fragment.left) : fragment.width
159
- pdf.fill_rectangle [fragment.left, fragment.top + v_gap * 0.5], fragment_width, (fragment.height + v_gap)
160
- pdf.fill_color prev_fill_color
161
- end
162
- end
163
- end
164
- end
@@ -1,4 +0,0 @@
1
- require 'rouge'
2
- require_relative 'rouge_ext/formatters/prawn'
3
- require_relative 'rouge_ext/css_theme'
4
- require_relative 'rouge_ext/themes/pastie'
@@ -1,88 +0,0 @@
1
- begin
2
- require 'unicode' unless defined? Unicode::VERSION
3
- rescue LoadError
4
- begin
5
- require 'active_support/multibyte' unless defined? ActiveSupport::Multibyte
6
- rescue LoadError; end
7
- end
8
-
9
- module Asciidoctor
10
- module Pdf
11
- module Sanitizer
12
- BuiltInEntityChars = {
13
- '&lt;' => '<',
14
- '&gt;' => '>',
15
- '&amp;' => '&'
16
- }
17
- BuiltInEntityCharRx = /(?:#{BuiltInEntityChars.keys * '|'})/
18
- BuiltInEntityCharOrTagRx = /(?:#{BuiltInEntityChars.keys * '|'}|<)/
19
- InverseBuiltInEntityChars = BuiltInEntityChars.invert
20
- InverseBuiltInEntityCharRx = /[#{InverseBuiltInEntityChars.keys.join}]/
21
- NumericCharRefRx = /&#(\d{2,6});/
22
- XmlSanitizeRx = /<[^>]+>/
23
- SegmentPcdataRx = /(?:(&[a-z]+;|<[^>]+>)|([^&<]+))/
24
-
25
- # Strip leading, trailing and repeating whitespace, remove XML tags and
26
- # resolve all entities in the specified string.
27
- #
28
- # FIXME move to a module so we can mix it in elsewhere
29
- # FIXME add option to control escaping entities, or a filter mechanism in general
30
- def sanitize string
31
- string.strip
32
- .gsub(XmlSanitizeRx, '')
33
- .tr_s(' ', ' ')
34
- .gsub(NumericCharRefRx) { [$1.to_i].pack('U*') }
35
- .gsub(BuiltInEntityCharRx, BuiltInEntityChars)
36
- end
37
-
38
- def escape_xml string
39
- string.gsub InverseBuiltInEntityCharRx, InverseBuiltInEntityChars
40
- end
41
-
42
- def uppercase_pcdata string
43
- if BuiltInEntityCharOrTagRx =~ string
44
- string.gsub(SegmentPcdataRx) { $2 ? (uppercase_mb $2) : $1 }
45
- else
46
- uppercase_mb string
47
- end
48
- end
49
-
50
- if RUBY_VERSION >= '2.4'
51
- def uppercase_mb string
52
- string.upcase
53
- end
54
-
55
- def lowercase_mb string
56
- string.downcase
57
- end
58
- # NOTE Unicode library is 4x as fast as ActiveSupport::MultiByte::Chars
59
- elsif defined? ::Unicode
60
- def uppercase_mb string
61
- string.ascii_only? ? string.upcase : (::Unicode.upcase string)
62
- end
63
-
64
- def lowercase_mb string
65
- string.ascii_only? ? string.downcase : (::Unicode.downcase string)
66
- end
67
- elsif defined? ::ActiveSupport::Multibyte
68
- MultibyteChars = ::ActiveSupport::Multibyte::Chars
69
-
70
- def uppercase_mb string
71
- string.ascii_only? ? string.upcase : (MultibyteChars.new string).upcase.to_s
72
- end
73
-
74
- def lowercase_mb string
75
- string.ascii_only? ? string.downcase : (MultibyteChars.new string).downcase.to_s
76
- end
77
- else
78
- def uppercase_mb string
79
- string.upcase
80
- end
81
-
82
- def lowercase_mb string
83
- string.downcase
84
- end
85
- end
86
- end
87
- end
88
- end
@@ -1,13 +0,0 @@
1
- module Asciidoctor
2
- module Pdf
3
- module TemporaryPath
4
- def unlink
5
- ::File.unlink self
6
- end
7
-
8
- def exist?
9
- ::File.file? self
10
- end
11
- end
12
- end
13
- end
@@ -1,247 +0,0 @@
1
- require 'safe_yaml/load'
2
- require 'ostruct'
3
- require_relative 'core_ext/ostruct'
4
- require_relative 'measurements'
5
-
6
- module Asciidoctor
7
- module Pdf
8
- class ThemeLoader
9
- include ::Asciidoctor::Pdf::Measurements
10
-
11
- DataDir = ::File.expand_path(::File.join(::File.dirname(__FILE__), '..', '..', 'data'))
12
- ThemesDir = ::File.join DataDir, 'themes'
13
- FontsDir = ::File.join DataDir, 'fonts'
14
- DefaultThemePath = ::File.expand_path 'default-theme.yml', ThemesDir
15
- BaseThemePath = ::File.expand_path 'base-theme.yml', ThemesDir
16
-
17
- VariableRx = /\$([a-z0-9_]+)/
18
- LoneVariableRx = /^\$([a-z0-9_]+)$/
19
- HexColorEntryRx = /^(?<k>[[:blank:]]*[[:graph:]]+): +(?!null$)(?<q>["']?)#?(?<v>\w{3,6})\k<q> *(?:#.*)?$/
20
- MultiplyDivideOpRx = /(-?\d+(?:\.\d+)?) +([*\/]) +(-?\d+(?:\.\d+)?)/
21
- AddSubtractOpRx = /(-?\d+(?:\.\d+)?) +([+\-]) +(-?\d+(?:\.\d+)?)/
22
- PrecisionFuncRx = /^(round|floor|ceil)\(/
23
-
24
- # TODO implement white? & black? methods
25
- module ColorValue; end
26
-
27
- class HexColorValue < String
28
- include ColorValue
29
- end
30
-
31
- # A marker module for a normalized CMYK array
32
- # Prevents normalizing CMYK value more than once
33
- module CmykColorValue
34
- include ColorValue
35
- def to_s
36
- %([#{join ', '}])
37
- end
38
- end
39
-
40
- def self.resolve_theme_file theme_name = nil, theme_path = nil
41
- theme_name ||= 'default'
42
- # if .yml extension is given, assume it's a full file name
43
- if (theme_name.end_with? '.yml')
44
- # FIXME restrict to jail!
45
- # QUESTION why are we not using expand_path in this case?
46
- theme_path ? (::File.join theme_path, theme_name) : theme_name
47
- else
48
- # QUESTION should we append '-theme.yml' or just '.yml'?
49
- ::File.expand_path %(#{theme_name}-theme.yml), (theme_path || ThemesDir)
50
- end
51
- end
52
-
53
- def self.resolve_theme_asset asset_path, theme_path = nil
54
- ::File.expand_path asset_path, (theme_path || ThemesDir)
55
- end
56
-
57
- # NOTE base theme is loaded "as is" (no post-processing)
58
- def self.load_base_theme
59
- ::OpenStruct.new(::SafeYAML.load_file BaseThemePath)
60
- end
61
-
62
- def self.load_theme theme_name = nil, theme_path = nil, opts = {}
63
- if (theme_file = resolve_theme_file theme_name, theme_path) == BaseThemePath ||
64
- (theme_file != DefaultThemePath && (opts.fetch :apply_base_theme, true))
65
- theme_data = load_base_theme
66
- else
67
- theme_data = nil
68
- end
69
-
70
- if theme_file == BaseThemePath
71
- theme_data
72
- else
73
- load_file theme_file, theme_data
74
- end
75
- end
76
-
77
- def self.load_file filename, theme_data = nil
78
- raw_data = (::IO.read filename, encoding: ::Encoding::UTF_8).each_line.map {|l| l.sub HexColorEntryRx, '\k<k>: \'\k<v>\'' }.join
79
- self.new.load((::SafeYAML.load raw_data), theme_data)
80
- end
81
-
82
- def load hash, theme_data = nil
83
- theme_data ||= ::OpenStruct.new
84
- return theme_data unless ::Hash === hash
85
- hash.inject(theme_data) {|data, (key, val)| process_entry key, val, data }
86
- # NOTE remap legacy running content keys (e.g., header_recto_content_left => header_recto_left_content)
87
- %w(header_recto header_verso footer_recto footer_verso).each do |periphery_face|
88
- %w(left center right).each do |align|
89
- if (val = theme_data.delete %(#{periphery_face}_content_#{align}))
90
- theme_data[%(#{periphery_face}_#{align}_content)] = val
91
- end
92
- end
93
- end
94
- theme_data.base_align ||= 'left'
95
- # QUESTION should we do any other post-load calculations or defaults?
96
- theme_data
97
- end
98
-
99
- private
100
-
101
- def process_entry key, val, data
102
- if key.start_with? 'font_'
103
- data[key] = val
104
- elsif key.start_with? 'admonition_icon_'
105
- data[key] = (val || {}).map do |(key2, val2)|
106
- [key2.to_sym, (key2.end_with? '_color') ? to_color(evaluate val2, data) : (evaluate val2, data)]
107
- end.to_h
108
- elsif ::Hash === val
109
- val.each do |key2, val2|
110
- process_entry %(#{key}_#{key2.tr '-', '_'}), val2, data
111
- end
112
- elsif key.end_with? '_color'
113
- # QUESTION do we need to evaluate_math in this case?
114
- data[key] = to_color(evaluate val, data)
115
- elsif %(#{key.chomp '_'}_).include? '_content_'
116
- data[key] = (expand_vars val.to_s, data).to_s
117
- else
118
- data[key] = evaluate val, data
119
- end
120
- data
121
- end
122
-
123
- def evaluate expr, vars
124
- case expr
125
- when ::String
126
- evaluate_math(expand_vars expr, vars)
127
- when ::Array
128
- expr.map {|e| evaluate e, vars }
129
- else
130
- expr
131
- end
132
- end
133
-
134
- # NOTE we assume expr is a String
135
- def expand_vars expr, vars
136
- if (idx = (expr.index '$'))
137
- if idx == 0 && expr =~ LoneVariableRx
138
- if vars.respond_to? $1
139
- vars[$1]
140
- else
141
- warn %(asciidoctor: WARNING: unknown variable reference in PDF theme: $#{$1})
142
- expr
143
- end
144
- else
145
- expr.gsub(VariableRx) {
146
- if vars.respond_to? $1
147
- vars[$1]
148
- else
149
- warn %(asciidoctor: WARNING: unknown variable reference in PDF theme: $#{$1})
150
- $&
151
- end
152
- }
153
- end
154
- else
155
- expr
156
- end
157
- end
158
-
159
- def evaluate_math expr
160
- return expr if !(::String === expr) || ColorValue === expr
161
- # resolve measurement values (e.g., 0.5in => 36)
162
- # QUESTION should we round the value? perhaps leave that to the precision functions
163
- # NOTE leave % as a string; handled by converter for now
164
- expr = resolve_measurement_values(original = expr)
165
- while true
166
- result = expr.gsub(MultiplyDivideOpRx) { $1.to_f.send $2.to_sym, $3.to_f }
167
- unchanged = (result == expr)
168
- expr = result
169
- break if unchanged
170
- end
171
- while true
172
- result = expr.gsub(AddSubtractOpRx) { $1.to_f.send $2.to_sym, $3.to_f }
173
- unchanged = (result == expr)
174
- expr = result
175
- break if unchanged
176
- end
177
- if (expr.end_with? ')') && expr =~ PrecisionFuncRx
178
- op = $1
179
- offset = op.length + 1
180
- expr = expr[offset...-1].to_f.send op.to_sym
181
- end
182
- if expr == original
183
- original
184
- else
185
- (int_val = expr.to_i) == (flt_val = expr.to_f) ? int_val : flt_val
186
- end
187
- end
188
-
189
- def to_color value
190
- case value
191
- when ColorValue
192
- # already converted
193
- return value
194
- when ::String
195
- if value == 'transparent'
196
- # FIXME should we have a TransparentColorValue class?
197
- return HexColorValue.new value
198
- elsif value.length == 6
199
- return HexColorValue.new value.upcase
200
- end
201
- when ::Array
202
- case value.length
203
- # CMYK value
204
- when 4
205
- value = value.map do |e|
206
- if ::Numeric === e
207
- e = e * 100.0 unless e > 1
208
- else
209
- e = e.to_s.chomp('%').to_f
210
- end
211
- e == (int_e = e.to_i) ? int_e : e
212
- end
213
- case value
214
- when [0, 0, 0, 0]
215
- return HexColorValue.new 'FFFFFF'
216
- when [100, 100, 100, 100]
217
- return HexColorValue.new '000000'
218
- else
219
- value.extend CmykColorValue
220
- return value
221
- end
222
- # RGB value
223
- when 3
224
- return HexColorValue.new value.map {|e| '%02X' % e}.join
225
- # Nonsense array value; flatten to string
226
- else
227
- value = value.join
228
- end
229
- else
230
- # Unknown type; coerce to a string
231
- value = value.to_s
232
- end
233
- value = case value.length
234
- when 6
235
- value
236
- when 3
237
- # expand hex shorthand (e.g., f00 -> ff0000)
238
- value.each_char.map {|c| c * 2 }.join
239
- else
240
- # truncate or pad with leading zeros (e.g., ff -> 0000ff)
241
- value[0..5].rjust 6, '0'
242
- end
243
- HexColorValue.new value.upcase
244
- end
245
- end
246
- end
247
- end
@@ -1,8 +0,0 @@
1
- # patch ttfunk 1.5.0; see https://github.com/prawnpdf/ttfunk/issues/39
2
- class TTFunk::Subset::Base
3
- alias __checksum checksum
4
- def checksum data
5
- return 0 if data.length == 0
6
- __checksum data
7
- end
8
- end