asciidoctor-pdf 1.5.0.beta.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +277 -2
  3. data/LICENSE.adoc +1 -1
  4. data/NOTICE.adoc +1 -1
  5. data/README.adoc +486 -292
  6. data/asciidoctor-pdf.gemspec +12 -11
  7. data/bin/asciidoctor-pdf +2 -6
  8. data/bin/asciidoctor-pdf-optimize +20 -0
  9. data/data/fonts/ABOUT-mplus1mn-subset +26 -0
  10. data/data/fonts/ABOUT-mplus1p-subset +26 -0
  11. data/data/fonts/ABOUT-notoemoji-subset +3 -0
  12. data/data/fonts/ABOUT-notoserif-subset +26 -0
  13. data/data/fonts/{LICENSE-mplus-testflight-58 → LICENSE-mplus} +2 -2
  14. data/data/fonts/{LICENSE-noto-2015-06-05 → LICENSE-notoserif} +0 -0
  15. data/data/fonts/mplus1mn-bold-ascii.ttf +0 -0
  16. data/data/fonts/mplus1mn-bold-subset.ttf +0 -0
  17. data/data/fonts/mplus1mn-bold_italic-ascii.ttf +0 -0
  18. data/data/fonts/mplus1mn-bold_italic-subset.ttf +0 -0
  19. data/data/fonts/mplus1mn-italic-ascii.ttf +0 -0
  20. data/data/fonts/mplus1mn-italic-subset.ttf +0 -0
  21. data/data/fonts/mplus1mn-regular-ascii-conums.ttf +0 -0
  22. data/data/fonts/mplus1mn-regular-subset.ttf +0 -0
  23. data/data/fonts/mplus1p-regular-fallback.ttf +0 -0
  24. data/data/fonts/notoemoji-subset.ttf +0 -0
  25. data/data/fonts/notoserif-bold-subset.ttf +0 -0
  26. data/data/fonts/notoserif-bold_italic-subset.ttf +0 -0
  27. data/data/fonts/notoserif-italic-subset.ttf +0 -0
  28. data/data/fonts/notoserif-regular-subset.ttf +0 -0
  29. data/data/themes/base-theme.yml +22 -4
  30. data/data/themes/default-theme.yml +59 -29
  31. data/data/themes/default-with-fallback-font-theme.yml +4 -17
  32. data/docs/theming-guide.adoc +1647 -167
  33. data/lib/asciidoctor/pdf/converter.rb +4489 -0
  34. data/lib/{asciidoctor-pdf/asciidoctor_ext → asciidoctor/pdf/ext/asciidoctor}/abstract_block.rb +2 -0
  35. data/lib/asciidoctor/pdf/ext/asciidoctor/abstract_node.rb +7 -0
  36. data/lib/{asciidoctor-pdf/asciidoctor_ext → asciidoctor/pdf/ext/asciidoctor}/document.rb +2 -0
  37. data/lib/asciidoctor/pdf/ext/asciidoctor/image.rb +35 -0
  38. data/lib/{asciidoctor-pdf/asciidoctor_ext → asciidoctor/pdf/ext/asciidoctor}/list.rb +4 -2
  39. data/lib/{asciidoctor-pdf/asciidoctor_ext → asciidoctor/pdf/ext/asciidoctor}/list_item.rb +3 -1
  40. data/lib/asciidoctor/pdf/ext/asciidoctor/logging_shim.rb +33 -0
  41. data/lib/{asciidoctor-pdf/asciidoctor_ext → asciidoctor/pdf/ext/asciidoctor}/section.rb +9 -6
  42. data/lib/asciidoctor/pdf/ext/asciidoctor.rb +11 -0
  43. data/lib/{asciidoctor-pdf/core_ext → asciidoctor/pdf/ext/core}/array.rb +6 -0
  44. data/lib/asciidoctor/pdf/ext/core/file.rb +9 -0
  45. data/lib/{asciidoctor-pdf/core_ext → asciidoctor/pdf/ext/core}/hash.rb +2 -0
  46. data/lib/{asciidoctor-pdf/core_ext → asciidoctor/pdf/ext/core}/numeric.rb +5 -3
  47. data/lib/{asciidoctor-pdf/core_ext → asciidoctor/pdf/ext/core}/object.rb +3 -1
  48. data/lib/{asciidoctor-pdf/core_ext → asciidoctor/pdf/ext/core}/quantifiable_stdout.rb +9 -1
  49. data/lib/{asciidoctor-pdf/core_ext → asciidoctor/pdf/ext/core}/regexp.rb +2 -0
  50. data/lib/{asciidoctor-pdf/core_ext → asciidoctor/pdf/ext/core}/string.rb +9 -13
  51. data/lib/asciidoctor/pdf/ext/core.rb +10 -0
  52. data/lib/asciidoctor/pdf/ext/pdf-core/page.rb +54 -0
  53. data/lib/asciidoctor/pdf/ext/pdf-core/pdf_object.rb +8 -0
  54. data/lib/asciidoctor/pdf/ext/pdf-core.rb +4 -0
  55. data/lib/asciidoctor/pdf/ext/prawn/coderay_encoder.rb +117 -0
  56. data/lib/asciidoctor/pdf/ext/prawn/extensions.rb +922 -0
  57. data/lib/{asciidoctor-pdf/prawn_ext → asciidoctor/pdf/ext/prawn}/font/afm.rb +14 -10
  58. data/lib/asciidoctor/pdf/ext/prawn/font_metric_cache.rb +9 -0
  59. data/lib/asciidoctor/pdf/ext/prawn/formatted_text/box.rb +66 -0
  60. data/lib/{asciidoctor-pdf/prawn_ext → asciidoctor/pdf/ext/prawn}/formatted_text/fragment.rb +16 -12
  61. data/lib/asciidoctor/pdf/ext/prawn/images.rb +54 -0
  62. data/lib/asciidoctor/pdf/ext/prawn-svg/interface.rb +14 -0
  63. data/lib/{asciidoctor-pdf/prawn-svg_ext.rb → asciidoctor/pdf/ext/prawn-svg.rb} +3 -1
  64. data/lib/asciidoctor/pdf/ext/prawn-table/cell/asciidoc.rb +76 -0
  65. data/lib/{asciidoctor-pdf/prawn-table_ext → asciidoctor/pdf/ext/prawn-table}/cell/text.rb +6 -3
  66. data/lib/{asciidoctor-pdf/prawn-table_ext → asciidoctor/pdf/ext/prawn-table}/cell.rb +10 -10
  67. data/lib/asciidoctor/pdf/ext/prawn-table.rb +6 -0
  68. data/lib/{asciidoctor-pdf/prawn-templates_ext.rb → asciidoctor/pdf/ext/prawn-templates.rb} +2 -0
  69. data/lib/asciidoctor/pdf/ext/prawn.rb +9 -0
  70. data/lib/asciidoctor/pdf/ext/pygments.rb +34 -0
  71. data/lib/asciidoctor/pdf/ext/rouge/formatters/prawn.rb +208 -0
  72. data/lib/{asciidoctor-pdf/rouge_ext → asciidoctor/pdf/ext/rouge}/themes/asciidoctor_pdf_default.rb +2 -0
  73. data/lib/asciidoctor/pdf/ext/rouge.rb +5 -0
  74. data/lib/asciidoctor/pdf/ext.rb +9 -0
  75. data/lib/asciidoctor/pdf/formatted_text/formatter.rb +43 -0
  76. data/lib/asciidoctor/pdf/formatted_text/fragment_position_renderer.rb +14 -0
  77. data/lib/asciidoctor/pdf/formatted_text/inline_destination_marker.rb +21 -0
  78. data/lib/asciidoctor/pdf/formatted_text/inline_image_arranger.rb +134 -0
  79. data/lib/asciidoctor/pdf/formatted_text/inline_image_renderer.rb +51 -0
  80. data/lib/asciidoctor/pdf/formatted_text/inline_text_aligner.rb +22 -0
  81. data/lib/{asciidoctor-pdf → asciidoctor/pdf}/formatted_text/parser.rb +31 -7
  82. data/lib/{asciidoctor-pdf → asciidoctor/pdf}/formatted_text/parser.treetop +3 -4
  83. data/lib/asciidoctor/pdf/formatted_text/source_wrap.rb +43 -0
  84. data/lib/asciidoctor/pdf/formatted_text/text_background_and_border_renderer.rb +55 -0
  85. data/lib/asciidoctor/pdf/formatted_text/transform.rb +394 -0
  86. data/lib/{asciidoctor-pdf → asciidoctor/pdf}/formatted_text.rb +4 -0
  87. data/lib/asciidoctor/pdf/index_catalog.rb +133 -0
  88. data/lib/asciidoctor/pdf/measurements.rb +62 -0
  89. data/lib/asciidoctor/pdf/optimizer.rb +44 -0
  90. data/lib/asciidoctor/pdf/pdfmark.rb +41 -0
  91. data/lib/asciidoctor/pdf/roman_numeral.rb +128 -0
  92. data/lib/asciidoctor/pdf/sanitizer.rb +45 -0
  93. data/lib/asciidoctor/pdf/text_transformer.rb +116 -0
  94. data/lib/asciidoctor/pdf/theme_loader.rb +305 -0
  95. data/lib/asciidoctor/pdf/version.rb +8 -1
  96. data/lib/asciidoctor/pdf.rb +15 -1
  97. data/lib/asciidoctor-pdf/converter.rb +2 -3824
  98. data/lib/asciidoctor-pdf/version.rb +3 -6
  99. data/lib/asciidoctor-pdf.rb +3 -4
  100. metadata +130 -85
  101. data/lib/asciidoctor-pdf/asciidoctor_ext/image.rb +0 -24
  102. data/lib/asciidoctor-pdf/asciidoctor_ext/logging_shim.rb +0 -25
  103. data/lib/asciidoctor-pdf/asciidoctor_ext.rb +0 -8
  104. data/lib/asciidoctor-pdf/core_ext/ostruct.rb +0 -8
  105. data/lib/asciidoctor-pdf/core_ext.rb +0 -6
  106. data/lib/asciidoctor-pdf/formatted_text/formatter.rb +0 -40
  107. data/lib/asciidoctor-pdf/formatted_text/inline_destination_marker.rb +0 -21
  108. data/lib/asciidoctor-pdf/formatted_text/inline_image_arranger.rb +0 -160
  109. data/lib/asciidoctor-pdf/formatted_text/inline_image_renderer.rb +0 -46
  110. data/lib/asciidoctor-pdf/formatted_text/inline_text_aligner.rb +0 -20
  111. data/lib/asciidoctor-pdf/formatted_text/text_background_and_border_renderer.rb +0 -45
  112. data/lib/asciidoctor-pdf/formatted_text/transform.rb +0 -294
  113. data/lib/asciidoctor-pdf/implicit_header_processor.rb +0 -63
  114. data/lib/asciidoctor-pdf/index_catalog.rb +0 -127
  115. data/lib/asciidoctor-pdf/measurements.rb +0 -58
  116. data/lib/asciidoctor-pdf/pdf-core_ext/page.rb +0 -25
  117. data/lib/asciidoctor-pdf/pdf-core_ext/pdf_object.rb +0 -6
  118. data/lib/asciidoctor-pdf/pdf-core_ext.rb +0 -2
  119. data/lib/asciidoctor-pdf/pdfmark.rb +0 -33
  120. data/lib/asciidoctor-pdf/prawn-svg_ext/interface.rb +0 -10
  121. data/lib/asciidoctor-pdf/prawn-table_ext/cell/asciidoc.rb +0 -69
  122. data/lib/asciidoctor-pdf/prawn-table_ext.rb +0 -4
  123. data/lib/asciidoctor-pdf/prawn_ext/coderay_encoder.rb +0 -115
  124. data/lib/asciidoctor-pdf/prawn_ext/extensions.rb +0 -904
  125. data/lib/asciidoctor-pdf/prawn_ext/images.rb +0 -51
  126. data/lib/asciidoctor-pdf/prawn_ext.rb +0 -5
  127. data/lib/asciidoctor-pdf/roman_numeral.rb +0 -126
  128. data/lib/asciidoctor-pdf/rouge_ext/formatters/prawn.rb +0 -175
  129. data/lib/asciidoctor-pdf/rouge_ext/themes/bw.rb +0 -38
  130. data/lib/asciidoctor-pdf/rouge_ext.rb +0 -4
  131. data/lib/asciidoctor-pdf/sanitizer.rb +0 -101
  132. data/lib/asciidoctor-pdf/temporary_path.rb +0 -13
  133. data/lib/asciidoctor-pdf/theme_loader.rb +0 -280
  134. data/lib/asciidoctor-pdf/ttfunk_ext.rb +0 -8
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Asciidoctor::AbstractBlock
2
4
  def sections?
