Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Community feedback request for Asciidoctor 5. #742

Open
ysb33r opened this issue Nov 30, 2024 · 3 comments
Open

Community feedback request for Asciidoctor 5. #742

ysb33r opened this issue Nov 30, 2024 · 3 comments
Milestone

Comments

@ysb33r
Copy link
Member

ysb33r commented Nov 30, 2024

There is a requirement to make this plugin configuration cache-compatible and also to prepare for some future Gradle features such as isolated projects and declartative gradle..
This also means that we'll only support Gradle 7.3 and later.
It gives us the chance to do some much needed restructuring and use Asciidoctorj 3.x engine.

To prepare a 5.x release of this plugin-suite I propose some radical (and breaking) changes to the DSL.
It would be great to get some feedback from the community on these.

The current DSL

A typical usage might be something like

plugins {
 id 'org.asciidoctor.jvm.convert' version '4.0.1'
 id 'org.asciidoctor.jvm.pdf' version '4.0.1'
}

asciidoctorj {
  // Global configuration
}

asciidoctor {
  asciidoctorj {
    // local customisation for HTML conversion
  }
}

asciidoctorPdf {
  asciidoctorj {
    // local customisation for PDF conversion
  }
}

Feedback from the community has indicated that the major issue with this is that this needs to use two different sources and that asciidoctorPdf needs to be modified to use the same source as the asciidoctor task.
They would prefer to have one task again and declare all of the output types in one place like it was with the 1.x & 2.x releases
With 3.x & 4.x we broke away from that becasue we did want to provide better DSLs for specific output types and we did not want to unnecessarily have asciidoctor output jars on the classpath that are not needed.

The changes for v5

Instead of customising tasks, I think we should move to a model, which are gaing momentum in the Gradle world, and that is to declare source sets and each declaration will then create the appropriate tasks.
This means that we can still have a asciidoctor and an asciidoctorPdf task, but that we do all the common configuration in the source set.

asciidoc {
    sourceSets {
        main {
            sourceDir = 'src/docs/asciidoc' // This will be the default location as before
            sources {
                include 'toplevel.adoc', 'another.adoc', 'third.adoc'
            }
            backends {
                jvm {
                    pdf {
                        // configuration specific to PDF output
                    }
                    revealjs {
                        // configuration specific to Reveal.js output
                    }
                }
                js {
                    html5 {
                        // configuration specific to HTML5 output when run with asciidoctor.js
                    }
                }
            }

            engines {
                asciidoctorj {
                    // configuration specific to the asciidoctoj engine
                }
            }

        }
        myExtra {
            sources {
                include 'foo.adoc', 'bar.adoc'
            }
        }
    }
}

This will create two source sets.
By default the source directories will be src/docs/asciidoc and src/docs/asciidocMyExtra.
Output directories will be build/docs/asciidoc and build/adocs/asciidocMyExtra.

Most of the configuration that is availabe today as per https://github.com/asciidoctor/asciidoctor-gradle-plugin/blob/release_4_0_3/docs/modules/ROOT/pages/common-task-configuration.adoc will be available on each sourceset.

All the backends for output will be declared in one place.
Certain backends will only be available if another plugin is applied.
The backends also declare on which engine it should be run - JVM or JS.
Engines are made available via plugins.
I will not be possioble to run the same backend (output format) on two different engines within the same source set.

If no backends are specified, it will be assumed that it will html5 on the Ja

Assuming that all the plugins have been applied, the above will create the following tasks:

  • asciidoctor
  • asciidoctorPdf
  • asciidoctorEpub
  • myExtraAsciidoctor

Example: Working with PDF

import org.asciidoctor.pdf.theme.Local
import org.asciidoctor.pdf.theme.Github

plugins {
    id 'org.asciidoctor.jvm.convert' version '5.0.0'
    id 'org.asciidoctor.jvm.pdf' version '5.0.0'
}

asciidoc {
    pdf { // Themes are global to all source sets.
        themes {
            basic(Local) {
                themeDir = file('themes/basic')
                themeName = 'very-basic'
            }
            fancy(Github) {
                organisation = 'fwilhe2'
                repository = 'corporate-theme'
                relativePath = 'resources/themes'
                tag = '1.0.1'
            }
        }
    }
    sourceSets {
        main {
            backends {
                jvm {
                    pdf {
                        theme = 'basic' // Use the defined theme.
                    }
                }
            }
        }
    }
}

It is proposed that the pdfThemes extension becomes an extension on asciidoc extension.

@ysb33r ysb33r added this to the 5.0 milestone Nov 30, 2024
@wilkinsona
Copy link
Contributor

I like the idea of moving to a model-based approach. I think it'll improve the DSL and, as noted above, it's more closely aligned with the modern way of doing things in Gradle. I do wonder a bit about the terminology, however.

Naming's always hard, but I find it a little counter-intuitive to be configuring the backends, themes etc – settings that are all about how the output is produced – on something that's called a source set. A source set, in my mind at least, is almost entirely about the input side of things with the output side being limited to where the output will be written and some links to the tasks that will produce that output. Perhaps this could be addressed with different terminology?

Alternatively, I wonder if the source set-specific configuration of backends and themes, etc, should move to tasks that are connected" to a source set. This would be analogous to SourceSet#getCompileJavaTaskName() and the various configuration settings that are available on JavaCompile. The global configuration could perhaps then be used as the conventions for the source set-specific tasks' configuration. Something that's somewhat analogous to JavaPluginExtension could be used to configure the global settings just as things like source and target compatibility can be configured globally for Java compilation.

Having written the above, I'm not sure that it works when you want to have different tasks for PDF, ePub, etc. How would a user indicate that those tasks should be created if there's no setting on the "source set" to allow them to do so? I'll leave it here as hopefully the thought process is still of some use and may help to spark some other ideas…

@ysb33r
Copy link
Member Author

ysb33r commented Dec 8, 2024

@wilkinsona Maybe instead of the word backends, formats can be used.

And maybe instead of sourceSets we can say publications ?

asciidoc {
  publications {
    main {
       sourceDir = 'src/docs/asciidoc' // This will be the default location as before
       sources {
          include 'toplevel.adoc', 'another.adoc', 'third.adoc'
       }       
     formats {
       pdf {
          useJvmEngine() // Tell it to produce a pdf using the asciidoctorj engine
       }
     }
    }
  }
}

@wilkinsona
Copy link
Contributor

formats sounds good to me.

publications I am not sure sure about as it overlaps with Gradle's publishing terminology. Perhaps documents? I realise there's some overlap with Asciidoctor terminology but maybe that's less bad in the context of a Gradle build script?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants