metanorma / metanorma-plugin-lutaml

Metanorma plugin: access LutaML objects from within a Metanorma document
BSD 2-Clause "Simplified" License
1 stars 1 forks source link

Registration ordering for plugins #103

Open opoudjis opened 6 months ago

opoudjis commented 6 months ago

As a result of the massive refactoring done in https://github.com/metanorma/metanorma/issues/352, I require the preprocessor Metanorma::Standoc::ResolveIncludePreprocessor to be registered BEFORE any any external plugin.

https://github.com/metanorma/metanorma-standoc/blob/74450d1d9b3c69b0f90a30e2ec6378833cce04bb/lib/metanorma/standoc/converter.rb#L24

Moreover, external preprocessor plugins must return an instance of the PreprocessorNoIfdefReader class, so that they always skip ifdefs until those can be processed by the AsciiDoctor parser.

https://github.com/metanorma/metanorma-plugin-lutaml/blob/main/lib/metanorma/plugin/lutaml/asciidoctor/preprocessor.rb

This is contrary to @ronaldtse ’s intention:

@opoudjis the problem with having standoc manage registration is that people cannot create their own plugins. I would rather have some sort of priority sequence number when registering.

This was my requirement when we first developed the plugin architecture. Standoc should not need to know everything about everyone when registering a plugin.

A similar pattern has been used in Rails as in Railties.

But having plugins register with Asciidoctor within the plugin gem, without the ordering of preprocessor registration set by standoc, is unacceptable.

Either: plugins should instead expose a register method, that standoc can invoke when it is good and ready to. Or: I order the sequencing of requires, so that it does not disrupt the flow of information. (And ordering is important in preprocessors.)

standoc converter.rb starts like this:

    class Converter
      Asciidoctor::Extensions.register do
        preprocessor Metanorma::Standoc::ResolveIncludePreprocessor
        preprocessor Metanorma::Plugin::Lutaml::LutamlPreprocessor
        preprocessor Metanorma::Plugin::Lutaml::LutamlUmlAttributesTablePreprocessor
        preprocessor Metanorma::Plugin::Lutaml::LutamlUmlDatamodelDescriptionPreprocessor
        preprocessor Metanorma::Plugin::Lutaml::LutamlUmlClassPreprocessor
        inline_macro Metanorma::Plugin::Lutaml::LutamlFigureInlineMacro
        inline_macro Metanorma::Plugin::Lutaml::LutamlTableInlineMacro
        block_macro Metanorma::Plugin::Lutaml::LutamlDiagramBlockMacro
        block Metanorma::Plugin::Lutaml::LutamlDiagramBlock
        preprocessor Metanorma::Standoc::EmbedIncludeProcessor
        preprocessor Metanorma::Standoc::LinkProtectPreprocessor
        preprocessor Metanorma::Standoc::Datamodel::AttributesTablePreprocessor
        preprocessor Metanorma::Standoc::Datamodel::DiagramPreprocessor
        preprocessor Metanorma::Plugin::Datastruct::Json2TextPreprocessor
        preprocessor Metanorma::Plugin::Datastruct::Yaml2TextPreprocessor
        preprocessor Metanorma::Plugin::Glossarist::DatasetPreprocessor
        preprocessor Metanorma::Standoc::NamedEscapePreprocessor
...

I cannot just allow external plugins to register before ResolveIncludePreprocessor. Giving me an arbitrary sequence number defined externally doesn't make sense either: I should still set the sequence. (What the hell does an external dev know about the relative ordering of Lutaml and Glossarist? And why should they?)

So the following makes much more sense to me :

    class Converter
      Asciidoctor::Extensions.register do
        preprocessor Metanorma::Standoc::ResolveIncludePreprocessor
      end
   require  "plugin 1"
      Asciidoctor::Extensions.register do
        preprocessor Metanorma::Plugin::Lutaml::LutamlPreprocessor
        preprocessor Metanorma::Plugin::Lutaml::LutamlUmlAttributesTablePreprocessor
        preprocessor Metanorma::Plugin::Lutaml::LutamlUmlDatamodelDescriptionPreprocessor
        preprocessor Metanorma::Plugin::Lutaml::LutamlUmlClassPreprocessor
      end
   require  "plugin 2"

That way I know what is going on. It's not like standoc is going to do anything with external plugins unless it requires their gems; but I should still dictate when they are sequenced. I don't see a compelling case here for sequence numbers, in fact: ordering registration order, and interspersing it with requires of plugins, is sufficient.

Your task is to implement... something that will address both Ronald's architecture need, and my need for external plugins to register in an order that I have some control over.