Improving the Document#display API

Displaying object properties is one of the most frequently used features when developing XWiki applications but at the same time it is basically impossible to use the API correctly/in the correct context: On the one hand, the API might produce a {{html}} macro, so you need to use it in a context where wiki syntax is parsed, on the other hand it can return wiki syntax that should not be interpreted, leading to bugs like XWIKI-20465. Frequently, the code using the API also adds other HTML code and thus already contains an {{html}} macro, leading to further problems and ugly workarounds like this code that strips the generated HTML macro.

I would like to start a discussion how we can improve this situation while keeping the changes to a minimum to increase chances that this will actually be implemented and used.

Ultimately, it would be nice to have an API based on XDOM blocks. Until we get there, I guess it could be interesting to just wrap the result of the existing underlying APIs that are string-based either in a raw HTML block or to parse it as plain text when there is no HTML. Maybe we could also remove the conversion to HTML in some cases like custom displayers that use XWiki syntax internally and should thus produce an XDOM at some point, anyways, without breaking backwards-compatibility.

On top of this block-based API, I would add helper methods that return either HTML or XWiki syntax from these blocks. My idea would be to have basically drop-in replacements for the existing variants of the display()-method such that existing code can be easily migrated. Then we can deprecate the old API (or at least discourage its usage) and replace the old API usage by two new APIs:

  1. An API that always returns HTML and must be used in an HTML macro with wiki="false". The API would also ensure that the output doesn’t contain {{/html}}.
  2. An API that always returns XWiki syntax. It would wrap the raw HTML blocks in an HTML macro.

All of these APIs (both block-based and for output) should be implemented as components with script service wrappers to avoid adding more methods to the existing, already huge classes.

I think we should also convert the existing methods to be thin wrappers around the new block-based implementation.

Any thoughts and opinions? Any existing proposals I missed?

Note that we already have a generic HTMLDisplayer framework, so it should probably be used as the basis for the implementation. Probably not directly using the script service most of the time as it means getting the object Property and passing it to the script service, I’m afraid that If we want to have any chance that people use it instead of the old one, we need something as easy as $obj.displayHTML('myproperty').