How to generate sections in extension ?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

How to generate sections in extension ?

domgold
I have been working on a `gherkin` extension.

The extension provides a possibility to 'pretty-print' gherkin (files) (*.feature) to html or docbook/pdf.
The feature files get parsed by the extension and converted to asciidoc markdown which then is included into the document.

While I was able to produce a working solution by setting up an IncludeProcessor, I was wondering if there was a simple solution to do this in a *BlockProcessor*.
The block processor would have to return complex content (section with nested subsections and paragraphs etc) and not just a simple image or paragraph as in most extension examples.

For example, processing the following block:

[source,asciidoc]
----

[gherkin]
....
Feature: A simple feature

  Scenario: A simple scenario
    Given a simple step
    Then another simple step
....
----

should return a *section* block element corresponding to the following asciidoc source:

[source,asciidoc]
----
== A simple feature

=== A simple scenario

* Given a simple step
* The another simple step
----

Any hints how to do this (in Java) or where to find more information (not the gherkin parsing part, just the block creation stuff)? Thanks a lot.

Dominik
Reply | Threaded
Open this post in threaded view
|

Re: How to generate sections in extension ?

asotobu
I have not tried but I think you should do something like:

I think this is not going to be possible in Java yet. Because I have seen that you only can create Block, but not Section (which is also a Block),in Ruby implementation you will be able to do it but not in Java, so if you can open an issue I will address for next version :).

Maybe you can try something like return createBlock(parent, "section", Arrays.asList(upperLines), attributes, new HashMap<Object, Object>());

But I am sure that it won't work pretty well.
Reply | Threaded
Open this post in threaded view
|

Re: How to generate sections in extension ?

asotobu
I am resolving this issue, in 1.5.1 you will be able to do it. :)
Reply | Threaded
Open this post in threaded view
|

Re: How to generate sections in extension ?

asotobu
I think there is a bug in Asciidoctor. I am reviewing but if you return a Section in a block extension instead of a Block, next exception is thrown

org.jruby.exceptions.RaiseException: (NoMethodError) undefined method `lines' for #<Asciidoctor::Section:0x26350ea2>


So now I am not sure if it will be possible to create a section inside a block.

I will keep you informed :)
Reply | Threaded
Open this post in threaded view
|

Re: How to generate sections in extension ?

mojavelinux
Administrator
I can confirm that it's not possible to _return_ a Section instance from a BlockProcessor or BlockMacroProcessor. However, there are two solutions you can use to generate a section.

One solution is to push new lines onto the document reader and return nil. This will make Asciidoctor process the generated lines instead of the lines in the block. Here's an example in Ruby:

```ruby
block { 
  named :gherkin
  on_context :literal
  parse_content_as :raw
  process do |parent, reader, attrs|
    parent.reader.push_include ['== New Section], 'generated', 'generated', 1, {}
    nil
  end
}
```

Another, and much better, approach is to manually add a new section and child blocks to the parent and, again, return nil. Here's an example in Ruby:

```ruby
block {
  named :gherkin
  on_context :literal
  parse_content_as :raw
  process do |parent, reader, attrs|
    sect = Section.new parent, 1, (parent.document.attr 'sectnums')
    sect.title = 'New Section'

    para = create_paragraph parent, 'new paragraph'
    sect << para
    parent << sect
    nil
  end
}
```

I don't necessarily see it as a bad thing that you need to append the section (either in source or AST form) manually and return nil. There are certain assumptions we make internally that a block-level processor is going to return a concrete block and not a section (an abstract block). Having said that, I do think it should be possible eventually. But until we've made the necessary changes, one of the two approaches I suggested are what you'll need to use in the interim.

This is obviously key information for the (planned) extension writing guide.

I'm super excited about the gherkin extension. I'd love to add that to the extensions-lab when it's ready!

Cheers,

-Dan

On Wed, Sep 10, 2014 at 12:37 PM, asotobu [via Asciidoctor :: Discussion] <[hidden email]> wrote:
I think there is a bug in Asciidoctor. I am reviewing but if you return a Section in a block extension instead of a Block, next exception is thrown

org.jruby.exceptions.RaiseException: (NoMethodError) undefined method `lines' for #<Asciidoctor::Section:0x26350ea2>


So now I am not sure if it will be possible to create a section inside a block.

I will keep you informed :)


If you reply to this email, your message will be added to the discussion below:
http://discuss.asciidoctor.org/How-to-generate-sections-in-extension-tp2142p2178.html
To start a new topic under Asciidoctor :: Discussion, email [hidden email]
To unsubscribe from Asciidoctor :: Discussion, click here.
NAML



--
Reply | Threaded
Open this post in threaded view
|

Re: How to generate sections in extension ?

domgold
OK I'll give it a try when I have some spare time. This is more complicated than I thought, at least it won't work as a pure Java extension, which is what I planned to do initially.

`parent.reader.push_include` is not accessible via the Java API from a Blockprocessor, I think.

I'll have to learn some Ruby :)

Another solution I was looking into is to use the `parse_content` method in Processor. Again this method is not available in the Java API, so I tried invoking it via JRuby without much success.
Reply | Threaded
Open this post in threaded view
|

Re: How to generate sections in extension ?

asotobu
Nope I think reader is not available, if you can open an issue about getting reader instance from block in asciidocotrj, and I will implement for version 1.5.1. :) 

2014-09-17 15:17 GMT+02:00 domgold [via Asciidoctor :: Discussion] <[hidden email]>:
OK I'll give it a try when I have some spare time. This is more complicated than I thought, at least it won't work as a pure Java extension, which is what I planned to do initially.

`parent.reader.push_include` is not accessible via the Java API from a Blockprocessor, I think.

I'll have to learn some Ruby :)

Another solution I was looking into is to use the `parse_content` method in Processor. Again this method is not available in the Java API, so I tried invoking it via JRuby without much success.



If you reply to this email, your message will be added to the discussion below:
http://discuss.asciidoctor.org/How-to-generate-sections-in-extension-tp2142p2240.html
To unsubscribe from How to generate sections in extension ?, click here.
NAML



--
+----------------------------------------------------------+
  Alex Soto Bueno - Computer Engineer
  www.lordofthejars.com
+----------------------------------------------------------+
Reply | Threaded
Open this post in threaded view
|

Re: How to generate sections in extension ?

domgold
It's been a while, but I finally figured it out. I ended up implementing the extension in ruby (using some java bits where it saved me time).

From the ruby block macro processor, the following line creates the sections and subsections :

----
parent.document.reader.push_include rendered_template_output, target, target, 1, attributes
----

where `rendered_template_output` is a string containing the asciidoc markup to be 'included'.

If you want to check out the complete gherkin extension, have a look here :

https://github.com/domgold/asciidoctor-gherkin-extension

By the way, I found implementing extensions in ruby MUCH more comfortable than using the java API, even with my (today) limited ruby knowledge.

The Java API lacks the dsl and most of the convenience methods to create blocks, content and so on.
Reply | Threaded
Open this post in threaded view
|

Re: How to generate sections in extension ?

mojavelinux
Administrator
If you want to check out the complete gherkin extension, have a look here:
 

https://github.com/domgold/asciidoctor-gherkin-extension 

Cool! I'm in the process of writing a whole bunch of scenarios in Gherkin, so I'll definitely check it out!

The Java API lacks the dsl and most of the convenience methods to create blocks, content and so on.

That's where the Groovy DSL for Asciidoctor extensions is going to come in. See:


Cheers,