Author: hboutemy
Date: Sun Sep 20 07:20:53 2015
New Revision: 1704101

URL: http://svn.apache.org/viewvc?rev=1704101&view=rev
Log:
[DOXIA-529] Added macro support to XHTML
Submitted by: Masatake Iwasaki
Applied with minor formatting issue reported by Checkstyle

Modified:
    
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java
    
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/java/org/apache/maven/doxia/module/xhtml/XhtmlParserTest.java
    
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/resources/test.xhtml

Modified: 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java
URL: 
http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java?rev=1704101&r1=1704100&r2=1704101&view=diff
==============================================================================
--- 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java
 (original)
+++ 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java
 Sun Sep 20 07:20:53 2015
@@ -19,15 +19,26 @@ package org.apache.maven.doxia.module.xh
  * under the License.
  */
 
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
 import javax.swing.text.html.HTML.Attribute;
 
 import org.apache.maven.doxia.macro.MacroExecutionException;
+import org.apache.maven.doxia.macro.manager.MacroNotFoundException;
+import org.apache.maven.doxia.macro.MacroRequest;
+import org.apache.maven.doxia.parser.ParseException;
 import org.apache.maven.doxia.parser.Parser;
 import org.apache.maven.doxia.parser.XhtmlBaseParser;
 import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.sink.SinkEventAttributeSet;
 
 import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.xml.pull.XmlPullParser;
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
 
@@ -49,6 +60,9 @@ public class XhtmlParser
     /** Empty elements don't write a closing tag. */
     private boolean isEmptyElement;
 
+    /** The source content of the input reader. Used to pass into macros. */
+    private String sourceContent;
+
     /** {@inheritDoc} */
     protected void handleStartTag( XmlPullParser parser, Sink sink )
         throws XmlPullParserException, MacroExecutionException
@@ -207,6 +221,109 @@ public class XhtmlParser
     }
 
     /** {@inheritDoc} */
+    @Override
+    protected void handleComment( XmlPullParser parser, Sink sink )
+        throws XmlPullParserException
+    {
+        String text = getText( parser ).trim();
+
+        if ( text.startsWith( "MACRO" ) && !isSecondParsing() )
+        {
+            processMacro( text, sink );
+        }
+        else
+        {
+            super.handleComment( parser, sink );
+        }
+    }
+
+    /** process macro embedded in XHTML commment */
+    private void processMacro( String text, Sink sink )
+        throws XmlPullParserException
+    {
+        String s = text.substring( text.indexOf( '{' ) + 1, text.indexOf( '}' 
) );
+        s = escapeForMacro( s );
+        String[] params = StringUtils.split( s, "|" );
+        String macroName = params[0];
+
+        Map<String, Object> parameters = new HashMap<String, Object>();
+        for ( int i = 1; i < params.length; i++ )
+        {
+            String[] param = StringUtils.split( params[i], "=" );
+            if ( param.length == 1 )
+            {
+                throw new XmlPullParserException( "Missing 'key=value' pair 
for macro parameter: " + params[i] );
+            }
+
+            String key = unescapeForMacro( param[0] );
+            String value = unescapeForMacro( param[1] );
+            parameters.put( key, value );
+        }
+
+        parameters.put( "sourceContent", sourceContent );
+        XhtmlParser xhtmlParser = new XhtmlParser();
+        xhtmlParser.setSecondParsing( true );
+        parameters.put( "parser", xhtmlParser );
+        MacroRequest request = new MacroRequest( parameters, getBasedir() );
+        try
+        {
+            executeMacro( macroName, request, sink );
+        }
+        catch ( MacroExecutionException e )
+        {
+            throw new XmlPullParserException( "Unable to execute macro in the 
document: " + macroName );
+        }
+        catch ( MacroNotFoundException me )
+        {
+            throw new XmlPullParserException( "Macro not found: " + macroName 
);
+        }
+    }
+
+    /**
+     * escapeForMacro
+     *
+     * @param s String
+     * @return String
+     */
+    private String escapeForMacro( String s )
+    {
+        if ( s == null || s.length() < 1 )
+        {
+            return s;
+        }
+
+        String result = s;
+
+        // use some outrageously out-of-place chars for text
+        // (these are device control one/two in unicode)
+        result = StringUtils.replace( result, "\\=", "\u0011" );
+        result = StringUtils.replace( result, "\\|", "\u0012" );
+
+        return result;
+    }
+
+    /**
+     * unescapeForMacro
+     *
+     * @param s String
+     * @return String
+     */
+    private String unescapeForMacro( String s )
+    {
+        if ( s == null || s.length() < 1 )
+        {
+            return s;
+        }
+
+        String result = s;
+
+        result = StringUtils.replace( result, "\u0011", "=" );
+        result = StringUtils.replace( result, "\u0012", "|" );
+
+        return result;
+    }
+
+    /** {@inheritDoc} */
     protected void init()
     {
         super.init();
@@ -214,4 +331,26 @@ public class XhtmlParser
         this.boxed = false;
         this.isEmptyElement = false;
     }
+
+    /** {@inheritDoc} */
+    public void parse( Reader source, Sink sink )
+        throws ParseException
+    {
+        this.sourceContent = null;
+        try
+        {
+            StringWriter contentWriter = new StringWriter();
+            IOUtil.copy( source, contentWriter );
+            sourceContent = contentWriter.toString();
+            super.parse( new StringReader( sourceContent ), sink );
+        }
+        catch ( IOException ex )
+        {
+            throw new ParseException( "Error reading the input source: " + 
ex.getMessage(), ex );
+        }
+        finally
+        {
+            this.sourceContent = null;
+        }
+    }
 }

Modified: 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/java/org/apache/maven/doxia/module/xhtml/XhtmlParserTest.java
URL: 
http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/java/org/apache/maven/doxia/module/xhtml/XhtmlParserTest.java?rev=1704101&r1=1704100&r2=1704101&view=diff
==============================================================================
--- 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/java/org/apache/maven/doxia/module/xhtml/XhtmlParserTest.java
 (original)
+++ 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/java/org/apache/maven/doxia/module/xhtml/XhtmlParserTest.java
 Sun Sep 20 07:20:53 2015
@@ -154,4 +154,36 @@ public class XhtmlParserTest
         assertEquals( "unknown", it.next().getName() );
         assertFalse( it.hasNext() );
     }
