001package org.apache.maven.doxia.module.markdown;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.util.HashSet;
023import java.util.Set;
024import java.util.regex.Matcher;
025import java.util.regex.Pattern;
026
027import com.vladsch.flexmark.ext.wikilink.internal.WikiLinkLinkResolver;
028import com.vladsch.flexmark.html.IndependentLinkResolverFactory;
029import com.vladsch.flexmark.html.LinkResolver;
030import com.vladsch.flexmark.html.LinkResolverFactory;
031import com.vladsch.flexmark.html.renderer.LinkResolverContext;
032import com.vladsch.flexmark.html.renderer.LinkStatus;
033import com.vladsch.flexmark.html.renderer.LinkType;
034import com.vladsch.flexmark.html.renderer.ResolvedLink;
035import com.vladsch.flexmark.util.ast.Node;
036
037/**
038 * The FlexmarkDoxiaLinkResolver rewrites the md, markdown links to html.
039 *
040 * Sample links it rewrites:
041 * - doc.md to doc.html
042 * - doc.markdown to doc.html
043 * - doc.md#anchor to doc.html#anchor
044 * - doc.markdown#anchor to doc.html#anchor
045 * - ../doc.markdown#anchor to ../doc.html#anchor
046 * - :doc.md to :doc.html
047 * - :doc.markdown to :doc.html
048 *
049 * Sample links it leaves untouched:
050 * - http://doc.md
051 * - https://doc.markdown
052 * - doc.md.badformat
053 * - doc.md#bad#format
054 * - doc.md#bad.format
055 */
056public class FlexmarkDoxiaLinkResolver implements LinkResolver
057{
058    final Pattern pattern;
059
060    /**
061     * <p>Constructor for FlexmarkDoxiaLinkResolver.</p>
062     *
063     * @param context a {@link com.vladsch.flexmark.html.renderer.LinkResolverContext} object.
064     */
065    public FlexmarkDoxiaLinkResolver( LinkResolverContext context )
066    {
067        this.pattern = Pattern.compile(
068                            "^(?![^:]+:)((?:\\./)?(?:\\.\\./)*[^\\.]+).(?:"
069                          + MarkdownParserModule.FILE_EXTENSION
070                          + "|"
071                          + MarkdownParserModule.ALTERNATE_FILE_EXTENSION
072                          + ")(#[^#\\.]*){0,1}$"
073                        );
074    }
075
076    /** {@inheritDoc} */
077    @Override
078    public ResolvedLink resolveLink( Node node, LinkResolverContext context, ResolvedLink link )
079    {
080        if ( link.getLinkType() == LinkType.LINK )
081        {
082            Matcher matcher = this.pattern.matcher( link.getUrl() );
083            if ( matcher.matches() )
084            {
085                return link.withStatus( LinkStatus.VALID ).withUrl( matcher.replaceAll( "$1.html$2" ) );
086            }
087        }
088
089        return link;
090    }
091
092    /**
093     * Factory that creates FlexmarkDoxiaLinkResolver objects.
094     */
095    public static class Factory extends IndependentLinkResolverFactory
096    {
097        @Override
098        public Set<Class<? extends LinkResolverFactory>> getBeforeDependents()
099        {
100            Set<Class<? extends LinkResolverFactory>> set = new HashSet<>();
101            set.add( WikiLinkLinkResolver.Factory.class );
102            return set;
103        }
104
105        @Override
106            public LinkResolver create( LinkResolverContext context )
107        {
108            return new FlexmarkDoxiaLinkResolver( context );
109        }
110    }
111}