asciidoctor / asciidoctor.org

:globe_with_meridians: Asciidoctor project site. Composed in AsciiDoc. Baked with Awestruct.
https://asciidoctor.org
Other
322 stars 808 forks source link

ShellSessionTreeProcessor tree processor example from docs breaks on definition lists, which don't have .context #874

Closed cirosantilli closed 2 years ago

cirosantilli commented 4 years ago

At https://asciidoctor.org/docs/user-manual/#tree-processor-example

First I add missing requires and convert the deprecated EOL to Asciidoctor::LF to make it work again, put it all in one file, and it gives:

require 'asciidoctor'
require 'asciidoctor/extensions'

class ShellSessionTreeProcessor < Asciidoctor::Extensions::TreeProcessor
  def process document
    return unless document.blocks?
    process_blocks document
    nil
  end

  def process_blocks node
    node.blocks.each_with_index do |block, i|
      if block.context == :literal &&
          (((first_line = block.lines.first).start_with? '$ ') ||
            (first_line.start_with? '> '))
        node.blocks[i] = convert_to_terminal_listing block
      else
        process_blocks block if block.blocks?
      end
    end
  end

  def convert_to_terminal_listing block
    attrs = block.attributes
    attrs['role'] = 'terminal'
    prompt_attr = (attrs.has_key? 'prompt') ?
        %( data-prompt="#{block.sub_specialchars attrs['prompt']}") : nil
    lines = block.lines.map do |line|
      line = block.sub_specialchars line.chomp
      if line.start_with? '$ '
        %(<span class="command"#{prompt_attr}>#{line[2..-1]}</span>)
      elsif line.start_with? '&gt; '
        %(<span class="output">#{line[5..-1]}</span>)
      else
        line
      end
    end
    create_listing_block block.document, lines * Asciidoctor::LF, attrs, subs: nil
  end
end

Asciidoctor::Extensions.register do
  treeprocessor ShellSessionTreeProcessor
end

Asciidoctor.convert_file 'sample-with-shell-session.adoc', :safe => :safe

This works for the tested example document on the docs:

 $ echo "Hello, World!"
 > Hello, World!

 $ gem install asciidoctor

However, if I add a definition list to the example, it fails:

 $ echo "Hello, World!"
 > Hello, World!

 $ gem install asciidoctor

a:: b

because it doesn't have context:

Traceback (most recent call last):
        18: from main.rb:46:in `<main>'
        17: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/convert.rb:183:in `convert_file'
        16: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/convert.rb:183:in `open'
        15: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/convert.rb:183:in `block in convert_file'
        14: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/convert.rb:78:in `convert'
        13: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/load.rb:83:in `load'
        12: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/document.rb:555:in `parse'
        11: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/document.rb:555:in `each'
        10: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/document.rb:556:in `block in parse'
         9: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/document.rb:556:in `[]'
         8: from main.rb:7:in `process'
         7: from main.rb:12:in `process_blocks'
         6: from main.rb:12:in `each_with_index'
         5: from main.rb:12:in `each'
         4: from main.rb:18:in `block in process_blocks'
         3: from main.rb:12:in `process_blocks'
         2: from main.rb:12:in `each_with_index'
         1: from main.rb:12:in `each'
main.rb:13:in `block in process_blocks': undefined method `context' for #<Array:0x000056192626b9f8> (NoMethodError)
        18: from main.rb:46:in `<main>'
        17: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/convert.rb:183:in `convert_file'
        16: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/convert.rb:183:in `open'
        15: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/convert.rb:183:in `block in convert_file'
        14: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/convert.rb:78:in `convert'
        13: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/load.rb:83:in `load'
        12: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/document.rb:555:in `parse'
        11: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/document.rb:555:in `each'
        10: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/document.rb:556:in `block in parse'
         9: from /home/ciro/.rvm/gems/ruby-2.6.0/gems/asciidoctor-2.0.10/lib/asciidoctor/document.rb:556:in `[]'
         8: from main.rb:7:in `process'
         7: from main.rb:12:in `process_blocks'
         6: from main.rb:12:in `each_with_index'
         5: from main.rb:12:in `each'
         4: from main.rb:18:in `block in process_blocks'
         3: from main.rb:12:in `process_blocks'
         2: from main.rb:12:in `each_with_index'
         1: from main.rb:12:in `each'
main.rb:13:in `block in process_blocks': asciidoctor: FAILED: /home/ciro/test/main.adoc: Failed to load AsciiDoc document - undefined method `context' for #<Array:0x000056192626b9f8> (NoMethodError)

I don't know what's the best way to handle it, but it would be good to use it in that example.

cirosantilli commented 4 years ago

Ah, likely (document.find_by context: :literal).each do |literal| is the way to go by copying from: https://github.com/asciidoctor/asciidoctor-extensions-lab/blob/e922e9ed10244586d510d5cdc35e3be6cad9c297/lib/multirow-table-header-tree-processor.rb

ggrossetie commented 4 years ago

I think we should transfer this issue to: https://github.com/asciidoctor/asciidoctor.org

Ah, likely (document.find_by context: :literal).each do |literal| is the way to go

Yes, could you please submit your changes at: https://github.com/asciidoctor/asciidoctor.org/blob/master/docs/_includes/exten-tree.adoc

But keep in mind that the future documentation site will be using: https://github.com/asciidoctor/asciidoctor/blob/v1.5.7-docs/docs/asciidoctor/modules/api/pages/tree-processor.adoc

mojavelinux commented 4 years ago

I also don't like that there is code in asciidoctor.org. The real code is in the extensions lab, and that's the code that should be in the docs. The code sample stored in asciidoctor.org has never been tested.

mojavelinux commented 4 years ago

Here's the real code: https://github.com/asciidoctor/asciidoctor-extensions-lab/blob/master/lib/shell-session-treeprocessor/extension.rb

cirosantilli commented 4 years ago

Good to see that the docs will move into the main repo! Is it going to be on master, or just a separate branch? master would be awesome.

mojavelinux commented 4 years ago

Yes, they are being moved to the repositories where the code lives (docs as code). So the main docs for Asciidoctor will be in asciidoctor/asciidoctor. This is the repository that will assemble the docs: https://github.com/asciidoctor/docs.asciidoctor.org

mojavelinux commented 4 years ago

The docs will live with the branch that they document. So the docs in development will be on master. The docs for a specific release will be on the release branch. That also means the docs will be versioned for the first time.

mojavelinux commented 2 years ago

The migration of the docs is now complete. See https://docs.asciidoctor.org.

mojavelinux commented 2 years ago

It turns out the example code was just woefully out of date. I've updated it and confirmed that it works with the latest version of Asciidoctor. See https://docs.asciidoctor.org/asciidoctor/latest/extensions/tree-processor/