asciidoctor 2.0.0.rc.2 → 2.0.0.rc.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +31 -3
- data/README-de.adoc +2 -8
- data/README-fr.adoc +2 -8
- data/README-jp.adoc +2 -2
- data/README-zh_CN.adoc +2 -2
- data/README.adoc +3 -7
- data/data/locale/attributes-fr.adoc +1 -1
- data/data/stylesheets/asciidoctor-default.css +3 -2
- data/lib/asciidoctor.rb +13 -7
- data/lib/asciidoctor/abstract_block.rb +33 -27
- data/lib/asciidoctor/abstract_node.rb +6 -10
- data/lib/asciidoctor/block.rb +4 -4
- data/lib/asciidoctor/cli/options.rb +23 -24
- data/lib/asciidoctor/converter.rb +17 -16
- data/lib/asciidoctor/converter/docbook5.rb +102 -102
- data/lib/asciidoctor/converter/html5.rb +142 -84
- data/lib/asciidoctor/converter/manpage.rb +81 -81
- data/lib/asciidoctor/converter/template.rb +2 -2
- data/lib/asciidoctor/core_ext.rb +1 -0
- data/lib/asciidoctor/core_ext/hash/merge.rb +7 -0
- data/lib/asciidoctor/document.rb +28 -14
- data/lib/asciidoctor/extensions.rb +4 -3
- data/lib/asciidoctor/inline.rb +2 -9
- data/lib/asciidoctor/parser.rb +27 -17
- data/lib/asciidoctor/reader.rb +41 -26
- data/lib/asciidoctor/section.rb +1 -8
- data/lib/asciidoctor/substitutors.rb +125 -124
- data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +1 -1
- data/lib/asciidoctor/table.rb +1 -1
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +4 -4
- data/man/asciidoctor.adoc +1 -1
- metadata +3 -2
@@ -58,7 +58,7 @@ class Converter::TemplateConverter < Converter::Base
|
|
58
58
|
@safe = opts[:safe]
|
59
59
|
@active_engines = {}
|
60
60
|
@engine = opts[:template_engine]
|
61
|
-
@engine_options = {}.tap {|accum| DEFAULT_ENGINE_OPTIONS.each {|engine, engine_opts| accum[engine] = engine_opts.
|
61
|
+
@engine_options = {}.tap {|accum| DEFAULT_ENGINE_OPTIONS.each {|engine, engine_opts| accum[engine] = engine_opts.merge } }
|
62
62
|
if opts[:htmlsyntax] == 'html' # if not set, assume xml since this converter is also used for DocBook (which doesn't specify htmlsyntax)
|
63
63
|
@engine_options[:haml][:format] = :html5
|
64
64
|
@engine_options[:slim][:format] = :html
|
@@ -124,7 +124,7 @@ class Converter::TemplateConverter < Converter::Base
|
|
124
124
|
#
|
125
125
|
# Returns a [Hash] of Tilt template objects keyed by template name.
|
126
126
|
def templates
|
127
|
-
@templates.
|
127
|
+
@templates.merge
|
128
128
|
end
|
129
129
|
|
130
130
|
# Public: Registers a Tilt template with this converter.
|
data/lib/asciidoctor/core_ext.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require_relative 'core_ext/float/truncate'
|
3
|
+
require_relative 'core_ext/hash/merge'
|
3
4
|
require_relative 'core_ext/match_data/names' if RUBY_ENGINE == 'opal'
|
4
5
|
require_relative 'core_ext/nil_or_empty'
|
5
6
|
require_relative 'core_ext/regexp/is_match'
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# NOTE remove once minimum required Ruby version is at least 2.6
|
3
|
+
Hash.prepend(Module.new do
|
4
|
+
def merge *args
|
5
|
+
(len = args.length) < 1 ? super({}) : (len > 1 ? args.inject(self) {|acc, arg| acc.merge arg } : (super args[0]))
|
6
|
+
end
|
7
|
+
end) if (Hash.instance_method :merge).arity == 1
|
data/lib/asciidoctor/document.rb
CHANGED
@@ -241,7 +241,7 @@ class Document < AbstractBlock
|
|
241
241
|
#
|
242
242
|
# data - The AsciiDoc source data as a String or String Array. (default: nil)
|
243
243
|
# options - A Hash of options to control processing (e.g., safe mode value (:safe), backend (:backend),
|
244
|
-
#
|
244
|
+
# standalone enclosure (:standalone), custom attributes (:attributes)). (default: {})
|
245
245
|
#
|
246
246
|
# Duplication of the options Hash is handled in the enclosing API.
|
247
247
|
#
|
@@ -257,10 +257,10 @@ class Document < AbstractBlock
|
|
257
257
|
@parent_document = parent_doc
|
258
258
|
options[:base_dir] ||= parent_doc.base_dir
|
259
259
|
options[:catalog_assets] = true if parent_doc.options[:catalog_assets]
|
260
|
-
@catalog = parent_doc.catalog.
|
260
|
+
@catalog = parent_doc.catalog.merge footnotes: []
|
261
261
|
# QUESTION should we support setting attribute in parent document from nested document?
|
262
262
|
# NOTE we must dup or else all the assignments to the overrides clobbers the real attributes
|
263
|
-
@attribute_overrides = attr_overrides = parent_doc.attributes.
|
263
|
+
@attribute_overrides = attr_overrides = parent_doc.attributes.merge
|
264
264
|
parent_doctype = attr_overrides.delete 'doctype'
|
265
265
|
attr_overrides.delete 'compat-mode'
|
266
266
|
attr_overrides.delete 'toc'
|
@@ -284,7 +284,7 @@ class Document < AbstractBlock
|
|
284
284
|
footnotes: [],
|
285
285
|
links: [],
|
286
286
|
images: [],
|
287
|
-
indexterms: [],
|
287
|
+
#indexterms: [],
|
288
288
|
callouts: Callouts.new,
|
289
289
|
includes: {},
|
290
290
|
}
|
@@ -328,6 +328,7 @@ class Document < AbstractBlock
|
|
328
328
|
@path_resolver = PathResolver.new
|
329
329
|
initialize_extensions = (defined? ::Asciidoctor::Extensions) ? true : nil
|
330
330
|
@extensions = nil # initialize furthur down if initialize_extensions is true
|
331
|
+
options[:standalone] = options[:header_footer] if (options.key? :header_footer) && !(options.key? :standalone)
|
331
332
|
end
|
332
333
|
|
333
334
|
@parsed = false
|
@@ -335,20 +336,20 @@ class Document < AbstractBlock
|
|
335
336
|
@counters = {}
|
336
337
|
@attributes_modified = ::Set.new
|
337
338
|
@docinfo_processor_extensions = {}
|
338
|
-
|
339
|
+
standalone = options[:standalone]
|
339
340
|
(@options = options).freeze
|
340
341
|
|
341
342
|
attrs = @attributes
|
342
343
|
#attrs['encoding'] = 'UTF-8'
|
343
344
|
attrs['sectids'] = ''
|
344
345
|
attrs['toc-placement'] = 'auto'
|
345
|
-
if
|
346
|
+
if standalone
|
346
347
|
attrs['copycss'] = ''
|
347
|
-
# sync embedded attribute with :
|
348
|
+
# sync embedded attribute with :standalone option value
|
348
349
|
attr_overrides['embedded'] = nil
|
349
350
|
else
|
350
351
|
attrs['notitle'] = ''
|
351
|
-
# sync embedded attribute with :
|
352
|
+
# sync embedded attribute with :standalone option value
|
352
353
|
attr_overrides['embedded'] = ''
|
353
354
|
end
|
354
355
|
attrs['stylesheet'] = ''
|
@@ -606,7 +607,8 @@ class Document < AbstractBlock
|
|
606
607
|
when :refs
|
607
608
|
@catalog[:refs][value[0]] ||= (ref = value[1])
|
608
609
|
ref
|
609
|
-
when :footnotes, :indexterms
|
610
|
+
#when :footnotes, :indexterms
|
611
|
+
when :footnotes
|
610
612
|
@catalog[type] << value
|
611
613
|
else
|
612
614
|
@catalog[type] << (type == :images ? (ImageReference.new value[0], value[1]) : value) if @options[:catalog_assets]
|
@@ -723,6 +725,10 @@ class Document < AbstractBlock
|
|
723
725
|
end
|
724
726
|
alias name doctitle
|
725
727
|
|
728
|
+
def xreftext xrefstyle = nil
|
729
|
+
(val = reftext) && !val.empty? ? val : title
|
730
|
+
end
|
731
|
+
|
726
732
|
# Public: Convenience method to retrieve the document attribute 'author'
|
727
733
|
#
|
728
734
|
# returns the full name of the author as a String
|
@@ -928,7 +934,13 @@ class Document < AbstractBlock
|
|
928
934
|
end
|
929
935
|
end
|
930
936
|
else
|
931
|
-
|
937
|
+
if opts.key? :standalone
|
938
|
+
transform = opts[:standalone] ? 'document' : 'embedded'
|
939
|
+
elsif opts.key? :header_footer
|
940
|
+
transform = opts[:header_footer] ? 'document' : 'embedded'
|
941
|
+
else
|
942
|
+
transform = @options[:standalone] ? 'document' : 'embedded'
|
943
|
+
end
|
932
944
|
output = @converter.convert self, transform
|
933
945
|
end
|
934
946
|
|
@@ -1053,10 +1065,12 @@ class Document < AbstractBlock
|
|
1053
1065
|
|
1054
1066
|
# TODO allow document to control whether extension docinfo is contributed
|
1055
1067
|
if @extensions && (docinfo_processors? location)
|
1056
|
-
(content
|
1068
|
+
((content || []).concat @docinfo_processor_extensions[location].map {|ext| ext.process_method[self] }.compact).join LF
|
1069
|
+
elsif content
|
1070
|
+
content.join LF
|
1071
|
+
else
|
1072
|
+
''
|
1057
1073
|
end
|
1058
|
-
|
1059
|
-
content ? (content.join LF) : ''
|
1060
1074
|
end
|
1061
1075
|
|
1062
1076
|
def docinfo_processors?(location = :head)
|
@@ -1235,7 +1249,7 @@ class Document < AbstractBlock
|
|
1235
1249
|
end
|
1236
1250
|
end
|
1237
1251
|
|
1238
|
-
@header_attributes = attrs.
|
1252
|
+
@header_attributes = attrs.merge
|
1239
1253
|
end
|
1240
1254
|
|
1241
1255
|
# Internal: Assign the local and document datetime attributes, which includes localdate, localyear, localtime,
|
@@ -201,7 +201,7 @@ module Extensions
|
|
201
201
|
end
|
202
202
|
|
203
203
|
def create_inline parent, context, text, opts = {}
|
204
|
-
Inline.new parent, context, text, opts
|
204
|
+
Inline.new parent, context, text, context == :quoted ? ({ type: :unquoted }.merge opts) : opts
|
205
205
|
end
|
206
206
|
|
207
207
|
# Public: Parses blocks in the content and attaches the block to the parent.
|
@@ -211,7 +211,7 @@ module Extensions
|
|
211
211
|
# QUESTION is parse_content the right method name? should we wrap in open block automatically?
|
212
212
|
def parse_content parent, content, attributes = nil
|
213
213
|
reader = Reader === content ? content : (Reader.new content)
|
214
|
-
while ((block = Parser.next_block reader, parent, (attributes ? attributes.
|
214
|
+
while ((block = Parser.next_block reader, parent, (attributes ? attributes.merge : {})) && parent << block) ||
|
215
215
|
reader.has_more_lines?
|
216
216
|
end
|
217
217
|
parent
|
@@ -225,7 +225,8 @@ module Extensions
|
|
225
225
|
[:create_pass_block, :create_block, :pass],
|
226
226
|
[:create_listing_block, :create_block, :listing],
|
227
227
|
[:create_literal_block, :create_block, :literal],
|
228
|
-
[:create_anchor, :create_inline, :anchor]
|
228
|
+
[:create_anchor, :create_inline, :anchor],
|
229
|
+
[:create_inline_pass, :create_inline, :quoted],
|
229
230
|
].each do |method_name, delegate_method_name, context|
|
230
231
|
define_method method_name do |*args|
|
231
232
|
args.unshift args.shift, context
|
data/lib/asciidoctor/inline.rb
CHANGED
@@ -3,7 +3,7 @@ module Asciidoctor
|
|
3
3
|
# Public: Methods for managing inline elements in AsciiDoc block
|
4
4
|
class Inline < AbstractNode
|
5
5
|
# Public: Get the text of this inline element
|
6
|
-
|
6
|
+
attr_accessor :text
|
7
7
|
|
8
8
|
# Public: Get the type (qualifier) of this inline element
|
9
9
|
attr_reader :type
|
@@ -12,19 +12,12 @@ class Inline < AbstractNode
|
|
12
12
|
attr_accessor :target
|
13
13
|
|
14
14
|
def initialize(parent, context, text = nil, opts = {})
|
15
|
-
super(parent, context)
|
15
|
+
super(parent, context, opts)
|
16
16
|
@node_name = %(inline_#{context})
|
17
|
-
|
18
17
|
@text = text
|
19
|
-
|
20
18
|
@id = opts[:id]
|
21
19
|
@type = opts[:type]
|
22
20
|
@target = opts[:target]
|
23
|
-
|
24
|
-
# value of attributes option for inline nodes may be nil
|
25
|
-
if (attrs = opts[:attributes])
|
26
|
-
@attributes = attrs.dup
|
27
|
-
end
|
28
21
|
end
|
29
22
|
|
30
23
|
def block?
|
data/lib/asciidoctor/parser.rb
CHANGED
@@ -346,7 +346,10 @@ class Parser
|
|
346
346
|
while reader.has_more_lines?
|
347
347
|
parse_block_metadata_lines reader, document, attributes
|
348
348
|
if (next_level = is_next_line_section?(reader, attributes))
|
349
|
-
|
349
|
+
if document.attr? 'leveloffset'
|
350
|
+
next_level += (document.attr 'leveloffset').to_i
|
351
|
+
next_level = 0 if next_level < 0
|
352
|
+
end
|
350
353
|
if next_level > current_level
|
351
354
|
if expected_next_level
|
352
355
|
unless next_level == expected_next_level || (expected_next_level_alt && next_level == expected_next_level_alt) || expected_next_level < 0
|
@@ -445,7 +448,7 @@ class Parser
|
|
445
448
|
# of a section that need to get transfered to the next section
|
446
449
|
# see "trailing block attributes transfer to the following section" in
|
447
450
|
# test/attributes_test.rb for an example
|
448
|
-
[section != parent ? section : nil, attributes.
|
451
|
+
[section != parent ? section : nil, attributes.merge]
|
449
452
|
end
|
450
453
|
|
451
454
|
# Public: Parse and return the next Block at the Reader's current location
|
@@ -579,14 +582,14 @@ class Parser
|
|
579
582
|
end
|
580
583
|
# style doesn't have special meaning for media macros
|
581
584
|
attributes.delete 'style' if attributes.key? 'style'
|
582
|
-
if
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
# otherwise, drop the line
|
587
|
-
else
|
585
|
+
if target.include? ATTR_REF_HEAD
|
586
|
+
if (expanded_target = block.sub_attributes target).empty? &&
|
587
|
+
(doc_attrs['attribute-missing'] || Compliance.attribute_missing) == 'drop-line' &&
|
588
|
+
(block.sub_attributes target + ' ', attribute_missing: 'drop-line', drop_line_severity: :ignore).empty?
|
588
589
|
attributes.clear
|
589
590
|
return
|
591
|
+
else
|
592
|
+
target = expanded_target
|
590
593
|
end
|
591
594
|
end
|
592
595
|
if blk_ctx == :image
|
@@ -616,12 +619,16 @@ class Parser
|
|
616
619
|
if report_unknown_block_macro
|
617
620
|
logger.debug message_with_context %(unknown name for block macro: #{$1}), source_location: reader.cursor_at_mark
|
618
621
|
else
|
619
|
-
target = $2
|
620
622
|
content = $3
|
621
|
-
if (target
|
622
|
-
(
|
623
|
-
|
624
|
-
|
623
|
+
if (target = $2).include? ATTR_REF_HEAD
|
624
|
+
if (expanded_target = parent.sub_attributes target).empty? &&
|
625
|
+
(doc_attrs['attribute-missing'] || Compliance.attribute_missing) == 'drop-line' &&
|
626
|
+
(parent.sub_attributes target + ' ', attribute_missing: 'drop-line', drop_line_severity: :ignore).empty?
|
627
|
+
attributes.clear
|
628
|
+
return
|
629
|
+
else
|
630
|
+
target = expanded_target
|
631
|
+
end
|
625
632
|
end
|
626
633
|
if extension.config[:content_model] == :attributes
|
627
634
|
document.parse_attributes content, extension.config[:pos_attrs] || [], sub_input: true, into: attributes if content
|
@@ -903,7 +910,7 @@ class Parser
|
|
903
910
|
end
|
904
911
|
# FIXME remove the need for this update!
|
905
912
|
block.attributes.update(attributes) unless attributes.empty?
|
906
|
-
block.
|
913
|
+
block.commit_subs
|
907
914
|
|
908
915
|
#if doc_attrs.key? :pending_attribute_entries
|
909
916
|
# doc_attrs.delete(:pending_attribute_entries).each do |entry|
|
@@ -1025,7 +1032,7 @@ class Parser
|
|
1025
1032
|
if (extension = options[:extension])
|
1026
1033
|
# QUESTION do we want to delete the style?
|
1027
1034
|
attributes.delete('style')
|
1028
|
-
if (block = extension.process_method[parent, block_reader || (Reader.new lines), attributes.
|
1035
|
+
if (block = extension.process_method[parent, block_reader || (Reader.new lines), attributes.merge])
|
1029
1036
|
attributes.replace block.attributes
|
1030
1037
|
# FIXME if the content model is set to compound, but we only have simple in this context, then
|
1031
1038
|
# forcefully set the content_model to simple to prevent parsing blocks from children
|
@@ -1749,7 +1756,10 @@ class Parser
|
|
1749
1756
|
else
|
1750
1757
|
raise %(Unrecognized section at #{reader.cursor_at_prev_line})
|
1751
1758
|
end
|
1752
|
-
|
1759
|
+
if document.attr? 'leveloffset'
|
1760
|
+
sect_level += (document.attr 'leveloffset').to_i
|
1761
|
+
sect_level = 0 if sect_level < 0
|
1762
|
+
end
|
1753
1763
|
[sect_id, sect_reftext, sect_title, sect_level, atx]
|
1754
1764
|
end
|
1755
1765
|
|
@@ -2448,7 +2458,7 @@ class Parser
|
|
2448
2458
|
end
|
2449
2459
|
|
2450
2460
|
if m[1]
|
2451
|
-
1.upto(m[1].to_i) { specs << spec.
|
2461
|
+
1.upto(m[1].to_i) { specs << spec.merge }
|
2452
2462
|
else
|
2453
2463
|
specs << spec
|
2454
2464
|
end
|
data/lib/asciidoctor/reader.rb
CHANGED
@@ -902,30 +902,28 @@ class PreprocessorReader < Reader
|
|
902
902
|
# attributes are case insensitive
|
903
903
|
target = target.downcase unless (no_target = target.empty?)
|
904
904
|
|
905
|
-
# must have a target before brackets if ifdef or ifndef
|
906
|
-
# must not have text between brackets if endif
|
907
|
-
# skip line if it doesn't meet this criteria
|
908
|
-
# QUESTION should we warn for these bogus declarations?
|
909
|
-
return false if (no_target && (keyword == 'ifdef' || keyword == 'ifndef')) || (text && keyword == 'endif')
|
910
|
-
|
911
905
|
if keyword == 'endif'
|
912
|
-
if
|
913
|
-
logger.error message_with_context %(
|
906
|
+
if text
|
907
|
+
logger.error message_with_context %(malformed preprocessor directive - text not permitted: endif::#{target}[#{text}]), source_location: cursor
|
908
|
+
elsif @conditional_stack.empty?
|
909
|
+
logger.error message_with_context %(unmatched preprocessor directive: endif::#{target}[]), source_location: cursor
|
914
910
|
elsif no_target || target == (pair = @conditional_stack[-1])[:target]
|
915
911
|
@conditional_stack.pop
|
916
912
|
@skipping = @conditional_stack.empty? ? false : @conditional_stack[-1][:skipping]
|
917
913
|
else
|
918
|
-
logger.error message_with_context %(mismatched
|
914
|
+
logger.error message_with_context %(mismatched preprocessor directive: endif::#{target}[], expected endif::#{pair[:target]}[]), source_location: cursor
|
919
915
|
end
|
920
916
|
return true
|
921
|
-
|
922
|
-
|
923
|
-
if @skipping
|
917
|
+
elsif @skipping
|
924
918
|
skip = false
|
925
919
|
else
|
926
920
|
# QUESTION any way to wrap ifdef & ifndef logic up together?
|
927
921
|
case keyword
|
928
922
|
when 'ifdef'
|
923
|
+
if no_target
|
924
|
+
logger.error message_with_context %(malformed preprocessor directive - missing target: ifdef::[#{text}]), source_location: cursor
|
925
|
+
return true
|
926
|
+
end
|
929
927
|
case delimiter
|
930
928
|
when ','
|
931
929
|
# skip if no attribute is defined
|
@@ -938,6 +936,10 @@ class PreprocessorReader < Reader
|
|
938
936
|
skip = !@document.attributes.key?(target)
|
939
937
|
end
|
940
938
|
when 'ifndef'
|
939
|
+
if no_target
|
940
|
+
logger.error message_with_context %(malformed preprocessor directive - missing target: ifndef::[#{text}]), source_location: cursor
|
941
|
+
return true
|
942
|
+
end
|
941
943
|
case delimiter
|
942
944
|
when ','
|
943
945
|
# skip if any attribute is defined
|
@@ -950,15 +952,19 @@ class PreprocessorReader < Reader
|
|
950
952
|
skip = @document.attributes.key?(target)
|
951
953
|
end
|
952
954
|
when 'ifeval'
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
955
|
+
if no_target
|
956
|
+
# the text in brackets must match a conditional expression
|
957
|
+
if text && EvalExpressionRx =~ text.strip
|
958
|
+
# regex enforces a restricted set of math-related operations (==, !=, <=, >=, <, >)
|
959
|
+
skip = ((resolve_expr_val $1).send $2, (resolve_expr_val $3)) ? false : true
|
960
|
+
else
|
961
|
+
logger.error message_with_context %(malformed preprocessor directive - #{text ? 'invalid expression' : 'missing expression'}: ifeval::[#{text}]), source_location: cursor
|
962
|
+
return true
|
963
|
+
end
|
964
|
+
else
|
965
|
+
logger.error message_with_context %(malformed preprocessor directive - target not permitted: ifeval::#{target}[#{text}]), source_location: cursor
|
966
|
+
return true
|
967
|
+
end
|
962
968
|
end
|
963
969
|
end
|
964
970
|
|
@@ -1008,12 +1014,20 @@ class PreprocessorReader < Reader
|
|
1008
1014
|
def preprocess_include_directive target, attrlist
|
1009
1015
|
doc = @document
|
1010
1016
|
if ((expanded_target = target).include? ATTR_REF_HEAD) &&
|
1011
|
-
(expanded_target = doc.sub_attributes target, attribute_missing: 'drop-line').empty?
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1017
|
+
(expanded_target = doc.sub_attributes target, attribute_missing: ((attr_missing = doc.attributes['attribute-missing'] || Compliance.attribute_missing) == 'warn' ? 'drop-line' : attr_missing)).empty?
|
1018
|
+
if attr_missing == 'drop-line' && (doc.sub_attributes target + ' ', attribute_missing: 'drop-line', drop_line_severity: :ignore).empty?
|
1019
|
+
logger.info { message_with_context %(include dropped due to missing attribute: include::#{target}[#{attrlist}]), source_location: cursor }
|
1020
|
+
shift
|
1021
|
+
true
|
1022
|
+
elsif (doc.parse_attributes attrlist, [], sub_input: true)['optional-option']
|
1023
|
+
logger.info { message_with_context %(optional include dropped #{attr_missing == 'warn' && (doc.sub_attributes target + ' ', attribute_missing: 'drop-line', drop_line_severity: :ignore).empty? ? 'due to missing attribute' : 'because resolved target is blank'}: include::#{target}[#{attrlist}]), source_location: cursor }
|
1024
|
+
shift
|
1025
|
+
true
|
1026
|
+
else
|
1027
|
+
logger.warn message_with_context %(include dropped #{attr_missing == 'warn' && (doc.sub_attributes target + ' ', attribute_missing: 'drop-line', drop_line_severity: :ignore).empty? ? 'due to missing attribute' : 'because resolved target is blank'}: include::#{target}[#{attrlist}]), source_location: cursor
|
1028
|
+
# QUESTION should this line include target or expanded_target (or escaped target?)
|
1029
|
+
replace_next_line %(Unresolved directive in #{@path} - include::#{target}[#{attrlist}])
|
1015
1030
|
end
|
1016
|
-
true
|
1017
1031
|
elsif include_processors? && (ext = @include_processor_extensions.find {|candidate| candidate.instance.handles? expanded_target })
|
1018
1032
|
shift
|
1019
1033
|
# FIXME parse attributes only if requested by extension
|
@@ -1222,6 +1236,7 @@ class PreprocessorReader < Reader
|
|
1222
1236
|
inc_path = doc.normalize_system_path target, @dir, nil, target_name: 'include file'
|
1223
1237
|
unless ::File.file? inc_path
|
1224
1238
|
if attributes['optional-option']
|
1239
|
+
logger.info { message_with_context %(optional include dropped because include file not found: #{inc_path}), source_location: cursor }
|
1225
1240
|
shift
|
1226
1241
|
return true
|
1227
1242
|
else
|
data/lib/asciidoctor/section.rb
CHANGED
@@ -111,14 +111,7 @@ class Section < AbstractBlock
|
|
111
111
|
# Returns the section number as a String
|
112
112
|
def sectnum(delimiter = '.', append = nil)
|
113
113
|
append ||= (append == false ? '' : delimiter)
|
114
|
-
|
115
|
-
%(#{@numeral}#{append})
|
116
|
-
elsif @level > 1
|
117
|
-
Section === @parent ? %(#{@parent.sectnum(delimiter, delimiter)}#{@numeral}#{append}) : %(#{@numeral}#{append})
|
118
|
-
else # @level == 0
|
119
|
-
# NOTE coerce @numeral to int just in case not set; can happen if section nesting is out of sequence
|
120
|
-
%(#{Helpers.int_to_roman @numeral.to_i}#{append})
|
121
|
-
end
|
114
|
+
@level > 1 && Section === @parent ? %(#{@parent.sectnum(delimiter, delimiter)}#{@numeral}#{append}) : %(#{@numeral}#{append})
|
122
115
|
end
|
123
116
|
|
124
117
|
# (see AbstractBlock#xreftext)
|
@@ -395,9 +395,9 @@ module Substitutors
|
|
395
395
|
when :none
|
396
396
|
replacement
|
397
397
|
when :bounding
|
398
|
-
|
398
|
+
m[1] + replacement + m[2]
|
399
399
|
else # :leading
|
400
|
-
|
400
|
+
m[1] + replacement
|
401
401
|
end
|
402
402
|
end
|
403
403
|
end
|
@@ -416,7 +416,7 @@ module Substitutors
|
|
416
416
|
# Returns the [String] text with the attribute references replaced with resolved values
|
417
417
|
def sub_attributes text, opts = {}
|
418
418
|
doc_attrs = @document.attributes
|
419
|
-
drop = drop_line = drop_empty_line = attribute_undefined = attribute_missing = nil
|
419
|
+
drop = drop_line = drop_line_severity = drop_empty_line = attribute_undefined = attribute_missing = nil
|
420
420
|
text = text.gsub AttributeReferenceRx do
|
421
421
|
# escaped attribute, return unescaped
|
422
422
|
if $1 == RS || $4 == RS
|
@@ -426,7 +426,7 @@ module Substitutors
|
|
426
426
|
when 'set'
|
427
427
|
_, value = Parser.store_attribute args[0], args[1] || '', @document
|
428
428
|
# NOTE since this is an assignment, only drop-line applies here (skip and drop imply the same result)
|
429
|
-
if value || (attribute_undefined ||= doc_attrs['attribute-undefined'] || Compliance.attribute_undefined) != 'drop-line'
|
429
|
+
if value || (attribute_undefined ||= (doc_attrs['attribute-undefined'] || Compliance.attribute_undefined)) != 'drop-line'
|
430
430
|
drop = drop_empty_line = DEL
|
431
431
|
else
|
432
432
|
drop = drop_line = CAN
|
@@ -442,11 +442,15 @@ module Substitutors
|
|
442
442
|
elsif (value = INTRINSIC_ATTRIBUTES[key])
|
443
443
|
value
|
444
444
|
else
|
445
|
-
case (attribute_missing ||= opts[:attribute_missing] || doc_attrs['attribute-missing'] || Compliance.attribute_missing)
|
445
|
+
case (attribute_missing ||= (opts[:attribute_missing] || doc_attrs['attribute-missing'] || Compliance.attribute_missing))
|
446
446
|
when 'drop'
|
447
447
|
drop = drop_empty_line = DEL
|
448
448
|
when 'drop-line'
|
449
|
-
|
449
|
+
if (drop_line_severity ||= (opts[:drop_line_severity] || :info)) == :info
|
450
|
+
logger.info { %(dropping line containing reference to missing attribute: #{key}) }
|
451
|
+
#elsif drop_line_severity == :warn
|
452
|
+
# logger.warn %(dropping line containing reference to missing attribute: #{key})
|
453
|
+
end
|
450
454
|
drop = drop_line = CAN
|
451
455
|
when 'warn'
|
452
456
|
logger.warn %(skipping reference to missing attribute: #{key})
|
@@ -460,7 +464,7 @@ module Substitutors
|
|
460
464
|
if drop
|
461
465
|
# drop lines from text
|
462
466
|
if drop_empty_line
|
463
|
-
lines = (text.
|
467
|
+
lines = (text.squeeze DEL).split LF, -1
|
464
468
|
if drop_line
|
465
469
|
(lines.reject {|line| line == DEL || line == CAN || (line.start_with? CAN) || (line.include? CAN) }.join LF).delete DEL
|
466
470
|
else
|
@@ -486,13 +490,54 @@ module Substitutors
|
|
486
490
|
def sub_macros(text)
|
487
491
|
#return text if text.nil_or_empty?
|
488
492
|
# some look ahead assertions to cut unnecessary regex calls
|
489
|
-
|
490
|
-
found_square_bracket = found[:square_bracket] = text.include? '['
|
493
|
+
found_square_bracket = text.include? '['
|
491
494
|
found_colon = text.include? ':'
|
492
|
-
found_macroish =
|
495
|
+
found_macroish = found_square_bracket && found_colon
|
493
496
|
found_macroish_short = found_macroish && (text.include? ':[')
|
494
497
|
doc_attrs = (doc = @document).attributes
|
495
498
|
|
499
|
+
# TODO allow position of substitution to be controlled (before or after other macros)
|
500
|
+
# TODO this handling needs some cleanup
|
501
|
+
if (extensions = doc.extensions) && extensions.inline_macros? # && found_macroish
|
502
|
+
extensions.inline_macros.each do |extension|
|
503
|
+
text = text.gsub extension.instance.regexp do
|
504
|
+
# honor the escape
|
505
|
+
next $&.slice 1, $&.length if $&.start_with? RS
|
506
|
+
extconf = extension.config
|
507
|
+
if $~.names.empty?
|
508
|
+
target, content = $1, $2
|
509
|
+
else
|
510
|
+
target, content = ($~[:target] rescue nil), ($~[:content] rescue nil)
|
511
|
+
end
|
512
|
+
attributes = (attributes = extconf[:default_attrs]) ? attributes.merge : {}
|
513
|
+
if content.nil_or_empty?
|
514
|
+
attributes['text'] = content if content && extconf[:content_model] != :attributes
|
515
|
+
else
|
516
|
+
content = unescape_bracketed_text content
|
517
|
+
# QUESTION should we store the unparsed attrlist in the attrlist key?
|
518
|
+
if extconf[:content_model] == :attributes
|
519
|
+
parse_attributes content, extconf[:pos_attrs] || [], into: attributes
|
520
|
+
else
|
521
|
+
attributes['text'] = content
|
522
|
+
end
|
523
|
+
end
|
524
|
+
# NOTE for convenience, map content (unparsed attrlist) to target when format is short
|
525
|
+
target ||= extconf[:format] == :short ? content : target
|
526
|
+
if (Inline === (replacement = extension.process_method[self, target, attributes]))
|
527
|
+
if (inline_subs = replacement.attributes.delete 'subs')
|
528
|
+
replacement.text = apply_subs replacement.text, (expand_subs inline_subs)
|
529
|
+
end
|
530
|
+
replacement.convert
|
531
|
+
elsif replacement
|
532
|
+
logger.info %(expected substitution value for custom inline macro to be of type Inline; got #{replacement.class}: #{$&})
|
533
|
+
replacement
|
534
|
+
else
|
535
|
+
''
|
536
|
+
end
|
537
|
+
end
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
496
541
|
if doc_attrs.key? 'experimental'
|
497
542
|
if found_macroish_short && ((text.include? 'kbd:') || (text.include? 'btn:'))
|
498
543
|
text = text.gsub InlineKbdBtnMacroRx do
|
@@ -509,7 +554,7 @@ module Substitutors
|
|
509
554
|
# NOTE handle special case where keys ends with delimiter (e.g., Ctrl++ or Ctrl,,)
|
510
555
|
if keys.end_with? delim
|
511
556
|
keys = (keys.chop.split delim, -1).map {|key| key.strip }
|
512
|
-
keys[-1]
|
557
|
+
keys[-1] += delim
|
513
558
|
else
|
514
559
|
keys = keys.split(delim).map {|key| key.strip }
|
515
560
|
end
|
@@ -557,39 +602,6 @@ module Substitutors
|
|
557
602
|
end
|
558
603
|
end
|
559
604
|
|
560
|
-
# FIXME this location is somewhat arbitrary, probably need to be able to control ordering
|
561
|
-
# TODO this handling needs some cleanup
|
562
|
-
if (extensions = doc.extensions) && extensions.inline_macros? # && found_macroish
|
563
|
-
extensions.inline_macros.each do |extension|
|
564
|
-
text = text.gsub extension.instance.regexp do
|
565
|
-
# honor the escape
|
566
|
-
next $&.slice 1, $&.length if $&.start_with? RS
|
567
|
-
extconf = extension.config
|
568
|
-
if $~.names.empty?
|
569
|
-
target, content = $1, $2
|
570
|
-
else
|
571
|
-
target, content = ($~[:target] rescue nil), ($~[:content] rescue nil)
|
572
|
-
end
|
573
|
-
attributes = (attributes = extconf[:default_attrs]) ? attributes.dup : {}
|
574
|
-
if content.nil_or_empty?
|
575
|
-
attributes['text'] = content if content && extconf[:content_model] != :attributes
|
576
|
-
else
|
577
|
-
content = unescape_bracketed_text content
|
578
|
-
# QUESTION should we store the unparsed attrlist in the attrlist key?
|
579
|
-
if extconf[:content_model] == :attributes
|
580
|
-
parse_attributes content, extconf[:pos_attrs] || [], into: attributes
|
581
|
-
else
|
582
|
-
attributes['text'] = content
|
583
|
-
end
|
584
|
-
end
|
585
|
-
# NOTE for convenience, map content (unparsed attrlist) to target when format is short
|
586
|
-
target ||= extconf[:format] == :short ? content : target
|
587
|
-
replacement = extension.process_method[self, target, attributes]
|
588
|
-
Inline === replacement ? replacement.convert : replacement
|
589
|
-
end
|
590
|
-
end
|
591
|
-
end
|
592
|
-
|
593
605
|
if found_macroish && ((text.include? 'image:') || (text.include? 'icon:'))
|
594
606
|
# image:filename.png[Alt Text]
|
595
607
|
text = text.gsub InlineImageMacroRx do
|
@@ -625,7 +637,7 @@ module Substitutors
|
|
625
637
|
|
626
638
|
# indexterm:[Tigers,Big cats]
|
627
639
|
terms = split_simple_csv normalize_string $2, true
|
628
|
-
doc.register :indexterms, terms
|
640
|
+
#doc.register :indexterms, terms
|
629
641
|
(Inline.new self, :indexterm, nil, attributes: { 'terms' => terms }).convert
|
630
642
|
when 'indexterm2'
|
631
643
|
# honor the escape
|
@@ -633,7 +645,7 @@ module Substitutors
|
|
633
645
|
|
634
646
|
# indexterm2:[Tigers]
|
635
647
|
term = normalize_string $2, true
|
636
|
-
doc.register :indexterms, [term]
|
648
|
+
#doc.register :indexterms, [term]
|
637
649
|
(Inline.new self, :indexterm, term, type: :visible).convert
|
638
650
|
else
|
639
651
|
text = $3
|
@@ -661,12 +673,12 @@ module Substitutors
|
|
661
673
|
if visible
|
662
674
|
# ((Tigers))
|
663
675
|
term = normalize_string text
|
664
|
-
doc.register :indexterms, [term]
|
676
|
+
#doc.register :indexterms, [term]
|
665
677
|
subbed_term = (Inline.new self, :indexterm, term, type: :visible).convert
|
666
678
|
else
|
667
679
|
# (((Tigers,Big cats)))
|
668
680
|
terms = split_simple_csv(normalize_string text)
|
669
|
-
doc.register :indexterms, terms
|
681
|
+
#doc.register :indexterms, terms
|
670
682
|
subbed_term = (Inline.new self, :indexterm, nil, attributes: { 'terms' => terms }).convert
|
671
683
|
end
|
672
684
|
before ? %(#{before}#{subbed_term}#{after}) : subbed_term
|
@@ -771,15 +783,14 @@ module Substitutors
|
|
771
783
|
end
|
772
784
|
end
|
773
785
|
|
774
|
-
if found_macroish && ((text.include? 'link:') || (text.include? '
|
786
|
+
if found_macroish && ((text.include? 'link:') || (text.include? 'ilto:'))
|
775
787
|
# inline link macros, link:target[text]
|
776
788
|
text = text.gsub InlineLinkMacroRx do
|
777
789
|
# honor the escape
|
778
790
|
if $&.start_with? RS
|
779
791
|
next $&.slice 1, $&.length
|
780
792
|
elsif (mailto = $1)
|
781
|
-
target =
|
782
|
-
mailto_text = $2
|
793
|
+
target = 'mailto:' + (mailto_text = $2)
|
783
794
|
else
|
784
795
|
target = $2
|
785
796
|
end
|
@@ -854,7 +865,7 @@ module Substitutors
|
|
854
865
|
# honor the escape
|
855
866
|
next $1 == RS ? ($&.slice 1, $&.length) : $& if $1
|
856
867
|
|
857
|
-
target =
|
868
|
+
target = 'mailto:' + $&
|
858
869
|
# QUESTION should this be registered as an e-mail address?
|
859
870
|
doc.register(:links, target)
|
860
871
|
|
@@ -862,65 +873,11 @@ module Substitutors
|
|
862
873
|
end
|
863
874
|
end
|
864
875
|
|
865
|
-
if
|
866
|
-
text = text.gsub InlineFootnoteMacroRx do
|
867
|
-
# honor the escape
|
868
|
-
next $&.slice 1, $&.length if $&.start_with? RS
|
869
|
-
|
870
|
-
# footnoteref
|
871
|
-
if $1
|
872
|
-
if $3
|
873
|
-
id, text = $3.split ',', 2
|
874
|
-
logger.warn %(found deprecated footnoteref macro: #{$&}; use footnote macro with target instead) unless doc.compat_mode
|
875
|
-
else
|
876
|
-
next $&
|
877
|
-
end
|
878
|
-
# footnote
|
879
|
-
else
|
880
|
-
id = $2
|
881
|
-
text = $3
|
882
|
-
end
|
883
|
-
|
884
|
-
if id
|
885
|
-
if text
|
886
|
-
# REVIEW it's a dirty job, but somebody's gotta do it
|
887
|
-
text = restore_passthroughs(sub_inline_xrefs(sub_inline_anchors(normalize_string text, true)))
|
888
|
-
index = doc.counter('footnote-number')
|
889
|
-
doc.register(:footnotes, Document::Footnote.new(index, id, text))
|
890
|
-
type, target = :ref, nil
|
891
|
-
else
|
892
|
-
if (footnote = doc.footnotes.find {|candidate| candidate.id == id })
|
893
|
-
index, text = footnote.index, footnote.text
|
894
|
-
else
|
895
|
-
logger.warn %(invalid footnote reference: #{id})
|
896
|
-
index, text = nil, id
|
897
|
-
end
|
898
|
-
type, target, id = :xref, id, nil
|
899
|
-
end
|
900
|
-
elsif text
|
901
|
-
# REVIEW it's a dirty job, but somebody's gotta do it
|
902
|
-
text = restore_passthroughs(sub_inline_xrefs(sub_inline_anchors(normalize_string text, true)))
|
903
|
-
index = doc.counter('footnote-number')
|
904
|
-
doc.register(:footnotes, Document::Footnote.new(index, id, text))
|
905
|
-
type = target = nil
|
906
|
-
else
|
907
|
-
next $&
|
908
|
-
end
|
909
|
-
Inline.new(self, :footnote, text, attributes: { 'index' => index }, id: id, target: target, type: type).convert
|
910
|
-
end
|
911
|
-
end
|
912
|
-
|
913
|
-
sub_inline_xrefs(sub_inline_anchors(text, found), found)
|
914
|
-
end
|
915
|
-
|
916
|
-
# Internal: Substitute normal and bibliographic anchors
|
917
|
-
def sub_inline_anchors(text, found = nil)
|
918
|
-
if @context == :list_item && @parent.style == 'bibliography'
|
876
|
+
if found_square_bracket && @context == :list_item && @parent.style == 'bibliography'
|
919
877
|
text = text.sub(InlineBiblioAnchorRx) { (Inline.new self, :anchor, $2, type: :bibref, id: $1).convert }
|
920
878
|
end
|
921
879
|
|
922
|
-
if (
|
923
|
-
((!found || found[:macroish]) && text.include?('or:'))
|
880
|
+
if (found_square_bracket && text.include?('[[')) || (found_macroish && text.include?('or:'))
|
924
881
|
text = text.gsub InlineAnchorRx do
|
925
882
|
# honor the escape
|
926
883
|
next $&.slice 1, $&.length if $1
|
@@ -938,17 +895,13 @@ module Substitutors
|
|
938
895
|
end
|
939
896
|
end
|
940
897
|
|
941
|
-
text
|
942
|
-
|
943
|
-
|
944
|
-
# Internal: Substitute cross reference links
|
945
|
-
def sub_inline_xrefs(content, found = nil)
|
946
|
-
if ((found ? found[:macroish] : (content.include? '[')) && (content.include? 'xref:')) || ((content.include? '&') && (content.include? 'lt;&'))
|
947
|
-
content = content.gsub InlineXrefMacroRx do
|
898
|
+
#if (text.include? ';&l') || (found_macroish && (text.include? 'xref:'))
|
899
|
+
if ((text.include? '&') && (text.include? ';&l')) || (found_macroish && (text.include? 'xref:'))
|
900
|
+
text = text.gsub InlineXrefMacroRx do
|
948
901
|
# honor the escape
|
949
902
|
next $&.slice 1, $&.length if $&.start_with? RS
|
950
903
|
|
951
|
-
attrs
|
904
|
+
attrs = {}
|
952
905
|
if (refid = $1)
|
953
906
|
refid, text = refid.split ',', 2
|
954
907
|
text = text.lstrip if text
|
@@ -994,14 +947,14 @@ module Substitutors
|
|
994
947
|
# handles: #id
|
995
948
|
if target
|
996
949
|
refid = fragment
|
997
|
-
logger.
|
950
|
+
logger.info %(possible invalid reference: #{refid}) if logger.info? && !doc.catalog[:refs][refid]
|
998
951
|
elsif path
|
999
952
|
# handles: path#, path#id, path.adoc#, path.adoc#id, or path.adoc (xref macro only)
|
1000
953
|
# the referenced path is the current document, or its contents have been included in the current document
|
1001
954
|
if src2src && (doc.attributes['docname'] == path || doc.catalog[:includes][path])
|
1002
955
|
if fragment
|
1003
956
|
refid, path, target = fragment, nil, %(##{fragment})
|
1004
|
-
logger.
|
957
|
+
logger.info %(possible invalid reference: #{refid}) if logger.info? && !doc.catalog[:refs][refid]
|
1005
958
|
else
|
1006
959
|
refid, path, target = nil, nil, '#'
|
1007
960
|
end
|
@@ -1016,7 +969,7 @@ module Substitutors
|
|
1016
969
|
# handles: id (in compat mode or when natural xrefs are disabled)
|
1017
970
|
elsif doc.compat_mode || !Compliance.natural_xrefs
|
1018
971
|
refid, target = fragment, %(##{fragment})
|
1019
|
-
logger.
|
972
|
+
logger.info %(possible invalid reference: #{refid}) if logger.info? && doc.catalog[:refs][refid]
|
1020
973
|
# handles: id
|
1021
974
|
elsif doc.catalog[:refs][fragment]
|
1022
975
|
refid, target = fragment, %(##{fragment})
|
@@ -1026,14 +979,62 @@ module Substitutors
|
|
1026
979
|
fragment, target = refid, %(##{refid})
|
1027
980
|
else
|
1028
981
|
refid, target = fragment, %(##{fragment})
|
1029
|
-
logger.
|
982
|
+
logger.info %(possible invalid reference: #{refid}) if logger.info?
|
1030
983
|
end
|
1031
|
-
attrs['path']
|
984
|
+
attrs['path'] = path
|
985
|
+
attrs['fragment'] = fragment
|
986
|
+
attrs['refid'] = refid
|
1032
987
|
Inline.new(self, :anchor, text, type: :xref, target: target, attributes: attrs).convert
|
1033
988
|
end
|
1034
989
|
end
|
1035
990
|
|
1036
|
-
|
991
|
+
if found_macroish && (text.include? 'tnote')
|
992
|
+
text = text.gsub InlineFootnoteMacroRx do
|
993
|
+
# honor the escape
|
994
|
+
next $&.slice 1, $&.length if $&.start_with? RS
|
995
|
+
|
996
|
+
# footnoteref
|
997
|
+
if $1
|
998
|
+
if $3
|
999
|
+
id, text = $3.split ',', 2
|
1000
|
+
logger.warn %(found deprecated footnoteref macro: #{$&}; use footnote macro with target instead) unless doc.compat_mode
|
1001
|
+
else
|
1002
|
+
next $&
|
1003
|
+
end
|
1004
|
+
# footnote
|
1005
|
+
else
|
1006
|
+
id = $2
|
1007
|
+
text = $3
|
1008
|
+
end
|
1009
|
+
|
1010
|
+
if id
|
1011
|
+
if text
|
1012
|
+
text = restore_passthroughs(normalize_string text, true)
|
1013
|
+
index = doc.counter('footnote-number')
|
1014
|
+
doc.register(:footnotes, Document::Footnote.new(index, id, text))
|
1015
|
+
type, target = :ref, nil
|
1016
|
+
else
|
1017
|
+
if (footnote = doc.footnotes.find {|candidate| candidate.id == id })
|
1018
|
+
index, text = footnote.index, footnote.text
|
1019
|
+
else
|
1020
|
+
logger.warn %(invalid footnote reference: #{id})
|
1021
|
+
index, text = nil, id
|
1022
|
+
end
|
1023
|
+
type, target, id = :xref, id, nil
|
1024
|
+
end
|
1025
|
+
elsif text
|
1026
|
+
text = restore_passthroughs(normalize_string text, true)
|
1027
|
+
index = doc.counter('footnote-number')
|
1028
|
+
doc.register(:footnotes, Document::Footnote.new(index, id, text))
|
1029
|
+
type = target = nil
|
1030
|
+
else
|
1031
|
+
next $&
|
1032
|
+
end
|
1033
|
+
Inline.new(self, :footnote, text, attributes: { 'index' => index }, id: id, target: target, type: type).convert
|
1034
|
+
end
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
text
|
1037
1038
|
end
|
1038
1039
|
|
1039
1040
|
# Public: Substitute callout source references
|
@@ -1473,7 +1474,7 @@ module Substitutors
|
|
1473
1474
|
# Internal: Inserts text into a formatted text enclosure; used by xreftext
|
1474
1475
|
alias sub_placeholder sprintf unless RUBY_ENGINE == 'opal'
|
1475
1476
|
|
1476
|
-
# Internal:
|
1477
|
+
# Internal: Commit the requested substitutions to this block.
|
1477
1478
|
#
|
1478
1479
|
# Looks for an attribute named "subs". If present, resolves substitutions
|
1479
1480
|
# from the value of that attribute and assigns them to the subs property on
|
@@ -1482,7 +1483,7 @@ module Substitutors
|
|
1482
1483
|
# the content model of the block.
|
1483
1484
|
#
|
1484
1485
|
# Returns The Array of resolved substitutions now assigned to this block
|
1485
|
-
def
|
1486
|
+
def commit_subs
|
1486
1487
|
unless (default_subs = @default_subs)
|
1487
1488
|
case @content_model
|
1488
1489
|
when :simple
|