Author: ltheussl Date: Mon Mar 2 10:54:56 2009 New Revision: 749267 URL: http://svn.apache.org/viewvc?rev=749267&view=rev Log: [DOXIA-241] Xdoc/XhtmlBaseParser doesn't close sections properly
Modified: maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/parser/XhtmlBaseParserTest.java maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocParser.java maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/main/java/org/apache/maven/doxia/module/xhtml/XhtmlParser.java Modified: maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java?rev=749267&r1=749266&r2=749267&view=diff ============================================================================== --- maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java (original) +++ maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java Mon Mar 2 10:54:56 2009 @@ -507,12 +507,48 @@ } /** - * Close open sections. The current level is set to newLevel afterwards. + * Make sure sections are nested consecutively. + * + * <p> + * HTML doesn't have any sections, only sectionTitles (<h2>, etc), that means we have to + * open close any sections that are missing in between. + * </p> + * + * <p> + * For instance, if the following sequence is parsed: + * <pre> + * <h3></h3> + * <h6></h6> + * </pre> + * we have to insert two section starts before we open the <code><h6></code>. + * In the following sequence + * <pre> + * <h6></h6> + * <h3></h3> + * </pre> + * we have to close two sections before we open the <code><h3></code>. + * </p> + * + * <p>The current level is set to newLevel afterwards.</p> * * @param newLevel the new section level, all upper levels have to be closed. * @param sink the sink to receive the events. */ - protected void closeOpenSections( int newLevel, Sink sink ) + protected void consecutiveSections( int newLevel, Sink sink ) + { + closeOpenSections( newLevel, sink ); + openMissingSections( newLevel, sink ); + + this.sectionLevel = newLevel; + } + + /** + * Close open sections. + * + * @param newLevel the new section level, all upper levels have to be closed. + * @param sink the sink to receive the events. + */ + private void closeOpenSections( int newLevel, Sink sink ) { while ( this.sectionLevel >= newLevel ) { @@ -539,8 +575,41 @@ this.sectionLevel--; } + } - this.sectionLevel = newLevel; + /** + * Open missing sections. + * + * @param newLevel the new section level, all lower levels have to be opened. + * @param sink the sink to receive the events. + */ + private void openMissingSections( int newLevel, Sink sink ) + { + while ( this.sectionLevel < newLevel - 1 ) + { + this.sectionLevel++; + + if ( sectionLevel == Sink.SECTION_LEVEL_5 ) + { + sink.section5(); + } + else if ( sectionLevel == Sink.SECTION_LEVEL_4 ) + { + sink.section4(); + } + else if ( sectionLevel == Sink.SECTION_LEVEL_3 ) + { + sink.section3(); + } + else if ( sectionLevel == Sink.SECTION_LEVEL_2 ) + { + sink.section2(); + } + else if ( sectionLevel == Sink.SECTION_LEVEL_1 ) + { + sink.section1(); + } + } } /** @@ -793,7 +862,7 @@ private void handleSectionStart( Sink sink, int sectionLevel, SinkEventAttributeSet attribs ) { - closeOpenSections( sectionLevel, sink ); + consecutiveSections( sectionLevel, sink ); sink.section( sectionLevel, attribs ); sink.sectionTitle( sectionLevel, attribs ); } Modified: maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/parser/XhtmlBaseParserTest.java URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/parser/XhtmlBaseParserTest.java?rev=749267&r1=749266&r2=749267&view=diff ============================================================================== --- maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/parser/XhtmlBaseParserTest.java (original) +++ maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/parser/XhtmlBaseParserTest.java Mon Mar 2 10:54:56 2009 @@ -88,6 +88,49 @@ assertEquals( "section1", ( (SinkEventElement) it.next() ).getName() ); assertEquals( "sectionTitle1", ( (SinkEventElement) it.next() ).getName() ); assertEquals( "sectionTitle1_", ( (SinkEventElement) it.next() ).getName() ); + // this one is missing because we enclose everything in <p> which is not valid xhtml, + // needs to be tested in overriding parser, eg XhtmlParser, XdocParser. + //assertEquals( "section1_", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "paragraph_", ( (SinkEventElement) it.next() ).getName() ); + assertFalse( it.hasNext() ); + } + + /** @throws Exception */ + public void testNestedHeadingEventsList() + throws Exception + { + // DOXIA-241 + String text = "<p><h2></h2><h6></h6><h3></h3></p>"; + + parser.parse( text, sink ); + + Iterator it = sink.getEventList().iterator(); + + assertEquals( "paragraph", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section1", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "sectionTitle1", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "sectionTitle1_", ( (SinkEventElement) it.next() ).getName() ); + + assertEquals( "section2", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section3", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section4", ( (SinkEventElement) it.next() ).getName() ); + + assertEquals( "section5", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "sectionTitle5", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "sectionTitle5_", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section5_", ( (SinkEventElement) it.next() ).getName() ); + + assertEquals( "section4_", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section3_", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section2_", ( (SinkEventElement) it.next() ).getName() ); + + assertEquals( "section2", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "sectionTitle2", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "sectionTitle2_", ( (SinkEventElement) it.next() ).getName() ); + // these two are missing because we enclose everything in <p> which is not valid xhtml, + // needs to be tested in overriding parser, eg XhtmlParser, XdocParser. + //assertEquals( "section2_", ( (SinkEventElement) it.next() ).getName() ); + //assertEquals( "section1_", ( (SinkEventElement) it.next() ).getName() ); assertEquals( "paragraph_", ( (SinkEventElement) it.next() ).getName() ); assertFalse( it.hasNext() ); } Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocParser.java URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocParser.java?rev=749267&r1=749266&r2=749267&view=diff ============================================================================== --- maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocParser.java (original) +++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/main/java/org/apache/maven/doxia/module/xdoc/XdocParser.java Mon Mar 2 10:54:56 2009 @@ -141,7 +141,7 @@ } else if ( parser.getName().equals( SECTION_TAG.toString() ) ) { - closeOpenSections( Sink.SECTION_LEVEL_1, sink ); + consecutiveSections( Sink.SECTION_LEVEL_1, sink ); Object id = attribs.getAttribute( Attribute.ID.toString() ); if ( id != null ) @@ -160,7 +160,7 @@ } else if ( parser.getName().equals( SUBSECTION_TAG.toString() ) ) { - closeOpenSections( Sink.SECTION_LEVEL_2, sink ); + consecutiveSections( Sink.SECTION_LEVEL_2, sink ); Object id = attribs.getAttribute( Attribute.ID.toString() ); if ( id != null ) @@ -300,7 +300,7 @@ } else if ( parser.getName().equals( Tag.BODY.toString() ) ) { - closeOpenSections( 0, sink ); + consecutiveSections( 0, sink ); sink.body_(); } @@ -370,15 +370,13 @@ } else if ( parser.getName().equals( SECTION_TAG.toString() ) ) { - closeOpenSections( 0, sink ); + consecutiveSections( 0, sink ); sink.section1_(); } else if ( parser.getName().equals( SUBSECTION_TAG.toString() ) ) { - closeOpenSections( Sink.SECTION_LEVEL_1, sink ); - - sink.section2_(); + consecutiveSections( Sink.SECTION_LEVEL_1, sink ); } else if ( parser.getName().equals( Tag.SCRIPT.toString() ) ) { @@ -413,12 +411,19 @@ } } + /** {...@inheritdoc} */ + protected void consecutiveSections( int newLevel, Sink sink ) + { + closeOpenSections( newLevel, sink ); + openMissingSections( newLevel, sink ); + + setSectionLevel( newLevel ); + } + /** - * {...@inheritdoc} - * - * Close open h4, h5, h6 sections. The current level is set to newLevel afterwards. + * Close open h4, h5, h6 sections. */ - protected void closeOpenSections( int newLevel, Sink sink ) + private void closeOpenSections( int newLevel, Sink sink ) { while ( getSectionLevel() >= newLevel ) { @@ -434,10 +439,40 @@ { sink.section3_(); } + else if ( getSectionLevel() == Sink.SECTION_LEVEL_2 ) + { + sink.section2_(); + } setSectionLevel( getSectionLevel() - 1 ); } + } - setSectionLevel( newLevel ); + /** + * Open missing h4, h5, h6 sections. + */ + private void openMissingSections( int newLevel, Sink sink ) + { + while ( getSectionLevel() < newLevel - 1 ) + { + setSectionLevel( getSectionLevel() + 1 ); + + if ( getSectionLevel() == Sink.SECTION_LEVEL_5 ) + { + sink.section5(); + } + else if ( getSectionLevel() == Sink.SECTION_LEVEL_4 ) + { + sink.section4(); + } + else if ( getSectionLevel() == Sink.SECTION_LEVEL_3 ) + { + sink.section3(); + } + else if ( getSectionLevel() == Sink.SECTION_LEVEL_2 ) + { + sink.section2(); + } + } } } Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java?rev=749267&r1=749266&r2=749267&view=diff ============================================================================== --- maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java (original) +++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocParserTest.java Mon Mar 2 10:54:56 2009 @@ -213,6 +213,44 @@ } /** @throws Exception */ + public void testNestedSectionsEventsList() + throws Exception + { + // DOXIA-241 + String text = "<section name=\"section\"><h6>h6</h6><subsection name=\"subsection\"></subsection></section>"; + + SinkEventTestingSink sink = new SinkEventTestingSink(); + + parser.parse( text, sink ); + + Iterator it = sink.getEventList().iterator(); + + assertEquals( "section1", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "sectionTitle1", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "text", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "sectionTitle1_", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section2", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section3", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section4", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section5", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "sectionTitle5", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "text", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "sectionTitle5_", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section5_", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section4_", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section3_", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section2_", ( (SinkEventElement) it.next() ).getName() ); + + assertEquals( "section2", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "sectionTitle2", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "text", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "sectionTitle2_", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section2_", ( (SinkEventElement) it.next() ).getName() ); + assertEquals( "section1_", ( (SinkEventElement) it.next() ).getName() ); + assertFalse( it.hasNext() ); + } + + /** @throws Exception */ public void testSourceEventsList() throws Exception { 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=749267&r1=749266&r2=749267&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 Mon Mar 2 10:54:56 2009 @@ -210,7 +210,7 @@ } else if ( parser.getName().equals( Tag.BODY.toString() ) ) { - closeOpenSections( 0, sink ); + consecutiveSections( 0, sink ); sink.body_(); }