diff --git a/lib/ES/Util.pm b/lib/ES/Util.pm index 906d1a83d93f7..3f3a3abaacf12 100644 --- a/lib/ES/Util.pm +++ b/lib/ES/Util.pm @@ -93,6 +93,7 @@ sub build_chunked { # '-a' => 'attribute-missing=warn', '-a' => 'asciidoc-dir=' . $asciidoc_dir, $resources ? ( '-a' => 'resources=' . join(',', @$resources)) : (), + '-a' => 'inline-callouts', '--destination-dir=' . $dest, docinfo($index), $index @@ -211,6 +212,7 @@ sub build_single { $private ? () : ( '-a' => "edit_url=$edit_url" ), '-a' => 'asciidoc-dir=' . $asciidoc_dir, $resources ? ( '-a' => 'resources=' . join(',', @$resources)) : (), + '-a' => 'inline-callouts', # Disable warning on missing attributes because we have # missing attributes! # '-a' => 'attribute-missing=warn', diff --git a/resources/asciidoctor/lib/extensions.rb b/resources/asciidoctor/lib/extensions.rb index b7eaa25ee5445..b579a22712ac6 100644 --- a/resources/asciidoctor/lib/extensions.rb +++ b/resources/asciidoctor/lib/extensions.rb @@ -6,6 +6,9 @@ require_relative 'elastic_compat_preprocessor/extension' require_relative 'elastic_include_tagged/extension' +# This extensions is special because it is evil - just loading it is enough +require_relative 'inline_callout/extension' + Extensions.register Added Extensions.register do # Enable storing the source locations so we can look at them. This is required diff --git a/resources/asciidoctor/lib/inline_callout/extension.rb b/resources/asciidoctor/lib/inline_callout/extension.rb new file mode 100644 index 0000000000000..208d27f9d2ac7 --- /dev/null +++ b/resources/asciidoctor/lib/inline_callout/extension.rb @@ -0,0 +1,69 @@ +require 'asciidoctor' + +include Asciidoctor + +## +# Enables inline callouts which asciidoc supports but asciidoctor doesn't. +# Filed as enhancement request at +# https://github.com/asciidoctor/asciidoctor/issues/3037 +# +# Usage +# +# POST <1> /_search/scroll <2> +# +# NOTE: This isn't an asciidoctor extension so much as a hack. Just including +# the file causes us to monkey patch its code into asciidoctor. By default we +# don't change asciidoctor, but if you set the `inline-callouts` attribute so +# you need to *ask* for the change in behavior. +# +module InlineCallout + InlineCalloutScanRx = /\\?/ + InlineCalloutSourceRx = %r(((?://|#|--|;;) ?)?(\\)?<!?(|--)(\d+|\.)\3>) + InlineCalloutSourceRxt = "(\\\\)?<()(\\d+|\\.)>" + InlineCalloutSourceRxMap = ::Hash.new {|h, k| h[k] = /(#{::Regexp.escape k} ?)?#{InlineCalloutSourceRxt}/ } + + # Disable VERBOSE so we don't log any warnings. It really isn't great to + # have to patch these in like this but it gets the job done and we're looking + # to get this into Asciidoctor proper. These methods are basically the same + # as the methods in asciidoctor but with new regexes. + old_verbose = $VERBOSE + $VERBOSE = false + Parser.class_eval do + def self.catalog_callouts(text, document) + found = false + autonum = 0 + callout_rx = (document.attr? 'inline-callouts') ? InlineCalloutScanRx : CalloutScanRx + text.scan(callout_rx) { + captured, num = $&, $2 + document.callouts.register num == '.' ? (autonum += 1).to_s : num unless captured.start_with? '\\' + # we have to mark as found even if it's escaped so it can be unescaped + found = true + } if text.include? '<' + found + end + end + + Substitutors.module_eval do + def sub_callouts(text) + autonum = 0 + text.gsub(callout_rx) { + # honor the escape + if $2 + # use sub since it might be behind a line comment + $&.sub(RS, '') + else + Inline.new(self, :callout, $4 == '.' ? (autonum += 1).to_s : $4, :id => @document.callouts.read_next_id, :attributes => { 'guard' => $1 }).convert + end + } + end + + def callout_rx + if attr? 'line-comment' + ((attr? 'inline-callouts') ? InlineCalloutSourceRxMap : CalloutSourceRxMap)[attr 'line-comment'] + else + (attr? 'inline-callouts') ? InlineCalloutSourceRx : CalloutSourceRx + end + end + end + $VERBOSE = old_verbose +end diff --git a/resources/asciidoctor/spec/inline_callout_spec.rb b/resources/asciidoctor/spec/inline_callout_spec.rb new file mode 100644 index 0000000000000..071cae1c8202d --- /dev/null +++ b/resources/asciidoctor/spec/inline_callout_spec.rb @@ -0,0 +1,57 @@ +require 'inline_callout/extension' + +RSpec.describe InlineCallout do + it "enables support for inline callouts if requested" do + attributes = { + 'inline-callouts' => '', + } + input = <<~ASCIIDOC + ---- + POST <1> /_search/scroll <2> + ---- + <1> words + <2> other words + ASCIIDOC + expected = <<~DOCBOOK + + + POST /_search/scroll + + + words + + + other words + + + + DOCBOOK + expect(convert(input, attributes)).to eq(expected.strip) + end + + it "does not enable support for inline callouts by default" do + input = <<~ASCIIDOC + ---- + POST <1> /_search/scroll <2> + ---- + <1> words + <2> other words + ASCIIDOC + expected = <<~DOCBOOK + + + POST <1> /_search/scroll + + + words + + + other words + + + + DOCBOOK + actual = convert input, {}, eq('WARN: : line 4: no callout found for <1>') + expect(actual).to eq(expected.strip) + end +end \ No newline at end of file