Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XRENDERING-563: Handle metadata rendering in HTML macro #175

Merged
merged 5 commits into from
May 16, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions xwiki-rendering-macros/xwiki-rendering-macro-html/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.xwiki.rendering</groupId>
<artifactId>xwiki-rendering-syntax-annotatedxhtml</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xwiki.component.annotation.Component;
import org.xwiki.component.manager.ComponentLookupException;
import org.xwiki.component.manager.ComponentManager;
import org.xwiki.rendering.block.Block;
import org.xwiki.rendering.block.Block.Axes;
import org.xwiki.rendering.block.MacroBlock;
Expand Down Expand Up @@ -102,13 +104,12 @@ public class HTMLMacro extends AbstractMacro<HTMLMacroParameters>
private HTMLCleaner htmlCleaner;

/**
* Factory to create special XHTML renderer for the HTML Macro. We override the default XHTML renderer since we want
* special behaviors, for example to not escape special symbols (since we don't want to escape HTML tags for
* example).
* Default Factory to create special XHTML renderer for the HTML Macro.
* It is used as fallback in {@link #getRendererFactory(Syntax)}.
*/
@Inject
@Named("xhtmlmacro/1.0")
private PrintRendererFactory xhtmlRendererFactory;
private PrintRendererFactory defaultXHTMLRendererFactory;

