lib/asciidoctor/substituters.rb in asciidoctor-0.0.9 vs lib/asciidoctor/substituters.rb in asciidoctor-0.1.0
- old
+ new
@@ -248,18 +248,29 @@
result = lines.map {|line|
reject = false
subject = line.dup
subject.gsub!(REGEXP[:attr_ref]) {
+ # alias match for Ruby 1.8.7 compat
+ m = $~
+ key = m[2].downcase
+ # escaped attribute
if !$1.empty? || !$3.empty?
"{#$2}"
- elsif document.attributes.has_key? $2
- document.attributes[$2]
- elsif INTRINSICS.has_key? $2
- INTRINSICS[$2]
+ elsif m[2].start_with?('counter:')
+ args = m[2].split(':')
+ @document.counter(args[1], args[2])
+ elsif m[2].start_with?('counter2:')
+ args = m[2].split(':')
+ @document.counter(args[1], args[2])
+ ''
+ elsif document.attributes.has_key? key
+ @document.attributes[key]
+ elsif INTRINSICS.has_key? key
+ INTRINSICS[key]
else
- Asciidoctor.debug { "Missing attribute: #$2, line marked for removal" }
+ Asciidoctor.debug { "Missing attribute: #{m[2]}, line marked for removal" }
reject = true
break '{undefined}'
end
} if subject.include?('{')
@@ -279,106 +290,207 @@
def sub_macros(text)
return text if text.nil? || text.empty?
result = text.dup
- # inline images, image:target.ext[Alt]
- result.gsub!(REGEXP[:image_macro]) {
- # alias match for Ruby 1.8.7 compat
- m = $~
- # honor the escape
- if m[0].start_with? '\\'
- next m[0][1..-1]
- end
- target = sub_attributes(m[1])
- @document.register(:images, target)
- attrs = parse_attributes(m[2], ['alt', 'width', 'height'])
- if !attrs.has_key?('alt') || attrs['alt'].empty?
- attrs['alt'] = File.basename(target, File.extname(target))
- end
- Inline.new(self, :image, nil, :target => target, :attributes => attrs).render
- } unless !result.include?('image:')
+ # some look ahead assertions to cut unnecessary regex calls
+ found = {}
+ found[:square_bracket] = result.include?('[')
+ found[:round_bracket] = result.include?('(')
+ found[:macroish] = (found[:square_bracket] && result.include?(':'))
+ found[:macroish_short_form] = (found[:square_bracket] && result.include?(':['))
+ found[:uri] = result.include?('://')
- # inline urls, target[text] (optionally prefixed with link: and optionally surrounded by <>)
- result.gsub!(REGEXP[:link_inline]) {
- # alias match for Ruby 1.8.7 compat
- m = $~
- # honor the escape
- if m[2].start_with? '\\'
- next "#{m[1]}#{m[2][1..-1]}#{m[3]}"
- # not a valid macro syntax w/o trailing square brackets
- # we probably shouldn't even get here...our regex is doing too much
- elsif m[1] == 'link:' && m[3].nil?
- next m[0]
- end
- prefix = (m[1] != 'link:' ? m[1] : '')
- target = m[2]
- # strip the <> around the link
- if prefix.end_with? '<'
- prefix = prefix[0..-5]
- end
- if target.end_with? '>'
- target = target[0..-5]
- end
- @document.register(:links, target)
- text = !m[3].nil? ? sub_attributes(m[3].gsub('\]', ']')) : ''
- "#{prefix}#{Inline.new(self, :anchor, (!text.empty? ? text : target), :type => :link, :target => target).render}"
- } unless !result.include?('http')
+ if found[:macroish] && result.include?('image:')
+ # image:filename.png[Alt Text]
+ result.gsub!(REGEXP[:image_macro]) {
+ # alias match for Ruby 1.8.7 compat
+ m = $~
+ # honor the escape
+ if m[0].start_with? '\\'
+ next m[0][1..-1]
+ end
+ target = sub_attributes(m[1])
+ @document.register(:images, target)
+ attrs = parse_attributes(m[2], ['alt', 'width', 'height'])
+ if !attrs.has_key?('alt') || attrs['alt'].empty?
+ attrs['alt'] = File.basename(target, File.extname(target))
+ end
+ Inline.new(self, :image, nil, :target => target, :attributes => attrs).render
+ }
+ end
- # inline link macros, link:target[text]
- result.gsub!(REGEXP[:link_macro]) {
- # alias match for Ruby 1.8.7 compat
- m = $~
- # honor the escape
- if m[0].start_with? '\\'
- next m[0][1..-1]
- end
- target = m[1]
- @document.register(:links, target)
- text = sub_attributes(m[2].gsub('\]', ']'))
- Inline.new(self, :anchor, (!text.empty? ? text : target), :type => :link, :target => target).render
- } unless !result.include?('link:')
+ if found[:macroish_short_form] || found[:round_bracket]
+ # indexterm:[Tigers,Big cats]
+ # (((Tigers,Big cats)))
+ result.gsub!(REGEXP[:indexterm_macro]) {
+ # alias match for Ruby 1.8.7 compat
+ m = $~
+ # honor the escape
+ if m[0].start_with? '\\'
+ next m[0][1..-1]
+ end
- result.gsub!(REGEXP[:xref_macro]) {
- # alias match for Ruby 1.8.7 compat
- m = $~
- # honor the escape
- if m[0].start_with? '\\'
- next m[0][1..-1]
- end
- if !m[1].nil?
- id, reftext = m[1].split(',', 2)
- id.sub!(/^("|)(.*)\1$/, '\2')
- reftext.sub!(/^("|)(.*)\1$/m, '\2') unless reftext.nil?
- else
- id = m[2]
- reftext = !m[3].empty? ? m[3] : nil
- end
- Inline.new(self, :anchor, reftext, :type => :xref, :target => id).render
- }
+ terms = (m[1] || m[2]).strip.tr("\n", ' ').gsub('\]', ']').split(REGEXP[:csv_delimiter])
+ document.register(:indexterms, [*terms])
+ Inline.new(self, :indexterm, text, :attributes => {'terms' => terms}).render
+ }
+
+ # indexterm2:[Tigers]
+ # ((Tigers))
+ result.gsub!(REGEXP[:indexterm2_macro]) {
+ # alias match for Ruby 1.8.7 compat
+ m = $~
+ # honor the escape
+ if m[0].start_with? '\\'
+ next m[0][1..-1]
+ end
- result.gsub!(REGEXP[:anchor_macro]) {
- # alias match for Ruby 1.8.7 compat
- m = $~
- # honor the escape
- if m[0].start_with? '\\'
- next m[0][1..-1]
- end
- id, reftext = m[1].split(',')
- id.sub!(/^("|)(.*)\1$/, '\2')
- if reftext.nil?
- reftext = "[#{id}]"
- else
- reftext.sub!(/^("|)(.*)\1$/m, '\2')
- end
- # NOTE the reftext should also match what's in our references dic
- if !@document.references[:ids].has_key? id
- Asciidoctor.debug { "Missing reference for anchor #{id}" }
- end
- Inline.new(self, :anchor, reftext, :type => :ref, :target => id).render
- } unless !result.include?('[[')
+ text = (m[1] || m[2]).strip.tr("\n", ' ').gsub('\]', ']')
+ document.register(:indexterms, [text])
+ Inline.new(self, :indexterm, text, :type => :visible).render
+ }
+ end
+ if found[:uri]
+ # inline urls, target[text] (optionally prefixed with link: and optionally surrounded by <>)
+ result.gsub!(REGEXP[:link_inline]) {
+ # alias match for Ruby 1.8.7 compat
+ m = $~
+ # honor the escape
+ if m[2].start_with? '\\'
+ next "#{m[1]}#{m[2][1..-1]}#{m[3]}"
+ # not a valid macro syntax w/o trailing square brackets
+ # we probably shouldn't even get here...our regex is doing too much
+ elsif m[1] == 'link:' && m[3].nil?
+ next m[0]
+ end
+ prefix = (m[1] != 'link:' ? m[1] : '')
+ target = m[2]
+ # strip the <> around the link
+ if prefix.end_with? '<'
+ prefix = prefix[0..-5]
+ end
+ if target.end_with? '>'
+ target = target[0..-5]
+ end
+ @document.register(:links, target)
+ text = !m[3].nil? ? sub_attributes(m[3].gsub('\]', ']')) : ''
+ "#{prefix}#{Inline.new(self, :anchor, (!text.empty? ? text : target), :type => :link, :target => target).render}"
+ }
+ end
+
+ if found[:macroish] && result.include?('link:')
+ # inline link macros, link:target[text]
+ result.gsub!(REGEXP[:link_macro]) {
+ # alias match for Ruby 1.8.7 compat
+ m = $~
+ # honor the escape
+ if m[0].start_with? '\\'
+ next m[0][1..-1]
+ end
+ target = m[1]
+ @document.register(:links, target)
+ text = sub_attributes(m[2].gsub('\]', ']'))
+ Inline.new(self, :anchor, (!text.empty? ? text : target), :type => :link, :target => target).render
+ }
+ end
+
+ if found[:macroish_short_form] && result.include?('footnote')
+ result.gsub!(REGEXP[:footnote_macro]) {
+ # alias match for Ruby 1.8.7 compat
+ m = $~
+ # honor the escape
+ if m[0].start_with? '\\'
+ next m[0][1..-1]
+ end
+ if m[1] == 'footnote'
+ # hmmmm
+ text = restore_passthroughs(m[2])
+ id = nil
+ index = @document.counter('footnote-number')
+ @document.register(:footnotes, Document::Footnote.new(index, id, text))
+ type = nil
+ target = nil
+ else
+ id, text = m[2].split(/ *, */, 2)
+ if !text.nil?
+ # hmmmm
+ text = restore_passthroughs(text)
+ index = @document.counter('footnote-number')
+ @document.register(:footnotes, Document::Footnote.new(index, id, text))
+ type = :ref
+ target = nil
+ else
+ fn = @document.references[:footnotes].find {|fn| fn.id == id }
+ target = id
+ id = nil
+ index = fn.index
+ text = fn.text
+ type = :xref
+ end
+ end
+ Inline.new(self, :footnote, text, :attributes => {'index' => index}, :id => id, :target => target, :type => type).render
+ }
+ end
+
+ if found[:macroish] || result.include?('<<')
+ result.gsub!(REGEXP[:xref_macro]) {
+ # alias match for Ruby 1.8.7 compat
+ m = $~
+ # honor the escape
+ if m[0].start_with? '\\'
+ next m[0][1..-1]
+ end
+ if !m[1].nil?
+ id, reftext = m[1].split(REGEXP[:csv_delimiter], 2)
+ id.sub!(/^("|)(.*)\1$/, '\2')
+ reftext.sub!(/^("|)(.*)\1$/m, '\2') unless reftext.nil?
+ else
+ id = m[2]
+ reftext = !m[3].empty? ? m[3] : nil
+ end
+ Inline.new(self, :anchor, reftext, :type => :xref, :target => id).render
+ }
+ end
+
+ if found[:square_bracket] && result.include?('[[[')
+ result.gsub!(REGEXP[:biblio_macro]) {
+ # alias match for Ruby 1.8.7 compat
+ m = $~
+ # honor the escape
+ if m[0].start_with? '\\'
+ next m[0][1..-1]
+ end
+ id = reftext = m[1]
+ Inline.new(self, :anchor, reftext, :type => :bibref, :target => id).render
+ }
+ end
+
+ if found[:square_bracket] && result.include?('[[')
+ result.gsub!(REGEXP[:anchor_macro]) {
+ # alias match for Ruby 1.8.7 compat
+ m = $~
+ # honor the escape
+ if m[0].start_with? '\\'
+ next m[0][1..-1]
+ end
+ id, reftext = m[1].split(REGEXP[:csv_delimiter])
+ id.sub!(/^("|)(.*)\1$/, '\2')
+ if reftext.nil?
+ reftext = "[#{id}]"
+ else
+ reftext.sub!(/^("|)(.*)\1$/m, '\2')
+ end
+ # NOTE the reftext should also match what's in our references dic
+ if !@document.references[:ids].has_key? id
+ Asciidoctor.debug { "Missing reference for anchor #{id}" }
+ end
+ Inline.new(self, :anchor, reftext, :type => :ref, :target => id).render
+ }
+ end
+
result
end
# Public: Substitute callout references
#
@@ -401,10 +513,17 @@
#
# text - The String text to process
#
# returns The String with the post replacements rendered using the backend templates
def sub_post_replacements(text)
- text.gsub(REGEXP[:line_break]) { Inline.new(self, :break, $1, :type => :line).render }
+ if @document.attr? 'hardbreaks'
+ lines = text.lines.entries
+ return text if lines.size == 1
+ last = lines.pop
+ "#{lines.map {|line| Inline.new(self, :break, line.rstrip.chomp(' +'), :type => :line).render } * "\n"}\n#{last}"
+ else
+ text.gsub(REGEXP[:line_break]) { Inline.new(self, :break, $1, :type => :line).render }
+ end
end
# Internal: Transform (render) a quoted text region
#
# match - The MatchData for the quoted text region