asciidoctor 1.5.8 → 2.0.0.rc.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.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +162 -17
  3. data/LICENSE +1 -1
  4. data/README-de.adoc +12 -13
  5. data/README-fr.adoc +11 -12
  6. data/README-jp.adoc +11 -12
  7. data/README-zh_CN.adoc +12 -13
  8. data/README.adoc +6 -7
  9. data/asciidoctor.gemspec +19 -24
  10. data/bin/asciidoctor +5 -4
  11. data/data/reference/syntax.adoc +283 -0
  12. data/data/stylesheets/asciidoctor-default.css +56 -52
  13. data/data/stylesheets/coderay-asciidoctor.css +7 -9
  14. data/lib/asciidoctor.rb +171 -232
  15. data/lib/asciidoctor/abstract_block.rb +96 -105
  16. data/lib/asciidoctor/abstract_node.rb +118 -139
  17. data/lib/asciidoctor/attribute_list.rb +10 -14
  18. data/lib/asciidoctor/block.rb +20 -19
  19. data/lib/asciidoctor/callouts.rb +4 -2
  20. data/lib/asciidoctor/cli.rb +3 -2
  21. data/lib/asciidoctor/cli/invoker.rb +14 -21
  22. data/lib/asciidoctor/cli/options.rb +64 -54
  23. data/lib/asciidoctor/converter.rb +357 -185
  24. data/lib/asciidoctor/converter/composite.rb +40 -48
  25. data/lib/asciidoctor/converter/docbook5.rb +604 -640
  26. data/lib/asciidoctor/converter/html5.rb +949 -963
  27. data/lib/asciidoctor/converter/manpage.rb +569 -548
  28. data/lib/asciidoctor/converter/template.rb +231 -272
  29. data/lib/asciidoctor/core_ext.rb +5 -18
  30. data/lib/asciidoctor/core_ext/float/truncate.rb +19 -0
  31. data/lib/asciidoctor/core_ext/match_data/names.rb +7 -0
  32. data/lib/asciidoctor/core_ext/nil_or_empty.rb +1 -0
  33. data/lib/asciidoctor/core_ext/regexp/is_match.rb +4 -2
  34. data/lib/asciidoctor/document.rb +399 -377
  35. data/lib/asciidoctor/extensions.rb +72 -140
  36. data/lib/asciidoctor/helpers.rb +122 -83
  37. data/lib/asciidoctor/inline.rb +5 -1
  38. data/lib/asciidoctor/list.rb +13 -11
  39. data/lib/asciidoctor/logging.rb +17 -16
  40. data/lib/asciidoctor/parser.rb +390 -423
  41. data/lib/asciidoctor/path_resolver.rb +10 -5
  42. data/lib/asciidoctor/reader.rb +286 -263
  43. data/lib/asciidoctor/rouge_ext.rb +39 -0
  44. data/lib/asciidoctor/section.rb +9 -8
  45. data/lib/asciidoctor/stylesheets.rb +19 -37
  46. data/lib/asciidoctor/substitutors.rb +364 -509
  47. data/lib/asciidoctor/syntax_highlighter.rb +238 -0
  48. data/lib/asciidoctor/syntax_highlighter/coderay.rb +87 -0
  49. data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +26 -0
  50. data/lib/asciidoctor/syntax_highlighter/html_pipeline.rb +10 -0
  51. data/lib/asciidoctor/syntax_highlighter/prettify.rb +27 -0
  52. data/lib/asciidoctor/syntax_highlighter/pygments.rb +149 -0
  53. data/lib/asciidoctor/syntax_highlighter/rouge.rb +129 -0
  54. data/lib/asciidoctor/table.rb +73 -66
  55. data/lib/asciidoctor/timings.rb +4 -2
  56. data/lib/asciidoctor/version.rb +2 -1
  57. data/lib/asciidoctor/writer.rb +30 -0
  58. data/man/asciidoctor.1 +19 -15
  59. data/man/asciidoctor.adoc +14 -12
  60. metadata +69 -216
  61. data/CONTRIBUTING.adoc +0 -185
  62. data/Gemfile +0 -60
  63. data/Rakefile +0 -129
  64. data/bin/asciidoctor-safe +0 -15
  65. data/features/open_block.feature +0 -92
  66. data/features/pass_block.feature +0 -66
  67. data/features/step_definitions.rb +0 -49
  68. data/features/text_formatting.feature +0 -57
  69. data/features/xref.feature +0 -1039
  70. data/lib/asciidoctor/converter/base.rb +0 -59
  71. data/lib/asciidoctor/converter/docbook45.rb +0 -93
  72. data/lib/asciidoctor/converter/factory.rb +0 -226
  73. data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +0 -6
  74. data/lib/asciidoctor/core_ext/1.8.7/concurrent/hash.rb +0 -5
  75. data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +0 -4
  76. data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +0 -6
  77. data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +0 -5
  78. data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +0 -6
  79. data/lib/asciidoctor/core_ext/1.8.7/string/limit_bytesize.rb +0 -29
  80. data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +0 -6
  81. data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +0 -6
  82. data/lib/asciidoctor/core_ext/string/limit_bytesize.rb +0 -10
  83. data/test/api_test.rb +0 -1240
  84. data/test/attribute_list_test.rb +0 -242
  85. data/test/attributes_test.rb +0 -1623
  86. data/test/blocks_test.rb +0 -3870
  87. data/test/converter_test.rb +0 -470
  88. data/test/document_test.rb +0 -1853
  89. data/test/extensions_test.rb +0 -1560
  90. data/test/fixtures/asciidoc_index.txt +0 -521
  91. data/test/fixtures/basic-docinfo-footer.html +0 -6
  92. data/test/fixtures/basic-docinfo-footer.xml +0 -8
  93. data/test/fixtures/basic-docinfo.html +0 -1
  94. data/test/fixtures/basic-docinfo.xml +0 -4
  95. data/test/fixtures/basic.asciidoc +0 -5
  96. data/test/fixtures/chapter-a.adoc +0 -3
  97. data/test/fixtures/child-include.adoc +0 -5
  98. data/test/fixtures/circle.svg +0 -9
  99. data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
  100. data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
  101. data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
  102. data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
  103. data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
  104. data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
  105. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
  106. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
  107. data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
  108. data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
  109. data/test/fixtures/docinfo-footer.html +0 -1
  110. data/test/fixtures/docinfo-footer.xml +0 -9
  111. data/test/fixtures/docinfo.html +0 -1
  112. data/test/fixtures/docinfo.xml +0 -3
  113. data/test/fixtures/doctime-localtime.adoc +0 -2
  114. data/test/fixtures/dot.gif +0 -0
  115. data/test/fixtures/encoding.asciidoc +0 -13
  116. data/test/fixtures/file-with-missing-include.adoc +0 -1
  117. data/test/fixtures/grandchild-include.adoc +0 -3
  118. data/test/fixtures/hello-asciidoctor.pdf +0 -69
  119. data/test/fixtures/include-file.asciidoc +0 -24
  120. data/test/fixtures/include-file.jsx +0 -8
  121. data/test/fixtures/include-file.ml +0 -3
  122. data/test/fixtures/include-file.xml +0 -5
  123. data/test/fixtures/lists.adoc +0 -96
  124. data/test/fixtures/master.adoc +0 -5
  125. data/test/fixtures/mismatched-end-tag.adoc +0 -7
  126. data/test/fixtures/other-chapters.adoc +0 -11
  127. data/test/fixtures/outer-include.adoc +0 -5
  128. data/test/fixtures/parent-include-restricted.adoc +0 -5
  129. data/test/fixtures/parent-include.adoc +0 -5
  130. data/test/fixtures/sample.asciidoc +0 -30
  131. data/test/fixtures/section-a.adoc +0 -4
  132. data/test/fixtures/stylesheets/custom.css +0 -3
  133. data/test/fixtures/subdir/index.adoc +0 -3
  134. data/test/fixtures/subdir/inner-include.adoc +0 -3
  135. data/test/fixtures/subdir/middle-include.adoc +0 -5
  136. data/test/fixtures/subs-docinfo.html +0 -2
  137. data/test/fixtures/subs.adoc +0 -6
  138. data/test/fixtures/tagged-class-enclosed.rb +0 -25
  139. data/test/fixtures/tagged-class.rb +0 -23
  140. data/test/fixtures/tip.gif +0 -0
  141. data/test/fixtures/unclosed-tag.adoc +0 -3
  142. data/test/fixtures/unexpected-end-tag.adoc +0 -4
  143. data/test/invoker_test.rb +0 -745
  144. data/test/links_test.rb +0 -855
  145. data/test/lists_test.rb +0 -5151
  146. data/test/logger_test.rb +0 -211
  147. data/test/manpage_test.rb +0 -660
  148. data/test/options_test.rb +0 -262
  149. data/test/paragraphs_test.rb +0 -562
  150. data/test/parser_test.rb +0 -742
  151. data/test/paths_test.rb +0 -395
  152. data/test/preamble_test.rb +0 -173
  153. data/test/reader_test.rb +0 -2161
  154. data/test/sections_test.rb +0 -3575
  155. data/test/substitutions_test.rb +0 -2066
  156. data/test/tables_test.rb +0 -2036
  157. data/test/test_helper.rb +0 -447
  158. data/test/text_test.rb +0 -309
