[DOXIA-584] Rewrite .md and .markdown links to .html

[DOXIA-584] Rewrite .md and .markdown links to .html

[DOXIA-584] Reimplemented as regexp

[DOXIA-584] Added test for link rewrite at MarkdownParser level

[DOXIA-584] Cleaned up some checkstyle issues

[DOXIA-584] Corrected ortographical error

fixed formatting issues (no Checkstyle for tests but still useful)
diff --git a/doxia-modules/doxia-module-markdown/pom.xml b/doxia-modules/doxia-module-markdown/pom.xml
index d3f6488..d138b91 100644
--- a/doxia-modules/doxia-module-markdown/pom.xml
+++ b/doxia-modules/doxia-module-markdown/pom.xml
@@ -59,7 +59,7 @@
     <dependency>
       <groupId>com.vladsch.flexmark</groupId>
       <artifactId>flexmark-all</artifactId>
-      <version>0.18.4</version>
+      <version>0.40.12</version>
     </dependency>
     <dependency>
       <groupId>org.apache.maven.doxia</groupId>
diff --git a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/FlexmarkDoxiaLinkResolver.java b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/FlexmarkDoxiaLinkResolver.java
new file mode 100644
index 0000000..10810af
--- /dev/null
+++ b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/FlexmarkDoxiaLinkResolver.java
@@ -0,0 +1,104 @@
+package org.apache.maven.doxia.module.markdown;
+
+/*
+ * 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.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.vladsch.flexmark.ext.wikilink.internal.WikiLinkLinkResolver;
+import com.vladsch.flexmark.html.IndependentLinkResolverFactory;
+import com.vladsch.flexmark.html.LinkResolver;
+import com.vladsch.flexmark.html.LinkResolverFactory;
+import com.vladsch.flexmark.html.renderer.LinkResolverContext;
+import com.vladsch.flexmark.html.renderer.LinkStatus;
+import com.vladsch.flexmark.html.renderer.LinkType;
+import com.vladsch.flexmark.html.renderer.ResolvedLink;
+import com.vladsch.flexmark.util.ast.Node;
+
+/**
+ * The FlexmarkDoxiaLinkResolver rewrites the md, markdown links to html.
+ *
+ * Sample links it rewrites:
+ * - doc.md -> doc.html
+ * - doc.markdown -> doc.html
+ * - doc.md#anchor -> doc.html#anchor
+ * - doc.markdown#anchor -> doc.html#anchor
+ * - :doc.md -> :doc.html
+ * - :doc.markdown -> :doc.html
+ *
+ * Sample links it leaves untouched:
+ * - http://doc.md
+ * - https://doc.markdown
+ * - doc.md.badformat
+ * - doc.md#bad#format
+ * - doc.md#bad.format
+ */
+public class FlexmarkDoxiaLinkResolver implements LinkResolver
+{
+    final Pattern pattern;
+
+    public FlexmarkDoxiaLinkResolver( LinkResolverContext context )
+    {
+        this.pattern = Pattern.compile(
+                            "^(?![^:]+:)([^\\.]+).(?:"
+                          + MarkdownParserModule.FILE_EXTENSION
+                          + "|"
+                          + MarkdownParserModule.ALTERNATE_FILE_EXTENSION
+                          + ")(#[^#\\.]*){0,1}$"
+                        );
+    }
+
+    @Override
+    public ResolvedLink resolveLink( Node node, LinkResolverContext context, ResolvedLink link )
+    {
+        if ( link.getLinkType() == LinkType.LINK )
+        {
+            Matcher matcher = this.pattern.matcher( link.getUrl() );
+            if ( matcher.matches() )
+            {
+                return link.withStatus( LinkStatus.VALID ).withUrl( matcher.replaceAll( "$1.html$2" ) );
+            }
+        }
+
+        return link;
+    }
+
+    /**
+     * Factory that creates FlexmarkDoxiaLinkResolver objects.
+     */
+    public static class Factory extends IndependentLinkResolverFactory
+    {
+        @Override
+        public Set<Class<? extends LinkResolverFactory>> getBeforeDependents()
+        {
+            Set<Class<? extends LinkResolverFactory>> set = new HashSet<Class<? extends LinkResolverFactory>>();
+            set.add( WikiLinkLinkResolver.Factory.class );
+            return set;
+        }
+
+        @Override
+            public LinkResolver create( LinkResolverContext context )
+        {
+            return new FlexmarkDoxiaLinkResolver( context );
+        }
+    }
+}
diff --git a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownParser.java b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownParser.java
index bb264fe..fa1454f 100644
--- a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownParser.java
+++ b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownParser.java
@@ -22,7 +22,7 @@
 import com.vladsch.flexmark.Extension;
 import com.vladsch.flexmark.ast.Heading;
 import com.vladsch.flexmark.ast.HtmlCommentBlock;
