Index: src/main/java/org/apache/maven/doxia/module/confluence/ConfluenceParser.java =================================================================== --- src/main/java/org/apache/maven/doxia/module/confluence/ConfluenceParser.java (revision 589863) +++ src/main/java/org/apache/maven/doxia/module/confluence/ConfluenceParser.java (working copy) @@ -26,6 +26,7 @@ import org.apache.maven.doxia.module.confluence.parser.Block; import org.apache.maven.doxia.module.confluence.parser.BlockParser; +import org.apache.maven.doxia.module.confluence.parser.FigureBlockParser; import org.apache.maven.doxia.module.confluence.parser.HorizontalRuleBlockParser; import org.apache.maven.doxia.module.confluence.parser.ParagraphBlockParser; import org.apache.maven.doxia.module.confluence.parser.SectionBlockParser; @@ -39,10 +40,10 @@ import org.apache.maven.doxia.util.ByLineSource; /** - * Parse the Confluence. - * See - * Confluence Notation Guide Overview - * + * Parse the Confluence. See Confluence Notation Guide + * Overview + * * @version $Id$ * @since 1.0 * @plexus.component role="org.apache.maven.doxia.parser.Parser" role-hint="confluence" @@ -50,25 +51,24 @@ public class ConfluenceParser extends AbstractTextParser { - + private BlockParser[] parsers; public ConfluenceParser() { BlockParser headingParser = new SectionBlockParser(); + BlockParser figureParser = new FigureBlockParser(); BlockParser verbatimParser = new VerbatimBlockParser(); BlockParser horizontalRuleParser = new HorizontalRuleBlockParser(); BlockParser paragraphParser = new ParagraphBlockParser(); BlockParser listParser = new ListBlockParser(); BlockParser tableParser = new TableBlockParser(); - parsers = new BlockParser[]{headingParser, verbatimParser, horizontalRuleParser, listParser, tableParser, - paragraphParser}; + parsers = + new BlockParser[] { headingParser, figureParser, verbatimParser, horizontalRuleParser, listParser, + tableParser, paragraphParser }; } - //TODO: (empty line) Produces a new paragraph - //TODO: better support for anchors - public List parse( ByLineSource source ) throws ParseException { @@ -92,11 +92,10 @@ if ( parser.accept( line, source ) ) { /* - System.out.println( "------------------------------------------------------------" ); - System.out.println( "line = " + line ); - System.out.println( "line accepted by: " + parser ); - System.out.println( "------------------------------------------------------------" ); - */ + * System.out.println( "------------------------------------------------------------" ); + * System.out.println( "line = " + line ); System.out.println( "line accepted by: " + parser ); + * System.out.println( "------------------------------------------------------------" ); + */ accepted = true; @@ -107,19 +106,16 @@ } /* - if ( !accepted ) - { - throw new ParseException( "don't know how to handle line: " + source.getLineNumber() + ": " + line ); - } - */ + * if ( !accepted ) { throw new ParseException( "don't know how to handle line: " + source.getLineNumber() + ": " + + * line ); } + */ } return blocks; } /** {@inheritDoc} */ - public synchronized void parse( Reader reader, - Sink sink ) + public synchronized void parse( Reader reader, Sink sink ) throws ParseException { List blocks; Index: src/main/java/org/apache/maven/doxia/module/confluence/parser/ChildBlocksBuilder.java =================================================================== --- src/main/java/org/apache/maven/doxia/module/confluence/parser/ChildBlocksBuilder.java (revision 589863) +++ src/main/java/org/apache/maven/doxia/module/confluence/parser/ChildBlocksBuilder.java (working copy) @@ -23,6 +23,8 @@ import java.util.Arrays; import java.util.List; +import org.apache.maven.doxia.parser.ParseException; +import org.apache.maven.doxia.util.ByLineSource; import org.codehaus.plexus.util.StringUtils; /** @@ -110,7 +112,7 @@ break; case '{': - if ( input.charAt( i + 1 ) == '{' ) // it's monospaced + if ( charAt( input, i ) == '{' ) // it's monospaced { i++; } @@ -122,7 +124,7 @@ // System.out.println( "line = " + line ); - if ( input.length() > i + 1 && input.charAt( i + 1 ) == '}' ) + if ( charAt( input, i ) == '}' ) { i++; TextBlock tb = new TextBlock( text.toString() ); @@ -148,7 +150,7 @@ // System.out.println( "line = " + line ); - if ( input.charAt( i + 1 ) == '\\' ) + if ( charAt( input, i ) == '\\' ) { i++; text = addTextBlockIfNecessary( blocks, text ); @@ -174,6 +176,11 @@ return blocks; } + private static char charAt( String input, int i ) + { + return input.length() > i + 1 ? input.charAt( i + 1 ) : '\0'; + } + private StringBuffer addTextBlockIfNecessary( List blocks, StringBuffer text ) { if ( text.length() == 0 ) @@ -183,4 +190,55 @@ blocks.add( new TextBlock( text.toString() ) ); return new StringBuffer(); } + + /** + * Slurp lines from the source starting with the given line appending them together into a StringBuffer until an + * empty line is reached, and while the source contains more lines. The result can be passed to the + * {@link #getBlocks(String)} method. + * + * @param line the first line + * @param source the source to read new lines from + * @return a StringBuffer appended with lines + * @throws ParseException + */ + public String appendUntilEmptyLine( ByLineSource source ) + throws ParseException + { + StringBuffer text = new StringBuffer(); + + String line; + + while ( ( line = source.getNextLine() ) != null ) + { + + if ( line.trim().length() == 0 ) + { + break; + } + + if ( text.length() == 0 ) + { + text.append( line.trim() ); + } + else + { + text.append( " " + line.trim() ); + } + + } + // TODO: instead of just flying along we should probably test new lines + // in the other parsers + // to make sure there aren't things that should be handled by other + // parsers. For example, right + // now: + // Blah blah blah blah + // # one + // # two + // + // Will not get processed correctly. This parser will try to deal with + // it when it should be handled + // by the list parser. + + return text.toString(); + } } Index: src/main/java/org/apache/maven/doxia/module/confluence/parser/FigureBlock.java =================================================================== --- src/main/java/org/apache/maven/doxia/module/confluence/parser/FigureBlock.java (revision 0) +++ src/main/java/org/apache/maven/doxia/module/confluence/parser/FigureBlock.java (revision 0) @@ -0,0 +1,37 @@ +package org.apache.maven.doxia.module.confluence.parser; + +import org.apache.maven.doxia.sink.Sink; + +public class FigureBlock + implements Block +{ + + private String location; + + private String caption; + + public FigureBlock( String location ) + { + this.location = location; + } + + public FigureBlock( String image, String caption ) + { + this.location = image; + this.caption = caption; + } + + public void traverse( Sink sink ) + { + sink.figure(); + sink.figureGraphics( location ); + if ( caption != null && caption.length()>0) + { + sink.figureCaption(); + new TextBlock(caption).traverse( sink ); + sink.figureCaption_(); + } + sink.figure_(); + } + +} Index: src/main/java/org/apache/maven/doxia/module/confluence/parser/FigureBlockParser.java =================================================================== --- src/main/java/org/apache/maven/doxia/module/confluence/parser/FigureBlockParser.java (revision 0) +++ src/main/java/org/apache/maven/doxia/module/confluence/parser/FigureBlockParser.java (revision 0) @@ -0,0 +1,33 @@ +package org.apache.maven.doxia.module.confluence.parser; + +import org.apache.maven.doxia.parser.ParseException; +import org.apache.maven.doxia.util.ByLineSource; + +public class FigureBlockParser + implements BlockParser +{ + + public boolean accept( String line, ByLineSource source ) + { + return line.startsWith( "!" ) && line.lastIndexOf( "!" ) > 1; + } + + public Block visit( String line, ByLineSource source ) + throws ParseException + { + String image = line.substring( 1, line.lastIndexOf( "!" ) ); + line = line.substring( line.lastIndexOf( "!" )+1 ).trim(); + if (line.startsWith( "\\\\" )) { + // ignore linebreak at start of caption + line = line.substring( 2 ).trim(); + } + ChildBlocksBuilder builder = new ChildBlocksBuilder(); + String caption = line + builder.appendUntilEmptyLine( source ); + if ( caption.trim().length() > 0 ) + { + return new FigureBlock( image, caption ); + } + return new FigureBlock( image ); + } + +} Index: src/main/java/org/apache/maven/doxia/module/confluence/parser/ParagraphBlockParser.java =================================================================== --- src/main/java/org/apache/maven/doxia/module/confluence/parser/ParagraphBlockParser.java (revision 589863) +++ src/main/java/org/apache/maven/doxia/module/confluence/parser/ParagraphBlockParser.java (working copy) @@ -35,42 +35,9 @@ throws ParseException { - StringBuffer text = new StringBuffer(); - - do - { - - if ( line.trim().length() == 0 ) - { - break; - } - - if ( text.length() == 0 ) - { - text.append( line.trim() ); - } - else - { - text.append( " " + line.trim() ); - } - - } - // TODO: instead of just flying along we should probably test new lines - // in the other parsers - // to make sure there aren't things that should be handled by other - // parsers. For example, right - // now: - // Blah blah blah blah - // # one - // # two - // - // Will not get processed correctly. This parser will try to deal with - // it when it should be handled - // by the list parser. - while ( ( line = source.getNextLine() ) != null ); - ChildBlocksBuilder builder = new ChildBlocksBuilder(); - + StringBuffer text = new StringBuffer( line ); + text.append( builder.appendUntilEmptyLine( source ) ); return new ParagraphBlock( builder.getBlocks( text.toString() ) ); } Index: src/test/java/org/apache/maven/doxia/module/confluence/ConfluenceParserTest.java =================================================================== --- src/test/java/org/apache/maven/doxia/module/confluence/ConfluenceParserTest.java (revision 589863) +++ src/test/java/org/apache/maven/doxia/module/confluence/ConfluenceParserTest.java (working copy) @@ -207,6 +207,29 @@ assertEquals( 2, result.split( "end:verbatim\n" ).length ); } + /** @throws Exception */ + public void testFigure() + throws Exception + { + String result = locateAndParseTestSourceFile( "figure" ); + + assertContainsLines( result, "begin:figure\nfigureGraphics, name: images/photo.jpg\nend:figure\n" ); + assertContainsLines( result, "attempted inline !image.jpg! (should fail)" ); + // this isn't ideal... Doxia captions are not the same as what people would use to add text to a confluence + assertContainsLines( result, "figureGraphics, name: images/photo.jpg\n" + + "begin:figureCaption\ntext: With caption on same line\n" + "end:figureCaption" ); + assertContainsLines( result, "figureGraphics, name: images/nolinebreak.jpg\n" + + "begin:figureCaption\ntext: With caption underneath and no linebreak\nend:figureCaption" ); + // ignore linebreak after figure insert... + assertContainsLines( result, "figureGraphics, name: images/linebreak.jpg\n" + + "begin:figureCaption\ntext: With caption underneath and linebreak\nend:figureCaption" ); + // ignore formtting in caption... + assertContainsLines( result, "figureGraphics, name: images/bold.jpg\n" + + "begin:figureCaption\ntext: With *bold* caption underneath\nend:figureCaption" ); + // 2 paragraphs in the input... (the figures do not go in a paragraph by analogy with AptParser) + assertEquals( 3, result.split( "end:paragraph\n" ).length ); + } + private void assertContainsLines( String message, String result, String lines ) { lines = StringUtils.replace( lines, "\n", EOL ); Index: src/test/resources/figure.confluence =================================================================== --- src/test/resources/figure.confluence (revision 0) +++ src/test/resources/figure.confluence (revision 0) @@ -0,0 +1,16 @@ +Simple paragraph. + +!images/photo.jpg! + +Simple paragraph with attempted inline !image.jpg! (should fail). + +!images/photo.jpg! With caption on same line + +!images/linebreak.jpg!\\ +With caption underneath and linebreak + +!images/nolinebreak.jpg! +With caption underneath and no linebreak + +!images/bold.jpg! +With *bold* caption underneath