mdoc
mdoc copied to clipboard
Request for a PostModifier start/end of life-cycle method
Hope I am not overstepping my bounds here but I have a use-case that I cannot get around and this request seems to be a good way to solve it. Any suggestion for an alternative workaround is welcome. Some background and context. I am using a PostModifier to process code fences that generate plots via a JavaScript library (in this case PlotlyJS). In order to generate static documents (PDF) via Laika I need to render and convert those plots into raster images (png, tiff, etc). To do this I need to instantiate a JavaFX application (with a WebKit component) that will execute the JS script and render the plots headless to files.
So what is the problem? This process is executed as a Miil module (akin to an SBT plug-in) in a forked JVM. Because of the JavaFX application daemon thread, the spawned job will not terminate. In order to termnate this task I need to explicitly stop the headless javaFX application. However I can only do this when I know that MDoc has finished all processing. Hence the request to add such a method. Here I can place a call that stops the javaFX thread. Once no more files need processing, MDoc closes the PostModifier.
So my question are: is this viable and acceptable? Are their mechanisms for me to do this shutdown without the need for such changes?
TIA
Thank you for reporting! Big 👍 from me. Would you be interested in contributing this feature?
One question: how should the start/end methods work under --watch mode?
You might be able to get some inspiration for how to implement this by looking at postProcess on PreModifier
https://github.com/scalameta/mdoc/blob/3afbd52afae896e975701547d94779c02a8aedbd/mdoc/src/main/scala/mdoc/PreModifier.scala#L20
Example: the mdoc:js modifier is a PreModifier that collects all mdoc:js code fences during process
https://github.com/scalameta/mdoc/blob/3afbd52afae896e975701547d94779c02a8aedbd/mdoc-js/src/main/scala-2.12/mdoc/modifiers/JsModifier.scala#L219
During postProcess, we use the Scala.js compiler to link a JavaScript file and add links to the generated JS
https://github.com/scalameta/mdoc/blob/3afbd52afae896e975701547d94779c02a8aedbd/mdoc-js/src/main/scala-2.12/mdoc/modifiers/JsModifier.scala#L127
@olafurpg Ok, I will take a look at the links you show and see what I can come up with.
In regards to the --watch flag I confess I did not think about this. I will have to give it some more though. But right now I think that the strategy I outlined above will won't work. The JavaFX platform cannot be started more than once per JVM.
Will come back to you on this.
One thing we can do it several callbacks for different events 🤔
- add
onExit: before mdoc is shutting down - add
onWatchIterationEnd: after completing compilation after a single --watch iteration
I had to revisit the stuff I made in order to determine how to stop/start the JavaFX application and this can be used within MDoc. I have two sets of operations:
- One that starts and stops the JFX platform and application
- One that starts the JFX platform once and keeps it alive but restarts the application
Seem to be working correctly.
We have 2 different cases:
- Lunching MDoc and executing the PostModifier in a forked JVM once
- Lunching MDoc and executing the PostModifier in the build tool JVM repeatedly
The problem here is how to support both scenarios at the same time. In case 1 I can start and stop both platform and application with a postProcess method (the constructor will be used for the start). That solves the issue.
In case 2 I would have to :
- Initialize the Platform when MDoc starts up
- Start the application when the PostModifier starts (use the constructor?)
- Stop the application when the PostModifier stops
- Stop the Platform when MDoc stops
The above steps lets us use MDoc with --watch (no need to restart between watches). It also subsumes case 1. So I would need 4 methods:
- MDoc
onStart - PostModifier
preProcess - PostModifier
postProcess - MDoc
onExit
Don't know if a onWatchIterationEndmay be useful for someone else.
Is this ok? Can it be done with minor changes to the current code base ?
TIA
Side note:
I am using MDoc as a Mill task. Mill has the -w/--watch and .runBackground modes. This means that I will use Mill to scan and check for any changes in the MDoc sources. Not as efficient as MDoc's watch but it allows me to play nicely with the build tool's interactive mode. I can try using MDoc directly but will experiment with this later.
@hmf thanks for the update. Feel free to add only the hooks that you need. We can add onWatchIterationEnd separately.
I am using MDoc as a Mill task. Mill has the -w/--watch and .runBackground modes.
The reason mdoc has its own --watch is to be able to reuse the compiler instance between compilations. The 2nd/3rd/... compilations are usually 10x faster than the 1st compilation.