@@ -1,309 +1,268 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
2
  module Asciidoctor
3
- # A {Converter} implementation that uses templates composed in template
4
- # languages supported by {https://github.com/rtomayko/tilt Tilt} to convert
5
- # {AbstractNode} objects from a parsed AsciiDoc document tree to the backend
6
- # format.
7
- #
8
- # The converter scans the specified directories for template files that are
9
- # supported by Tilt. If an engine name (e.g., "slim") is specified in the
10
- # options Hash passed to the constructor, the scan is restricted to template
11
- # files that have a matching extension (e.g., ".slim"). The scanner trims any
12
- # extensions from the basename of the file and uses the resulting name as the
13
- # key under which to store the template. When the {Converter#convert} method
14
- # is invoked, the transform argument is used to select the template from this
15
- # table and use it to convert the node.
16
- #
17
- # For example, the template file "path/to/templates/paragraph.html.slim" will
18
- # be registered as the "paragraph" transform. The template is then used to
19
- # convert a paragraph {Block} object from the parsed AsciiDoc tree to an HTML
20
- # backend format (e.g., "html5").
21
- #
22
- # As an optimization, scan results and templates are cached for the lifetime
23
- # of the Ruby process. If the {https://rubygems.org/gems/concurrent-ruby
24
- # concurrent-ruby} gem is installed, these caches are guaranteed to be thread
25
- # safe. If this gem is not present, there is no such guarantee and a warning
26
- # will be issued.
27
- class Converter::TemplateConverter < Converter::Base
28
- DEFAULT_ENGINE_OPTIONS = {
29
- :erb => { :trim => '<' },
30
- # TODO line 466 of haml/compiler.rb sorts the attributes; file an issue to make this configurable
31
- # NOTE AsciiDoc syntax expects HTML/XML output to use double quotes around attribute values
32
- :haml => { :format => :xhtml, :attr_wrapper => '"', :escape_attrs => false, :ugly => true },
33
- :slim => { :disable_escape => true, :sort_attrs => false, :pretty => false }
34
- }
3
+ # A {Converter} implementation that uses templates composed in template
4
+ # languages supported by {https://github.com/rtomayko/tilt Tilt} to convert
5
+ # {AbstractNode} objects from a parsed AsciiDoc document tree to the backend
6
+ # format.
7
+ #
8
+ # The converter scans the specified directories for template files that are
9
+ # supported by Tilt. If an engine name (e.g., "slim") is specified in the
10
+ # options Hash passed to the constructor, the scan is restricted to template
11
+ # files that have a matching extension (e.g., ".slim"). The scanner trims any
12
+ # extensions from the basename of the file and uses the resulting name as the
13
+ # key under which to store the template. When the {Converter#convert} method
14
+ # is invoked, the transform argument is used to select the template from this
15
+ # table and use it to convert the node.
16
+ #
17
+ # For example, the template file "path/to/templates/paragraph.html.slim" will
18
+ # be registered as the "paragraph" transform. The template is then used to
19
+ # convert a paragraph {Block} object from the parsed AsciiDoc tree to an HTML
20
+ # backend format (e.g., "html5").
21
+ #
22
+ # As an optimization, scan results and templates are cached for the lifetime
23
+ # of the Ruby process. If the {https://rubygems.org/gems/concurrent-ruby
24
+ # concurrent-ruby} gem is installed, these caches are guaranteed to be thread
25
+ # safe. If this gem is not present, there is no such guarantee and a warning
26
+ # will be issued.
27
+ class Converter::TemplateConverter < Converter::Base
28
+ DEFAULT_ENGINE_OPTIONS = {
29
+ erb: { trim: 0 },
30
+ # TODO line 466 of haml/compiler.rb sorts the attributes; file an issue to make this configurable
31
+ # NOTE AsciiDoc syntax expects HTML/XML output to use double quotes around attribute values
32
+ haml: { format: :xhtml, attr_wrapper: '"', escape_attrs: false, ugly: true },
33
+ slim: { disable_escape: true, sort_attrs: false, pretty: false },
34
+ }
35
35
 
