asciidoctor 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of asciidoctor might be problematic. Click here for more details.
- data/README.asciidoc +11 -2
- data/asciidoctor.gemspec +3 -2
- data/lib/asciidoctor.rb +95 -62
- data/lib/asciidoctor/abstract_block.rb +7 -5
- data/lib/asciidoctor/abstract_node.rb +63 -15
- data/lib/asciidoctor/attribute_list.rb +3 -1
- data/lib/asciidoctor/backends/base_template.rb +17 -7
- data/lib/asciidoctor/backends/docbook45.rb +182 -150
- data/lib/asciidoctor/backends/html5.rb +138 -110
- data/lib/asciidoctor/block.rb +21 -18
- data/lib/asciidoctor/callouts.rb +3 -1
- data/lib/asciidoctor/cli/invoker.rb +3 -3
- data/lib/asciidoctor/cli/options.rb +6 -6
- data/lib/asciidoctor/debug.rb +7 -6
- data/lib/asciidoctor/document.rb +197 -25
- data/lib/asciidoctor/errors.rb +1 -1
- data/lib/asciidoctor/helpers.rb +29 -0
- data/lib/asciidoctor/inline.rb +11 -4
- data/lib/asciidoctor/lexer.rb +338 -182
- data/lib/asciidoctor/list_item.rb +14 -12
- data/lib/asciidoctor/reader.rb +423 -206
- data/lib/asciidoctor/renderer.rb +59 -15
- data/lib/asciidoctor/section.rb +7 -4
- data/lib/asciidoctor/substituters.rb +536 -511
- data/lib/asciidoctor/table.rb +473 -472
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +23 -14
- data/man/asciidoctor.ad +13 -7
- data/test/attributes_test.rb +42 -8
- data/test/blocks_test.rb +161 -1
- data/test/document_test.rb +134 -16
- data/test/invoker_test.rb +14 -6
- data/test/lexer_test.rb +45 -18
- data/test/lists_test.rb +79 -0
- data/test/paragraphs_test.rb +9 -1
- data/test/reader_test.rb +456 -19
- data/test/sections_test.rb +19 -0
- data/test/substitutions_test.rb +14 -12
- data/test/tables_test.rb +10 -10
- metadata +3 -5
data/lib/asciidoctor/block.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
module Asciidoctor
|
1
2
|
# Public: Methods for managing blocks of Asciidoc content in a section.
|
2
3
|
#
|
3
4
|
# Examples
|
@@ -5,7 +6,7 @@
|
|
5
6
|
# block = Asciidoctor::Block.new(document, :paragraph, ["`This` is a <test>"])
|
6
7
|
# block.content
|
7
8
|
# => ["<em>This</em> is a <test>"]
|
8
|
-
class
|
9
|
+
class Block < AbstractBlock
|
9
10
|
|
10
11
|
# Public: Create alias for context to be consistent w/ AsciiDoc
|
11
12
|
alias :blockname :context
|
@@ -32,7 +33,8 @@ class Asciidoctor::Block < Asciidoctor::AbstractBlock
|
|
32
33
|
# rendered and returned as content that can be included in the
|
33
34
|
# parent block's template.
|
34
35
|
def render
|
35
|
-
|
36
|
+
Debug.debug { "Now rendering #{@context} block for #{self}" }
|
37
|
+
@document.playback_attributes @attributes
|
36
38
|
out = renderer.render("block_#{@context}", self)
|
37
39
|
@document.callouts.next_list if @context == :colist
|
38
40
|
out
|
@@ -40,42 +42,42 @@ class Asciidoctor::Block < Asciidoctor::AbstractBlock
|
|
40
42
|
|
41
43
|
def splain(parent_level = 0)
|
42
44
|
parent_level += 1
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
Debug.puts_indented(parent_level, "Block id: #{id}") unless self.id.nil?
|
46
|
+
Debug.puts_indented(parent_level, "Block title: #{title}") unless self.title.nil?
|
47
|
+
Debug.puts_indented(parent_level, "Block caption: #{caption}") unless self.caption.nil?
|
48
|
+
Debug.puts_indented(parent_level, "Block level: #{level}") unless self.level.nil?
|
49
|
+
Debug.puts_indented(parent_level, "Block context: #{context}") unless self.context.nil?
|
48
50
|
|
49
|
-
|
51
|
+
Debug.puts_indented(parent_level, "Blocks: #{@blocks.count}")
|
50
52
|
|
51
53
|
if buffer.is_a? Enumerable
|
52
54
|
buffer.each_with_index do |buf, i|
|
53
|
-
|
54
|
-
|
55
|
-
|
55
|
+
Debug.puts_indented(parent_level, "v" * (60 - parent_level*2))
|
56
|
+
Debug.puts_indented(parent_level, "Buffer ##{i} is a #{buf.class}")
|
57
|
+
Debug.puts_indented(parent_level, "Name is #{buf.title rescue 'n/a'}")
|
56
58
|
|
57
59
|
if buf.respond_to? :splain
|
58
60
|
buf.splain(parent_level)
|
59
61
|
else
|
60
|
-
|
62
|
+
Debug.puts_indented(parent_level, "Buffer: #{buf}")
|
61
63
|
end
|
62
|
-
|
64
|
+
Debug.puts_indented(parent_level, "^" * (60 - parent_level*2))
|
63
65
|
end
|
64
66
|
else
|
65
67
|
if buffer.respond_to? :splain
|
66
68
|
buffer.splain(parent_level)
|
67
69
|
else
|
68
|
-
|
70
|
+
Debug.puts_indented(parent_level, "Buffer: #{@buffer}")
|
69
71
|
end
|
70
72
|
end
|
71
73
|
|
72
74
|
@blocks.each_with_index do |block, i|
|
73
|
-
|
74
|
-
|
75
|
-
|
75
|
+
Debug.puts_indented(parent_level, "v" * (60 - parent_level*2))
|
76
|
+
Debug.puts_indented(parent_level, "Block ##{i} is a #{block.class}")
|
77
|
+
Debug.puts_indented(parent_level, "Name is #{block.title rescue 'n/a'}")
|
76
78
|
|
77
79
|
block.splain(parent_level) if block.respond_to? :splain
|
78
|
-
|
80
|
+
Debug.puts_indented(parent_level, "^" * (60 - parent_level*2))
|
79
81
|
end
|
80
82
|
|
81
83
|
nil
|
@@ -119,3 +121,4 @@ class Asciidoctor::Block < Asciidoctor::AbstractBlock
|
|
119
121
|
"#{super.to_s} - #@context [blocks:#{(@blocks || []).size}]"
|
120
122
|
end
|
121
123
|
end
|
124
|
+
end
|
data/lib/asciidoctor/callouts.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
+
module Asciidoctor
|
1
2
|
# Public: Maintains a catalog of callouts and their associations.
|
2
|
-
class
|
3
|
+
class Callouts
|
3
4
|
def initialize
|
4
5
|
@lists = []
|
5
6
|
@list_index = 0
|
@@ -115,3 +116,4 @@ class Asciidoctor::Callouts
|
|
115
116
|
"CO#{list_index}-#{co_index}"
|
116
117
|
end
|
117
118
|
end
|
119
|
+
end
|
@@ -14,12 +14,12 @@ module Asciidoctor
|
|
14
14
|
@code = 0
|
15
15
|
@timings = {}
|
16
16
|
options = options.flatten
|
17
|
-
if !options.empty? && options.first.is_a?(
|
17
|
+
if !options.empty? && options.first.is_a?(Cli::Options)
|
18
18
|
@options = options.first
|
19
19
|
elsif options.first.is_a? Hash
|
20
|
-
@options =
|
20
|
+
@options = Cli::Options.new(options)
|
21
21
|
else
|
22
|
-
@options =
|
22
|
+
@options = Cli::Options.parse!(options)
|
23
23
|
# hmmm
|
24
24
|
if @options.is_a?(Integer)
|
25
25
|
@code = @options
|
@@ -10,7 +10,7 @@ module Asciidoctor
|
|
10
10
|
self[:attributes] = options[:attributes] || {}
|
11
11
|
self[:input_file] = options[:input_file] || nil
|
12
12
|
self[:output_file] = options[:output_file] || nil
|
13
|
-
self[:safe] = options[:safe] ||
|
13
|
+
self[:safe] = options[:safe] || SafeMode::UNSAFE
|
14
14
|
self[:header_footer] = options[:header_footer] || true
|
15
15
|
self[:template_dir] = options[:template_dir] || nil
|
16
16
|
if options[:doctype]
|
@@ -55,15 +55,15 @@ Example: asciidoctor -b html5 source.asciidoc
|
|
55
55
|
self[:output_file] = output_file
|
56
56
|
end
|
57
57
|
opts.on('--safe',
|
58
|
-
'set safe mode to safe (default:
|
58
|
+
'set safe mode level to safe (default: unsafe)',
|
59
59
|
'enables include macros, but restricts access to ancestor paths of source file',
|
60
60
|
'provided for compatibility with the asciidoc command') do
|
61
|
-
self[:safe] =
|
61
|
+
self[:safe] = SafeMode::SAFE
|
62
62
|
end
|
63
|
-
opts.on('-S', '--safe-mode SAFE_MODE', ['unsafe', 'safe', 'secure'],
|
64
|
-
'set safe mode level explicitly: [unsafe, safe, secure] (default:
|
63
|
+
opts.on('-S', '--safe-mode SAFE_MODE', ['unsafe', 'safe', 'server', 'secure'],
|
64
|
+
'set safe mode level explicitly: [unsafe, safe, server, secure] (default: unsafe)',
|
65
65
|
'disables potentially dangerous macros in source files, such as include::[]') do |safe_mode|
|
66
|
-
self[:safe] =
|
66
|
+
self[:safe] = SafeMode.const_get(safe_mode.upcase)
|
67
67
|
end
|
68
68
|
opts.on('-s', '--no-header-footer', 'suppress output of header and footer (default: false)') do
|
69
69
|
self[:header_footer] = false
|
data/lib/asciidoctor/debug.rb
CHANGED
@@ -1,24 +1,25 @@
|
|
1
1
|
module Asciidoctor
|
2
|
+
module Debug
|
2
3
|
@show_debug = nil
|
3
|
-
|
4
|
+
|
4
5
|
def self.debug
|
5
6
|
puts yield if self.show_debug_output?
|
6
7
|
end
|
7
|
-
|
8
|
+
|
8
9
|
def self.set_debug(value)
|
9
10
|
@show_debug = value
|
10
11
|
end
|
11
|
-
|
12
|
+
|
12
13
|
def self.show_debug_output?
|
13
14
|
@show_debug || (ENV['DEBUG'] == 'true' && ENV['SUPPRESS_DEBUG'] != 'true')
|
14
15
|
end
|
15
|
-
|
16
|
+
|
16
17
|
def self.puts_indented(level, *args)
|
17
18
|
indentation = " " * level * 2
|
18
|
-
|
19
|
+
|
19
20
|
args.each do |arg|
|
20
21
|
self.debug { "#{indentation}#{arg}" }
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
24
|
-
|
25
|
+
end
|
data/lib/asciidoctor/document.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
module Asciidoctor
|
1
2
|
# Public: Methods for parsing Asciidoc documents and rendering them
|
2
3
|
# using erb templates.
|
3
4
|
#
|
@@ -15,11 +16,19 @@
|
|
15
16
|
#
|
16
17
|
# notitle - The h1 heading should not be shown
|
17
18
|
# noheader - The header block (h1 heading, author, revision info) should not be shown
|
18
|
-
class
|
19
|
-
|
20
|
-
include Asciidoctor
|
19
|
+
class Document < AbstractBlock
|
21
20
|
|
22
21
|
Footnote = Struct.new(:index, :id, :text)
|
22
|
+
AttributeEntry = Struct.new(:name, :value, :negate) do
|
23
|
+
def initialize(name, value, negate = nil)
|
24
|
+
super(name, value, negate.nil? ? value.nil? : false)
|
25
|
+
end
|
26
|
+
|
27
|
+
def save_to(block_attributes)
|
28
|
+
block_attributes[:attribute_entries] ||= []
|
29
|
+
block_attributes[:attribute_entries] << self
|
30
|
+
end
|
31
|
+
end
|
23
32
|
|
24
33
|
# Public A read-only integer value indicating the level of security that
|
25
34
|
# should be enforced while processing this document. The value must be
|
@@ -122,43 +131,66 @@ class Asciidoctor::Document < Asciidoctor::AbstractBlock
|
|
122
131
|
@attributes['asciidoctor-version'] = VERSION
|
123
132
|
@attributes['sectids'] = ''
|
124
133
|
@attributes['encoding'] = 'UTF-8'
|
125
|
-
|
126
|
-
|
134
|
+
@attributes['notitle'] = '' if !@options[:header_footer]
|
135
|
+
|
136
|
+
# language strings
|
137
|
+
# TODO load these based on language settings
|
138
|
+
@attributes['caution-caption'] = 'Caution'
|
139
|
+
@attributes['important-caption'] = 'Important'
|
140
|
+
@attributes['note-caption'] = 'Note'
|
141
|
+
@attributes['tip-caption'] = 'Tip'
|
142
|
+
@attributes['warning-caption'] = 'Warning'
|
143
|
+
@attributes['appendix-caption'] = 'Appendix'
|
144
|
+
@attributes['example-caption'] = 'Example'
|
145
|
+
@attributes['figure-caption'] = 'Figure'
|
146
|
+
@attributes['table-caption'] = 'Table'
|
147
|
+
@attributes['toc-title'] = 'Table of Contents'
|
148
|
+
|
149
|
+
@attribute_overrides = options[:attributes] || {}
|
127
150
|
|
128
151
|
# the only way to set the include-depth attribute is via the document options
|
129
152
|
# 10 is the AsciiDoc default, though currently Asciidoctor only supports 1 level
|
130
|
-
attribute_overrides['include-depth'] ||= 10
|
153
|
+
@attribute_overrides['include-depth'] ||= 10
|
131
154
|
|
132
155
|
# if the base_dir option is specified, it overrides docdir as the root for relative paths
|
133
156
|
# otherwise, the base_dir is the directory of the source file (docdir) or the current
|
134
157
|
# directory of the input is a string
|
135
158
|
if options[:base_dir].nil?
|
136
|
-
if attribute_overrides['docdir']
|
137
|
-
@base_dir = attribute_overrides['docdir'] = File.expand_path(attribute_overrides['docdir'])
|
159
|
+
if @attribute_overrides['docdir']
|
160
|
+
@base_dir = @attribute_overrides['docdir'] = File.expand_path(@attribute_overrides['docdir'])
|
138
161
|
else
|
139
162
|
# perhaps issue a warning here?
|
140
|
-
@base_dir = attribute_overrides['docdir'] = Dir.pwd
|
163
|
+
@base_dir = @attribute_overrides['docdir'] = Dir.pwd
|
141
164
|
end
|
142
165
|
else
|
143
|
-
@base_dir = attribute_overrides['docdir'] = File.expand_path(options[:base_dir])
|
166
|
+
@base_dir = @attribute_overrides['docdir'] = File.expand_path(options[:base_dir])
|
167
|
+
end
|
168
|
+
|
169
|
+
# allow common attributes backend and doctype to be set using options hash
|
170
|
+
unless @options[:backend].nil?
|
171
|
+
@attribute_overrides['backend'] = @options[:backend]
|
172
|
+
end
|
173
|
+
|
174
|
+
unless @options[:doctype].nil?
|
175
|
+
@attribute_overrides['doctype'] = @options[:doctype]
|
144
176
|
end
|
145
177
|
|
146
178
|
if @safe >= SafeMode::SERVER
|
147
179
|
# restrict document from setting source-highlighter and backend
|
148
|
-
attribute_overrides['source-highlighter'] ||= nil
|
149
|
-
attribute_overrides['backend'] ||= DEFAULT_BACKEND
|
180
|
+
@attribute_overrides['source-highlighter'] ||= nil
|
181
|
+
@attribute_overrides['backend'] ||= DEFAULT_BACKEND
|
150
182
|
# restrict document from seeing the docdir and trim docfile to relative path
|
151
|
-
if attribute_overrides.has_key?('docfile') && @parent_document.nil?
|
152
|
-
attribute_overrides['docfile'] = attribute_overrides['docfile'][(attribute_overrides['docdir'].length + 1)..-1]
|
183
|
+
if @attribute_overrides.has_key?('docfile') && @parent_document.nil?
|
184
|
+
@attribute_overrides['docfile'] = @attribute_overrides['docfile'][(@attribute_overrides['docdir'].length + 1)..-1]
|
153
185
|
end
|
154
|
-
attribute_overrides['docdir'] = ''
|
186
|
+
@attribute_overrides['docdir'] = ''
|
155
187
|
# restrict document from enabling icons
|
156
188
|
if @safe >= SafeMode::SECURE
|
157
|
-
attribute_overrides['icons'] ||= nil
|
189
|
+
@attribute_overrides['icons'] ||= nil
|
158
190
|
end
|
159
191
|
end
|
160
192
|
|
161
|
-
attribute_overrides.delete_if {|key, val|
|
193
|
+
@attribute_overrides.delete_if {|key, val|
|
162
194
|
verdict = false
|
163
195
|
# a nil or negative key undefines the attribute
|
164
196
|
if val.nil? || key[-1..-1] == '!'
|
@@ -184,7 +216,7 @@ class Asciidoctor::Document < Asciidoctor::AbstractBlock
|
|
184
216
|
# don't need to do the extra processing within our own document
|
185
217
|
@reader = Reader.new(data)
|
186
218
|
else
|
187
|
-
@reader = Reader.new(data, self,
|
219
|
+
@reader = Reader.new(data, self, true, &block)
|
188
220
|
end
|
189
221
|
|
190
222
|
# dynamic intrinstic attribute values
|
@@ -202,13 +234,11 @@ class Asciidoctor::Document < Asciidoctor::AbstractBlock
|
|
202
234
|
@attributes['iconsdir'] ||= File.join(@attributes.fetch('imagesdir', 'images'), 'icons')
|
203
235
|
|
204
236
|
# Now parse the lines in the reader into blocks
|
205
|
-
Lexer.parse(@reader, self)
|
206
|
-
# or we could make it...
|
207
|
-
#self << *Lexer.parse(@reader, self)
|
237
|
+
Lexer.parse(@reader, self, :header_only => @options.fetch(:parse_header_only, false))
|
208
238
|
|
209
239
|
@callouts.rewind
|
210
240
|
|
211
|
-
|
241
|
+
Debug.debug {
|
212
242
|
msg = []
|
213
243
|
msg << "Found #{@blocks.size} blocks in this document:"
|
214
244
|
@blocks.each {|b|
|
@@ -276,12 +306,25 @@ class Asciidoctor::Document < Asciidoctor::AbstractBlock
|
|
276
306
|
end
|
277
307
|
end
|
278
308
|
|
309
|
+
def footnotes?
|
310
|
+
not @references[:footnotes].empty?
|
311
|
+
end
|
312
|
+
|
313
|
+
def footnotes
|
314
|
+
@references[:footnotes]
|
315
|
+
end
|
316
|
+
|
279
317
|
def nested?
|
280
318
|
!@parent_document.nil?
|
281
319
|
end
|
282
320
|
|
283
321
|
# Make the raw source for the Document available.
|
284
322
|
def source
|
323
|
+
@reader.source.join if @reader
|
324
|
+
end
|
325
|
+
|
326
|
+
# Make the raw source lines for the Document available.
|
327
|
+
def source_lines
|
285
328
|
@reader.source if @reader
|
286
329
|
end
|
287
330
|
|
@@ -289,13 +332,17 @@ class Asciidoctor::Document < Asciidoctor::AbstractBlock
|
|
289
332
|
@attributes['doctype']
|
290
333
|
end
|
291
334
|
|
335
|
+
def backend
|
336
|
+
@attributes['backend']
|
337
|
+
end
|
338
|
+
|
292
339
|
# The title explicitly defined in the document attributes
|
293
340
|
def title
|
294
341
|
@attributes['title']
|
295
342
|
end
|
296
343
|
|
297
344
|
def title=(title)
|
298
|
-
@header
|
345
|
+
@header ||= Section.new self
|
299
346
|
@header.title = title
|
300
347
|
end
|
301
348
|
|
@@ -311,6 +358,20 @@ class Asciidoctor::Document < Asciidoctor::AbstractBlock
|
|
311
358
|
end
|
312
359
|
alias :name :doctitle
|
313
360
|
|
361
|
+
# Public: Convenience method to retrieve the document attribute 'author'
|
362
|
+
#
|
363
|
+
# returns the full name of the author as a String
|
364
|
+
def author
|
365
|
+
@attributes['author']
|
366
|
+
end
|
367
|
+
|
368
|
+
# Public: Convenience method to retrieve the document attribute 'revdate'
|
369
|
+
#
|
370
|
+
# returns the date of last revision for the document as a String
|
371
|
+
def revdate
|
372
|
+
@attributes['revdate']
|
373
|
+
end
|
374
|
+
|
314
375
|
def notitle
|
315
376
|
@attributes.has_key? 'notitle'
|
316
377
|
end
|
@@ -327,6 +388,114 @@ class Asciidoctor::Document < Asciidoctor::AbstractBlock
|
|
327
388
|
def has_header?
|
328
389
|
!@header.nil?
|
329
390
|
end
|
391
|
+
|
392
|
+
# Internal: Branch the attributes so that the original state can be restored
|
393
|
+
# at a future time.
|
394
|
+
def save_attributes
|
395
|
+
# css-signature cannot be updated after header attributes are processed
|
396
|
+
if @id.nil? && @attributes.has_key?('css-signature')
|
397
|
+
@id = @attributes['css-signature']
|
398
|
+
end
|
399
|
+
@original_attributes = @attributes.dup
|
400
|
+
end
|
401
|
+
|
402
|
+
# Internal: Restore the attributes to the previously saved state
|
403
|
+
def restore_attributes
|
404
|
+
@attributes = @original_attributes
|
405
|
+
end
|
406
|
+
|
407
|
+
# Internal: Delete any attributes stored for playback
|
408
|
+
def clear_playback_attributes(attributes)
|
409
|
+
attributes.delete(:attribute_entries)
|
410
|
+
end
|
411
|
+
|
412
|
+
# Internal: Replay attribute assignments at the block level
|
413
|
+
def playback_attributes(block_attributes)
|
414
|
+
if block_attributes.has_key? :attribute_entries
|
415
|
+
block_attributes[:attribute_entries].each do |entry|
|
416
|
+
if entry.negate
|
417
|
+
@attributes.delete(entry.name)
|
418
|
+
else
|
419
|
+
@attributes[entry.name] = entry.value
|
420
|
+
end
|
421
|
+
end
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
# Public: Set the specified attribute on the document if the name is not locked
|
426
|
+
#
|
427
|
+
# If the attribute is locked, false is returned. Otherwise, the value is
|
428
|
+
# assigned to the attribute name after first performing attribute
|
429
|
+
# substitutions on the value. If the attribute name is 'backend', then the
|
430
|
+
# value of backend-related attributes are updated.
|
431
|
+
#
|
432
|
+
# name - the String attribute name
|
433
|
+
# value - the String attribute value
|
434
|
+
#
|
435
|
+
# returns true if the attribute was set, false if it was not set because it's locked
|
436
|
+
def set_attribute(name, value)
|
437
|
+
if attribute_locked?(name)
|
438
|
+
false
|
439
|
+
else
|
440
|
+
@attributes[name] = apply_attribute_value_subs(value)
|
441
|
+
if name == 'backend'
|
442
|
+
update_backend_attributes()
|
443
|
+
end
|
444
|
+
true
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
# Public: Delete the specified attribute from the document if the name is not locked
|
449
|
+
#
|
450
|
+
# If the attribute is locked, false is returned. Otherwise, the attribute is deleted.
|
451
|
+
#
|
452
|
+
# name - the String attribute name
|
453
|
+
#
|
454
|
+
# returns true if the attribute was deleted, false if it was not because it's locked
|
455
|
+
def delete_attribute(name)
|
456
|
+
if attribute_locked?(name)
|
457
|
+
false
|
458
|
+
else
|
459
|
+
@attributes.delete(name)
|
460
|
+
true
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
# Public: Determine if the attribute has been locked by being assigned in document options
|
465
|
+
#
|
466
|
+
# key - The attribute key to check
|
467
|
+
#
|
468
|
+
# Returns true if the attribute is locked, false otherwise
|
469
|
+
def attribute_locked?(name)
|
470
|
+
@attribute_overrides.has_key?(name) || @attribute_overrides.has_key?("#{name}!")
|
471
|
+
end
|
472
|
+
|
473
|
+
# Internal: Apply substitutions to the attribute value
|
474
|
+
#
|
475
|
+
# If the value is an inline passthrough macro (e.g., pass:[text]), then
|
476
|
+
# apply the substitutions defined on the macro to the text. Otherwise,
|
477
|
+
# apply the verbatim substitutions to the value.
|
478
|
+
#
|
479
|
+
# value - The String attribute value on which to perform substitutions
|
480
|
+
#
|
481
|
+
# Returns The String value with substitutions performed.
|
482
|
+
def apply_attribute_value_subs(value)
|
483
|
+
if value.match(REGEXP[:pass_macro_basic])
|
484
|
+
# copy match for Ruby 1.8.7 compat
|
485
|
+
m = $~
|
486
|
+
subs = []
|
487
|
+
if !m[1].empty?
|
488
|
+
subs = resolve_subs(m[1])
|
489
|
+
end
|
490
|
+
if !subs.empty?
|
491
|
+
apply_subs(m[2], subs)
|
492
|
+
else
|
493
|
+
m[2]
|
494
|
+
end
|
495
|
+
else
|
496
|
+
apply_header_subs(value)
|
497
|
+
end
|
498
|
+
end
|
330
499
|
|
331
500
|
# Public: Update the backend attributes to reflect a change in the selected backend
|
332
501
|
def update_backend_attributes()
|
@@ -355,7 +524,7 @@ class Asciidoctor::Document < Asciidoctor::AbstractBlock
|
|
355
524
|
end
|
356
525
|
|
357
526
|
def splain
|
358
|
-
|
527
|
+
Debug.debug {
|
359
528
|
msg = ''
|
360
529
|
if @header
|
361
530
|
msg = "Header is #{@header}"
|
@@ -381,11 +550,12 @@ class Asciidoctor::Document < Asciidoctor::AbstractBlock
|
|
381
550
|
render_options = {}
|
382
551
|
|
383
552
|
# Load up relevant Document @options
|
384
|
-
if @options
|
553
|
+
if @options.has_key? :template_dir
|
385
554
|
render_options[:template_dir] = @options[:template_dir]
|
386
555
|
end
|
387
556
|
|
388
557
|
render_options[:backend] = @attributes.fetch('backend', 'html5')
|
558
|
+
render_options[:template_engine] = @options[:template_engine]
|
389
559
|
render_options[:eruby] = @options.fetch(:eruby, 'erb')
|
390
560
|
render_options[:compact] = @options.fetch(:compact, false)
|
391
561
|
|
@@ -400,6 +570,7 @@ class Asciidoctor::Document < Asciidoctor::AbstractBlock
|
|
400
570
|
# or a template is missing, the renderer will fall back to
|
401
571
|
# using the appropriate built-in template.
|
402
572
|
def render(opts = {})
|
573
|
+
restore_attributes
|
403
574
|
r = renderer(opts)
|
404
575
|
@options.merge(opts)[:header_footer] ? r.render('document', self).strip : r.render('embedded', self)
|
405
576
|
end
|
@@ -415,3 +586,4 @@ class Asciidoctor::Document < Asciidoctor::AbstractBlock
|
|
415
586
|
end
|
416
587
|
|
417
588
|
end
|
589
|
+
end
|