New $services.rendering.transform() API

Hi everyone,

I need to convert the content of a wiki page from its storage XWiki 2.1 syntax to the new UniAst syntax used by the BlockNote editor. I would like to perform this conversion from a Velocity script because the BlockNote integration relies on the Edit Module. Technically, I could do it from Java, but this means moving some HTML generating code from a template to Java. Moreover, I can’t rely on Document#getRenderedContent() API because the Edit Module decouples the edited content from the source document, and there’s no safe Document#getRenderedContent() signature to cover my case.

The rendering script service already has APIs to parse and render the content. It’s missing an API to execute the rendering transformations. Note that executing rendering transformations means executing script macros which is an important attack vector so it needs to be properly secured. The means using the right “transformation context”. In order to create this context we need to know:

  • the target syntax
  • whether to enable restricted mode or not
  • the lists of transformations
  • the context document (to evaluate script rights on)

In order to accept these parameters and possibly others in the future I suggest we use the builder pattern. The new API could be used like this:

#set ($targetSyntax = 'uniast/1.0')
#set ($xdom = $services.rendering.parse($content, $contentSyntax))
#set ($discard = $services.rendering.transform($xdom)
  .withTransformations(['macro'])
  .withTargetSyntax($targetSyntax)
  .withRestricted(true)
  .withContextDocument($editedDocument)
  .perform())
#set ($renderedContent = $services.rendering.render($xdom, $targetSyntax))

The script macros will be executed with the rights of the current context user, evaluated against the specified context document.

WDYT?

Thanks,
Marius

+1 thanks.

Small note: the javadoc should specify what is the order of the transformations executed (the order of the passed list or the transformation order).

That’s no fully accurate. The rights are evaluated on the content (secure) document, you just happen to also use it as context document by default.

+1 for the general idea, just need to refine a bit the naming (and there might be surprises requiring adding more stuff to the builder while implementing this)