3
5
  !sections.empty?
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Asciidoctor::AbstractNode
4
+ def remove_attr name
5
+ @attributes.delete name
6
+ end unless method_defined? :remove_attr
7
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Asciidoctor::Document
2
4
  alias catalog references unless method_defined? :catalog
3
5
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor
4
+ module Image
5
+ DataUriRx = /^data:image\/(?<fmt>png|jpe?g|gif|pdf|bmp|tiff|svg\+xml);base64,(?<data>.*)$/
6
+ FormatAliases = { 'jpg' => 'jpeg', 'svg+xml' => 'svg' }
7
+
8
+ class << self
9
+ def format image_path, attributes = nil
10
+ (attributes && attributes['format']) || ((ext = ::File.extname image_path).downcase.slice 1, ext.length)
11
+ end
12
+
13
+ def target_and_format image_path, attributes = nil
14
+ if (image_path.start_with? 'data:') && (m = DataUriRx.match image_path)
15
+ [(m[:data].extend ::Base64), (FormatAliases.fetch m[:fmt], m[:fmt])]
16
+ else
17
+ [image_path, (attributes && attributes['format']) || ((ext = ::File.extname image_path).downcase.slice 1, ext.length)]
18
+ end
19
+ end
20
+ end
21
+
22
+ def format
23
+ (attr 'format', nil, false) || ((ext = ::File.extname(inline? ? target : (attr 'target'))).downcase.slice 1, ext.length)
24
+ end
25
+
26
+ def target_and_format
27
+ image_path = inline? ? target : (attr 'target')
28
+ if (image_path.start_with? 'data:') && (m = DataUriRx.match image_path)
29
+ [(m[:data].extend ::Base64), (FormatAliases.fetch m[:fmt], m[:fmt])]
30
+ else
31
+ [image_path, (attr 'format', nil, false) || ((ext = ::File.extname image_path).downcase.slice 1, ext.length)]
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,4 +1,6 @@
1
- # TODO add these methods to Asciidoctor core
1
+ # frozen_string_literal: true
2
+
3
+ # TODO: add these methods to Asciidoctor core
2
4
  class Asciidoctor::List