36
- begin
37
- unless defined? ::Concurrent::Hash
38
- require ::RUBY_MIN_VERSION_1_9 ? 'concurrent/hash' : 'asciidoctor/core_ext/1.8.7/concurrent/hash'
39
- end
40
- @caches = { :scans => ::Concurrent::Hash.new, :templates => ::Concurrent::Hash.new }
41
- rescue ::LoadError
42
- @caches = { :scans => {}, :templates => {} }
43
- end
36
+ begin
37
+ require 'concurrent/hash' unless defined? ::Concurrent::Hash
38
+ @caches = { scans: ::Concurrent::Hash.new, templates: ::Concurrent::Hash.new }
39
+ rescue ::LoadError
40
+ @caches = { scans: {}, templates: {} }
41
+ end
44
42
 
45
- def self.caches
46
- @caches
47
- end
43
+ def self.caches
44
+ @caches
45
+ end
48
46
 
49
- def self.clear_caches
50
- @caches[:scans].clear if @caches[:scans]
51
- @caches[:templates].clear if @caches[:templates]
52
- end
47
+ def self.clear_caches
48
+ @caches[:scans].clear if @caches[:scans]
49
+ @caches[:templates].clear if @caches[:templates]
50
+ end
53
51
 
54
- def initialize backend, template_dirs, opts = {}
55
- Helpers.require_library 'tilt' unless defined? ::Tilt
56
- @backend = backend
57
- @templates = {}
58
- @template_dirs = template_dirs
59
- @eruby = opts[:eruby]
60
- @safe = opts[:safe]
61
- @active_engines = {}
62
- @engine = opts[:template_engine]
63
- @engine_options = DEFAULT_ENGINE_OPTIONS.inject({}) do |accum, (engine, default_opts)|
64
- accum[engine] = default_opts.dup
65
- accum
66
- end
67
- if opts[:htmlsyntax] == 'html'
68
- @engine_options[:haml][:format] = :html5
69
- @engine_options[:slim][:format] = :html
70
- end
71
- @engine_options[:slim][:include_dirs] = template_dirs.reverse.map {|dir| ::File.expand_path dir }
72
- if (overrides = opts[:template_engine_options])
73
- overrides.each do |engine, override_opts|
74
- (@engine_options[engine] ||= {}).update override_opts
75
- end
76
- end
77
- case opts[:template_cache]
78
- when true
79
- logger.warn 'gem \'concurrent-ruby\' is not installed. This gem is recommended when using the built-in template cache.' unless defined? ::Concurrent::Hash
80
- @caches = self.class.caches
81
- when ::Hash
82
- @caches = opts[:template_cache]
83
- else
84
- @caches = {} # the empty Hash effectively disables caching
52
+ def initialize backend, template_dirs, opts = {}
53
+ Helpers.require_library 'tilt' unless defined? ::Tilt.new
54
+ @backend = backend
55
+ @templates = {}
56
+ @template_dirs = template_dirs
57
+ @eruby = opts[:eruby]
58
+ @safe = opts[:safe]
59
+ @active_engines = {}
60
+ @engine = opts[:template_engine]
61
+ @engine_options = {}.tap {|accum| DEFAULT_ENGINE_OPTIONS.each {|engine, engine_opts| accum[engine] = engine_opts.dup } }
62
+ if opts[:htmlsyntax] == 'html' # if not set, assume xml since this converter is also used for DocBook (which doesn't specify htmlsyntax)
63
+ @engine_options[:haml][:format] = :html5
64
+ @engine_options[:slim][:format] = :html
65
+ end
66
+ @engine_options[:slim][:include_dirs] = template_dirs.reverse.map {|dir| ::File.expand_path dir }
67
+ if (overrides = opts[:template_engine_options])
68
+ overrides.each do |engine, override_opts|
69
+ (@engine_options[engine] ||= {}).update override_opts
85
70
  end
