[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).
+