Extending XWiki Rendering
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:
{
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):
- The Rendering Test Framework: Allows to easily write tests to assert that your Parser or Renderer does the right thing.
- The Compatibility Test Suite: A well-known suite of commmon Tests for all Syntaxes to pass.
Best Practices
XWiki 11.3+
There's now the concept of a Syntax Registry and new Syntaxes are expected to register themselves in that registry. This is achieved by implementing the Provider<List<Syntax>> component role. For example to register a html/4.01 syntax you'd write:
@Component
@Named("html/4.01")
@Singleton
public class HTML401SyntaxProvider implements Provider<List<Syntax>>
{
/**
* HTML syntax type.
*/
public static final SyntaxType HTML = new SyntaxType("html", "HTML");
/**
* HTML 4.01 syntax.
*/
public static final Syntax HTML_4_01 = new Syntax(HTML, "4.01");
@Override
public List<Syntax> get()
{
return Collections.singletonList(HTML_4_01);
}
}
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:
@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.
You can also configure the WYSIWYG editor to be able to use the new Link Type.
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.