/**
* The parser used to parse macro content.
Expand All @@ -122,6 +123,9 @@ public class HTMLMacro extends AbstractMacro<HTMLMacroParameters>
@Inject
private RenderingContext renderingContext;

@Inject
private ComponentManager componentManager;

/**
* Create and initialize the descriptor of the macro.
*/
Expand Down Expand Up @@ -280,7 +284,7 @@ private String renderWikiSyntax(String content, Transformation transformation, M

// Render the whole parsed content as a XHTML string
WikiPrinter printer = new DefaultWikiPrinter();
PrintRenderer renderer = this.xhtmlRendererFactory.createRenderer(printer);
PrintRenderer renderer = this.getRendererFactory(this.renderingContext.getTargetSyntax()).createRenderer(printer);
for (Block block : htmlMacroMarker.getChildren()) {
block.traverse(renderer);
}
Expand All @@ -294,6 +298,26 @@ private String renderWikiSyntax(String content, Transformation transformation, M
return xhtml;
}

/**
* Retrieve the renderer factory based on the given target syntax.
* In practice it's always a {@link HTMLMacroXHTMLRendererFactory} which is returned but the hint is used to build
* the right renderer in the factory.
*
* @param targetSyntax the syntax for which we want a {@link PrintRenderer}.
* @return a {@link HTMLMacroXHTMLRendererFactory} with the hint to build the right {@link PrintRenderer}.
* It fallbacks on {@link #defaultXHTMLRendererFactory} in case of ComponentLookupException.
* @since 11.4RC1
*/
private PrintRendererFactory getRendererFactory(Syntax targetSyntax)
{
String hint = HTMLMacroXHTMLRendererFactory.PREFIX_SYNTAX + targetSyntax.toIdString();
try {
return this.componentManager.getInstance(PrintRendererFactory.class, hint);
} catch (ComponentLookupException e) {
return this.defaultXHTMLRendererFactory;
}
}

/**
* @param context the macro transformation context
* @return the appropriate cleaner configuration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
* We override the default XHTML renderer since we want special behaviors, for example to not escape special symbols
* (since we don't want to escape HTML tags for example).
*
* @version $Id $
* @version $Id$
* @since 1.8.3
*/
public class HTMLMacroXHTMLChainingRenderer extends XHTMLChainingRenderer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@

/**
* Renderer that generates XHTML from a XDOM resulting from the parsing of text containing HTML mixed with wiki syntax.
* We override the default XHTML renderer since we want special behaviors, for example to not escape special symbols
* (since we don't want to escape HTML tags for example).
* It uses {@link HTMLMacroXHTMLChainingRenderer} to handle custom behaviours.
*
* @version $Id $
* @version $Id$
* @since 1.8.3
*/
@Component
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,90 @@
*/
package org.xwiki.rendering.internal.macro.html;

import javax.inject.Named;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Singleton;

import org.xwiki.component.annotation.Component;
import org.xwiki.component.descriptor.ComponentDescriptor;
import org.xwiki.rendering.internal.renderer.AbstractPrintRendererFactory;
import org.xwiki.rendering.syntax.Syntax;
import org.xwiki.rendering.syntax.SyntaxType;

/**
* Create XHTML Renderers for the HTML Macro, see {@link HTMLMacroXHTMLRenderer}.
* Create Renderers for the HTML Macro.
* It computes the renderer to creates based on the given hint. By default it creates a {@link HTMLMacroXHTMLRenderer}.
*
* @version $Id$
* @since 2.0M3
*/
@Component
@Named("xhtmlmacro/1.0")
@Component(hints = {"xhtmlmacro/1.0", "htmlmacro+annotatedxhtml/1.0"})
surli marked this conversation as resolved.
Show resolved Hide resolved
@Singleton
public class HTMLMacroXHTMLRendererFactory extends AbstractPrintRendererFactory
{
/**
* Prefix for supported syntaxes in HTML Macro.
* @since 11.4RC1
*/
public static final String PREFIX_SYNTAX = "htmlmacro+";

/**
* The special syntax to recognize the HTML Macro XHTML Renderer.
*/
private static final Syntax SYNTAX = new Syntax(new SyntaxType("xhtmlmacro", "XHTML Macro"), "1.0");
private static final Syntax XHTML_SYNTAX = new Syntax(new SyntaxType("xhtmlmacro", "XHTML Macro"), "1.0");

/**
* List of supported syntaxes in HTML Macro.
*/
private static final List<Syntax> SUPPORTED_SYNTAXES = Arrays.asList(Syntax.ANNOTATED_XHTML_1_0);

/**
* List of HTML Macro syntaxes based on the {@link #SUPPORTED_SYNTAXES} with the {@link #PREFIX_SYNTAX} to use
* the dedicated renderers.
*/
private final List<Syntax> htmlMacroSyntaxes;

/**
* Used to retrieve the hint of the component.
*/
@Inject
private ComponentDescriptor componentDescriptor;

/**
* Constructor that builds the list of {@link #htmlMacroSyntaxes}.
*
* @since 11.4RC1
*/
public HTMLMacroXHTMLRendererFactory()
{
this.htmlMacroSyntaxes = new ArrayList<>();
for (Syntax existedAcceptedSyntax : SUPPORTED_SYNTAXES) {
SyntaxType type = existedAcceptedSyntax.getType();
this.htmlMacroSyntaxes.add(new Syntax(
new SyntaxType(PREFIX_SYNTAX + type.getId(), "HTML Macro " + type.getName()),
existedAcceptedSyntax.getVersion()));
}
}

/**
* {@inheritDoc}
* @return the syntax based on the component hint. Fallback on {@link #XHTML_SYNTAX}.
*/
@Override
public Syntax getSyntax()
{
return SYNTAX;
Syntax result = XHTML_SYNTAX;
String roleHint = this.componentDescriptor.getRoleHint();

for (Syntax acceptedSyntax : this.htmlMacroSyntaxes) {
if (roleHint.equals(acceptedSyntax.toIdString())) {
result = acceptedSyntax;
}
}

return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.xwiki.rendering.internal.macro.html.renderers.annotatedxhtml;

import java.util.LinkedHashMap;
import java.util.Map;

import org.xwiki.rendering.internal.macro.html.HTMLMacroXHTMLChainingRenderer;
import org.xwiki.rendering.internal.parser.xhtml.wikimodel.XHTMLXWikiGeneratorListener;
import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.listener.MetaData;
import org.xwiki.rendering.listener.chaining.ListenerChain;
import org.xwiki.stability.Unstable;

/**
* Renderer that generates AnnotatedXHTML from a XDOM resulting from the parsing of text containing HTML mixed
* with wiki syntax.
* We override the {@link HTMLMacroXHTMLChainingRenderer} since we want special behaviors to handle metadata.
*
* @version $Id$
* @since 11.4RC1
*/
@Unstable
public class HTMLMacroAnnotatedXHTMLChainingRenderer extends HTMLMacroXHTMLChainingRenderer
{
/**
* @param linkRenderer the object to render link events into XHTML. This is done so that it's pluggable because link
* rendering depends on how the underlying system wants to handle it. For example for XWiki we check if
* the document exists, we get the document URL, etc.
* @param imageRenderer the object to render image events into XHTML. This is done so that it's pluggable because
* image rendering depends on how the underlying system wants to handle it. For example for XWiki we
* check if the image exists as a document attachments, we get its URL, etc.
* @param listenerChain the chain of listener filters used to compute various states
* @since 2.0M3
*/
public HTMLMacroAnnotatedXHTMLChainingRenderer(XHTMLLinkRenderer linkRenderer,
XHTMLImageRenderer imageRenderer, ListenerChain listenerChain)
{
super(linkRenderer, imageRenderer, listenerChain);
}

/**
* @return a span element if we are inside an inline macro. Else a div.
*/
private String getMetadataContainerElement()
{
if (getBlockState().isInLine()) {
return "span";
} else {
return "div";
}
}

@Override
public void beginMetaData(MetaData metadata)
{
Map<String, String> attributes = new LinkedHashMap<>();

for (Map.Entry<String, Object> metadataPair : metadata.getMetaData().entrySet()) {
attributes.put(XHTMLXWikiGeneratorListener.METADATA_ATTRIBUTE_PREFIX + metadataPair.getKey(),
metadataPair.getValue().toString());
}

attributes.put("class", XHTMLXWikiGeneratorListener.METADATA_CONTAINER_CLASS);

this.getXHTMLWikiPrinter().printXMLStartElement(getMetadataContainerElement(), attributes);
}

@Override
public void endMetaData(MetaData metadata)
{
getXHTMLWikiPrinter().printXMLEndElement(getMetadataContainerElement());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.xwiki.rendering.internal.macro.html.renderers.annotatedxhtml;

import javax.inject.Inject;
import javax.inject.Named;

import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.InstantiationStrategy;
import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
import org.xwiki.component.phase.Initializable;
import org.xwiki.component.phase.InitializationException;
import org.xwiki.rendering.internal.macro.html.HTMLMacroBlockStateChainingListener;
import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
import org.xwiki.rendering.listener.chaining.ListenerChain;
import org.xwiki.rendering.listener.chaining.MetaDataStateChainingListener;
import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
import org.xwiki.stability.Unstable;

/**
* Renderer that generates Annotated XHTML from a XDOM resulting from the parsing of text containing HTML mixed with
* wiki syntax. It uses {@link HTMLMacroAnnotatedXHTMLChainingRenderer} to handle custom behaviours.
*
* @version $Id$
* @since 11.4RC1
*/
@Component
@Named("htmlmacro+annotatedxhtml/1.0")
@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
@Unstable
public class HTMLMacroAnnotatedXHTMLRenderer extends AbstractChainingPrintRenderer implements Initializable
{
/**
* To render link events into XHTML. This is done so that it's pluggable because link rendering depends on how the
* underlying system wants to handle it. For example for XWiki we check if the document exists, we get the document
* URL, etc.
*/
@Inject
@Named("annotated")
private XHTMLLinkRenderer linkRenderer;

/**
* To render image events into XHTML. This is done so that it's pluggable because image rendering depends on how the
* underlying system wants to handle it. For example for XWiki we check if the image exists as a document
* attachments, we get its URL, etc.
*/
@Inject
@Named("annotated")
private XHTMLImageRenderer imageRenderer;

/**
* {@inheritDoc}
*
* @since 2.0M3
*/
@Override
public void initialize() throws InitializationException
{
ListenerChain chain = new ListenerChain();
setListenerChain(chain);

// Construct the listener chain in the right order. Listeners early in the chain are called before listeners
// placed later in the chain.
chain.addListener(this);
chain.addListener(new HTMLMacroBlockStateChainingListener(chain));
chain.addListener(new EmptyBlockChainingListener(chain));
chain.addListener(new MetaDataStateChainingListener(chain));
chain.addListener(new HTMLMacroAnnotatedXHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
org.xwiki.rendering.internal.macro.html.HTMLMacro
org.xwiki.rendering.internal.macro.html.HTMLMacroXHTMLRenderer
org.xwiki.rendering.internal.macro.html.HTMLMacroXHTMLRendererFactory
org.xwiki.rendering.internal.macro.html.HTMLMacroXHTMLRendererFactory
org.xwiki.rendering.internal.macro.html.renderers.annotatedxhtml.HTMLMacroAnnotatedXHTMLRenderer
Loading