All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vladsch.flexmark.formatter.internal.MergeLinkResolver Maven / Gradle / Ivy

There is a newer version: 0.50.50
Show newest version
package com.vladsch.flexmark.formatter.internal;

import com.vladsch.flexmark.ast.Image;
import com.vladsch.flexmark.ast.Link;
import com.vladsch.flexmark.ast.Reference;
import com.vladsch.flexmark.formatter.Formatter;
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.ResolvedLink;
import com.vladsch.flexmark.util.Utils;
import com.vladsch.flexmark.util.ast.Document;
import com.vladsch.flexmark.util.ast.Node;

import java.util.Set;

public class MergeLinkResolver implements LinkResolver {
    private final String docRelativeURL;
    private final String docRootURL;
    private final String[] relativeParts;

    public MergeLinkResolver(LinkResolverContext context) {
        // can use context for custom settings
        // context.getDocument();
        // context.getHtmlOptions();
        String docRelativeURL = Formatter.DOC_RELATIVE_URL.getFrom(context.getOptions());
        if (docRelativeURL != null) {
            docRelativeURL = Utils.removeStart(docRelativeURL, '/');
        }

        String docRootURL = Formatter.DOC_ROOT_URL.getFrom(context.getOptions());
        if (docRootURL != null) {
            docRootURL = Utils.removeStart(docRootURL, '/');
        }

        this.docRelativeURL = docRelativeURL;
        this.docRootURL = docRootURL;
        relativeParts = docRelativeURL.split("/");
    }

    @Override
    public ResolvedLink resolveLink(Node node, LinkResolverContext context, ResolvedLink link) {
        Document document = node.getDocument();

        if (node instanceof Image || node instanceof Link || node instanceof Reference) {
            // resolve link
            String url = link.getUrl();

            if (docRelativeURL.isEmpty() && docRootURL.isEmpty()) {
                // resolve url, return one of LinkStatus other than LinkStatus.UNKNOWN
                return link.withStatus(LinkStatus.VALID)
                        .withUrl(url);
            }

            if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("ftp://") || url.startsWith("sftp://")) {
                // resolve url, return one of LinkStatus other than LinkStatus.UNKNOWN
                return link.withStatus(LinkStatus.VALID)
                        .withUrl(url);
            } else if (url.startsWith("file:/")) {
                // assume it is good
                return link.withStatus(LinkStatus.VALID)
                        .withUrl(url);
            } else if (url.startsWith("/")) {
                if (docRootURL != null && !docRootURL.isEmpty()) {
                    // this one is root url, prefix with merged root url, without the trailing /
                    url = (!docRootURL.startsWith("/") ? "/" : "") + docRootURL + url;

                    return link.withStatus(LinkStatus.VALID)
                            .withUrl(url);
                }
            } else if (!url.matches("^(?:[a-z]+:|#|\\?)")) {
                // relative, we will process it as a relative path to the docRelativeURL
                String pageRef = url;
                String suffix = "";
                int pos = url.indexOf('#');
                if (pos == 0) {
                    return link.withStatus(LinkStatus.VALID);
                } else {
                    if (pos > 0) {
                        // remove anchor
                        suffix = url.substring(pos);
                        pageRef = url.substring(0, pos);
                    } else if (url.contains("?")) {
                        // remove query
                        suffix = url.substring(pos);
                        pageRef = url.substring(0, pos);
                    }

                    String[] pathParts = pageRef.split("/");
                    int docParts = relativeParts.length;
                    int iMax = pathParts.length;
                    StringBuilder resolved = new StringBuilder();
                    String sep = "";

                    for (int i = 0; i < iMax; i++) {
                        String part = pathParts[i];
                        if (part.equals(".")) {
                            // skp
                        } else if (part.equals("..")) {
                            // remove one doc part
                            if (docParts == 0) return link;
                            docParts--;
                        } else {
                            resolved.append(sep);
                            resolved.append(part);
                            sep = "/";
                        }
                    }

                    // prefix with remaining docParts
                    StringBuilder resolvedURL = new StringBuilder();

                    sep = docRelativeURL.startsWith("/") ? "/" : "";

                    iMax = docParts;
                    for (int i = 0; i < iMax; i++) {
                        resolvedURL.append(sep);
                        resolvedURL.append(relativeParts[i]);
                        sep = "/";
                    }

                    resolvedURL.append('/').append(resolved).append(suffix);
                    return link.withStatus(LinkStatus.VALID)
                            .withUrl(resolvedURL.toString());
                }
            }
        }
        return link;
    }

    public static class Factory implements LinkResolverFactory {
        @Override
        public Set> getAfterDependents() {
            return null;
        }

        @Override
        public Set> getBeforeDependents() {
            return null;
        }

        @Override
        public boolean affectsGlobalScope() {
            return false;
        }

        @Override
        public LinkResolver apply(LinkResolverContext context) {
            return new MergeLinkResolver(context);
        }
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy