maven-doxia-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ltheu...@apache.org
Subject svn commit: r656154 - in /maven/doxia: doxia-sitetools/trunk/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/ doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/ doxia/trunk/doxia-core/src/main/java/org/apache/mave...
Date Wed, 14 May 2008 08:44:31 GMT
Author: ltheussl
Date: Wed May 14 01:44:30 2008
New Revision: 656154

URL: http://svn.apache.org/viewvc?rev=656154&view=rev
Log:
[DOXIA-208] Standardize link-anchor handling. Remove StructureSinkUtils, the methods have been moved to AptUtils.
            The parameter in link( String name ) has to start with a '#' if it's a link to an anchor.
            Anchors and id's have to be valid doxia id's as defined in DoxiaUtils.encodeId().

Removed:
    maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/util/StructureSinkUtils.java
    maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/util/StructureSinkUtilsTest.java
Modified:
    maven/doxia/doxia-sitetools/trunk/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/DefaultSiteRendererTest.java
    maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/parser/XhtmlBaseParser.java
    maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/SinkAdapter.java
    maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/XhtmlBaseSink.java
    maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/util/DoxiaUtils.java
    maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/util/HtmlTools.java
    maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/AbstractSinkTest.java
    maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/SinkTestDocument.java
    maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java
    maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptSink.java
    maven/doxia/doxia/trunk/doxia-modules/doxia-module-docbook-simple/src/main/java/org/apache/maven/doxia/module/docbook/DocBookSink.java
    maven/doxia/doxia/trunk/doxia-modules/doxia-module-fml/src/main/java/org/apache/maven/doxia/module/fml/FmlParser.java
    maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoAggregateSink.java
    maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoSink.java
    maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoUtils.java
    maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/test/java/org/apache/maven/doxia/module/fo/FoSinkTest.java
    maven/doxia/doxia/trunk/doxia-modules/doxia-module-itext/src/main/java/org/apache/maven/doxia/module/itext/ITextSink.java
    maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocSinkTest.java
    maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/java/org/apache/maven/doxia/module/xhtml/XhtmlSinkTest.java
    maven/doxia/site/src/site/apt/references/doxia-apt.apt

Modified: maven/doxia/doxia-sitetools/trunk/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/DefaultSiteRendererTest.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia-sitetools/trunk/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/DefaultSiteRendererTest.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia-sitetools/trunk/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/DefaultSiteRendererTest.java (original)
+++ maven/doxia/doxia-sitetools/trunk/doxia-site-renderer/src/test/java/org/apache/maven/doxia/siterenderer/DefaultSiteRendererTest.java Wed May 14 01:44:30 2008
@@ -972,8 +972,7 @@
         a = (HtmlAnchor) elementIterator.next();
         assertEquals( "cdc.html", a.getAttributeValue( "href" ) );
         a = (HtmlAnchor) elementIterator.next();
-        // TODO:
-        //assertEquals( "cdc.pdf", a.getAttributeValue( "href" ) );
+        assertEquals( "cdc.pdf", a.getAttributeValue( "href" ) );
         a = (HtmlAnchor) elementIterator.next();
         assertEquals( "./cdc.txt", a.getAttributeValue( "href" ) );
     }
@@ -1083,7 +1082,6 @@
         a = (HtmlAnchor) elementIterator.next();
         assertEquals( "./cdc.html", a.getAttributeValue( "href" ) );
         a = (HtmlAnchor) elementIterator.next();
-        // TODO:
-        //assertEquals( "#cdc.html", a.getAttributeValue( "href" ) );
+        assertEquals( "#cdc.html", a.getAttributeValue( "href" ) );
     }
 }

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=656154&r1=656153&r2=656154&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 Wed May 14 01:44:30 2008
@@ -25,6 +25,7 @@
 import org.apache.maven.doxia.macro.MacroExecutionException;
 import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.sink.SinkEventAttributeSet;
+import org.apache.maven.doxia.util.DoxiaUtils;
 
 import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.xml.pull.XmlPullParser;
@@ -281,14 +282,7 @@
 
             if ( href != null )
             {
-                String link = href;
-
-                if ( link.startsWith( "#" ) )
-                {
-                    link = link.substring( 1 );
-                }
-
-                sink.link( link, attribs  );
+                sink.link( href, attribs );
 
                 isLink = true;
             }
@@ -298,7 +292,7 @@
 
                 if ( name != null )
                 {
-                    sink.anchor( name, attribs  );
+                    sink.anchor( validAnchor( name ), attribs );
 
                     isAnchor = true;
                 }
@@ -308,7 +302,7 @@
 
                     if ( id != null )
                     {
-                        sink.anchor( id, attribs  );
+                        sink.anchor( validAnchor( id ), attribs );
 
                         isAnchor = true;
                     }
@@ -781,4 +775,22 @@
         return ( this.verbatimLevel != 0 );
     }
 
+    /**
+     * Checks if the given id is a valid Doxia id and if not, returns a transformed one.
+     *
+     * @param The id to validate.
+     * @return A transformed id or the original id if it was already valid.
+     * @see DoxiaUtils#encodeId(String)
+     */
+    protected String validAnchor( String id )
+    {
+        if ( !DoxiaUtils.isValidId( id ) )
+        {
+            getLog().warn( "Modified invalid anchor name: " + id );
+
+            return DoxiaUtils.encodeId( id );
+        }
+
+        return id;
+    }
 }

Modified: maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/SinkAdapter.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/SinkAdapter.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/SinkAdapter.java (original)
+++ maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/SinkAdapter.java Wed May 14 01:44:30 2008
@@ -834,24 +834,6 @@
     }
 
     /** {@inheritDoc} */
