Emit event after component versions have been registered
We're considering emitting an event named componentsRegistered after all of the component versions have been registered, but before any files have been added to the content catalog. This transition point would be helpful for writing extensions that alter the component versions and URL patterns, for example, Antora Atlas.
Currently, it's either necessary to add entries to the content aggregate (contentAggregated) or to modify the content catalog after the files have been added (contentClassified). In the first case, the component version objects don't yet exist, so it's only possible to influence its properties indirectly. In the second case, all the URLs and latest versions have been computed, so making a change here often requires a lot of rewiring. Being able to run code in between these two stages would give the extension an ideal opportunity to modify the component version as it is being formed.
We'll need to decide how the event is emitted. Right now, the generateSite function emits all events. This is the first time an event will be emitted in a generator function (classifyContent). Fortunately, the generator context is bound to all generator functions, which means the functions have access to the generator context in order to emit events. Thus, one possibility is to update the classifyContent function to emit the event. Another approach would be for the generateSite function to pass in a callback function to the classifyContent function, which it would invoke after registering all component versions. That way, the classifyContent doesn't know its emitting an event. While we can consider that approach, it may not be consistent with Antora's design.
However the event is emitted, we'll need to deal with the fact that listeners can be asynchronous. To preserve backwards compatibility with existing custom site generators, the classifyContent function should not be labeled as asynchronous (at least not at this time). Rather, it should return a Promise only if there are listeners for the componentsRegistered event. Otherwise, it will work just as it did.