introduce a more fine-grained rewrite phase model#302
Merged
Conversation
# Conflicts: # core/shared/src/main/scala/laika/api/builder/OperationConfig.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This refactoring addresses a long-standing issue where the internal AST rewriting that happens between parsing and rendering introduced chicken-and-egg scenarios that led to unexpected results for users in some edge cases. In the past there were always options to introduce workarounds when a related issue surfaced (like in #263). However, a new issue was reported recently (#289) where applying duct tape was no longer possible, and it was time for a bigger refactoring.
The key ideas that should solve the vast majority of related issues for users without the need for them to do anything or even understand the underlying topics were the following two:
Introduce a third rewrite phase in addition to the existing two. The phase model now consists of:
RewritePhase.Buildthe first phase run after parsing and the only phase where new link targets can be introduced safely.RewritePhase.Resolvethe second phase which is mostly reserved for internal use (e.g. running the link resolver).RewritePhase.Render(OutputContext)the final phase run before rendering, which is specific to the selected output format and therefore parameterized. Rules and directives run in this phase get to see an "almost complete" AST. It is therefore the best place for extensions that produce navigation artefacts for example.Adapt the default phases that user-defined rules and directives are run in. The default depends on how a rule or directive is constructed and primarily distinguishes between rules and directives that have access to a
DocumentCursorand those that don't (the distinction is easy to make by the APIs that users call to create them).DocumentCursorit is impossible that it is used for tasks like generation of navigation structures and therefore it is run in the first phase by default. This means it is free to introduce new structure elements (even headers) itself.DocumentCursorit is treated differently and run in the last phase by default. This way the extension gets to see an "almost complete" version of the AST which is the best phase for tasks like generating navigation. Issues like Headers created in custom directives disappear #289 existed as previously all rules and directives were run in this phase even when there clearly was no need to.Fixes #289