You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by vm...@apache.org on 2008/01/18 09:40:41 UTC
svn commit: r613103 - in /maven/sandbox/trunk/doxia/doxia-module-xwiki/src:
main/java/org/apache/maven/doxia/module/xwiki/parser/
test/java/org/apache/maven/doxia/module/xwiki/parser/
Author: vmassol
Date: Fri Jan 18 00:40:40 2008
New Revision: 613103
URL: http://svn.apache.org/viewvc?rev=613103&view=rev
Log:
DOXIA-200: Add a Parser for XWiki
* Macro parsing should now work fine for most cases
Modified:
maven/sandbox/trunk/doxia/doxia-module-xwiki/src/main/java/org/apache/maven/doxia/module/xwiki/parser/MacroBlock.java
maven/sandbox/trunk/doxia/doxia-module-xwiki/src/main/java/org/apache/maven/doxia/module/xwiki/parser/MacroParser.java
maven/sandbox/trunk/doxia/doxia-module-xwiki/src/test/java/org/apache/maven/doxia/module/xwiki/parser/MacroParserTest.java
Modified: maven/sandbox/trunk/doxia/doxia-module-xwiki/src/main/java/org/apache/maven/doxia/module/xwiki/parser/MacroBlock.java
URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/doxia/doxia-module-xwiki/src/main/java/org/apache/maven/doxia/module/xwiki/parser/MacroBlock.java?rev=613103&r1=613102&r2=613103&view=diff
==============================================================================
--- maven/sandbox/trunk/doxia/doxia-module-xwiki/src/main/java/org/apache/maven/doxia/module/xwiki/parser/MacroBlock.java (original)
+++ maven/sandbox/trunk/doxia/doxia-module-xwiki/src/main/java/org/apache/maven/doxia/module/xwiki/parser/MacroBlock.java Fri Jan 18 00:40:40 2008
@@ -3,9 +3,9 @@
import org.apache.maven.doxia.module.confluence.parser.AbstractFatherBlock;
import org.apache.maven.doxia.sink.Sink;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.HashMap;
public class MacroBlock
extends AbstractFatherBlock
@@ -15,7 +15,7 @@
private Map parameters;
private String content;
-
+
public MacroBlock( String name, Map parameters, String content, List childBlocks )
{
super( childBlocks );
@@ -41,7 +41,7 @@
public Map getParameters()
{
- Map newParameters = new HashMap(this.parameters);
+ Map newParameters = new HashMap( this.parameters );
return newParameters;
}
Modified: maven/sandbox/trunk/doxia/doxia-module-xwiki/src/main/java/org/apache/maven/doxia/module/xwiki/parser/MacroParser.java
URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/doxia/doxia-module-xwiki/src/main/java/org/apache/maven/doxia/module/xwiki/parser/MacroParser.java?rev=613103&r1=613102&r2=613103&view=diff
==============================================================================
--- maven/sandbox/trunk/doxia/doxia-module-xwiki/src/main/java/org/apache/maven/doxia/module/xwiki/parser/MacroParser.java (original)
+++ maven/sandbox/trunk/doxia/doxia-module-xwiki/src/main/java/org/apache/maven/doxia/module/xwiki/parser/MacroParser.java Fri Jan 18 00:40:40 2008
@@ -11,7 +11,22 @@
* This class was written with performance in mind and thus is lacking clarity. Since this code is
* in the rendering path it's important it be very fast.
* <p/>
- * NOTE: Do NOT use this parser yet as it's not ready and not working.
+ * TODO: Compare speed with using regex. For example, something like this:
+ * <pre><code>
+ * Pattern p = Pattern.compile("(?:(.*)(?::)?)?(.*)?(?:/)}(?:(.*)\\{(?:\\/)\1})?");
+ * <p/>
+ * Matcher m = p.matcher(macro);
+ * m.find();
+ * Map parameters = new HashMap();
+ * if (m.group(2) != null && m.group(2).length() > 0) {
+ * StringTokenizer st = new StringTokenizer(m.group(2), "|");
+ * while (st.hasMoreTokens()) {
+ * String param = st.nextToken();
+ * StringTokenizer st2 = new StringTokenizer(param, "=");
+ * parameters.put(st2.nextToken(), st2.nextToken());
+ * }
+ * }
+ * </code></pre>
*/
public class MacroParser
{
@@ -81,14 +96,17 @@
break;
// {macroname:... /}. Contraction of {macroname:...}{/macroname}
case '/':
- if ( state == STATE_PARAM_VALUE || state == STATE_NAME)
+ if ( state == STATE_PARAM_VALUE || state == STATE_NAME )
{
if ( charAt( input, i ) == '}' )
{
i++;
- if (state == STATE_PARAM_VALUE) {
- parameters.put(parameterName, text.toString());
- } else {
+ if ( state == STATE_PARAM_VALUE )
+ {
+ parameters.put( parameterName, text.toString() );
+ }
+ else
+ {
macroName = text.toString();
}
state = STATE_END;
@@ -99,9 +117,12 @@
text.append( c );
}
}
- else if (state == STATE_CONTENT) {
- text.append(c);
- } else {
+ else if ( state == STATE_CONTENT )
+ {
+ text.append( c );
+ }
+ else
+ {
throw new ParseException( "Invalid position for character '/' in Macro" );
}
break;
@@ -111,32 +132,48 @@
// * {newmacro..}...{/newmacro}
// * {oldsinglelinemacro:...}
// * {oldmultilinemacro:...}...{oldmultilinemacro}
- // * {oldmultilinemacro:...}...{/oldmultilinemacro}
- if ( state == STATE_PARAM_VALUE)
+ if ( state == STATE_PARAM_VALUE )
{
- parameters.put(parameterName, text.toString());
+ parameters.put( parameterName, text.toString() );
text = new StringBuffer();
// {macro:...}
if ( isInCompatibilityMode )
{
- // TODO
- throw new ParseException( "Compatibility mode for macros not implemented yet" );
+ // Since we can't guess if a macro is a multiline one or a single line one we rely on
+ // a static list of known multiline macros...
+ if ( multilineMacros.contains( macroName ) )
+ {
+ state = STATE_CONTENT;
+ }
+ else
+ {
+ state = STATE_END;
+ }
}
else
{
state = STATE_CONTENT;
}
}
- else if ( state == STATE_NAME) {
+ else if ( state == STATE_NAME )
+ {
macroName = text.toString();
text = new StringBuffer();
// {macro:...}
if ( isInCompatibilityMode )
{
- // TODO
- throw new ParseException( "Compatibility mode for macros not implemented yet" );
+ // Since we can't guess if a macro is a multiline one or a single line one we rely on
+ // a static list of known multiline macros...
+ if ( multilineMacros.contains( macroName ) )
+ {
+ state = STATE_CONTENT;
+ }
+ else
+ {
+ state = STATE_END;
+ }
}
else
{
@@ -172,10 +209,12 @@
content = text.toString();
i++;
char cc;
- do {
+ do
+ {
i++;
cc = input.charAt( i );
- } while ( cc != '}' && i < input.length() );
+ }
+ while ( cc != '}' && i < input.length() );
state = STATE_END;
}
else
@@ -189,8 +228,23 @@
{
if ( isInCompatibilityMode )
{
- // TODO
- throw new ParseException( "Compatibility mode for macros not implemented yet" );
+ // Allow closing macros without using the '/' character
+ // TODO: Add special support for code macros nested in other code macros and for
+ // style macros nested in other style macros.
+
+ // Verify that the following characters are the name of the macro and thus that this
+ // '}' is the beginning of the macro closing.
+ int pos = input.indexOf( macroName + "}", i + 1 );
+ if ( pos == i + 1 )
+ {
+ state = STATE_END;
+ i += macroName.length() + 1;
+ content = text.toString();
+ }
+ else
+ {
+ text.append( c );
+ }
}
else
{
@@ -207,7 +261,7 @@
// supported too in param values.
if ( state == STATE_PARAM_VALUE )
{
- parameters.put(parameterName, text.toString());
+ parameters.put( parameterName, text.toString() );
text = new StringBuffer();
state = STATE_PARAM_NAME;
}
@@ -237,13 +291,27 @@
}
break;
default:
- text.append( c );
+ // Any non alphanumeric character found when parsing the macro name should stop the parsing since
+ // it means the text being parsed is not a macro.
+ if ( ( state == STATE_NAME ) && ( ( c < 'a' || c > 'z' ) && ( c < 'A' || c > 'Z' ) ) )
+ {
+ // Invalid macro, exit
+ state = STATE_END;
+ i = position - 1;
+ }
+ else
+ {
+ text.append( c );
+ }
}
i++;
}
- blocks.add( new MacroBlock( macroName, parameters, content, new ArrayList() ) );
+ if ( macroName != null )
+ {
+ blocks.add( new MacroBlock( macroName, parameters, content, new ArrayList() ) );
+ }
return i;
}
Modified: maven/sandbox/trunk/doxia/doxia-module-xwiki/src/test/java/org/apache/maven/doxia/module/xwiki/parser/MacroParserTest.java
URL: http://svn.apache.org/viewvc/maven/sandbox/trunk/doxia/doxia-module-xwiki/src/test/java/org/apache/maven/doxia/module/xwiki/parser/MacroParserTest.java?rev=613103&r1=613102&r2=613103&view=diff
==============================================================================
--- maven/sandbox/trunk/doxia/doxia-module-xwiki/src/test/java/org/apache/maven/doxia/module/xwiki/parser/MacroParserTest.java (original)
+++ maven/sandbox/trunk/doxia/doxia-module-xwiki/src/test/java/org/apache/maven/doxia/module/xwiki/parser/MacroParserTest.java Fri Jan 18 00:40:40 2008
@@ -5,7 +5,8 @@
import java.util.ArrayList;
import java.util.List;
-public class MacroParserTest extends TestCase
+public class MacroParserTest
+ extends TestCase
{
private MacroParser parser;
@@ -14,76 +15,125 @@
parser = new MacroParser();
}
- public void testParseSimplestMacroWithCondensedClosingStyle() throws Exception
+ public void testParseSimplestMacroWithCondensedClosingStyle()
+ throws Exception
{
List blocks = new ArrayList();
String macro = "{macro/}";
- int pos = parser.parse( macro + " ...", 1, blocks);
+ int pos = parser.parse( macro + " ...", 1, blocks );
- assertEquals(macro.length(), pos);
- assertEquals(1, blocks.size());
- MacroBlock macroBlock = (MacroBlock) blocks.get(0);
- assertEquals("macro", macroBlock.getName());
- assertEquals("", macroBlock.getContent());
- assertTrue(macroBlock.getParameters().isEmpty());
+ assertEquals( macro.length(), pos );
+ assertEquals( 1, blocks.size() );
+ MacroBlock macroBlock = (MacroBlock) blocks.get( 0 );
+ assertEquals( "macro", macroBlock.getName() );
+ assertEquals( "", macroBlock.getContent() );
+ assertTrue( macroBlock.getParameters().isEmpty() );
}
- public void testParseSimplestMacroWithExpandedClosingStyle() throws Exception
+ public void testParseSimplestMacroWithExpandedClosingStyle()
+ throws Exception
{
List blocks = new ArrayList();
String macro = "{macro}{/macro}";
- int pos = parser.parse( macro + " ...", 1, blocks);
+ int pos = parser.parse( macro + " ...", 1, blocks );
- assertEquals(macro.length(), pos);
- assertEquals(1, blocks.size());
- MacroBlock macroBlock = (MacroBlock) blocks.get(0);
- assertEquals("macro", macroBlock.getName());
- assertEquals("", macroBlock.getContent());
- assertTrue(macroBlock.getParameters().isEmpty());
+ assertEquals( macro.length(), pos );
+ assertEquals( 1, blocks.size() );
+ MacroBlock macroBlock = (MacroBlock) blocks.get( 0 );
+ assertEquals( "macro", macroBlock.getName() );
+ assertEquals( "", macroBlock.getContent() );
+ assertTrue( macroBlock.getParameters().isEmpty() );
}
- public void testParseMacroWithOneParameter() throws Exception
+ public void testParseMacroWithOneParameter()
+ throws Exception
{
List blocks = new ArrayList();
String macro = "{macro:param1=value1/}";
- int pos = parser.parse( macro + " ...", 1, blocks);
+ int pos = parser.parse( macro + " ...", 1, blocks );
- assertEquals(macro.length(), pos);
- assertEquals(1, blocks.size());
- MacroBlock macroBlock = (MacroBlock) blocks.get(0);
- assertEquals("macro", macroBlock.getName());
- assertEquals("", macroBlock.getContent());
- assertEquals(1, macroBlock.getParameters().size());
- assertEquals("value1", macroBlock.getParameters().get("param1"));
+ assertEquals( macro.length(), pos );
+ assertEquals( 1, blocks.size() );
+ MacroBlock macroBlock = (MacroBlock) blocks.get( 0 );
+ assertEquals( "macro", macroBlock.getName() );
+ assertEquals( "", macroBlock.getContent() );
+ assertEquals( 1, macroBlock.getParameters().size() );
+ assertEquals( "value1", macroBlock.getParameters().get( "param1" ) );
}
- public void testParseMacroWithSeveralParameters() throws Exception
+ public void testParseMacroWithSeveralParameters()
+ throws Exception
{
List blocks = new ArrayList();
String macro = "{macro:param1=value1|param2=value2/}";
- int pos = parser.parse( macro + " ...", 1, blocks);
+ int pos = parser.parse( macro + " ...", 1, blocks );
- assertEquals(macro.length(), pos);
- assertEquals(1, blocks.size());
- MacroBlock macroBlock = (MacroBlock) blocks.get(0);
- assertEquals("macro", macroBlock.getName());
- assertEquals("", macroBlock.getContent());
- assertEquals(2, macroBlock.getParameters().size());
- assertEquals("value1", macroBlock.getParameters().get("param1"));
- assertEquals("value2", macroBlock.getParameters().get("param2"));
+ assertEquals( macro.length(), pos );
+ assertEquals( 1, blocks.size() );
+ MacroBlock macroBlock = (MacroBlock) blocks.get( 0 );
+ assertEquals( "macro", macroBlock.getName() );
+ assertEquals( "", macroBlock.getContent() );
+ assertEquals( 2, macroBlock.getParameters().size() );
+ assertEquals( "value1", macroBlock.getParameters().get( "param1" ) );
+ assertEquals( "value2", macroBlock.getParameters().get( "param2" ) );
}
- public void testParseMacroWithContent() throws Exception
+ public void testParseMacroWithContent()
+ throws Exception
{
List blocks = new ArrayList();
String macro = "{macro}Some /=|content{/macro}";
- int pos = parser.parse( macro + " ...", 1, blocks);
+ int pos = parser.parse( macro + " ...", 1, blocks );
- assertEquals(macro.length(), pos);
- assertEquals(1, blocks.size());
- MacroBlock macroBlock = (MacroBlock) blocks.get(0);
- assertEquals("macro", macroBlock.getName());
- assertEquals("Some /=|content", macroBlock.getContent());
- assertEquals(0, macroBlock.getParameters().size());
+ assertEquals( macro.length(), pos );
+ assertEquals( 1, blocks.size() );
+ MacroBlock macroBlock = (MacroBlock) blocks.get( 0 );
+ assertEquals( "macro", macroBlock.getName() );
+ assertEquals( "Some /=|content", macroBlock.getContent() );
+ assertEquals( 0, macroBlock.getParameters().size() );
+ }
+
+ public void testParseMacroWithInvalidMacroName()
+ throws Exception
+ {
+ List blocks = new ArrayList();
+ // This is not a macro. It should be ignored and no macro block should be created
+ String macro = "{[link]/}";
+ int pos = parser.parse( macro + " ...", 1, blocks );
+
+ assertEquals( 1, pos );
+ assertEquals( 0, blocks.size() );
+ }
+
+ public void testParseOldStyleMacroInCompatibilityModeWhenMultilineMacro()
+ throws Exception
+ {
+ parser.setCompatibilityMode( true );
+ List blocks = new ArrayList();
+ String macro = "{code}Some content here{code}";
+ int pos = parser.parse( macro + " ...", 1, blocks );
+
+ assertEquals( macro.length(), pos );
+ assertEquals( 1, blocks.size() );
+ MacroBlock macroBlock = (MacroBlock) blocks.get( 0 );
+ assertEquals( "code", macroBlock.getName() );
+ assertEquals( "Some content here", macroBlock.getContent() );
+ assertEquals( 0, macroBlock.getParameters().size() );
+ }
+
+ public void testParseOldStyleMacroInCompatibilityModeWhenSinglelineMacro()
+ throws Exception
+ {
+ parser.setCompatibilityMode( true );
+ List blocks = new ArrayList();
+ String macro = "{somesinglelinemacro}";
+ int pos = parser.parse( macro + " ...", 1, blocks );
+
+ assertEquals( macro.length(), pos );
+ assertEquals( 1, blocks.size() );
+ MacroBlock macroBlock = (MacroBlock) blocks.get( 0 );
+ assertEquals( "somesinglelinemacro", macroBlock.getName() );
+ assertEquals( "", macroBlock.getContent() );
+ assertEquals( 0, macroBlock.getParameters().size() );
}
}