-    public void italic( SinkEventAttributes attributes )
-    {
-        italic();
-    }
-
-    /** {@inheritDoc} */
-    public void bold( SinkEventAttributes attributes )
-    {
-        bold();
-    }
-
-    /** {@inheritDoc} */
-    public void monospaced( SinkEventAttributes attributes )
-    {
-        monospaced();
-    }
-
-    /** {@inheritDoc} */
     public void lineBreak( SinkEventAttributes attributes )
     {
         lineBreak();

Modified: 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=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/XhtmlBaseSink.java (original)
+++ maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/XhtmlBaseSink.java Wed May 14 01:44:30 2008
@@ -27,8 +27,8 @@
 import javax.swing.text.html.HTML.Tag;
 
 import org.apache.maven.doxia.parser.Parser;
+import org.apache.maven.doxia.util.DoxiaUtils;
 import org.apache.maven.doxia.util.HtmlTools;
-import org.apache.maven.doxia.util.StructureSinkUtils;
 
 /**
  * Abstract base xhtml sink implementation.
@@ -737,12 +737,12 @@
         {
             atts = new SinkEventAttributeSet( 1 );
         }
-        
+
         if ( !atts.isDefined( SinkEventAttributes.CLASS ) )
         {
             atts.addAttribute( SinkEventAttributes.CLASS, "figure" );
         }
-        
+
         writeStartTag( Tag.DIV, atts );
     }
 
@@ -778,20 +778,20 @@
         {
             MutableAttributeSet atts = new SinkEventAttributeSet( 1 );
             atts.addAttribute( SinkEventAttributes.ALIGN, "center" );
-            
+
             writeStartTag( Tag.P, atts );
         }
-        
+
         int count = ( attributes == null ? 1 : attributes.getAttributeCount() + 1 );
-        
+
         MutableAttributeSet atts = new SinkEventAttributeSet( count );
-        
+
         atts.addAttribute( Attribute.SRC, src );
         atts.addAttributes( SinkUtils.filterAttributes(
                 attributes, SinkUtils.SINK_IMG_ATTRIBUTES ) );
-        
+
         writeStartTag( Tag.IMG, atts, true );
-        
+
         if ( inFigure )
         {
             writeEndTag( Tag.P );
@@ -823,7 +823,7 @@
             atts.addAttribute( SinkEventAttributes.ALIGN, "center" );
             atts.addAttributes( SinkUtils.filterAttributes(
                 attributes, SinkUtils.SINK_BASE_ATTRIBUTES  ) );
-            
+
             paragraph( atts );
             italic();
         }
@@ -1240,7 +1240,7 @@
      */
     public void tableCaption( SinkEventAttributes attributes )
     {
-        // TODO: tableCaption should be written before tableRows
+        // TODO: tableCaption should be written before tableRows (DOXIA-177)
         MutableAttributeSet atts = SinkUtils.filterAttributes(
                 attributes, SinkUtils.SINK_SECTION_ATTRIBUTES  );
 
@@ -1271,24 +1271,33 @@
      */
     public void anchor( String name, SinkEventAttributes attributes )
     {
-        if ( !headFlag )
+        if ( name == null )
         {
-            MutableAttributeSet atts = SinkUtils.filterAttributes(
-                    attributes, SinkUtils.SINK_BASE_ATTRIBUTES  );
+            throw new NullPointerException( "Anchor name cannot be null!" );
+        }
 
-            String id = HtmlTools.encodeId( name );
+        if ( headFlag )
+        {
+            return;
+        }
 
-            MutableAttributeSet att = new SinkEventAttributeSet();
+        MutableAttributeSet atts = SinkUtils.filterAttributes(
+                attributes, SinkUtils.SINK_BASE_ATTRIBUTES  );
 
-            if ( id != null )
-            {
-                att.addAttribute( Attribute.NAME, id );
-            }
+        String id = name;
 
-            att.addAttributes( atts );
+        if ( !DoxiaUtils.isValidId( id ) )
+        {
+            id = DoxiaUtils.encodeId( name );
 
-            writeStartTag( Tag.A, att );
+            getLog().warn( "Modified invalid anchor name: " + name );
         }
+
+        MutableAttributeSet att = new SinkEventAttributeSet();
+        att.addAttribute( Attribute.NAME, id );
+        att.addAttributes( atts );
+
+        writeStartTag( Tag.A, att );
     }
 
     /**
@@ -1331,6 +1340,11 @@
      */
     private void link( String href, String target, MutableAttributeSet attributes )
     {
+        if ( href == null )
+        {
+            throw new NullPointerException( "Link name cannot be null!" );
+        }
+
         if ( headFlag )
         {
             return;
@@ -1338,20 +1352,13 @@
 
         MutableAttributeSet att = new SinkEventAttributeSet();
 
-        if ( StructureSinkUtils.isExternalLink( href  ) || isExternalHtml( href  ) )
-        {
-            if ( isExternalLink( href  ) )
-            {
-                att.addAttribute( Attribute.CLASS, "externalLink" );
-            }
-
-            att.addAttribute( Attribute.HREF, HtmlTools.escapeHTML( href  ) );
-        }
-        else
+        if ( DoxiaUtils.isExternalLink( href  ) )
         {
-            att.addAttribute( Attribute.HREF, "#" + HtmlTools.escapeHTML( href  ) );
+            att.addAttribute( Attribute.CLASS, "externalLink" );
         }
 
+        att.addAttribute( Attribute.HREF, HtmlTools.escapeHTML( href  ) );
+
         if ( target != null )
         {
             att.addAttribute( Attribute.TARGET, target );
@@ -1368,37 +1375,6 @@
     }
 
     /**
-     * {@link StructureSinkUtils#isExternalLink(String)} also treats links to other documents as
-     * external links, those should not have a class="externalLink" attribute.
-     * @param href the link.
-     * @return true if the link starts with "http:/", "https:/", "ftp:/",
-     * "mailto:" or "file:/".
-     */
-    protected 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 "../".
-     * @param href the link.
-     * @return true if the link points to another source document.
-     */
-    protected 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
      */
@@ -1426,21 +1402,6 @@
      * {@inheritDoc}
      * @see javax.swing.text.html.HTML.Tag#I
      */
-    public void italic( SinkEventAttributes attributes )
-    {
-        if ( !headFlag )
-        {
-            MutableAttributeSet atts = SinkUtils.filterAttributes(
-                attributes, SinkUtils.SINK_BASE_ATTRIBUTES  );
-
-            writeStartTag( Tag.I, atts );
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     * @see javax.swing.text.html.HTML.Tag#I
-     */
     public void italic_()
     {
         if ( !headFlag )
@@ -1465,21 +1426,6 @@
      * {@inheritDoc}
      * @see javax.swing.text.html.HTML.Tag#B
      */
-    public void bold( SinkEventAttributes attributes )
-    {
-        if ( !headFlag )
-        {
-            MutableAttributeSet atts = SinkUtils.filterAttributes(
-                attributes, SinkUtils.SINK_BASE_ATTRIBUTES  );
-
-            writeStartTag( Tag.B, atts );
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     * @see javax.swing.text.html.HTML.Tag#B
-     */
     public void bold_()
     {
         if ( !headFlag )
@@ -1504,21 +1450,6 @@
      * {@inheritDoc}
      * @see javax.swing.text.html.HTML.Tag#TT
      */
-    public void monospaced( SinkEventAttributes attributes )
-    {
-        if ( !headFlag )
-        {
-            MutableAttributeSet atts = SinkUtils.filterAttributes(
-                attributes, SinkUtils.SINK_BASE_ATTRIBUTES  );
-
-            writeStartTag( Tag.TT, atts );
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     * @see javax.swing.text.html.HTML.Tag#TT
-     */
     public void monospaced_()
     {
         if ( !headFlag )
@@ -1622,9 +1553,9 @@
             {
                 writeStartTag( Tag.SUP );
             }
-            
+
             text( text );
-            
+
             if ( attributes.containsAttribute(SinkEventAttributes.VALIGN, "sup") )
             {
                 writeEndTag( Tag.SUP );

Modified: maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/util/DoxiaUtils.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/util/DoxiaUtils.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/util/DoxiaUtils.java (original)
+++ maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/util/DoxiaUtils.java Wed May 14 01:44:30 2008
@@ -19,6 +19,8 @@
  * under the License.
  */
 
+import java.io.UnsupportedEncodingException;
+
 /**
  * General Doxia utility methods. The methods in this class should not assume
  * any specific Doxia module or document format.
@@ -27,7 +29,8 @@
  * @since 1.0-beta-1
  * @version $Id$
  */
-public class DoxiaUtils {
+public class DoxiaUtils
+{
 
     /**
      * Checks if the given string corresponds to an internal link,
@@ -72,6 +75,176 @@
         return ( !isExternalLink( link ) && !isInternalLink( link ) );
     }
 
+    /**
+     * Construct a valid Doxia id.
+     *
+     * <p>
+     *   A valid Doxia id obeys the same constraints as an HTML ID or NAME token.
+     *   According to the <a href="http://www.w3.org/TR/html4/types.html#type-name">
+     *   HTML 4.01 specification section 6.2 SGML basic types</a>:
+     * </p>
+     * <p>
+     *   <i>ID and NAME tokens must begin with a letter ([A-Za-z]) and may be
+     *   followed by any number of letters, digits ([0-9]), hyphens ("-"),
+     *   underscores ("_"), colons (":"), and periods (".").</i>
+     * </p>
+     * <p>
+     *   According to <a href="http://www.w3.org/TR/xhtml1/#C_8">XHTML 1.0
+     *   section C.8. Fragment Identifiers</a>:
+     * </p>
+     * <p>
+     *   <i>When defining fragment identifiers to be backward-compatible, only
+     *   strings matching the pattern [A-Za-z][A-Za-z0-9:_.-]* should be used.</i>
+     * </p>
+     * <p>
+     *   To achieve this we need to convert the <i>id</i> String. Two conversions
+     *   are necessary and one is done to get prettier ids:
+     * </p>
+     * <ol>
+     *   <li>Remove whitespace at the start and end before starting to process</li>
+     *   <li>If the first character is not a letter, prepend the id with the letter 'a'</li>
+     *   <li>Any spaces are replaced with an underscore '_'</li>
+     *   <li>
+     *     Any characters not matching the above pattern are replaced according to the rules
+     *     specified in the
+     *     <a href="http://www.w3.org/TR/html4/appendix/notes.html#non-ascii-chars">HTML specs</a>.
+     *   </li>
+     * </ol>
+     * <p>
+     *   For letters, the case is preserved in the conversion.
+     * </p>
+     *
+     * <p>
+     * Here are some examples:
+     * </p>
+     * <pre>
+     * DoxiaUtils.encodeId( null )        = null
+     * DoxiaUtils.encodeId( "" )          = ""
+     * DoxiaUtils.encodeId( " _ " )       = "a_"
+     * DoxiaUtils.encodeId( "1" )         = "a1"
+     * DoxiaUtils.encodeId( "1anchor" )   = "a1anchor"
+     * DoxiaUtils.encodeId( "_anchor" )   = "a_anchor"
+     * DoxiaUtils.encodeId( "a b-c123 " ) = "a_b-c123"
+     * DoxiaUtils.encodeId( "   anchor" ) = "anchor"
+     * DoxiaUtils.encodeId( "myAnchor" )  = "myAnchor"
+     * </pre>
+     *
+     * @param id The id to be encoded.
+     * @return The trimmed and encoded id, or null if id is null.
+     */
+    public static String encodeId( String id )
+    {
+        if ( id == null )
+        {
+            return null;
+        }
+
+        id = id.trim();
+        int length = id.length();
+        StringBuffer buffer = new StringBuffer( length );
+
+        for ( int i = 0; i < length; ++i )
+        {
+            char c = id.charAt( i );
+
+            if ( ( i == 0 ) && ( !isAciiLetter( c ) ) )
+            {
+                buffer.append( "a" );
+            }
+
+            if ( c == ' ' )
+            {
+                buffer.append( "_" );
+            }
+            else if ( isAciiLetter( c ) || isAciiDigit( c ) || ( c == '-' ) || ( c == '_' ) || ( c == ':' ) || ( c == '.' ) )
+            {
+                buffer.append( c );
+            }
+            else
+            {
+                char[] unicode = new char[1];
+                byte[] bytes;
+
+                try
+                {
+                    unicode[0] = c;
+                    bytes = ( new String( unicode, 0, 1 ) ).getBytes( "UTF8" );
+                }
+                catch ( UnsupportedEncodingException cannotHappen )
+                {
+                    bytes = new byte[0];
+                }
+
+                for ( int j = 0; j < bytes.length; ++j )
+                {
+                    String hex = Integer.toHexString( bytes[j] & 0xFF );
+
+                    buffer.append( '%' );
+
+                    if ( hex.length() == 1 )
+                    {
+                        buffer.append( '0' );
+                    }
+
+                    buffer.append( hex );
+                }
+            }
+        }
+
+        return buffer.toString();
+    }
+
+    /**
+     * Determines if the specified text is a valid id according to the rules
+     * laid out in {@link #encodeId(String)}.
+     *
+     * @param text The text to be tested.
+     * @return <code>true</code> if the text is a valid id, otherwise <code>false</code>.
+     * @see #encodeId(String).
+     */
+    public static boolean isValidId( String text )
+    {
+        if ( text == null || text.length() == 0 )
+        {
+            return false;
+        }
+
+        for ( int i = 0; i < text.length(); ++i )
+        {
+            char c = text.charAt( i );
+
+            if ( i == 0 && !isAciiLetter( c ) )
+            {
+                return false;
+            }
+
+            if ( c == ' ' )
+            {
+                return false;
+            }
+            else if ( !isAciiLetter( c ) && !isAciiDigit( c ) && c != '-' && c != '_' && c != ':' && c != '.' )
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+      //
+     // private
+    //
+
+    private static boolean isAciiLetter( char c )
+    {
+        return ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) );
+    }
+
+    private static boolean isAciiDigit( char c )
+    {
+        return ( ( c >= '0' && c <= '9') );
+    }
+
     private DoxiaUtils() {
         // utility class
     }

Modified: maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/util/HtmlTools.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/util/HtmlTools.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/util/HtmlTools.java (original)
+++ maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/util/HtmlTools.java Wed May 14 01:44:30 2008
@@ -323,5 +323,5 @@
 
     private HtmlTools() {
         // utility class
-}
+    }
 }

Modified: maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/AbstractSinkTest.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/AbstractSinkTest.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/AbstractSinkTest.java (original)
+++ maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/AbstractSinkTest.java Wed May 14 01:44:30 2008
@@ -520,7 +520,7 @@
      */
     public void testLink()
     {
-        String link = "Link";
+        String link = "#Link";
         String text = "Text";
         sink.link( link );
         sink.text( text );

Modified: maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/SinkTestDocument.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/SinkTestDocument.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/SinkTestDocument.java (original)
+++ maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/SinkTestDocument.java Wed May 14 01:44:30 2008
@@ -478,7 +478,7 @@
         sink.anchor_();
 
         sink.text( ". Link to " );
-        sink.link( "Anchor" );
+        sink.link( "#Anchor" );
         sink.text( "Anchor" );
         sink.link_();
 
@@ -488,7 +488,7 @@
         sink.link_();
 
         sink.text( ". Link to " );
-        sink.link( "Anchor" );
+        sink.link( "#Anchor" );
         sink.text( "showing alternate text" );
         sink.link_();
 

Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java (original)
+++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java Wed May 14 01:44:30 2008
@@ -25,6 +25,8 @@
 import org.apache.maven.doxia.parser.AbstractTextParser;
 import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.sink.SinkAdapter;
+import org.apache.maven.doxia.util.DoxiaUtils;
+
 import org.codehaus.plexus.util.IOUtil;
 import org.codehaus.plexus.util.StringUtils;
 
@@ -431,13 +433,44 @@
                                 linkAnchor = getTraversedLink( text, i + 1, end );
                             }
 
+                            if ( !AptUtils.isExternalLink( linkAnchor ) )
+                            {
+                                linkAnchor = "#" + linkAnchor;
+                            }
+
+                            int hashIndex = linkAnchor.indexOf( "#" );
+
+                            if ( hashIndex != -1 )
+                            {
+                                String hash = linkAnchor.substring( hashIndex + 1 );
+
+                                if ( !DoxiaUtils.isValidId( hash ) )
+                                {
+                                    getLog().warn( "Modified invalid link: " + hash );
+
+                                    linkAnchor = linkAnchor.substring( 0, hashIndex ) + "#"
+                                        + DoxiaUtils.encodeId( hash );
+                                }
+                            }
+
                             sink.link( linkAnchor );
                         }
                         else
                         {
                             anchor = true;
                             flushTraversed( buffer, sink );
-                            sink.anchor( getTraversedAnchor( text, i + 1, end ) );
+
+                            String linkAnchor = getTraversedAnchor( text, i + 1, end );
+
+                            if ( !DoxiaUtils.isValidId( linkAnchor ) )
+                            {
+                                // debug only: anchors in apt may contain spaces
+                                getLog().debug( "Modified anchor name: " + linkAnchor );
+
+                                linkAnchor = DoxiaUtils.encodeId( linkAnchor );
+                            }
+
+                            sink.anchor( linkAnchor );
                         }
                     }
                     else

Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptSink.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptSink.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptSink.java (original)
+++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptSink.java Wed May 14 01:44:30 2008
@@ -710,7 +710,6 @@
     /** {@inheritDoc} */
     public void anchor( String name )
     {
-//        String id = HtmlTools.encodeId(name);
         write( ANCHOR_START_MARKUP );
     }
 

Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-docbook-simple/src/main/java/org/apache/maven/doxia/module/docbook/DocBookSink.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-docbook-simple/src/main/java/org/apache/maven/doxia/module/docbook/DocBookSink.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-modules/doxia-module-docbook-simple/src/main/java/org/apache/maven/doxia/module/docbook/DocBookSink.java (original)
+++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-docbook-simple/src/main/java/org/apache/maven/doxia/module/docbook/DocBookSink.java Wed May 14 01:44:30 2008
@@ -1487,21 +1487,36 @@
      */
     public void anchor( String name )
     {
-        if ( !authorDateFlag )
+        if ( name == null )
         {
-            // First char of ID cannot be a digit.
-            MutableAttributeSet att = new SimpleAttributeSet();
-            att.addAttribute( Attribute.ID, HtmlTools.encodeId( name ) );
+            throw new NullPointerException( "Anchor name cannot be null!" );
+        }
 
-            // TODO: why?
-            if ( xmlMode )
-            {
-                writeSimpleTag( ANCHOR_TAG, att );
-            }
-            else
-            {
-                writeStartTag( ANCHOR_TAG, att );
-            }
+        if ( authorDateFlag )
+        {
+            return;
+        }
+
+        String id = name;
+
+        if ( !DoxiaUtils.isValidId( id ) )
+        {
+            id = DoxiaUtils.encodeId( name );
+
+            getLog().warn( "Modified invalid anchor name: " + name );
+        }
+
+        MutableAttributeSet att = new SimpleAttributeSet();
+        att.addAttribute( Attribute.ID, id );
+
+        // TODO: why?
+        if ( xmlMode )
+        {
+            writeSimpleTag( ANCHOR_TAG, att );
+        }
+        else
+        {
+            writeStartTag( ANCHOR_TAG, att );
         }
     }
 
@@ -1531,19 +1546,23 @@
      */
     public void link( String name )
     {
+        if ( name == null )
+        {
+            throw new NullPointerException( "Link name cannot be null!" );
+        }
+
         if ( DoxiaUtils.isExternalLink( name ) )
         {
             externalLinkFlag = true;
             MutableAttributeSet att = new SimpleAttributeSet();
-            att.addAttribute( URL_ATTRIBUTE, escapeSGML( name, xmlMode ) );
+            att.addAttribute( URL_ATTRIBUTE, HtmlTools.escapeHTML( name, xmlMode ) );
 
             writeStartTag( ULINK_TAG, att );
         }
         else
         {
-            // First char of ID cannot be a digit.
             MutableAttributeSet att = new SimpleAttributeSet();
-            att.addAttribute( LINKEND_ATTRIBUTE, HtmlTools.encodeId( name ) );
+            att.addAttribute( LINKEND_ATTRIBUTE, HtmlTools.escapeHTML( name ) );
 
             writeStartTag( LINK_TAG, att );
         }

Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-fml/src/main/java/org/apache/maven/doxia/module/fml/FmlParser.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-fml/src/main/java/org/apache/maven/doxia/module/fml/FmlParser.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-modules/doxia-module-fml/src/main/java/org/apache/maven/doxia/module/fml/FmlParser.java (original)
+++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-fml/src/main/java/org/apache/maven/doxia/module/fml/FmlParser.java Wed May 14 01:44:30 2008
@@ -34,6 +34,7 @@
 import org.apache.maven.doxia.parser.ParseException;
 import org.apache.maven.doxia.parser.Parser;
 import org.apache.maven.doxia.sink.Sink;
+import org.apache.maven.doxia.util.DoxiaUtils;
 import org.apache.maven.doxia.util.HtmlTools;
 
 import org.codehaus.plexus.util.StringUtils;
@@ -120,6 +121,12 @@
                 throw new XmlPullParserException( "id attribute required for <part> at: ("
                     + parser.getLineNumber() + ":" + parser.getColumnNumber() + ")" );
             }
+            else if ( !DoxiaUtils.isValidId( currentPart.getId() ) )
+            {
+                getLog().warn( "Modified invalid id: " + currentPart.getId() );
+
+                currentPart.setId( DoxiaUtils.encodeId( currentPart.getId() ) );
+            }
         }
         else if ( parser.getName().equals( Tag.TITLE.toString() ) )
         {
@@ -149,6 +156,12 @@
                 throw new XmlPullParserException( "id attribute required for <faq> at: ("
                     + parser.getLineNumber() + ":" + parser.getColumnNumber() + ")" );
             }
+            else if ( !DoxiaUtils.isValidId( currentFaq.getId() ) )
+            {
+                getLog().warn( "Modified invalid id: " + currentFaq.getId() );
+
+                currentFaq.setId( DoxiaUtils.encodeId( currentFaq.getId() ) );
+            }
         }
         if ( parser.getName().equals( QUESTION_TAG.toString() ) )
         {
@@ -180,6 +193,7 @@
 
                 buffer.append( String.valueOf( EQUAL ) ).append( String.valueOf( QUOTE ) );
 
+                // TODO: why are attribute values HTML-encoded?
                 buffer.append( HtmlTools.escapeHTML( parser.getAttributeValue( i ) ) );
 
                 buffer.append( String.valueOf( QUOTE ) );
@@ -293,6 +307,7 @@
     {
         if ( buffer != null && parser.getText() != null )
         {
+            // TODO: why are entities HTML-escaped?
             buffer.append( HtmlTools.escapeHTML( parser.getText() ) );
         }
     }
@@ -347,7 +362,7 @@
             {
                 Faq faq = (Faq) faqIterator.next();
                 sink.numberedListItem();
-                sink.link( faq.getId() );
+                sink.link( "#" + faq.getId() );
 
                 if ( StringUtils.isNotEmpty( faq.getQuestion() ) )
                 {
@@ -455,7 +470,7 @@
 
         sink.tableRow();
         sink.tableCell();
-        sink.link( "top" );
+        sink.link( "#top" );
         sink.text( "[top]" );
         sink.link_();
         sink.tableCell_();

Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoAggregateSink.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoAggregateSink.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoAggregateSink.java (original)
+++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoAggregateSink.java Wed May 14 01:44:30 2008
@@ -29,7 +29,9 @@
 import org.apache.maven.doxia.document.DocumentModel;
 import org.apache.maven.doxia.document.DocumentTOC;
 import org.apache.maven.doxia.document.DocumentTOCItem;
+import org.apache.maven.doxia.util.DoxiaUtils;
 import org.apache.maven.doxia.util.HtmlTools;
+
 import org.codehaus.plexus.util.StringUtils;
 
 /**
@@ -225,17 +227,22 @@
     /** {@inheritDoc} */
     public void anchor( String name )
     {
-        String anchor = name;
-
-        if ( anchor.startsWith( "#" ) )
+        if ( name == null )
         {
-            anchor = "#" + HtmlTools.encodeId( anchor.substring( 1 ) );
+            throw new NullPointerException( "Anchor name cannot be null!" );
         }
-        else
+
+        String anchor = name;
+
+        if ( !DoxiaUtils.isValidId( anchor ) )
         {
-            anchor = "#" + HtmlTools.encodeId( anchor );
+            anchor = DoxiaUtils.encodeId( name );
+
+            getLog().warn( "[FO Sink] Modified invalid anchor name: " + name );
         }
 
+        anchor = "#" + anchor;
+
         if ( docName != null )
         {
             anchor = docName + anchor;
@@ -248,45 +255,33 @@
     /** {@inheritDoc} */
     public void link( String name )
     {
-        if ( name.startsWith( "http" ) || name.startsWith( "mailto" )
-            || name.startsWith( "ftp" ) )
+        if ( name == null )
+        {
+            throw new NullPointerException( "Link name cannot be null!" );
+        }
+
+        if ( DoxiaUtils.isExternalLink( name ) )
         {
             // external links
             writeStartTag( BASIC_LINK_TAG, "external-destination", HtmlTools.escapeHTML( name ) );
             writeStartTag( INLINE_TAG, "href.external" );
         }
-        else if ( name.startsWith( "./" ) )
+        else if ( DoxiaUtils.isInternalLink( name ) )
         {
-            // internal, non-local link (ie anchor is not in the same source document)
-            // and link destination source document is in the same directory
-
-            String anchor = name;
+            // internal link (ie anchor is in the same source document)
 
-            int dot = anchor.indexOf( ".", 2 );
+            String anchor = name.substring( 1 );
 
-            if ( dot != -1 )
+            if ( !DoxiaUtils.isValidId( anchor ) )
             {
-                int hash = anchor.indexOf( "#", dot );
+                anchor = DoxiaUtils.encodeId( anchor );
 
-                if ( hash != -1 )
-                {
-                    int dot2 = anchor.indexOf( ".", hash );
+                getLog().warn( "[FO Sink] Modified invalid link name: " + name );
+            }
 
-                    if ( dot2 != -1 )
-                    {
-                        anchor = anchor.substring( 0, dot ) + "#"
-                            + HtmlTools.encodeId( anchor.substring( hash + 1, dot2 ) );
-                    }
-                    else
-                    {
-                        anchor = anchor.substring( 0, dot ) + "#"
-                            + HtmlTools.encodeId( anchor.substring( hash + 1, anchor.length() ) );
-                    }
-                }
-                else
-                {
-                    anchor = anchor.substring( 0, dot );
-                }
+            if ( docName != null )
+            {
+                anchor = docName + "#" + anchor;
             }
 
             writeStartTag( BASIC_LINK_TAG, "internal-destination", HtmlTools.escapeHTML( anchor ) );
@@ -294,8 +289,7 @@
         }
         else if ( name.startsWith( "../" ) )
         {
-            // internal, non-local link (ie anchor is not in the same source document)
-            // and link destination source document is in a different directory
+            // local link (ie anchor is not in the same source document)
 
             String anchor = name;
 
@@ -320,34 +314,63 @@
                 }
             }
 
-            // call again with resolved link
-            link( base + "/" + anchor );
+            anchor = base + "/" + chopExtension ( anchor );
+
+            writeStartTag( BASIC_LINK_TAG, "internal-destination", HtmlTools.escapeHTML( anchor ) );
+            writeStartTag( INLINE_TAG, "href.internal" );
         }
         else
         {
-            // internal, local link (ie anchor is in the same source document)
+            // local link (ie anchor is not in the same source document)
 
             String anchor = name;
 
-            if ( anchor.startsWith( "#" ) )
+            if ( anchor.startsWith( "./" ) )
             {
-                anchor = "#" + HtmlTools.encodeId( anchor.substring( 1 ) );
-            }
-            else
-            {
-                anchor = "#" + HtmlTools.encodeId( anchor );
+                anchor = anchor.substring( 2 );
             }
 
-            if ( docName != null )
-            {
-                anchor = docName + anchor;
-            }
+            anchor = chopExtension ( anchor );
+
+            String base = docName.substring( 0, docName.lastIndexOf( "/" ) );
+            anchor = base + "/" + anchor;
 
             writeStartTag( BASIC_LINK_TAG, "internal-destination", HtmlTools.escapeHTML( anchor ) );
             writeStartTag( INLINE_TAG, "href.internal" );
         }
     }
 
+    private  String chopExtension( String anchor )
+    {
+        int dot = anchor.indexOf( "." );
+
+        if ( dot != -1 )
+        {
+            int hash = anchor.indexOf( "#", dot );
+
+            if ( hash != -1 )
+            {
+                int dot2 = anchor.indexOf( ".", hash );
+
+                if ( dot2 != -1 )
+                {
+                    anchor = anchor.substring( 0, dot ) + "#"
+                        + HtmlTools.encodeId( anchor.substring( hash + 1, dot2 ) );
+                }
+                else
+                {
+                    anchor = anchor.substring( 0, dot ) + "#"
+                        + HtmlTools.encodeId( anchor.substring( hash + 1, anchor.length() ) );
+                }
+            }
+            else
+            {
+                anchor = anchor.substring( 0, dot );
+            }
+        }
+
+        return anchor;
+    }
 
     // ----------------------------------------------------------------------
     //

Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoSink.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoSink.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoSink.java (original)
+++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoSink.java Wed May 14 01:44:30 2008
@@ -30,6 +30,7 @@
 import org.apache.maven.doxia.sink.AbstractXmlSink;
 import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.parser.Parser;
+import org.apache.maven.doxia.util.DoxiaUtils;
 import org.apache.maven.doxia.util.HtmlTools;
 
 /**
@@ -795,17 +796,22 @@
     /** {@inheritDoc} */
     public void anchor( String name )
     {
-        String anchor = name;
-
-        if ( anchor.startsWith( "#" ) )
+        if ( name == null )
         {
-            anchor = "#" + HtmlTools.encodeId( anchor.substring( 1 ) );
+            throw new NullPointerException( "Anchor name cannot be null!" );
         }
-        else
+
+        String anchor = name;
+
+        if ( !DoxiaUtils.isValidId( anchor ) )
         {
-            anchor = "#" + HtmlTools.encodeId( anchor );
+            anchor = DoxiaUtils.encodeId( name );
+
+            getLog().warn( "[FO Sink] Modified invalid anchor name: " + name );
         }
 
+        anchor = "#" + name;
+
         writeStartTag( INLINE_TAG, "id", anchor );
     }
 
@@ -818,27 +824,37 @@
     /** {@inheritDoc} */
     public void link( String name )
     {
-        if ( name.startsWith( "http" ) || name.startsWith( "mailto" )
-            || name.startsWith( "ftp" ) )
+        if ( name == null )
+        {
+            throw new NullPointerException( "Link name cannot be null!" );
+        }
+
+        if ( DoxiaUtils.isExternalLink( name ) )
         {
             writeStartTag( BASIC_LINK_TAG, "external-destination", HtmlTools.escapeHTML( name ) );
             writeStartTag( INLINE_TAG, "href.external" );
         }
-        else
+        else if ( DoxiaUtils.isInternalLink( name ) )
         {
-            // treat everything else as internal, local (ie anchor is in the same source document)
+            String anchor = name.substring( 1 );
 
-            String anchor = name;
-
-            if ( anchor.startsWith( "#" ) )
-            {
-                anchor = "#" + HtmlTools.encodeId( anchor.substring( 1 ) );
-            }
-            else
+            if ( !DoxiaUtils.isValidId( anchor ) )
             {
-                anchor = "#" + HtmlTools.encodeId( anchor );
+                anchor = DoxiaUtils.encodeId( anchor );
+
+                getLog().warn( "[FO Sink] Modified invalid link name: " + name );
             }
 
+            anchor = "#" + anchor;
+
+            writeStartTag( BASIC_LINK_TAG, "internal-destination", HtmlTools.escapeHTML( anchor ) );
+            writeStartTag( INLINE_TAG, "href.internal" );
+        }
+        else
+        {
+            // treat everything else as is
+            String anchor = name;
+
             writeStartTag( BASIC_LINK_TAG, "internal-destination", HtmlTools.escapeHTML( anchor ) );
             writeStartTag( INLINE_TAG, "href.internal" );
         }

Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoUtils.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoUtils.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoUtils.java (original)
+++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/main/java/org/apache/maven/doxia/module/fo/FoUtils.java Wed May 14 01:44:30 2008
@@ -142,4 +142,9 @@
         return url;
     }
 
+    private FoUtils()
+    {
+        // Utility class
+    }
+
 }

Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/test/java/org/apache/maven/doxia/module/fo/FoSinkTest.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/test/java/org/apache/maven/doxia/module/fo/FoSinkTest.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/test/java/org/apache/maven/doxia/module/fo/FoSinkTest.java (original)
+++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-fo/src/test/java/org/apache/maven/doxia/module/fo/FoSinkTest.java Wed May 14 01:44:30 2008
@@ -323,7 +323,7 @@
     /** {@inheritDoc} */
     protected String getAnchorBlock( String anchor )
     {
-        // assume that anchor doesn't start with #
+        // all anchors get '#' pre-pended
         return EOL + "<fo:inline id=\"#" + anchor + "\">" + anchor + "</fo:inline>";
     }
 
@@ -331,8 +331,7 @@
     protected String getLinkBlock( String link, String text )
     {
         String attribs = getConfig().getAttributeString( "href.internal" );
-        // assume that link doesn't start with #
-        return EOL + "<fo:basic-link internal-destination=\"#" + link + "\">" + EOL + "<fo:inline"
+        return EOL + "<fo:basic-link internal-destination=\"" + link + "\">" + EOL + "<fo:inline"
             + attribs + ">" + text + "</fo:inline></fo:basic-link>";
     }
 

Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-itext/src/main/java/org/apache/maven/doxia/module/itext/ITextSink.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-itext/src/main/java/org/apache/maven/doxia/module/itext/ITextSink.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-modules/doxia-module-itext/src/main/java/org/apache/maven/doxia/module/itext/ITextSink.java (original)
+++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-itext/src/main/java/org/apache/maven/doxia/module/itext/ITextSink.java Wed May 14 01:44:30 2008
@@ -38,6 +38,7 @@
 import com.lowagie.text.BadElementException;
 import com.lowagie.text.ElementTags;
 import com.lowagie.text.Image;
+import org.apache.maven.doxia.util.DoxiaUtils;
 
 /**
  * <p>A doxia Sink which produces an XML Front End document for <code>iText</code> framework.</p>
@@ -1254,6 +1255,11 @@
     /** {@inheritDoc} */
     public void link( String name )
     {
+        if ( name == null )
+        {
+            throw new NullPointerException( "Link name cannot be null!" );
+        }
+
         font.setColor( Color.BLUE );
         font.addUnderlined();
 
@@ -1280,8 +1286,22 @@
     /** {@inheritDoc} */
     public void anchor( String name )
     {
+        if ( name == null )
+        {
+            throw new NullPointerException( "Anchor name cannot be null!" );
+        }
+
+        String id = name;
+
+        if ( !DoxiaUtils.isValidId( id ) )
+        {
+            id = DoxiaUtils.encodeId( name );
+
+            getLog().warn( "Modified invalid anchor name: " + name );
+        }
+
         writeStartElement( ElementTags.ANCHOR );
-        writeAddAttribute( ElementTags.NAME, HtmlTools.encodeId( name ) );
+        writeAddAttribute( ElementTags.NAME, id );
 
         actionContext.setAction( SinkActionContext.ANCHOR );
     }

Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocSinkTest.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/XdocSinkTest.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocSinkTest.java (original)
+++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-xdoc/src/test/java/org/apache/maven/doxia/module/xdoc/XdocSinkTest.java Wed May 14 01:44:30 2008
@@ -175,7 +175,7 @@
     /** {@inheritDoc} */
     protected String getLinkBlock( String link, String text )
     {
-        return "<a href=\"#" + link + "\">" + text + "</a>";
+        return "<a href=\"" + link + "\">" + text + "</a>";
     }
 
     /** {@inheritDoc} */

Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/java/org/apache/maven/doxia/module/xhtml/XhtmlSinkTest.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/java/org/apache/maven/doxia/module/xhtml/XhtmlSinkTest.java?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/java/org/apache/maven/doxia/module/xhtml/XhtmlSinkTest.java (original)
+++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-xhtml/src/test/java/org/apache/maven/doxia/module/xhtml/XhtmlSinkTest.java Wed May 14 01:44:30 2008
@@ -199,7 +199,7 @@
     /** {@inheritDoc} */
     protected String getLinkBlock( String link, String text )
     {
-        return "<a href=\"#" + link + "\">" + text + "</a>";
+        return "<a href=\"" + link + "\">" + text + "</a>";
     }
 
     /** {@inheritDoc} */

Modified: maven/doxia/site/src/site/apt/references/doxia-apt.apt
URL: http://svn.apache.org/viewvc/maven/doxia/site/src/site/apt/references/doxia-apt.apt?rev=656154&r1=656153&r2=656154&view=diff
==============================================================================
--- maven/doxia/site/src/site/apt/references/doxia-apt.apt (original)
+++ maven/doxia/site/src/site/apt/references/doxia-apt.apt Wed May 14 01:44:30 2008
@@ -76,8 +76,24 @@
 ** {Anchor construction}
 
   Contrary to the original APT format, an anchor/link is <<not>> its text with
-  all non alphanumeric characters stripped. Instead, all non alphanumeric
-  characters are replaced by an underscore '_', so the anchor for the section
+  all non alphanumeric characters stripped. Ideally, an anchor should be a valid
+  Doxia id, ie it must begin with a letter (\[A\-Za\-z\]) and may be
+  followed by any number of letters, digits (\[0\-9\]), hyphens ("\-"),
+  underscores ("_"), colons (":"), and periods ("."). Any anchor that does not
+  satisfy this pattern is transformed according to the following rules:
+
+    * Any whitespace at the start and end is removed
+
+    * If the first character is not a letter, prepend the letter 'a'
+
+    * Any spaces are replaced with an underscore '_'
+
+    * Any characters not matching the above pattern are replaced according
+      to the rules specified in the
+      {{{http://www.w3.org/TR/html4/appendix/notes.html#non-ascii-chars}HTML specs}}.
+
+  Note in particular that case is preserved in this conversation and that APT
+  anchors and links are case-sensitive. So the anchor for the section
   title in the previous example would be <<<Anchors_for_section_titles>>>.
 
 * {Figure extensions}



Mime
View raw message