maven-doxia-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ltheu...@apache.org
Subject svn commit: r591684 - in /maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia: parser/XhtmlBaseParser.java sink/XhtmlBaseSink.java
Date Sat, 03 Nov 2007 20:54:56 GMT
Author: ltheussl
Date: Sat Nov  3 13:54:56 2007
New Revision: 591684

URL: http://svn.apache.org/viewvc?rev=591684&view=rev
Log:
Add some base classes to handle common html events

Added:
    maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java   (with props)
    maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/XhtmlBaseSink.java   (with props)

Added: 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=591684&view=auto
==============================================================================
--- maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java (added)
+++ maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java Sat Nov  3 13:54:56 2007
@@ -0,0 +1,668 @@
+package org.apache.maven.doxia.parser;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import javax.swing.text.html.HTML.Attribute;
+import javax.swing.text.html.HTML.Tag;
+
+import org.apache.maven.doxia.macro.MacroExecutionException;
+import org.apache.maven.doxia.parser.AbstractXmlParser;
+import org.apache.maven.doxia.sink.Sink;
+
+import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+
+/**
+ * Common base parser for xhtml events.
+ *
+ * @author <a href="mailto:jason@maven.org">Jason van Zyl</a>
+ * @author ltheussl
+ * @version $Id$
+ * @since 1.0
+ */
+public class XhtmlBaseParser
+    extends AbstractXmlParser
+{
+    /** Used to distinguish <a href=""> from <a name="">. */
+    private boolean isLink;
+
+    /** Used to distinguish <a href=""> from <a name="">. */
+    private boolean isAnchor;
+
+    /** Used for nested lists. */
+    private int orderedListDepth = 0;
+
+    /** For tables. */
+    private boolean hasCaption;
+
+    /** Counts section level. */
+    private int sectionLevel;
+
+    /**
+     * <p>
+     *   Goes through a common list of possible html start tags. These include only tags that can go into
+     *   the body of a xhtml document and so should be re-usable by different xhtml-based parsers.
+     * </p>
+     * <p>
+     *   The currently handled tags are:
+     * </p>
+     * <p>
+     *   <code>
+     *      &lt;h2&gt;, &lt;h3&gt;, &lt;h4&gt;, &lt;h5&gt;, &lt;h6&gt;, &lt;p&gt;, &lt;pre&gt;,
+     *      &lt;ul&gt;, &lt;ol&gt;, &lt;li&gt;, &lt;dl&gt;, &lt;dt&gt;, &lt;dd&gt;, &lt;b&gt;, &lt;strong&gt;,
+     *      &lt;i&gt;, &lt;em&gt;, &lt;code&gt;, &lt;samp&gt;, &lt;tt&gt;, &lt;a&gt;, &lt;table&gt;, &lt;tr&gt;,
+     *      &lt;th&gt;, &lt;td&gt;, &lt;caption&gt;, &lt;br/&gt;, &lt;hr/&gt;, &lt;img/&gt;.
+     *   </code>
+     * </p>
+     *
+     * @param parser A parser.
+     * @param sink the sink to receive the events.
+     * @return True if the event has been handled by this method, i.e. the tag was recognized, false otherwise.
+     */
+    public boolean baseStartTag( XmlPullParser parser, Sink sink )
+    {
+        boolean visited = true;
+
+        if ( parser.getName().equals( Tag.H2.toString() ) )
+        {
+            closeOpenSections( Sink.SECTION_LEVEL_1, sink );
+
+            sink.section1();
+
+            sink.sectionTitle1();
+        }
+        else if ( parser.getName().equals( Tag.H3.toString() ) )
+        {
+            closeOpenSections( Sink.SECTION_LEVEL_2, sink );
+
+            sink.section2();
+
+            sink.sectionTitle2();
+        }
+        else if ( parser.getName().equals( Tag.H4.toString() ) )
+        {
+            closeOpenSections( Sink.SECTION_LEVEL_3, sink );
+
+            sink.section3();
+
+            sink.sectionTitle3();
+        }
+        else if ( parser.getName().equals( Tag.H5.toString() ) )
+        {
+            closeOpenSections( Sink.SECTION_LEVEL_4, sink );
+
+            sink.section4();
+
+            sink.sectionTitle4();
+        }
+        else if ( parser.getName().equals( Tag.H6.toString() ) )
+        {
+            closeOpenSections( Sink.SECTION_LEVEL_5, sink );
+
+            sink.section5();
+
+            sink.sectionTitle5();
+        }
+        else if ( parser.getName().equals( Tag.P.toString() ) )
+        {
+            sink.paragraph();
+        }
+        /*
+         * The PRE element tells visual user agents that the enclosed text is
+         * "preformatted". When handling preformatted text, visual user agents:
+         * - May leave white space intact.
+         * - May render text with a fixed-pitch font.
+         * - May disable automatic word wrap.
+         * - Must not disable bidirectional processing.
+         * Non-visual user agents are not required to respect extra white space
+         * in the content of a PRE element.
+         */
+        else if ( parser.getName().equals( Tag.PRE.toString() ) )
+        {
+            sink.verbatim( false );
+        }
+        else if ( parser.getName().equals( Tag.UL.toString() ) )
+        {
+            sink.list();
+        }
+        else if ( parser.getName().equals( Tag.OL.toString() ) )
+        {
+            int numbering = Sink.NUMBERING_DECIMAL;
+
+            // this will have to be generalized if we handle styles
+            String style = parser.getAttributeValue( null, Attribute.STYLE.toString() );
+
+            if ( style != null )
+            {
+                if ( "list-style-type: upper-alpha".equals( style ) )
+                {
+                    numbering = Sink.NUMBERING_UPPER_ALPHA;
+                }
+                else if ( "list-style-type: lower-alpha".equals( style ) )
+                {
+                    numbering = Sink.NUMBERING_LOWER_ALPHA;
+                }
+                else if ( "list-style-type: upper-roman".equals( style ) )
+                {
+                    numbering = Sink.NUMBERING_UPPER_ROMAN;
+                }
+                else if ( "list-style-type: lower-roman".equals( style ) )
+                {
+                    numbering = Sink.NUMBERING_LOWER_ROMAN;
+                }
+                else if ( "list-style-type: decimal".equals( style ) )
+                {
+                    numbering = Sink.NUMBERING_DECIMAL;
+                }
+            }
+
+            sink.numberedList( numbering );
+            orderedListDepth++;
+        }
+        else if ( parser.getName().equals( Tag.LI.toString() ) )
+        {
+            if ( orderedListDepth == 0 )
+            {
+                sink.listItem();
+            }
+            else
+            {
+                sink.numberedListItem();
+            }
+        }
+        else if ( parser.getName().equals( Tag.DL.toString() ) )
+        {
+            sink.definitionList();
+        }
+        else if ( parser.getName().equals( Tag.DT.toString() ) )
+        {
+            sink.definitionListItem();
+            sink.definedTerm();
+        }
+        else if ( parser.getName().equals( Tag.DD.toString() ) )
+        {
+            sink.definition();
+        }
+        else if ( ( parser.getName().equals( Tag.B.toString() ) ) || ( parser.getName().equals( Tag.STRONG.toString() ) ) )
+        {
+            sink.bold();
+        }
+        else if ( ( parser.getName().equals( Tag.I.toString() ) ) || ( parser.getName().equals( Tag.EM.toString() ) ) )
+        {
+            sink.italic();
+        }
+        else if ( ( parser.getName().equals( Tag.CODE.toString() ) ) || ( parser.getName().equals( Tag.SAMP.toString() ) ) ||
+            ( parser.getName().equals( Tag.TT.toString() ) ) )
+        {
+            sink.monospaced();
+        }
+        else if ( parser.getName().equals( Tag.A.toString() ) )
+        {
+            String href = parser.getAttributeValue( null, Attribute.HREF.toString() );
+
+            if ( href != null )
+            {
+                String link = href;
+
+                if ( link.startsWith( "#" ) )
+                {
+                    link = link.substring( 1 );
+                }
+
+                sink.link( link );
+
+                isLink = true;
+            }
+            else
+            {
+                String name = parser.getAttributeValue( null, Attribute.NAME.toString() );
+
+                if ( name != null )
+                {
+                    sink.anchor( name );
+
+                    isAnchor = true;
+                }
+                else
+                {
+                    String id = parser.getAttributeValue( null, Attribute.ID.toString() );
+
+                    if ( id != null )
+                    {
+                        sink.anchor( id );
+
+                        isAnchor = true;
+                    }
+                }
+            }
+        }
+
+        // ----------------------------------------------------------------------
+        // Tables
+        // ----------------------------------------------------------------------
+
+        else if ( parser.getName().equals( Tag.TABLE.toString() ) )
+        {
+            sink.table();
+
+            String border = parser.getAttributeValue( null, Attribute.BORDER.toString() );
+
+            boolean grid = true;
+
+            if ( "0".equals( border ) )
+            {
+                grid = false;
+            }
+
+            String align = parser.getAttributeValue( null, Attribute.ALIGN.toString() );
+
+            int[] justif = { JUSTIFY_CENTER };
+
+            if ( "left".equals( align ) )
+            {
+                justif[0] = JUSTIFY_LEFT;
+            }
+            else if ( "right".equals( align ) )
+            {
+                justif[0] = JUSTIFY_RIGHT;
+            }
+
+            sink.tableRows( justif, grid );
+        }
+        else if ( parser.getName().equals( Tag.TR.toString() ) )
+        {
+            sink.tableRow();
+        }
+        else if ( parser.getName().equals( Tag.TH.toString() ) )
+        {
+            String width = parser.getAttributeValue( null, Attribute.WIDTH.toString() );
+
+            if ( width ==  null )
+            {
+                sink.tableHeaderCell();
+            }
+            else
+            {
+                sink.tableHeaderCell( width );
+            }
+        }
+        else if ( parser.getName().equals( Tag.TD.toString() ) )
+        {
+            String width = parser.getAttributeValue( null, Attribute.WIDTH.toString() );
+
+            if ( width ==  null )
+            {
+                sink.tableCell();
+            }
+            else
+            {
+                sink.tableCell( width );
+            }
+        }
+        else if ( parser.getName().equals( Tag.CAPTION.toString() ) )
+        {
+            sink.tableRows_();
+            this.hasCaption = true;
+            sink.tableCaption();
+        }
+
+        // ----------------------------------------------------------------------
+        // Empty elements: <br/>, <hr/> and <img />
+        // ----------------------------------------------------------------------
+
+        else if ( parser.getName().equals( Tag.BR.toString() ) )
+        {
+            sink.lineBreak();
+        }
+        else if ( parser.getName().equals( Tag.HR.toString() ) )
+        {
+            sink.horizontalRule();
+        }
+        else if ( parser.getName().equals( Tag.IMG.toString() ) )
+        {
+            String src = parser.getAttributeValue( null, Attribute.SRC.toString() );
+            String title = parser.getAttributeValue( null, Attribute.TITLE.toString() );
+            String alt = parser.getAttributeValue( null, Attribute.ALT.toString() );
+
+            sink.figure();
+
+            if ( src != null )
+            {
+                sink.figureGraphics( src );
+            }
+
+            if ( title != null )
+            {
+                sink.figureCaption();
+                sink.text( title );
+                sink.figureCaption_();
+            }
+            else if ( alt != null )
+            {
+                sink.figureCaption();
+                sink.text( alt );
+                sink.figureCaption_();
+            }
+
+            sink.figure_();
+        }
+        else
+        {
+            visited = false;
+        }
+
+        return visited;
+    }
+
+    /**
+     * <p>
+     *   Goes through a common list of possible html end tags.
+     *   These should be re-usable by different xhtml-based parsers.
+     *   The tags handled here are the same as for {@link #baseStartTag(XmlPullParser,Sink)},
+     *   except for the empty elements (<code>&lt;br/&gt;, &lt;hr/&gt;, &lt;img/&gt;<code>).
+     * </p>
+     *
+     * @param parser A parser.
+     * @param sink the sink to receive the events.
+     * @return True if the event has been handled by this method, false otherwise.
+     */
+    public boolean baseEndTag( XmlPullParser parser, Sink sink )
+    {
+        boolean visited = true;
+
+        if ( parser.getName().equals( Tag.P.toString() ) )
+        {
+            sink.paragraph_();
+        }
+        else if ( parser.getName().equals( Tag.PRE.toString() ) )
+        {
+            sink.verbatim_();
+        }
+        else if ( parser.getName().equals( Tag.UL.toString() ) )
+        {
+            sink.list_();
+        }
+        else if ( parser.getName().equals( Tag.OL.toString() ) )
+        {
+            sink.numberedList_();
+            orderedListDepth--;
+        }
+        else if ( parser.getName().equals( Tag.LI.toString() ) )
+        {
+            if ( orderedListDepth == 0 )
+            {
+                sink.listItem_();
+            }
+            else
+            {
+                sink.numberedListItem_();
+            }
+        }
+        else if ( parser.getName().equals( Tag.DL.toString() ) )
+        {
+            sink.definitionList_();
+        }
+        else if ( parser.getName().equals( Tag.DT.toString() ) )
+        {
+            sink.definedTerm_();
+        }
+        else if ( parser.getName().equals( Tag.DD.toString() ) )
+        {
+            sink.definition_();
+            sink.definitionListItem_();
+        }
+        else if ( ( parser.getName().equals( Tag.B.toString() ) ) || ( parser.getName().equals( Tag.STRONG.toString() ) ) )
+        {
+            sink.bold_();
+        }
+        else if ( ( parser.getName().equals( Tag.I.toString() ) ) || ( parser.getName().equals( Tag.EM.toString() ) ) )
+        {
+            sink.italic_();
+        }
+        else if ( ( parser.getName().equals( Tag.CODE.toString() ) ) || ( parser.getName().equals( Tag.SAMP.toString() ) ) ||
+            ( parser.getName().equals( Tag.TT.toString() ) ) )
+        {
+            sink.monospaced_();
+        }
+        else if ( parser.getName().equals( Tag.A.toString() ) )
+        {
+            if ( isLink )
+            {
+                sink.link_();
+
+                isLink = false;
+            }
+            else if ( isAnchor )
+            {
+                sink.anchor_();
+
+                isAnchor = false;
+            }
+        }
+
+        // ----------------------------------------------------------------------
+        // Tables
+        // ----------------------------------------------------------------------
+
+        else if ( parser.getName().equals( Tag.TABLE.toString() ) )
+        {
+            if ( !hasCaption )
+            {
+                sink.tableRows_();
+            }
+
+            this.hasCaption = false;
+
+            sink.table_();
+        }
+        else if ( parser.getName().equals( Tag.TR.toString() ) )
+        {
+            sink.tableRow_();
+        }
+        else if ( parser.getName().equals( Tag.TH.toString() ) )
+        {
+            sink.tableHeaderCell_();
+        }
+        else if ( parser.getName().equals( Tag.TD.toString() ) )
+        {
+            sink.tableCell_();
+        }
+        else if ( parser.getName().equals( Tag.CAPTION.toString() ) )
+        {
+            sink.tableCaption_();
+        }
+        else if ( parser.getName().equals( Tag.H2.toString() ) )
+        {
+            sink.sectionTitle1_();
+        }
+        else if ( parser.getName().equals( Tag.H3.toString() ) )
+        {
+            sink.sectionTitle2_();
+        }
+        else if ( parser.getName().equals( Tag.H4.toString() ) )
+        {
+            sink.sectionTitle3_();
+        }
+        else if ( parser.getName().equals( Tag.H5.toString() ) )
+        {
+            sink.sectionTitle4_();
+        }
+        else if ( parser.getName().equals( Tag.H6.toString() ) )
+        {
+            sink.sectionTitle5_();
+        }
+        else
+        {
+            visited = false;
+        }
+
+        return visited;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Just calls {@link baseStartTag(XmlPullParser,Sink)}, this should be
+     * overridden by implementing parsers to include additional tags.
+     */
+    protected void handleStartTag( XmlPullParser parser, Sink sink )
+        throws XmlPullParserException, MacroExecutionException
+    {
+        if ( !baseStartTag( parser, sink ) )
+        {
+            // TODO: log( "Unrecognized start tag!" );
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Just calls {@link baseEndTag(XmlPullParser,Sink)}, this should be
+     * overridden by implementing parsers to include additional tags.
+     */
+    protected void handleEndTag( XmlPullParser parser, Sink sink )
+        throws XmlPullParserException, MacroExecutionException
+    {
+        if ( !baseEndTag( parser, sink ) )
+        {
+            // TODO: log( "Unrecognized end tag!" );
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected void handleText( XmlPullParser parser, Sink sink )
+        throws XmlPullParserException
+    {
+        String text = parser.getText();
+
+        if ( StringUtils.isNotEmpty( text.trim() ) )
+        {
+            // emit separate text events for different lines
+            String[] lines = StringUtils.split( text, EOL );
+
+            for ( int i = 0; i < lines.length; i++ )
+            {
+                sink.text( lines[i] );
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected void handleCdsect( XmlPullParser parser, Sink sink )
+        throws XmlPullParserException
+    {
+        sink.text( parser.getText() );
+    }
+
+    /** {@inheritDoc} */
+    protected void handleComment( XmlPullParser parser, Sink sink )
+        throws XmlPullParserException
+    {
+        String text = parser.getText();
+
+        if ( "PB".equals( text.trim() ) )
+        {
+            sink.pageBreak();
+        }
+        else
+        {
+            sink.comment( text.trim() );
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected void handleEntity( XmlPullParser parser, Sink sink )
+        throws XmlPullParserException
+    {
+        String text = parser.getText();
+
+        int[] holder = new int[] {0, 0};
+        char[] chars = parser.getTextCharacters( holder );
+        String textChars = String.valueOf( chars, holder[0], holder[1] );
+
+        if ( "#160".equals( textChars ) )
+        {
+            sink.nonBreakingSpace();
+        }
+        else
+        {
+            sink.text( text );
+        }
+    }
+
+    /**
+     * Close open sections. The current level is set to newLevel afterwards.
+     *
+     * @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 )
+    {
+        while ( this.sectionLevel >= newLevel )
+        {
+            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_();
+            }
+
+            this.sectionLevel--;
+        }
+
+        this.sectionLevel = newLevel;
+    }
+
+    /**
+     * Return the current section level.
+     *
+     * @return the current section level.
+     */
+    protected int getSectionLevel()
+    {
+        return this.sectionLevel;
+    }
+
+    /**
+     * Set the current section level.
+     *
+     * @param newLevel the new section level.
+     */
+    protected void setSectionLevel( int newLevel )
+    {
+        this.sectionLevel = newLevel;
+    }
+
+}

Propchange: maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/XhtmlBaseSink.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/XhtmlBaseSink.java?rev=591684&view=auto
==============================================================================
--- maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/XhtmlBaseSink.java (added)
+++ maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/XhtmlBaseSink.java Sat Nov  3 13:54:56 2007
@@ -0,0 +1,1218 @@
+package org.apache.maven.doxia.sink;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.PrintWriter;
+import java.io.Writer;
+
+import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.html.HTML.Attribute;
+import javax.swing.text.html.HTML.Tag;
+
+import org.apache.maven.doxia.parser.Parser;
+import org.apache.maven.doxia.sink.AbstractXmlSink;
+import org.apache.maven.doxia.sink.StructureSink;
+import org.apache.maven.doxia.util.HtmlTools;
+
+/**
+ * Abstract base xhtml sink implementation.
+ *
+ * @author Jason van Zyl
+ * @author ltheussl
+ * @version $Id$
+ * @since 1.0
+ */
+public class XhtmlBaseSink
+    extends AbstractXmlSink
+{
+    // ----------------------------------------------------------------------
+    // Instance fields
+    // ----------------------------------------------------------------------
+
+    /** The PrintWriter to write the result. */
+    private PrintWriter writer;
+
+    /** Used to collect text events. */
+    private StringBuffer buffer = new StringBuffer();
+
+    /** An indication on if we're inside a head. */
+    private boolean headFlag;
+
+    /** An indication on if we're in verbatim mode. */
+    private boolean verbatimFlag;
+
+    /** Justification of table cells. */
+    private int[] cellJustif;
+
+    /** Number of cells in a table row. */
+    private int cellCount;
+
+    /** Used to style successive table rows differently. */
+    private boolean evenTableRow = true;
+
+    // ----------------------------------------------------------------------
+    // Constructor
+    // ----------------------------------------------------------------------
+
+    /**
+     * Constructor, initialize the PrintWriter.
+     *
+     * @param out The writer to write the result.
+     */
+    public XhtmlBaseSink( Writer out )
+    {
+        this.writer = new PrintWriter( out );
+    }
+
+    // ----------------------------------------------------------------------
+    // Accessor methods
+    // ----------------------------------------------------------------------
+
+    /**
+     * @return the current buffer.
+     */
+    protected StringBuffer getBuffer()
+    {
+        return buffer;
+    }
+
+    /**
+     * @param headFlag an header flag.
+     */
+    protected void setHeadFlag( boolean headFlag )
+    {
+        this.headFlag = headFlag;
+    }
+
+    /**
+     * @return the current headFlag.
+     */
+    protected boolean isHeadFlag()
+    {
+        return this.headFlag ;
+    }
+
+    /**
+     * @param verb a verbatim flag.
+     */
+    protected void setVerbatimFlag( boolean verb )
+    {
+        this.verbatimFlag = verb;
+    }
+
+    /**
+     * @return the current verbatim flag.
+     */
+    protected boolean isVerbatimFlag()
+    {
+        return this.verbatimFlag ;
+    }
+
+    /**
+     * @param justif the new cell justification array.
+     */
+    protected void setCellJustif( int[] justif )
+    {
+        this.cellJustif = justif;
+    }
+
+    /**
+     * @return the current cell justification array.
+     */
+    protected int[] getCellJustif()
+    {
+        return this.cellJustif ;
+    }
+
+    /**
+     * @param count the new cell count.
+     */
+    protected void setCellCount( int count )
+    {
+        this.cellCount = count;
+    }
+
+    /**
+     * @return the current cell count.
+     */
+    protected int getCellCount()
+    {
+        return this.cellCount ;
+    }
+
+    /**
+     * @param verb an evenTableRow flag.
+     */
+    protected void setEvenTableRow( boolean even )
+    {
+        this.evenTableRow = even;
+    }
+
+    /**
+     * @return the current evenTableRow flag.
+     */
+    protected boolean isEvenTableRow()
+    {
+        return this.evenTableRow ;
+    }
+
+    /**
+     * Reset all variables.
+     */
+    protected void resetState()
+    {
+        resetBuffer();
+        headFlag = false;
+        verbatimFlag = false;
+        cellJustif = null;
+        cellCount = 0;
+        evenTableRow = true;
+    }
+
+    /**
+     * Reset the buffer.
+     */
+    protected void resetBuffer()
+    {
+        this.buffer = new StringBuffer();
+    }
+
+
+    // ----------------------------------------------------------------------
+    // Sections
+    // ----------------------------------------------------------------------
+
+    /** {@inheritDoc} */
+    public void section1()
+    {
+        onSection( SECTION_LEVEL_1 );
+    }
+
+    /** {@inheritDoc} */
+    public void sectionTitle1()
+    {
+        onSectionTitle( SECTION_LEVEL_1 );
+    }
+
+    /** {@inheritDoc} */
+    public void sectionTitle1_()
+    {
+        onSectionTitle_( SECTION_LEVEL_1 );
+    }
+
+    /** {@inheritDoc} */
+    public void section1_()
+    {
+        onSection_( SECTION_LEVEL_1 );
+    }
+
+    /** {@inheritDoc} */
+    public void section2()
+    {
+        onSection( SECTION_LEVEL_2 );
+    }
+
+    /** {@inheritDoc} */
+    public void sectionTitle2()
+    {
+        onSectionTitle( SECTION_LEVEL_2 );
+    }
+
+    /** {@inheritDoc} */
+    public void sectionTitle2_()
+    {
+        onSectionTitle_( SECTION_LEVEL_2 );
+    }
+
+    /** {@inheritDoc} */
+    public void section2_()
+    {
+        onSection_( SECTION_LEVEL_2 );
+    }
+
+    /** {@inheritDoc} */
+    public void section3()
+    {
+        onSection( SECTION_LEVEL_3 );
+    }
+
+    /** {@inheritDoc} */
+    public void sectionTitle3()
+    {
+        onSectionTitle( SECTION_LEVEL_3 );
+    }
+
+    /** {@inheritDoc} */
+    public void sectionTitle3_()
+    {
+        onSectionTitle_( SECTION_LEVEL_3 );
+    }
+
+    /** {@inheritDoc} */
+    public void section3_()
+    {
+        onSection_( SECTION_LEVEL_3 );
+    }
+
+    /** {@inheritDoc} */
+    public void section4()
+    {
+        onSection( SECTION_LEVEL_4 );
+    }
+
+    /** {@inheritDoc} */
+    public void sectionTitle4()
+    {
+        onSectionTitle( SECTION_LEVEL_4 );
+    }
+
+    /** {@inheritDoc} */
+    public void sectionTitle4_()
+    {
+        onSectionTitle_( SECTION_LEVEL_4 );
+    }
+
+    /** {@inheritDoc} */
+    public void section4_()
+    {
+        onSection_( SECTION_LEVEL_4 );
+    }
+
+    /** {@inheritDoc} */
+    public void section5()
+    {
+        onSection( SECTION_LEVEL_5 );
+    }
+
+    /** {@inheritDoc} */
+    public void sectionTitle5()
+    {
+        onSectionTitle( SECTION_LEVEL_5 );
+    }
+
+    /** {@inheritDoc} */
+    public void sectionTitle5_()
+    {
+        onSectionTitle_( SECTION_LEVEL_5 );
+    }
+
+    /** {@inheritDoc} */
+    public void section5_()
+    {
+        onSection_( SECTION_LEVEL_5 );
+    }
+
+    /**
+     * Starts a section. The default class style is <code>section</code>.
+     *
+     * @param depth The level of the section.
+     * @see javax.swing.text.html.HTML.Tag#DIV
+     */
+    protected void onSection( int depth )
+    {
+        if ( depth >= SECTION_LEVEL_1 && depth <= SECTION_LEVEL_5 )
+        {
+            MutableAttributeSet att = new SimpleAttributeSet();
+            att.addAttribute( Attribute.CLASS, "section" );
+
+            writeStartTag( Tag.DIV, att );
+        }
+    }
+
+    /**
+     * Ends a section.
+     *
+     * @param depth The level of the section.
+     * @see javax.swing.text.html.HTML.Tag#DIV
+     */
+    protected void onSection_( int depth )
+    {
+        if ( depth >= SECTION_LEVEL_1 && depth <= SECTION_LEVEL_5 )
+        {
+            writeEndTag( Tag.DIV );
+        }
+    }
+
+    /**
+     * Starts a section title.
+     *
+     * @param depth The level of the section title.
+     * @see javax.swing.text.html.HTML.Tag#H2
+     * @see javax.swing.text.html.HTML.Tag#H3
+     * @see javax.swing.text.html.HTML.Tag#H4
+     * @see javax.swing.text.html.HTML.Tag#H5
+     * @see javax.swing.text.html.HTML.Tag#H6
+     */
+    protected void onSectionTitle( int depth )
+    {
+        if ( depth == SECTION_LEVEL_1 )
+        {
+            writeStartTag( Tag.H2 );
+        }
+        else if ( depth == SECTION_LEVEL_2 )
+        {
+            writeStartTag( Tag.H3 );
+        }
+        else if ( depth == SECTION_LEVEL_3 )
+        {
+            writeStartTag( Tag.H4 );
+        }
+        else if ( depth == SECTION_LEVEL_4 )
+        {
+            writeStartTag( Tag.H5 );
+        }
+        else if ( depth == SECTION_LEVEL_5 )
+        {
+            writeStartTag( Tag.H6 );
+        }
+    }
+
+    /**
+     * Ends a section title.
+     *
+     * @param depth The level of the section title.
+     * @see javax.swing.text.html.HTML.Tag#H2
+     * @see javax.swing.text.html.HTML.Tag#H3
+     * @see javax.swing.text.html.HTML.Tag#H4
+     * @see javax.swing.text.html.HTML.Tag#H5
+     * @see javax.swing.text.html.HTML.Tag#H6
+     */
+    protected void onSectionTitle_( int depth )
+    {
+        if ( depth == SECTION_LEVEL_1 )
+        {
+            writeEndTag( Tag.H2 );
+        }
+        else if ( depth == SECTION_LEVEL_2 )
+        {
+            writeEndTag( Tag.H3 );
+        }
+        else if ( depth == SECTION_LEVEL_3 )
+        {
+            writeEndTag( Tag.H4 );
+        }
+        else if ( depth == SECTION_LEVEL_4 )
+        {
+            writeEndTag( Tag.H5 );
+        }
+        else if ( depth == SECTION_LEVEL_5 )
+        {
+            writeEndTag( Tag.H6 );
+        }
+    }
+
+    // -----------------------------------------------------------------------
+    //
+    // -----------------------------------------------------------------------
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#UL
+     */
+    public void list()
+    {
+        writeStartTag( Tag.UL );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#UL
+     */
+    public void list_()
+    {
+        writeEndTag( Tag.UL );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#LI
+     */
+    public void listItem()
+    {
+        writeStartTag( Tag.LI );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#LI
+     */
+    public void listItem_()
+    {
+        writeEndTag( Tag.LI );
+    }
+
+    /**
+     * The default list style depends on the numbering.
+     *
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#OL
+     */
+    public void numberedList( int numbering )
+    {
+        String style;
+        switch ( numbering )
+        {
+            case NUMBERING_UPPER_ALPHA:
+                style = "upper-alpha";
+                break;
+            case NUMBERING_LOWER_ALPHA:
+                style = "lower-alpha";
+                break;
+            case NUMBERING_UPPER_ROMAN:
+                style = "upper-roman";
+                break;
+            case NUMBERING_LOWER_ROMAN:
+                style = "lower-roman";
+                break;
+            case NUMBERING_DECIMAL:
+            default:
+                style = "decimal";
+        }
+
+        MutableAttributeSet att = new SimpleAttributeSet();
+        att.addAttribute( Attribute.STYLE, "list-style-type: " + style );
+
+        writeStartTag( Tag.OL, att );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#OL
+     */
+    public void numberedList_()
+    {
+        writeEndTag( Tag.OL );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#LI
+     */
+    public void numberedListItem()
+    {
+        writeStartTag( Tag.LI );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#LI
+     */
+    public void numberedListItem_()
+    {
+        writeEndTag( Tag.LI );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#DL
+     */
+    public void definitionList()
+    {
+        writeStartTag( Tag.DL );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#DL
+     */
+    public void definitionList_()
+    {
+        writeEndTag( Tag.DL );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#DT
+     */
+    public void definedTerm()
+    {
+        writeStartTag( Tag.DT );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#DT
+     */
+    public void definedTerm_()
+    {
+        writeEndTag( Tag.DT );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#DD
+     */
+    public void definition()
+    {
+        writeStartTag( Tag.DD );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#DD
+     */
+    public void definition_()
+    {
+        writeEndTag( Tag.DD );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#IMG
+     */
+    public void figure()
+    {
+        write( String.valueOf( LESS_THAN ) + Tag.IMG );
+    }
+
+    /** {@inheritDoc} */
+    public void figure_()
+    {
+        write( String.valueOf( SPACE ) + String.valueOf( SLASH ) + String.valueOf( GREATER_THAN ) );
+    }
+
+    /** {@inheritDoc} */
+    public void figureGraphics( String name )
+    {
+        write( String.valueOf( SPACE ) + Attribute.SRC + String.valueOf( EQUAL ) + String.valueOf( QUOTE ) + name
+            + String.valueOf( QUOTE ) );
+    }
+
+    /** {@inheritDoc} */
+    public void figureCaption()
+    {
+        write( String.valueOf( SPACE ) + Attribute.ALT + String.valueOf( EQUAL ) + String.valueOf( QUOTE ) );
+    }
+
+    /** {@inheritDoc} */
+    public void figureCaption_()
+    {
+        write( String.valueOf( QUOTE ) );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#P
+     */
+    public void paragraph()
+    {
+        writeStartTag( Tag.P );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#P
+     */
+    public void paragraph_()
+    {
+        writeEndTag( Tag.P );
+    }
+
+    /**
+     * The default class style for boxed is <code>source</code>.
+     *
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#DIV
+     * @see javax.swing.text.html.HTML.Tag#PRE
+     */
+    public void verbatim( boolean boxed )
+    {
+        verbatimFlag = true;
+
+        MutableAttributeSet att = new SimpleAttributeSet();
+
+        if ( boxed )
+        {
+            att.addAttribute( Attribute.CLASS, "source" );
+        }
+
+        writeStartTag( Tag.DIV, att );
+        writeStartTag( Tag.PRE );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#DIV
+     * @see javax.swing.text.html.HTML.Tag#PRE
+     */
+    public void verbatim_()
+    {
+        writeEndTag( Tag.PRE );
+        writeEndTag( Tag.DIV );
+
+        verbatimFlag = false;
+
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#HR
+     */
+    public void horizontalRule()
+    {
+        writeSimpleTag( Tag.HR );
+    }
+
+    /** {@inheritDoc} */
+    public void table()
+    {
+        // start table with tableRows
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#TABLE
+     */
+    public void table_()
+    {
+        writeEndTag( Tag.TABLE );
+    }
+
+    /**
+     * The default class style is <code>bodyTable</code>.
+     * The default align is <code>center</code>.
+     *
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#TABLE
+     */
+    public void tableRows( int[] justification, boolean grid )
+    {
+        this.cellJustif = justification;
+
+        MutableAttributeSet att = new SimpleAttributeSet();
+        att.addAttribute( Attribute.ALIGN, "center" );
+        att.addAttribute( Attribute.BORDER, ( grid ? "1" : "0" ) );
+        att.addAttribute( Attribute.CLASS, "bodyTable" );
+
+        writeStartTag( Tag.TABLE, att );
+    }
+
+    /** {@inheritDoc} */
+    public void tableRows_()
+    {
+        this.cellJustif = null;
+
+        this.evenTableRow = true;
+    }
+
+    /**
+     * The default class style is <code>a</code> or <code>b</code> depending the row id.
+     *
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#TR
+     */
+    public void tableRow()
+    {
+        MutableAttributeSet att = new SimpleAttributeSet();
+
+        if ( evenTableRow )
+        {
+            att.addAttribute( Attribute.CLASS, "a" );
+        }
+        else
+        {
+            att.addAttribute( Attribute.CLASS, "b" );
+        }
+
+        writeStartTag( Tag.TR, att );
+
+        evenTableRow = !evenTableRow;
+
+        cellCount = 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#TR
+     */
+    public void tableRow_()
+    {
+        writeEndTag( Tag.TR );
+
+        cellCount = 0;
+    }
+
+    /** {@inheritDoc} */
+    public void tableCell()
+    {
+        tableCell( false );
+    }
+
+    /** {@inheritDoc} */
+    public void tableHeaderCell()
+    {
+        tableCell( true );
+    }
+
+    /**
+     * Starts a table cell.
+     *
+     * @param headerRow true if it is an header row
+     * @see javax.swing.text.html.HTML.Tag#TH
+     * @see javax.swing.text.html.HTML.Tag#TD
+     */
+    public void tableCell( boolean headerRow )
+    {
+        tableCell( headerRow, null );
+    }
+
+    /** {@inheritDoc} */
+    public void tableCell( String width )
+    {
+        tableCell( false, width );
+    }
+
+    /** {@inheritDoc} */
+    public void tableHeaderCell( String width )
+    {
+        tableCell( true, width );
+    }
+
+    /**
+     * @param headerRow true if it is an header row
+     * @param width the cell size
+     * @see javax.swing.text.html.HTML.Tag#TH
+     * @see javax.swing.text.html.HTML.Tag#TD
+     */
+    public void tableCell( boolean headerRow, String width )
+    {
+        String justif = null;
+
+        if ( cellJustif != null )
+        {
+            switch ( cellJustif[cellCount] )
+            {
+                case Parser.JUSTIFY_LEFT:
+                    justif = "left";
+                    break;
+                case Parser.JUSTIFY_RIGHT:
+                    justif = "right";
+                    break;
+                case Parser.JUSTIFY_CENTER:
+                default:
+                    justif = "center";
+                    break;
+            }
+        }
+
+
+        Tag t = ( headerRow ? Tag.TH : Tag.TD );
+
+        MutableAttributeSet att = new SimpleAttributeSet();
+
+        if ( width != null )
+        {
+            att.addAttribute( Attribute.WIDTH, width );
+        }
+
+        if ( justif != null )
+        {
+            att.addAttribute( Attribute.ALIGN, justif );
+        }
+
+        writeStartTag( t, att );
+    }
+
+    /** {@inheritDoc} */
+    public void tableCell_()
+    {
+        tableCell_( false );
+    }
+
+    /** {@inheritDoc} */
+    public void tableHeaderCell_()
+    {
+        tableCell_( true );
+    }
+
+    /**
+     * Ends a table cell.
+     *
+     * @param headerRow true if it is an header row
+     * @see javax.swing.text.html.HTML.Tag#TH
+     * @see javax.swing.text.html.HTML.Tag#TD
+     */
+    public void tableCell_( boolean headerRow )
+    {
+        Tag t = ( headerRow ? Tag.TH : Tag.TD );
+
+        writeEndTag( t );
+
+        ++cellCount;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#CAPTION
+     */
+    public void tableCaption()
+    {
+        // TODO: tableCaption should be written before tableRows
+        writeStartTag( Tag.CAPTION );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#CAPTION
+     */
+    public void tableCaption_()
+    {
+        writeEndTag( Tag.CAPTION );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#A
+     */
+    public void anchor( String name )
+    {
+        if ( !headFlag )
+        {
+            String id = HtmlTools.encodeId( name );
+
+            MutableAttributeSet att = new SimpleAttributeSet();
+
+            if ( id != null )
+            {
+                att.addAttribute( Attribute.NAME, id );
+            }
+
+            writeStartTag( Tag.A, att );
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#A
+     */
+    public void anchor_()
+    {
+        if ( !headFlag )
+        {
+            writeEndTag( Tag.A );
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void link( String name )
+    {
+        link( name, null );
+    }
+
+    /**
+     * Adds a link with an optional target.
+     * The default style class for external link is <code>externalLink</code>.
+     *
+     * @param name the link name.
+     * @param target the link target, may be null.
+     * @see javax.swing.text.html.HTML.Tag#A
+     */
+    public void link( String name, String target )
+    {
+        if ( headFlag )
+        {
+            return;
+        }
+
+        MutableAttributeSet att = new SimpleAttributeSet();
+
+        if ( target != null )
+        {
+            att.addAttribute( Attribute.TARGET, target );
+        }
+
+        if ( StructureSink.isExternalLink( name ) || isExternalHtml( name ) )
+        {
+            if ( isExternalLink( name ) )
+            {
+                att.addAttribute( Attribute.CLASS, "externalLink" );
+            }
+
+            att.addAttribute( Attribute.HREF, HtmlTools.escapeHTML( name ) );
+        }
+        else
+        {
+            att.addAttribute( Attribute.HREF, "#" + HtmlTools.escapeHTML( name ) );
+        }
+
+        writeStartTag( Tag.A, att );
+    }
+
+    /**
+     * {@link StructureSink#isExternalLink(String)} also treats links to other documents as
+     * external links, those should not have a class="externalLink" attribute.
+     */
+    private boolean isExternalLink( String href )
+    {
+        String text = href.toLowerCase();
+        return ( text.indexOf( "http:/" ) == 0 || text.indexOf( "https:/" ) == 0
+            || text.indexOf( "ftp:/" ) == 0 || text.indexOf( "mailto:" ) == 0
+            || text.indexOf( "file:/" ) == 0 );
+
+    }
+
+    /**
+     * Legacy: treat links to other html documents as external links.
+     * Note that links to other file formats (images, pdf) will still be broken,
+     * links to other documents should always start with "./" or "../".
+     */
+    private boolean isExternalHtml( String href )
+    {
+        String text = href.toLowerCase();
+        return ( text.indexOf( ".html#" ) != -1 || text.indexOf( ".htm#" ) != -1
+            || text.endsWith( ".htm" ) || text.endsWith( ".html" )
+            || !HtmlTools.isId( text ) );
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#A
+     */
+    public void link_()
+    {
+        if ( !headFlag )
+        {
+            writeEndTag( Tag.A );
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#I
+     */
+    public void italic()
+    {
+        if ( !headFlag )
+        {
+            writeStartTag( Tag.I );
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#I
+     */
+    public void italic_()
+    {
+        if ( !headFlag )
+        {
+            writeEndTag( Tag.I );
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#B
+     */
+    public void bold()
+    {
+        if ( !headFlag )
+        {
+            writeStartTag( Tag.B );
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#B
+     */
+    public void bold_()
+    {
+        if ( !headFlag )
+        {
+            writeEndTag( Tag.B );
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#TT
+     */
+    public void monospaced()
+    {
+        if ( !headFlag )
+        {
+            writeStartTag( Tag.TT );
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#TT
+     */
+    public void monospaced_()
+    {
+        if ( !headFlag )
+        {
+            writeEndTag( Tag.TT );
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see javax.swing.text.html.HTML.Tag#BR
+     */
+    public void lineBreak()
+    {
+        if ( headFlag )
+        {
+            getBuffer().append( EOL );
+        }
+        else
+        {
+            writeSimpleTag( Tag.BR );
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void pageBreak()
+    {
+        comment( "PB" );
+    }
+
+    /** {@inheritDoc} */
+    public void nonBreakingSpace()
+    {
+        if ( headFlag )
+        {
+            getBuffer().append( ' ' );
+        }
+        else
+        {
+            write( "&#160;" );
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void text( String text )
+    {
+        if ( headFlag )
+        {
+            getBuffer().append( text );
+        }
+        else if ( verbatimFlag )
+        {
+            verbatimContent( text );
+        }
+        else
+        {
+            content( text );
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void rawText( String text )
+    {
+        write( text );
+    }
+
+    /** {@inheritDoc} */
+    public void comment( String comment )
+    {
+        StringBuffer buf = new StringBuffer( comment.length() + 9 );
+
+        buf.append( LESS_THAN ).append( BANG ).append( MINUS ).append( MINUS ).append( SPACE );
+
+        buf.append( comment );
+
+        buf.append( SPACE ).append( MINUS ).append( MINUS ).append( GREATER_THAN );
+
+        rawText( buf.toString() );
+    }
+
+    /** {@inheritDoc} */
+    public void flush()
+    {
+        writer.flush();
+    }
+
+    /** {@inheritDoc} */
+    public void close()
+    {
+        writer.close();
+    }
+
+    // ----------------------------------------------------------------------
+    //
+    // ----------------------------------------------------------------------
+
+
+    /**
+     * Write HTML escaped text to output.
+     *
+     * @param text The text to write.
+     */
+    protected void content( String text )
+    {
+        write( escapeHTML( text ) );
+    }
+
+    /**
+     * Write HTML escaped text to output.
+     *
+     * @param text The text to write.
+     */
+    protected void verbatimContent( String text )
+    {
+        write( escapeHTML( text ) );
+    }
+
+    /**
+     * Forward to HtmlTools.escapeHTML( text ).
+     *
+     * @param text the String to escape, may be null
+     * @return the text escaped, "" if null String input
+     * @see org.apache.maven.doxia.util.HtmlTools#escapeHTML(String)
+     */
+    public static String escapeHTML( String text )
+    {
+        return HtmlTools.escapeHTML( text );
+    }
+
+    /**
+     * @param text
+     * @return a fragment encoded
+     * @see #encodeURL(String)
+     */
+    public static String encodeFragment( String text )
+    {
+        return encodeURL( StructureSink.linkToKey( text ) );
+    }
+
+    /**
+     * Forward to HtmlTools.encodeURL( text ).
+     *
+     * @param text the String to encode, may be null.
+     * @return the text encoded, null if null String input.
+     * @see org.apache.maven.doxia.util.HtmlTools#encodeURL(String)
+     */
+    public static String encodeURL( String text )
+    {
+        return HtmlTools.encodeURL( text );
+    }
+
+    /** {@inheritDoc} */
+    protected void write( String text )
+    {
+        writer.write( text );
+    }
+
+}

Propchange: maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/XhtmlBaseSink.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/XhtmlBaseSink.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"



Mime
View raw message