3
5
  # Check whether this list is an outline list (unordered or ordered).
4
6
  #
@@ -23,7 +25,7 @@ class Asciidoctor::List
23
25
  def outline_level
24
26
  l = 1
25
27
  ancestor = self
26
- # FIXME does not cross out of AsciiDoc table cell
28
+ # FIXME: does not cross out of AsciiDoc table cell
27
29
  while (ancestor = ancestor.parent)
28
30
  l += 1 if Asciidoctor::List === ancestor && ancestor.outline?
29
31
  end
@@ -1,4 +1,6 @@
1
- # TODO add these methods to Asciidoctor core
1
+ # frozen_string_literal: true
2
+
3
+ # TODO: add these methods to Asciidoctor core
2
4
  class Asciidoctor::ListItem
3
5
  # Check whether this list item has complex content (i.e., nested blocks other than an outline list).
4
6
  #
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor
4
+ class StubLogger
5
+ class << self
6
+ def info message = nil
7
+ # ignore since this isn't a real logger
8
+ end
9
+
10
+ def info?
11
+ false
12
+ end
13
+
14
+ def warn message = nil
15
+ ::Kernel.warn %(asciidoctor: WARNING: #{message || (block_given? ? yield : '???')})
16
+ end
17
+
18
+ def error message = nil
19
+ ::Kernel.warn %(asciidoctor: ERROR: #{message || (block_given? ? yield : '???')})
20
+ end
21
+ end
22
+ end
23
+
24
+ module Logging
25
+ def logger
26
+ StubLogger
27
+ end
28
+
29
+ def message_with_context text, _context = {}
30
+ text
31
+ end
32
+ end
33
+ end
@@ -1,21 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Asciidoctor::Section
2
4
  def numbered_title opts = {}
3
- unless (@cached_numbered_title ||= nil)
5
+ @cached_numbered_title ||= nil
6
+ unless @cached_numbered_title
4
7
  slevel = @level == 0 && @special ? 1 : @level
5
8
  if @numbered && !@caption && slevel <= (@document.attr 'sectnumlevels', 3).to_i
6
9
  @is_numbered = true
7
- @cached_formal_numbered_title = if @document.doctype == 'book'
10
+ if @document.doctype == 'book'
8
11
  if slevel == 0
9
12
  @cached_numbered_title = %(#{sectnum nil, ':'} #{title})
10
- %(#{@document.attr 'part-signifier', 'Part'} #{@cached_numbered_title}).lstrip
13
+ @cached_formal_numbered_title = %(#{@document.attr 'part-signifier', 'Part'} #{@cached_numbered_title}).lstrip
11
14
  elsif slevel == 1
12
15
  @cached_numbered_title = %(#{sectnum} #{title})
13
- %(#{@document.attr 'chapter-signifier', (@document.attr 'chapter-label', 'Chapter')} #{@cached_numbered_title}).lstrip
16
+ @cached_formal_numbered_title = %(#{@document.attr 'chapter-signifier', (@document.attr 'chapter-label', 'Chapter')} #{@cached_numbered_title}).lstrip
14
17
  else
15
- @cached_numbered_title = %(#{sectnum} #{title})
18
+ @cached_formal_numbered_title = @cached_numbered_title = %(#{sectnum} #{title})
16
19
  end
17
20
  else
18
- @cached_numbered_title = %(#{sectnum} #{title})
21
+ @cached_formal_numbered_title = @cached_numbered_title = %(#{sectnum} #{title})
19
22
  end
20
23
  elsif slevel == 0
21
24
  @is_numbered = false
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ # NOTE these are either candidates for inclusion in Asciidoctor core or backports
4
+ require_relative 'asciidoctor/logging_shim' unless defined? Asciidoctor::Logging
5
+ require_relative 'asciidoctor/abstract_node'
6
+ require_relative 'asciidoctor/abstract_block'
7
+ require_relative 'asciidoctor/document'
8
+ require_relative 'asciidoctor/section'
9
+ require_relative 'asciidoctor/list'
10
+ require_relative 'asciidoctor/list_item'
11
+ require_relative 'asciidoctor/image'
@@ -1,5 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Array
2
4
  def delete_all *entries
3
5
  entries.map {|entry| delete entry }.compact
4
6
  end unless method_defined? :delete_all
7
+
8
+ def sum
9
+ reduce(&:+)
10
+ end unless method_defined? :sum
5
11
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class File
4
+ class << self
5
+ def absolute_path? path
6
+ (path.start_with? '/') || (ALT_SEPARATOR && (path.start_with? (absolute_path path).slice 0, 3))
7
+ end unless method_defined? :absolute_path?
8
+ end
9
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Hash
2
4
  def compact
3
5
  select {|_, val| val }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # NOTE remove once minimum required Ruby version is at least 2.4
2
4
  Float.prepend (Module.new do
3
5
  def truncate *args
@@ -5,10 +7,10 @@ Float.prepend (Module.new do
5
7
  if (precision = Integer args.shift) == 0
6
8
  super
7
9
  elsif precision > 0
8
- precision_factor = 10.0 ** precision
10
+ precision_factor = 10.0**precision
9
11
  (self * precision_factor).to_i / precision_factor
10
12
  else
11
- precision_factor = 10 ** precision.abs
13
+ precision_factor = 10**precision.abs
12
14
  (self / precision_factor).to_i * precision_factor
13
15
  end
14
16
  else
@@ -18,7 +20,7 @@ Float.prepend (Module.new do
18
20
  end) if (Float.instance_method :truncate).arity == 0
19
21
 
20
22
  Integer.prepend (Module.new do
21
- def truncate *args
23
+ def truncate *_args
22
24
  super()
23
25
  end
24
26
  end) if (Integer.instance_method :truncate).arity == 0
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Object
2
4
  # Convert the object to a serialized PDF object.
3
- def to_pdf
5
+ def to_pdf_object
4
6
  ::PDF::Core.pdf_object self
5
7
  end
6
8
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'delegate'
2
4
 
3
5
  # A delegator that allows the size method to be used on the STDOUT object.
@@ -11,10 +13,16 @@ class QuantifiableStdout < SimpleDelegator
11
13
  def initialize delegate
12
14
  @size = 0
13
15
  super
16
+ delegate.binmode
17
+ end
18
+
19
+ def << content
20
+ @size += content.to_s.bytesize
21
+ super
14
22
  end
15
23
 
16
24
  def write content
17
- @size += content.bytesize
25
+ @size += content.to_s.bytesize
18
26
  super
19
27
  end
20
28
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Regexp
2
4
  alias match? === unless Regexp.method_defined? :match?
3
5
  end
@@ -1,26 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  def pred
3
- begin
4
- # integers
5
- %(#{(Integer self) - 1})
6
- rescue ::ArgumentError
7
- # chars (upper alpha, lower alpha, lower greek)
8
- ([65, 97, 945].include? ord) ? '0' : ([ord - 1].pack 'U1')
9
- end
5
+ # integers
6
+ ((Integer self) - 1).to_s
7
+ rescue ::ArgumentError
8
+ # chars (upper alpha, lower alpha, lower greek)
9
+ ([65, 97, 945].include? ord) ? '0' : ([ord - 1].pack 'U1')
10
10
  end unless method_defined? :pred
11
11
 
12
12
  # If the string is ASCII only, convert it to a PDF LiteralString object. Otherwise, return self.
13
13
  def as_pdf
14
- if ascii_only?
15
- ::PDF::Core::LiteralString.new(encode ::Encoding::ASCII_8BIT)
16
- else
17
- self
18
- end
14
+ ascii_only? ? (::PDF::Core::LiteralString.new encode ::Encoding::ASCII_8BIT) : self
19
15
  end
20
16
 
21
17
  # Convert the string to a serialized PDF object. If the string can be encoded as ASCII-8BIT, first convert it to a PDF
22
18
  # LiteralString object.
23
- def to_pdf
19
+ def to_pdf_object
24
20
  ::PDF::Core.pdf_object as_pdf
25
21
  end
26
22
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'core/object'
4
+ require_relative 'core/array'
5
+ require_relative 'core/file'
6
+ require_relative 'core/hash'
7
+ require_relative 'core/numeric'
8
+ require_relative 'core/string'
9
+ require_relative 'core/regexp'
10
+ require_relative 'core/quantifiable_stdout'
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PDF::Core::Page
4
+ InitialPageContent = %(q\n)
5
+
6
+ # Restore the new_content_stream method from PDF::Core::Page
7
+ #
8
+ # The prawn-templates gem relies on the new_content_stream method on
9
+ # PDF::Core::Page, which was removed in pdf-core 0.3.1. prawn-templates is
10
+ # used for importing a single-page PDF into the current document.
11
+ #
12
+ # see https://github.com/prawnpdf/pdf-core/commit/67f9a08a03bcfcc5a24cf76b135c218d3d3ab05d
13
+ def new_content_stream
14
+ return if in_stamp_stream?
15
+ dictionary.data[:Contents] = [content] unless Array === dictionary.data[:Contents]
16
+ @content = document.ref({})
17
+ dictionary.data[:Contents] << document.state.store[@content]
18
+ document.open_graphics_state
19
+ end unless method_defined? :new_content_stream
20
+
21
+ # NOTE alias method to avoid warning if another gem replaces this method
22
+ alias __new_content_stream new_content_stream
23
+
24
+ # Restore the imported_page? method from PDF::Core::Page
25
+ #
26
+ # see https://github.com/prawnpdf/pdf-core/commit/0e326a838e142061be8e062168190fae6b3b1dcf
27
+ def imported_page?
28
+ @imported_page
29
+ end unless method_defined? :imported_page?
30
+
31
+ # Record the page's current state as the tare content stream (i.e., empty, meaning no content has been written).
32
+ def tare_content_stream
33
+ @tare_content_stream = content.stream.filtered_stream
34
+ end
35
+
36
+ # Returns whether the current page is empty based on tare content stream (i.e., no content has been written).
37
+ # Returns false if a page has not yet been created.
38
+ def empty?
39
+ content.stream.filtered_stream == (@tare_content_stream ||= InitialPageContent) && document.page_number > 0
40
+ end
41
+
42
+ # Reset the content of the page.
43
+ # Note that this method may leave behind an orphaned background image.
44
+ def reset_content
45
+ unless content.stream.filtered_stream == InitialPageContent
46
+ xobjects.clear
47
+ ext_gstates.clear
48
+ new_content = document.state.store[document.ref({})]
49
+ new_content << 'q' << ?\n
50
+ content.replace new_content
51
+ @tare_content_stream = InitialPageContent
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ unless (defined? PDF::Core.pdf_object) == 'method'
4
+ module PDF::Core
5
+ alias pdf_object PdfObject
6
+ module_function :pdf_object # rubocop:disable Style/AccessModifierDeclarations
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'pdf-core/pdf_object'
4
+ require_relative 'pdf-core/page'
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ ######################################################################
4
+ #
5
+ # This file was copied from Prawn (manual/syntax_highlight.rb) and
6
+ # modified for use with Asciidoctor PDF.
7
+ #
8
+ # Prawn is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # Prawn is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with Prawn. If not, see <http://www.gnu.org/licenses/>.
20
+ #
21
+ # Copyright (C) Felipe Doria
22
+ # Copyright (C) 2014 OpenDevise Inc. and the Asciidoctor Project
23
+ #
24
+ ######################################################################
25
+
26
+ require 'coderay'
27
+
28
+ # Registers a to_prawn method with CodeRay. The method returns an array of hashes to be
29
+ # used with Prawn::Text.formatted_text(array).
30
+ #
31
+ # Usage:
32
+ #
33
+ # CodeRay.scan(string, :ruby).to_prawn
34
+ #
35
+ module Asciidoctor
36
+ module Prawn
37
+ class CodeRayEncoder < ::CodeRay::Encoders::Encoder
38
+ register_for :to_prawn
39
+
40
+ # Manni theme from Pygments
41
+ COLORS = {
42
+ default: '333333',
43
+ annotation: '9999FF',
44
+ attribute_name: '4F9FCF',
45
+ attribute_value: 'D44950',
46
+ class: '00AA88',
47
+ class_variable: '003333',
48
+ color: 'FF6600',
49
+ comment: '999999',
50
+ constant: '336600',
51
+ directive: '006699',
52
+ doctype: '009999',
53
+ entity: '999999',
54
+ float: 'FF6600',
55
+ function: 'CC00FF',
56
+ important: '9999FF',
57
+ inline_delimiter: 'EF804F',
58
+ instance_variable: '003333',
59
+ integer: 'FF6600',
60
+ key: '006699',
61
+ keyword: '006699',
62
+ method: 'CC00FF',
63
+ namespace: '00CCFF',
64
+ predefined_type: '007788',
65
+ regexp: '33AAAA',
66
+ string: 'CC3300',
67
+ symbol: 'FFCC33',
68
+ tag: '2F6F9F',
69
+ type: '007788',
70
+ value: '336600',
71
+ }
72
+
73
+ LF = ?\n
74
+ NoBreakSpace = ?\u00a0
75
+ InnerIndent = LF + ' '
76
+ GuardedIndent = ?\u00a0
77
+ GuardedInnerIndent = LF + GuardedIndent
78
+
79
+ def setup options
80
+ super
81
+ @out = []
82
+ @open = []
83
+ # NOTE tracks whether text token begins at the start of a line
84
+ @start_of_line = true
85
+ end
86
+
87
+ def text_token text, kind
88
+ if text == LF
89
+ @out << { text: text }
90
+ @start_of_line = true
91
+ # NOTE text is nil and kind is :error when CodeRay ends parsing on an error
92
+ elsif text
93
+ # NOTE add guard character to prevent Prawn from trimming indentation
94
+ text[0] = GuardedIndent if @start_of_line && (text.start_with? ' ')
95
+ text.gsub! InnerIndent, GuardedInnerIndent if text.include? InnerIndent
96
+
97
+ # NOTE this optimization assumes we don't support/use background colors
98
+ if text.rstrip.empty?
99
+ @out << { text: text }
100
+ else
101
+ # QUESTION should we default to no color?
102
+ @out << { text: text, color: (COLORS[kind] || COLORS[@open[-1]] || COLORS[:default]) }
103
+ end
104
+ @start_of_line = text.end_with? LF
105
+ end
106
+ end
107
+
108
+ def begin_group kind
109
+ @open << kind
110
+ end
111
+
112
+ def end_group _kind
113
+ @open.pop
114
+ end
115
+ end
116
+ end
117
+ end