asciidoctor

Asciidoctor - remove comments from included file


I'm using AsciiDoctor, and I include source files from another location, like so:

[source,java]
----
include::some/path/Source.java[tags=one,two,three]
----

I'd like to remove some comments from the java file, specifically comments that do //@formatter:off and //@formatter:on.

I've tried writing an extension, specifically IncludeProcessor like so:

require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'

include Asciidoctor

# Removes //@formatter:off and //@formatter:on comments from java source code.
class RemoveFormatterIncludeProcessor < Extensions::IncludeProcessor
  include Asciidoctor::Logging
  def handles? target
    target.end_with? '.java'
  end

  def process doc, reader, target, attributes
    source = File.readlines File.join(doc.base_dir, target)
    filtered_content = source.reject { |l| l.include? "@formatter:" }
    reader.push_include filtered_content, File.expand_path(target), target, 1, attributes
  end
end

Extensions.register do
  include_processor RemoveFormatterIncludeProcessor
end

It does work and removes unwanted comments. Unfortunately, the [tag=...] attribute is not processed anymore, and I get the full file.

I can't wrap my head around which processor to implement or how.


Solution

  • After further exploration, I found a solution, using a TreeProcessor:

    require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
    
    include Asciidoctor
    
    # Remove //@formatter:off and //@formatter:on comments from java source.
    class RemoveFormatter < Asciidoctor::Extensions::TreeProcessor
      def process(document)
        document.find_by(context: :listing) do |block|
          if block.attributes["style"] == "source" && block.attributes["language"] == "java"
            block.lines = block.lines.reject { |l| l.include? "@formatter:" }
          end
        end
        document
      end
    end
    
    Extensions.register do
      treeprocessor RemoveFormatter
    end
    

    This version removes //@formatter:on and //@formatter:off from all java source snippets in a naive way.

    Usage:

    asciidoctor --require ./remove_formatter_comments.rb *.adoc

    More selective filtering

    If you want to selectively turn it off or on, you can change the condition inside process to something finer-grained, like:

    if block.attributes["formatter"] == "off"
        # ... filtering code ...
    end
    

    In that case, in your document, you can enable the feature with:

    [source,java,formatter=off]
    ----
    // ... some java code ...
    ----