86
- scan
87
- #create_handlers
88
71
  end
72
+ case opts[:template_cache]
73
+ when true
74
+ logger.warn 'gem \'concurrent-ruby\' is not installed. This gem is recommended when using the built-in template cache.' unless defined? ::Concurrent::Hash
75
+ @caches = self.class.caches
76
+ when ::Hash
77
+ @caches = opts[:template_cache]
78
+ else
79
+ @caches = {} # the empty Hash effectively disables caching
80
+ end
81
+ scan
82
+ end
89
83
 
90
- =begin
91
- # Public: Called when this converter is added to a composite converter.
92
- def composed parent
93
- # TODO set the backend info determined during the scan
84
+ # Public: Convert an {AbstractNode} to the backend format using the named template.
85
+ #
86
+ # Looks for a template that matches the value of the template name or, if the template name is not specified, the
87
+ # value of the {AbstractNode#node_name} property.
88
+ #
89
+ # node - the AbstractNode to convert
90
+ # template_name - the String name of the template to use, or the value of
91
+ # the node_name property on the node if a template name is
92
+ # not specified. (optional, default: nil)
93
+ # opts - an optional Hash that is passed as local variables to the
94
+ # template. (optional, default: nil)
95
+ #
96
+ # Returns the [String] result from rendering the template
97
+ def convert node, template_name = nil, opts = nil
98
+ unless (template = @templates[template_name ||= node.node_name])
99
+ raise %(Could not find a custom template to handle transform: #{template_name})
94
100
  end
95
- =end
96
101
 
97
- # Internal: Scans the template directories specified in the constructor for Tilt-supported
98
- # templates, loads the templates and stores the in a Hash that is accessible via the
99
- # {TemplateConverter#templates} method.
100
- #
101
- # Returns nothing
102
- def scan
103
- path_resolver = PathResolver.new
104
- backend = @backend
105
- engine = @engine
106
- @template_dirs.each do |template_dir|
107
- # FIXME need to think about safe mode restrictions here
108
- next unless ::File.directory?(template_dir = (path_resolver.system_path template_dir))
102
+ # Slim doesn't include helpers in the template's execution scope (like HAML), so do it ourselves
103
+ node.extend ::Slim::Helpers if (defined? ::Slim::Helpers) && (::Slim::Template === template)
109
104
 
110
- if engine
111
- file_pattern = %(*.#{engine})
112
- # example: templates/haml
113
- if ::File.directory?(engine_dir = %(#{template_dir}/#{engine}))
114
- template_dir = engine_dir
115
- end
116
- else
117
- # NOTE last matching template wins for template name if no engine is given
118
- file_pattern = '*'
119
- end
105
+ # NOTE opts become locals in the template
106
+ if template_name == 'document'
107
+ (template.render node, opts).strip
108
+ else
109
+ (template.render node, opts).rstrip
110
+ end
111
+ end
120
112
 
121
- # example: templates/html5 (engine not set) or templates/haml/html5 (engine set)
122
- if ::File.directory?(backend_dir = %(#{template_dir}/#{backend}))
123
- template_dir = backend_dir
124
- end
113
+ # Public: Checks whether there is a Tilt template registered with the specified name.
114
+ #
115
+ # name - the String template name
116
+ #
117
+ # Returns a [Boolean] that indicates whether a Tilt template is registered for the
118
+ # specified template name.
119
+ def handles? name
120
+ @templates.key? name
121
+ end
125
122
 
126
- pattern = %(#{template_dir}/#{file_pattern})
123
+ # Public: Retrieves the templates that this converter manages.
124
+ #
125
+ # Returns a [Hash] of Tilt template objects keyed by template name.
126
+ def templates
127
+ @templates.dup
128
+ end
127
129
 
128
- if (scan_cache = @caches[:scans])
129
- template_cache = @caches[:templates]
130
- unless (templates = scan_cache[pattern])
131
- templates = (scan_cache[pattern] = (scan_dir template_dir, pattern, template_cache))
132
- end
133
- templates.each do |name, template|
134
- @templates[name] = template_cache[template.file] = template
135
- end
136
- else
137
- @templates.update scan_dir(template_dir, pattern, @caches[:templates])
138
- end
139
- nil
140
- end
130
+ # Public: Registers a Tilt template with this converter.
131
+ #
132
+ # name - the String template name
133
+ # template - the Tilt template object to register
134
+ #
135
+ # Returns the Tilt template object
136
+ def register name, template
137
+ @templates[name] = if (template_cache = @caches[:templates])
138
+ template_cache[template.file] = template
139
+ else
140
+ template
141
141
  end
142
+ #create_handler name, template
143
+ end
142
144
 
143
- =begin
144
- # Internal: Creates convert methods (e.g., inline_anchor) that delegate to the discovered templates.
145
- #
146
- # Returns nothing
147
- def create_handlers
148
- @templates.each do |name, template|
149
- create_handler name, template
150
- end
151
- nil
152
- end
145
+ private
153
146
 
154
- # Internal: Creates a convert method for the specified name that delegates to the specified template.
155
- #
156
- # Returns nothing
157
- def create_handler name, template
158
- metaclass = class << self; self; end
159
- if name == 'document'
160
- metaclass.send :define_method, name do |node|
161
- (template.render node).strip
147
+ # Internal: Scans the template directories specified in the constructor for Tilt-supported
148
+ # templates, loads the templates and stores the in a Hash that is accessible via the
149
+ # {TemplateConverter#templates} method.
150
+ #
151
+ # Returns nothing
152
+ def scan
153
+ path_resolver = PathResolver.new
154
+ backend = @backend
155
+ engine = @engine
156
+ @template_dirs.each do |template_dir|
157
+ # FIXME need to think about safe mode restrictions here
158
+ next unless ::File.directory?(template_dir = (path_resolver.system_path template_dir))
159
+
160
+ if engine
161
+ file_pattern = %(*.#{engine})
162
+ # example: templates/haml
163
+ if ::File.directory?(engine_dir = %(#{template_dir}/#{engine}))
164
+ template_dir = engine_dir
162
165
  end
163
166
  else
164
- metaclass.send :define_method, name do |node|
165
- (template.render node).rstrip
166
- end
167
+ # NOTE last matching template wins for template name if no engine is given
168
+ file_pattern = '*'
167
169
  end
168
- end
169
- =end
170
170
 
171
- # Public: Convert an {AbstractNode} to the backend format using the named template.
172
- #
173
- # Looks for a template that matches the value of the
174
- # {AbstractNode#node_name} property if a template name is not specified.
175
- #
176
- # node - the AbstractNode to convert
177
- # template_name - the String name of the template to use, or the value of
178
- # the node_name property on the node if a template name is
179
- # not specified. (optional, default: nil)
180
- # opts - an optional Hash that is passed as local variables to the
181
- # template. (optional, default: {})
182
- #
183
- # Returns the [String] result from rendering the template
184
- def convert node, template_name = nil, opts = {}
185
- template_name ||= node.node_name
186
- unless (template = @templates[template_name])
187
- raise %(Could not find a custom template to handle transform: #{template_name})
171
+ # example: templates/html5 (engine not set) or templates/haml/html5 (engine set)
172
+ if ::File.directory?(backend_dir = %(#{template_dir}/#{backend}))
173
+ template_dir = backend_dir
188
174
  end
189
175
 
190
- # Slim doesn't include helpers in the template's execution scope (like HAML), so do it ourselves
191
- node.extend ::Slim::Helpers if (defined? ::Slim::Helpers) && (::Slim::Template === template)
176
+ pattern = %(#{template_dir}/#{file_pattern})
192
177
 
193
- # NOTE opts become locals in the template
194
- if template_name == 'document'
195
- (template.render node, opts).strip
178
+ if (scan_cache = @caches[:scans])
179
+ template_cache = @caches[:templates]
180
+ unless (templates = scan_cache[pattern])
181
+ templates = scan_cache[pattern] = scan_dir template_dir, pattern, template_cache
182
+ end
183
+ templates.each do |name, template|
184
+ @templates[name] = template_cache[template.file] = template
185
+ end
196
186
  else
197
- (template.render node, opts).rstrip
187
+ @templates.update scan_dir(template_dir, pattern, @caches[:templates])
198
188
  end
189
+ nil
199
190
  end
191
+ end
200
192
 
201
- # Public: Checks whether there is a Tilt template registered with the specified name.
202
- #
203
- # name - the String template name
204
- #
205
- # Returns a [Boolean] that indicates whether a Tilt template is registered for the
206
- # specified template name.
207
- def handles? name
208
- @templates.key? name
209
- end
210
-
211
- # Public: Retrieves the templates that this converter manages.
212
- #
213
- # Returns a [Hash] of Tilt template objects keyed by template name.
214
- def templates
215
- @templates.dup
216
- end
217
-
218
- # Public: Registers a Tilt template with this converter.
219
- #
220
- # name - the String template name
221
- # template - the Tilt template object to register
222
- #
223
- # Returns the Tilt template object
224
- def register name, template
225
- @templates[name] = if (template_cache = @caches[:templates])
226
- template_cache[template.file] = template
227
- else
228
- template
193
+ # Internal: Scan the specified directory for template files matching pattern and instantiate
194
+ # a Tilt template for each matched file.
195
+ #
196
+ # Returns the scan result as a [Hash]
197
+ def scan_dir template_dir, pattern, template_cache = nil
198
+ result, helpers = {}, nil
199
+ # Grab the files in the top level of the directory (do not recurse)
200
+ ::Dir.glob(pattern).select {|match| ::File.file? match }.each do |file|
201
+ if (basename = ::File.basename file) == 'helpers.rb'
202
+ helpers = file
203
+ next
204
+ elsif (path_segments = basename.split '.').size < 2
205
+ next
229
206
  end
230
- #create_handler name, template
231
- end
232
-
233
- # Internal: Scan the specified directory for template files matching pattern and instantiate
234
- # a Tilt template for each matched file.
235
- #
236
- # Returns the scan result as a [Hash]
237
- def scan_dir template_dir, pattern, template_cache = nil
238
- result, helpers = {}, nil
239
- # Grab the files in the top level of the directory (do not recurse)
240
- ::Dir.glob(pattern).select {|match| ::File.file? match }.each do |file|
241
- if (basename = ::File.basename file) == 'helpers.rb'
242
- helpers = file
243
- next
244
- elsif (path_segments = basename.split '.').size < 2
245
- next
246
- end
247
- if (name = path_segments[0]) == 'block_ruler'
248
- name = 'thematic_break'
249
- elsif name.start_with? 'block_'
250
- name = name.slice 6, name.length
251
- end
252
- unless template_cache && (template = template_cache[file])
253
- template_class, extra_engine_options, extsym = ::Tilt, {}, path_segments[-1].to_sym
254
- case extsym
255
- when :slim
256
- unless @active_engines[extsym]
257
- # NOTE slim doesn't get automatically loaded by Tilt
258
- Helpers.require_library 'slim' unless defined? ::Slim
259
- ::Slim::Engine.define_options :asciidoc => {}
260
- # align safe mode of AsciiDoc embedded in Slim template with safe mode of current document
261
- # NOTE safe mode won't get updated if using template cache and changing safe mode
262
- (@engine_options[extsym][:asciidoc] ||= {})[:safe] ||= @safe if @safe && ::Slim::VERSION >= '3.0'
263
- # load include plugin when using Slim >= 2.1
264
- require 'slim/include' unless (defined? ::Slim::Include) || ::Slim::VERSION < '2.1'
265
- @active_engines[extsym] = true
266
- end
267
- when :haml
268
- unless @active_engines[extsym]
269
- Helpers.require_library 'haml' unless defined? ::Haml
270
- # NOTE Haml 5 dropped support for pretty printing
271
- @engine_options[extsym].delete :ugly if defined? ::Haml::TempleEngine
272
- @active_engines[extsym] = true
273
- end
274
- when :erb
275
- template_class, extra_engine_options = (@active_engines[extsym] ||= (load_eruby @eruby))
276
- when :rb
277
- next
278
- else
279
- next unless ::Tilt.registered? extsym.to_s
207
+ if (name = path_segments[0]) == 'block_ruler'
208
+ name = 'thematic_break'
209
+ elsif name.start_with? 'block_'
210
+ name = name.slice 6, name.length
211
+ end
212
+ unless template_cache && (template = template_cache[file])
213
+ template_class, extra_engine_options, extsym = ::Tilt, {}, path_segments[-1].to_sym
214
+ case extsym
215
+ when :slim
216
+ unless @active_engines[extsym]
217
+ # NOTE slim doesn't get automatically loaded by Tilt
218
+ Helpers.require_library 'slim' unless defined? ::Slim::Engine
219
+ require 'slim/include' unless defined? ::Slim::Include
220
+ ::Slim::Engine.define_options asciidoc: {}
221
+ # align safe mode of AsciiDoc embedded in Slim template with safe mode of current document
222
+ # NOTE safe mode won't get updated if using template cache and changing safe mode
223
+ (@engine_options[extsym][:asciidoc] ||= {})[:safe] ||= @safe if @safe
224
+ @active_engines[extsym] = true
280
225
  end
281
- template = template_class.new file, 1, (@engine_options[extsym] ||= {}).merge(extra_engine_options)
226
+ when :haml
227
+ unless @active_engines[extsym]
228
+ Helpers.require_library 'haml' unless defined? ::Haml::Engine
229
+ # NOTE Haml 5 dropped support for pretty printing
230
+ @engine_options[extsym].delete :ugly if defined? ::Haml::TempleEngine
231
+ @active_engines[extsym] = true
232
+ end
233
+ when :erb
234
+ template_class, extra_engine_options = (@active_engines[extsym] ||= (load_eruby @eruby))
235
+ when :rb
236
+ next
237
+ else
238
+ next unless ::Tilt.registered? extsym.to_s
282
239
  end
283
- result[name] = template
284
- end
285
- if helpers || ::File.file?(helpers = %(#{template_dir}/helpers.rb))
286
- require helpers
240
+ template = template_class.new file, 1, (@engine_options[extsym] ||= {}).merge(extra_engine_options)
287
241
  end
288
- result
242
+ result[name] = template
243
+ end
244
+ if helpers || ::File.file?(helpers = %(#{template_dir}/helpers.rb))
245
+ require helpers
289
246
  end
247
+ result
248
+ end
290
249
 
291
- # Internal: Load the eRuby implementation
292
- #
293
- # name - the String name of the eRuby implementation
294
- #
295
- # Returns an [Array] containing the Tilt template Class for the eRuby implementation
296
- # and a Hash of additional options to pass to the initializer
297
- def load_eruby name
298
- if !name || name == 'erb'
299
- require 'erb' unless defined? ::ERB
300
- [::Tilt::ERBTemplate, {}]
301
- elsif name == 'erubis'
302
- Helpers.require_library 'erubis' unless defined? ::Erubis::FastEruby
303
- [::Tilt::ErubisTemplate, { :engine_class => ::Erubis::FastEruby }]
304
- else
305
- raise ::ArgumentError, %(Unknown ERB implementation: #{name})
306
- end
250
+ # Internal: Load the eRuby implementation
251
+ #
252
+ # name - the String name of the eRuby implementation
253
+ #
254
+ # Returns an [Array] containing the Tilt template Class for the eRuby implementation
255
+ # and a Hash of additional options to pass to the initializer
256
+ def load_eruby name
257
+ if !name || name == 'erb'
258
+ require 'erb' unless defined? ::ERB.version
259
+ [::Tilt::ERBTemplate, {}]
260
+ elsif name == 'erubis'
261
+ Helpers.require_library 'erubis' unless defined? ::Erubis::FastEruby
262
+ [::Tilt::ErubisTemplate, { engine_class: ::Erubis::FastEruby }]
263
+ else
264
+ raise ::ArgumentError, %(Unknown ERB implementation: #{name})
307
265
  end
308
266
  end
309
267
  end
268
+ end