RenderingModule

Version 39.1 by Asiri Rathnayake on 2009/07/20 11:16
Warning: For security reasons, the document is displayed in restricted mode as it is not the current version. There may be differences and errors due to this.

Failed to execute the [velocity] macro. Cause: [The execution of the [velocity] script macro is not allowed in [extensions:Extension.Rendering Module.WebHome]. Check the rights of its last author or the parameters if it's rendered from another script.]. Click on this message for details.

Rendering Module

This module is in charge of converting textual input in a given syntax into some rendered output. It's used in XWiki notably for rendering pages in XHTML, for performing syntax conversions, for performing page refactorings and to provide users with access to the page's structured information directly inside their wiki pages using one of the supported scripting macros.

Features

  • Parsers for multiple syntaxes
  • Round trip between XWiki Syntax 2.0 and XHTML. This features allows us to have a strong WYSIWYG editor that doesn't loose information when editing wiki pages. It also allows us to import Office documents into XWiki without loosing information.
  • Macro support.
  • Ability to get the result of the parsing as an AST tree (called XDOM) which can then be used to get access to all structured elements from the flat text input.
  • Supports wiki syntax in link labels even for syntaxes that don't support it.
  • Automatic conversion from any of the supported input syntaxes to XWiki Syntax 2.0 or to XHTML.

General Architecture

rendering.png

  • Parser: Parses some textual input in a given syntax and generate a XDOM object which is an AST representing the input into structured blocks.
  • Renderer: Takes a XDOM as input and generates some output.
  • Transformation: Takes some XDOM and modifies it to generate modified XDOM. One important Transformation registered by default is the MacroTransformation which looks for all Macro Blocks in the XDOM object and replaces them by blocks generated by the various Macros. Note that executing Transformations is an optional step and if you don't run them then you'll get a XDOM object without any transformation applied on it (e.g. without Macros executed).
  • Macro: Takes a Macro definition as input and generates XDOM Blocks.

Macro Execution Process

Macros are executed by the Macro Transformation. Here are rules that apply:

  • Macros can be registered for a given syntax or for all syntaxes.
  • Macros also have a priority which allows some macros to execute before or after other macros. For example the Include macro runs first and the Table Of Content macro executes last (so that it can take into account all headers created by other macros).
  • The Macro Transformation finds all Macro Blocks defined in the passed XDOM object. For each Macro Block found it verifies if there's a Macro registered for that Macro Block and for the target syntax. It then sorts all Macros by priority and execute them one by one, replacing the Macro Block with the list of Blocks generated by the Macro, till there are no Macro Blocks left in the XDOM. Note that Macro can generate Macro Blocks.

Supported Syntaxes

Input Syntaxes:

  • XWiki Syntax 1.0 (xwiki/1.0)
  • XWiki Syntax 2.0 (xwiki/2.0)
  • Confluence Syntax (confluence/1.0)
  • JSPWiki Syntax (jspwiki/1.0)
  • TWiki Syntax (twiki/1.0)
  • Media Wiki Syntax (mediawiki/1.0)
  • Creole 1.0 Syntax (creole/1.0)
  • XHTML and HTML Syntaxes (xhtml/1.0 and html/4.01)
  • Plain Text (plain/1.0)

Output Syntaxes:

  • XWiki Syntax 2.0 (xwiki/2.0)
  • XHTML (xhtml/1.0)
  • Plain Text (plain/1.0): Print all than can be rendered in a simple notepad-like editor such as words, special symbols and spaces. It also generates link labels for links that have no labels and print the generated labels. Last it provides very basic formatting (e.g. separates paragraphs with new lines and separates list items with new lines).

Quick Examples

Render XWiki Syntax 2.0 content into XHTML

// Parse xwiki 2.0 syntax
Parser parser = componentManager.lookup(Parser.class, Syntax.XWIKI_2_0.toIdString());
XDOM xdom = parser.parse(new StringReader("This is **bold** {{code language=\"java\"}}something{{/code}}"));
       
// Run macros (and any other registered Transformations)
TransformationManager txManager = (TransformationManager) componentManager.lookup(TransformationManager.class);
txManager.performTransformations(xdom, parser.getSyntax());

// Generate XHTML (for example)
WikiPrinter printer = new DefaultWikiPrinter();
PrintRendererFactory prf = componentManager.lookup(PrintRendererFactory.class);
Renderer htmlRenderer = prf.createRenderer(Syntax.XHTML_1_0, printer);

// Perform the rendering        
xdom.traverse(htmlRenderer);

Assert.assertEquals("<p>This is <strong>bold</strong> <!--startmacro:code|-|language=\"java\"|-|something-->"
   + "<span class=\"box code\">something</span><!--stopmacro--></p>", printer.toString());

Note that in this example the generated XHTML contains a comment where the Code Macro was used. This to allow the XHTML parser to be able to regenerate the exact same XDOM object as the original input in XWiki 2.0 Syntax. This is what allows us to do round tripping between XHTML and wiki syntaxes.

Modify all Links to be displayed in italics

// Parse XWiki 2.0 Syntax
Parser parser = componentManager.lookup(Parser.class, Syntax.XWIKI_2_0.toIdString());
XDOM xdom = parser.parse(new StringReader("This a [[link>MyPage]]"));
       
// Find all links and make them italic
for (LinkBlock block : xdom.getChildrenByType(LinkBlock.class, true)) {
   // Note: in XWiki Core 2.0 the API has been improved and there's no need to clone the
   // block anymore and the replace() API has been modified.
   Block newBlock = new FormatBlock(Collections.<Block>singletonList(block.clone()), Format.ITALIC);
    block.replace(Collections.<Block>singletonList(newBlock));
}
       
// Generate XWiki 2.0 Syntax (for example)
WikiPrinter printer = new DefaultWikiPrinter();
PrintRendererFactory prf = componentManager.lookup(PrintRendererFactory.class);
Renderer xwikiRenderer = prf.createRenderer(Syntax.XWIKI_2_0, printer);

xdom.traverse(xwikiRenderer);

Assert.assertEquals("This a //[[link>MyPage]]//", printer.toString());

Tutorials

Adding a new Syntax

Adding support for a new syntax (i.e. the ability to write page contents using a new syntax) is as easy as implementing a Parser. To do so simply implement the Parser interface and register it as a component against the Component Manager.

Example:

public class MyParser implements Parser
{
   private static final Syntax SYNTAX = new Syntax(SyntaxType.getSyntaxType("mysyntax"), "1.0");

   public Syntax getSyntax()
   {
       return SYNTAX;
   }

   public XDOM parse(Reader source) throws ParseException
   {
        XDOM xdom = new XDOM(Collections.singletonList(new WordBlock("amazing")));
       return xdom;
   }
}

Adding a new Macro

Beginning with XWiki Enterprise 2.0M2 macros can be written in two ways. The easiest approach is to write a Wiki Macro while if you need to exploit the full power of XWiki rendering engine you can write a Rendering Macro. You may refer following tutorials for more information:

Adding a new Renderer

You have to implement the Renderer interface. Examples of Renderer source code:

Renderers are not components yet and thus in order to use the new Renderers you create you'll also need to modify the Default Print Renderer Factory component class or create a new component and override the default one.

Adding a new Transformation

At the time of this writing, the Transformation mechanism has not been finalized yet. While it's possible to write new Transformations the problem is that we don't yet have a generic marker mechanism in place so that the WYSIWYG editor considers transformed content as read only. If you're interested in this topic follow this JIRA issue.

Get Connected