asciidoctor / asciidoctorj

:coffee: Java bindings for Asciidoctor. Asciidoctor on the JVM!
http://asciidoctor.org
Apache License 2.0
617 stars 172 forks source link

It should be possible to register an instance in the javaConverterRegistry #932

Open ggrossetie opened 4 years ago

ggrossetie commented 4 years ago

Asciidoctor (Ruby) allows to register both class and instance. Registering an instance can be useful when you want to pass additional options.

Consider the following example:

class GoogleSlidesConverterRegistry : ConverterRegistry {
  override fun register(asciidoctor: Asciidoctor) {
    val googleSlidesConverter = GoogleSlidesConverter("googleslides", mapOf("credentials-path" to "/path/to/credentials.json"))
    asciidoctor.javaConverterRegistry().register(googleSlidesConverter, "googleslides")
  }
}

In this example, the converter needs a credentials file to authenticate with the Google Slides API.

robertpanzer commented 4 years ago

Agreed, we might want to add this too. Until then you could pass the options to convert() and then get them from the Document:

        asciidoctor.convert(document, OptionsBuilder.options()
                .option('credentials-path', '/path/to/credentials.json'').backend('googleslides')

And then in the Converter:

    @Override
    String convert(ContentNode node, String transform, Map<Object, Object> opts) {
      String credentials = node.getDocument().getOptions().get('credentials-path')
      ...
    }

I think this solution would also have some advantages in multithreaded environments when different threads/contexts would require different credentials.

ggrossetie commented 4 years ago

Thanks Robert for your reply.

Another alternative would be to retrieve the Document (and therefore the options) from the constructor. I didn't try but reading the Ruby code I believe that Asciidoctor (Ruby) passes the Document as an options when the converter is instantiated/created (see lib/asciidoctor/document.rb#L1128-L1144)

So in theory, the following should work:

class GoogleSlidesConverter extends AbstractConverter {
  public GoogleSlidesConverter(String backend, Map<Object, Object> opts) {
    String credentials = ((Document) opts.get("document")).getOptions().get("credentials-path")
  }
}
robertpanzer commented 4 years ago

Yes, that should work too.

chrylis commented 3 weeks ago

This ticket is stale but still open. It would be helpful to have a functional interface ConverterProvider so that, for example, dependency-injected applications could set up dependencies, and then the framework call provider.apply(backend, opts).