11# frozen_string_literal: true
22
3- require_relative '../scaffold .rb'
3+ require_relative '../delegating_converter .rb'
44require_relative 'copier.rb'
55
6+ ##
7+ # Copies images that are referenced into the same directory as the
8+ # output files.
9+ #
10+ # It finds the images by looking in a comma separated list of directories
11+ # defined by the `resources` attribute.
12+ #
13+ # It can also be configured to copy the images that number callout lists by
14+ # setting `copy-callout-images` to the file extension of the images to copy.
15+ #
16+ # It can also be configured to copy the that decoration admonitions by
17+ # setting `copy-admonition-images` to the file extension of the images
18+ # to copy.
619module CopyImages
20+ def self . activate ( registry )
21+ DelegatingConverter . setup ( registry . document ) { |doc | Converter . new doc }
22+ end
23+
724 ##
8- # Copies images that are referenced into the same directory as the
9- # output files.
10- #
11- # It finds the images by looking in a comma separated list of directories
12- # defined by the `resources` attribute.
13- #
14- # It can also be configured to copy the images that number callout lists by
15- # setting `copy-callout-images` to the file extension of the images to copy.
16- #
17- # It can also be configured to copy the that decoration admonitions by
18- # setting `copy-admonition-images` to the file extension of the images
19- # to copy.
20- #
21- class CopyImages < TreeProcessorScaffold
25+ # A Converter implementation that copies images as it sees them.
26+ class Converter < DelegatingConverter
2227 include Asciidoctor ::Logging
2328
2429 ADMONITION_IMAGE_FOR_REVISION_FLAG = {
@@ -27,130 +32,79 @@ class CopyImages < TreeProcessorScaffold
2732 'deleted' => 'warning' ,
2833 } . freeze
2934 CALLOUT_RX = /CO\d +-(\d +)/
30- INLINE_IMAGE_RX = /(\\ )?image:([^:\s \[ ](?:[^\n \[ ]*[^\s \[ ])?)\[ /m
31- DOCBOOK_IMAGE_RX = %r{<imagedata fileref="([^"]+)"/>}m
3235
33- def initialize ( name )
34- super
36+ def initialize ( delegate )
37+ super ( delegate )
3538 @copier = Copier . new
3639 end
3740
38- def process_block ( block )
39- process_inline_image_from_source block
40- process_inline_image_from_converted block
41- process_block_image block
42- process_callout block
43- process_admonition block
44- end
41+ #### "Conversion" methods
4542
46- def process_block_image ( block )
47- return unless block . context == :image
48-
49- uri = block . image_uri ( block . attr ( 'target' ) )
50- process_image block , uri
43+ def admonition ( node )
44+ if ( extension = node . attr 'copy-admonition-images' )
45+ if ( image = admonition_image node )
46+ path = "images/icons/#{ image } .#{ extension } "
47+ @copier . copy_image node , path
48+ end
49+ end
50+ yield
5151 end
5252
53- ##
54- # Scan the inline image from the asciidoc source. One day Asciidoc will
55- # parse inline things into the AST and we can get at them nicely. Today, we
56- # have to scrape them from the source of the node.
57- def process_inline_image_from_source ( block )
58- return unless block . content_model == :simple
59-
60- block . source . scan ( INLINE_IMAGE_RX ) do |( escape , target ) |
61- next if escape
62-
63- # We have to resolve attributes inside the target. But there is a
64- # "funny" ritual for that because attribute substitution is always
65- # against the document. We have to play the block's attributes against
66- # the document, then clear them on the way out.
67- block . document . playback_attributes block . attributes
68- target = block . sub_attributes target
69- block . document . clear_playback_attributes block . attributes
70- uri = block . image_uri target
71- process_image block , uri
53+ def colist ( node )
54+ if ( extension = node . attr 'copy-callout-images' )
55+ node . items . each do |item |
56+ copy_image_for_callout_items extension , item
57+ end
7258 end
59+ yield
7360 end
7461
75- ##
76- # Scan the inline image from the generated docbook. It is not nice that
77- # this is required but there isn't much we can do about it. We *could*
78- # rewrite all of the image copying to be against the generated docbook
79- # using this code but I feel like that'd be slower. For now, we'll stick
80- # with this.
81- def process_inline_image_from_converted ( block )
82- return unless block . context == :list_item &&
83- block . parent . context == :olist
84-
85- block . text . scan ( DOCBOOK_IMAGE_RX ) do |( target ) |
86- # We have to resolve attributes inside the target. But there is a
87- # "funny" ritual for that because attribute substitution is always
88- # against the document. We have to play the block's attributes against
89- # the document, then clear them on the way out.
90- uri = block . image_uri target
91- process_image block , uri
92- end
62+ def image ( node )
63+ copy_image node , node . attr ( 'target' )
64+ yield
65+ end
66+
67+ def inline_image ( node )
68+ # Inline images aren't "real" and don't have a source_location so we have
69+ # to get the location from the parent.
70+ copy_image node . parent , node . target
71+ yield
9372 end
9473
95- def process_image ( block , uri )
74+ #### Helper methods
75+ def copy_image ( node , uri )
9676 return unless uri
9777 return if Asciidoctor ::Helpers . uriish? uri # Skip external images
9878
99- @copier . copy_image block , uri
79+ @copier . copy_image node , uri
10080 end
10181
102- def process_callout ( block )
103- callout_extension = block . document . attr 'copy-callout-images'
104- return unless callout_extension
105- return unless block . parent && block . parent . context == :colist
106-
107- coids = block . attr ( 'coids' )
82+ def copy_image_for_callout_items ( callout_extension , node )
83+ coids = node . attr ( 'coids' )
10884 return unless coids
10985
11086 coids . scan ( CALLOUT_RX ) do |( index ) |
111- @copier . copy_image (
112- block , "images/icons/callouts/#{ index } .#{ callout_extension } "
113- )
87+ path = "images/icons/callouts/#{ index } .#{ callout_extension } "
88+ @copier . copy_image node , path
11489 end
11590 end
11691
117- def process_admonition ( block )
118- admonition_extension = block . document . attr 'copy-admonition-images'
119- return unless admonition_extension
92+ def admonition_image ( node )
93+ if ( revisionflag = node . attr 'revisionflag' )
94+ image = ADMONITION_IMAGE_FOR_REVISION_FLAG [ revisionflag ]
95+ return image if image
12096
121- process_standard_admonition admonition_extension , block
122- process_change_admonition admonition_extension , block
123- end
124-
125- def process_standard_admonition ( admonition_extension , block )
126- return unless block . context == :admonition
127-
128- # The image for a standard admonition comes from the style
129- style = block . attr 'style'
130- return unless style
131-
132- @copier . copy_image (
133- block , "images/icons/#{ style . downcase } .#{ admonition_extension } "
134- )
135- end
136-
137- def process_change_admonition ( admonition_extension , block )
138- revisionflag = block . attr 'revisionflag'
139- return unless revisionflag
140-
141- admonition_image = ADMONITION_IMAGE_FOR_REVISION_FLAG [ revisionflag ]
142- if admonition_image
143- @copier . copy_image (
144- block , "images/icons/#{ admonition_image } .#{ admonition_extension } "
145- )
146- else
14797 logger . warn (
14898 message_with_context (
14999 "unknow revisionflag #{ revisionflag } " ,
150- source_location : block . source_location
100+ source_location : node . source_location
151101 )
152102 )
103+ return
153104 end
105+ # The image for a standard admonition comes from the style
106+ style = node . attr 'style'
107+ style &.downcase
154108 end
155109 end
156110end
0 commit comments