Adding a new Syntax

You have 2 possibilities:

  • You might want to add the ability to write page content using a new input Syntax. In this case you'll need to write a Parser.
  • or you might want to be able to render page content in a new output Syntax. In this case you'll need to write a Renderer.

Adding a Parser

To add a Parser, 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(new SyntaxType("mysyntax", "My Syntax"), "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;
   }
}

In practice how the contributed Parser is implemented is left to the implementer.

More precisely we support several strategies:

  • Using WikiModel. Historically this project was used as an external dependency of XWiki Rendering and was providing Parser implementations for various syntaxes. We have coded a WikiModel bridge to convert WikiModel events to XWiki Rendering events. However since WikiModel wasn't really active and maintained (except by a few XWiki Rendering developers), we decided to fork the WikiModel's sources in the XWiki Rendering sources in the xwiki-rendering-wikimodel module. The goal in the future is to refactor this module and spread the code in various existing modules. For example this module uses JavaCC to generate Java source from grammar files. At the moment the JavaCC grammars are still located in that module but the plan is to move them to the various xwiki-rendering-syntax-XXX modules.
    • Examples of syntaxes using this strategy: XWiki 2.x syntaxes, Confluence syntax, MediaWiki syntax
  • We have also coded a Doxia bridge to allow using Doxia Parsers (the bridge converts Doxia events into XWiki Rendering events).
    • Examples of syntaxes using this strategy: Docbook, TeX
  • Some syntaxes use specific third-party Parsers.
    • Examples of syntaxes using this strategy: Markdown (which uses PegDown).
  • Last, parsing code can be implemented directly in the XWiki Rendering syntax module.
    • Examples of syntaxes using this strategy: None at this stage but in the future we'll probably move the full HTML syntax parsing code in the xwiki-rendering-syntax-xhtml module (the parsing code is currently mostly located in xwiki-rendering-wikimodel and a bit in xwiki-rendering-syntax-xhtml too).

Make sure to check existing parser implementations.

Adding a Renderer

TODO: Add tutorial

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

Adding Tests

You'll need to write tests to verify that your Parser/Renderer work fine. 

There are 2 Rendering test frameworks you can use (they're both located in the org.xwiki.rendering:xwiki-rendering-test module):

Adding a new Macro

Follow the Macro Tutorial.

Adding a new Transformation

To create a Transformation, create a Component implementing the org.xwiki.rendering.transformation.Transformation interface. To make it even easier you can simply extend org.xwiki.rendering.transformation.AbstractTransformation.

Example:

@Component
@Named("wikiword")
@Singleton
public class WikiWordTransformation extends AbstractTransformation
{
   /**
     * Regex Pattern to recognize a WikiWord.
     */

   private static final Pattern WIKIWORD_PATTERN = Pattern.compile(
       "\\p{javaUpperCase}+\\p{javaLowerCase}+(\\p{javaUpperCase}\\p{javaLowerCase}*)+");

   /**
     * Used to filter protected blocks (code macro marker block, etc).
     */

   private ProtectedBlockFilter filter = new ProtectedBlockFilter();

   @Override
   public void transform(Block block, TransformationContext transformationContext) throws TransformationException
   {
       // Find all Word blocks and for each of them check if they're a wiki word or not
       for (WordBlock wordBlock : this.filter.getChildrenByType(block, WordBlock.class, true)) {
            Matcher matcher = WIKIWORD_PATTERN.matcher(wordBlock.getWord());
           if (matcher.matches()) {
                ResourceReference linkReference = new DocumentResourceReference(wordBlock.getWord());
                wordBlock.getParent().replaceChild(new LinkBlock(wordBlock.getChildren(), linkReference, false),
                    wordBlock);
           }
       }
   }
}

Check out the full code with tests

Adding a new Link Type

When using the XWiki Syntax 2.1, it's possible to extend the link syntax. The generic link syntax is: [[label>>referenceType:referencePath]] and it's possible to add new referenceType. This is a several step process:

  • Implement a component with the org.xwiki.rendering.parser.ResourceReferenceTypeParser role. This is used to convert from a String to a ResourceReference. Here's is the source code for current implementations.
  • Implement a component with the org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkTypeRenderer role. This is used when rendering a link (i.e. a ResourceReference) into XHTML. Here's is the source code for current implementations.

Adding a new Image Type

When using the XWiki Syntax 2.1 and starting with XWiki 5.4, it's possible to extend the image syntax. The generic image syntax is: [[image:referenceType:referencePath]] and it's possible to add new referenceType. This is a several step process:

  • Implement a component with the org.xwiki.rendering.parser.ResourceReferenceTypeParser role. This is used to convert from a String to a ResourceReference. Here's is the source code for current implementations.
  • Implement a component with the org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageTypeRenderer role. This is used when rendering an image (i.e. a ResourceReference) into XHTML. Here's the source code for current implementations.
Tags:
Created by Vincent Massol on 2011/03/08 16:25
    
  • Powered by XWiki 8.2.1-node1. Hosted and managed by XWiki SAS

Get Connected