+
+    /** @throws Exception  */
+    public void testTocMacro()
+        throws Exception
+    {
+        String text = "<html><body>" +
+                "<!-- MACRO{toc|fromDepth=1|toDepth=2} -->" +
+                "<h1>heading 1</h1><h2>heading 2</h2><h3>heading 3</h3>" +
+                "</body></html>";
+
+        SinkEventTestingSink sink = new SinkEventTestingSink();
+
+        ( (XhtmlParser) createParser() ).parse( text, sink );
+
+        Iterator<SinkEventElement> it = sink.getEventList().iterator();
+
+        assertEquals( "body", it.next().getName() );
+        assertEquals( "list", it.next().getName() );
+        assertEquals( "listItem", it.next().getName() );
+        assertEquals( "link", it.next().getName() );
+        assertEquals( "text", it.next().getName() );
+        assertEquals( "link_", it.next().getName() );
+        assertEquals( "list", it.next().getName() );
+        assertEquals( "listItem", it.next().getName() );
+        assertEquals( "link", it.next().getName() );
+        assertEquals( "text", it.next().getName() );
+        assertEquals( "link_", it.next().getName() );
+        assertEquals( "listItem_", it.next().getName() );
+        assertEquals( "list_", it.next().getName() );
+        assertEquals( "listItem_", it.next().getName() );
+        assertEquals( "list_", it.next().getName() );
+    }
 }

Modified: 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/resources/test.xhtml
URL: 
http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/resources/test.xhtml?rev=1704101&r1=1704100&r2=1704101&view=diff
==============================================================================
--- 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/resources/test.xhtml
 (original)
+++ 
maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/resources/test.xhtml
 Sun Sep 20 07:20:53 2015
@@ -29,6 +29,8 @@ under the License.
 
 <body>
 
+<!-- MACRO{toc|fromDepth=0|toDepth=3} -->
+
 <p>Paragraph 1, line 1. Paragraph 1, line 2.</p>
 <p>Paragraph 2, line 1. Paragraph 2, line 2.</p>
 
@@ -147,4 +149,4 @@ under the License.
 
 </body>
 
-</html>
\ No newline at end of file
+</html>


Reply via email to