-import com.vladsch.flexmark.ast.Node;
+import com.vladsch.flexmark.util.ast.Node;
 import com.vladsch.flexmark.ast.util.TextCollectingVisitor;
 import com.vladsch.flexmark.html.HtmlRenderer;
 import com.vladsch.flexmark.profiles.pegdown.Extensions;
@@ -144,7 +144,10 @@
 
         com.vladsch.flexmark.parser.Parser parser = com.vladsch.flexmark.parser.Parser.builder( flexmarkOptions )
                 .build();
-        HtmlRenderer renderer = HtmlRenderer.builder( flexmarkOptions ).build();
+        HtmlRenderer renderer = HtmlRenderer.builder( flexmarkOptions )
+                                    .linkResolverFactory( new FlexmarkDoxiaLinkResolver.Factory() )
+                                    .build();
+
 
         StringBuilder html = new StringBuilder( 1000 );
         html.append( "<html>" );
diff --git a/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/FlexmarkDoxiaLinkResolverTest.java b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/FlexmarkDoxiaLinkResolverTest.java
new file mode 100644
index 0000000..126151a
--- /dev/null
+++ b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/FlexmarkDoxiaLinkResolverTest.java
@@ -0,0 +1,94 @@
+package org.apache.maven.doxia.module.markdown;
+
+/*
+ * 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 com.vladsch.flexmark.html.renderer.LinkStatus;
+import com.vladsch.flexmark.html.renderer.LinkType;
+import com.vladsch.flexmark.html.renderer.ResolvedLink;
+import junit.framework.TestCase;
+
+public class FlexmarkDoxiaLinkResolverTest
+    extends TestCase
+{
+
+    public void testResolveLink()
+    {
+        FlexmarkDoxiaLinkResolver flexmarkDoxiaLinkResolver = new FlexmarkDoxiaLinkResolver( null );
+
+        checkLinkRewritten( flexmarkDoxiaLinkResolver, "doc.md", "doc.html" );
+        checkLinkRewritten( flexmarkDoxiaLinkResolver, "doc.markdown", "doc.html" );
+
+        checkLinkRewritten( flexmarkDoxiaLinkResolver, "doc.md#anchor", "doc.html#anchor" );
+        checkLinkRewritten( flexmarkDoxiaLinkResolver, "doc.markdown#anchor", "doc.html#anchor" );
+
+        // these edge cases are still allowed
+        checkLinkRewritten( flexmarkDoxiaLinkResolver, ":doc.md", ":doc.html" );
+        checkLinkRewritten( flexmarkDoxiaLinkResolver, ":doc.markdown", ":doc.html" );
+
+        checkLinkRewritten( flexmarkDoxiaLinkResolver, ":doc.md#anchor", ":doc.html#anchor" );
+        checkLinkRewritten( flexmarkDoxiaLinkResolver, ":doc.markdown#anchor", ":doc.html#anchor" );
+
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "doc.md", LinkType.LINK_REF );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "doc.md", LinkType.IMAGE );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "doc.md", LinkType.IMAGE_REF );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "doc.markdown", LinkType.LINK_REF );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "doc.markdown", LinkType.IMAGE );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "doc.markdown", LinkType.IMAGE_REF );
+
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "http://doc.md", LinkType.LINK );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "https://doc.md", LinkType.LINK );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "ftp://doc.md", LinkType.LINK );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "http://doc.markdown", LinkType.LINK );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "https://doc.markdown", LinkType.LINK );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "ftp://doc.markdown", LinkType.LINK );
+
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "docs.md.badformat", LinkType.LINK );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "docs.markdown.badformat", LinkType.LINK );
+
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "docs.md#bad#format", LinkType.LINK );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "docs.md#bad.format", LinkType.LINK );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "docs.md.bad#format", LinkType.LINK );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "docs.markdown#bad#format", LinkType.LINK );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "docs.markdown#bad.format", LinkType.LINK );
+        checkLinkLeftUnchanged( flexmarkDoxiaLinkResolver, "docs.markdown.bad#format", LinkType.LINK );
+    }
+
+    private static void checkLinkLeftUnchanged( FlexmarkDoxiaLinkResolver flexmarkDoxiaLinkResolver, String url,
+                                                LinkType linkType )
+    {
+        ResolvedLink originalLink = new ResolvedLink( linkType, url );
+        ResolvedLink rewrittenLink = flexmarkDoxiaLinkResolver.resolveLink( null, null, originalLink );
+
+        assertEquals( originalLink.getLinkType(), rewrittenLink.getLinkType() );
+        assertEquals( originalLink.getUrl(), rewrittenLink.getUrl() );
+        assertEquals( originalLink.getStatus(), rewrittenLink.getStatus() );
+    }
+
+    private static void checkLinkRewritten( FlexmarkDoxiaLinkResolver flexmarkDoxiaLinkResolver, String originalUrl,
+                                            String expectedUrl )
+    {
+        ResolvedLink originalLink = new ResolvedLink( LinkType.LINK, originalUrl );
+        ResolvedLink rewrittenLink = flexmarkDoxiaLinkResolver.resolveLink( null, null, originalLink );
+
+        assertEquals( originalLink.getLinkType(), rewrittenLink.getLinkType() );
+        assertEquals( expectedUrl, rewrittenLink.getUrl() );
+        assertEquals( LinkStatus.VALID, rewrittenLink.getStatus() );
+    }
+}
diff --git a/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
index e1b2016..2f99bc9 100644
--- a/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
+++ b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
@@ -2,6 +2,7 @@
 
 import java.io.Reader;
 import java.util.Iterator;
+import java.util.List;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -164,7 +165,27 @@
 
         assertFalse( it.hasNext() );
     }
-    
+
+    /**
+     * Assert the link sink event is fired when parsing "link.md".
+     *
+     * @throws Exception if the event list is not correct when parsing the document.
+     */
+    public void testLinkRewriteSinkEvent()
+        throws Exception
+    {
+        List<SinkEventElement> eventList = parseFileToEventTestingSink( "link_rewrite" ).getEventList();
+
+        Iterator<SinkEventElement> it = eventList.iterator();
+        assertEquals( it, "head", "head_", "body", "paragraph", "text", "link", "text", "link_", "text", "link", "text",
+                      "link_", "text", "paragraph_", "body_" );
+
+        assertFalse( it.hasNext() );
+
+        assertEquals( "doc.html", eventList.get( 5 ).getArgs()[0] );
+        assertEquals( "ftp://doc.md", eventList.get( 9 ).getArgs()[0] );
+    }
+
     public void testLinkWithAnchorAndQuery() throws Exception
     {
         Iterator<SinkEventElement> it = parseFileToEventTestingSink( "link_anchor_query" ).getEventList().iterator();
diff --git a/doxia-modules/doxia-module-markdown/src/test/resources/link_rewrite.md b/doxia-modules/doxia-module-markdown/src/test/resources/link_rewrite.md
new file mode 100644
index 0000000..464860a
--- /dev/null
+++ b/doxia-modules/doxia-module-markdown/src/test/resources/link_rewrite.md
@@ -0,0 +1,3 @@
+This is a [link to be rewritten](doc.md).
+This is a [link to be left untouched](ftp://doc.md).
+