001/*
002 * JDrupes MDoclet
003 * Copyright (C) 2017, 2021  Michael N. Lipp
004 * 
005 * This program is free software; you can redistribute it and/or modify it 
006 * under the terms of the GNU Affero General Public License as published by 
007 * the Free Software Foundation; either version 3 of the License, or 
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful, but 
011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
013 * for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License along 
016 * with this program; if not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jdrupes.mdoclet.processors.flexmark;
020
021import org.jetbrains.annotations.NotNull;
022
023import com.vladsch.flexmark.ast.Link;
024import com.vladsch.flexmark.html.AttributeProvider;
025import com.vladsch.flexmark.html.HtmlRenderer;
026import com.vladsch.flexmark.html.HtmlRenderer.Builder;
027import com.vladsch.flexmark.html.IndependentAttributeProviderFactory;
028import com.vladsch.flexmark.html.renderer.AttributablePart;
029import com.vladsch.flexmark.html.renderer.LinkResolverContext;
030import com.vladsch.flexmark.util.ast.Node;
031import com.vladsch.flexmark.util.data.MutableDataHolder;
032import com.vladsch.flexmark.util.html.MutableAttributes;
033import com.vladsch.flexmark.util.misc.Extension;
034
035/**
036 * Provides an extension that adds "`target='_top'`" to all anchor links.
037 */
038public class TopAnchorLinkExtension
039        implements HtmlRenderer.HtmlRendererExtension {
040
041    /**
042     * Called with all options. Currently this extension supports no options and
043     * does nothing.
044     */
045    @Override
046    public void rendererOptions(MutableDataHolder options) {
047        // Currently no options supported.
048    }
049
050    /**
051     * This method is called once when the builder for the output is created.
052     * It must modify the passed in builder as required by the extension.  
053     */
054    @Override
055    public void extend(Builder rendererBuilder, String rendererType) {
056        rendererBuilder.attributeProviderFactory(
057            new IndependentAttributeProviderFactory() {
058
059                @Override
060                public @NotNull AttributeProvider
061                        apply(@NotNull LinkResolverContext context) {
062                    return new AttributeProvider() {
063
064                        @Override
065                        public void setAttributes(@NotNull Node node,
066                                @NotNull AttributablePart part,
067                                @NotNull MutableAttributes attributes) {
068                            if (node instanceof Link
069                                && part == AttributablePart.LINK) {
070                                attributes.replaceValue("target", "_top");
071                            }
072                        }
073
074                    };
075                }
076            });
077    }
078
079    /**
080     * Extensions are added by providing a class to flexmark. Flexmark then
081     * invokes the extension's static `create` method through reflection.
082     * 
083     * @return an instance of the extension
084     */
085    public static Extension create() {
086        return new TopAnchorLinkExtension();
087    }
088}