Flexmark Java markdown add target attribute to link

  • Flexmark Java is a java version of Markdown conversion tool, which basically supports all Markdown syntax and has good scalability. This paper mainly adds target attribute to link through extension form
  • The extension of this article will also support Spring Properties for dynamic configuration, domain name exclusion, relative path exclusion, and custom target property values

Define the LinkTargetProperties configuration class

@Configuration
@ConfigurationProperties(prefix = "markdown.link")
public class LinkTargetProperties{
    /**
     * Exclude links to add target attribute
     */
    private List<String> excludes;
    /**
     * target Value of property
     */
    private String target = "_target";

    /**
     * Relative path exclusion
     */
    private boolean relativeExclude = true;
    
    // get and set methods omitted
}

LinkTargetAttributeProvider class that implements AttributeProvider

The extension of flexmark Java is mainly modified through the implementation of AttributeProvider

public class LinkTargetAttributeProvider implements AttributeProvider {
    // Data for getting configuration
    private final DataHolder dataHolder;
    // Absolute path regular matching
    private final Pattern pattern = Pattern.compile("^[a-zA-z]+://[^\\s]*");

    public LinkTargetAttributeProvider(DataHolder dataHolder) {
        this.dataHolder = dataHolder;
    }

    @Override
    public void setAttributes(@NotNull Node node, @NotNull AttributablePart part, @NotNull Attributes attributes) {
        // Link only 
        if (node instanceof Link && part == AttributablePart.LINK) {

            // Get href Tags
            Attribute hrefAttr = attributes.get("href");
            if (hrefAttr == null) {
                return;
            }
            // Value cannot be empty
            String href = hrefAttr.getValue();
            if (StringUtils.isEmpty(href)) {
                return;
            }
            
            // Get configuration parameters
            // Note that dependency injection of Spring Boot cannot be used directly here
            // But it can be obtained in the form of applicationcontext.getbean
            LinkTargetProperties dataKey = FlexmarkExtensions.LINK_TARGET.get(this.dataHolder);
            
            // Determine whether it is an absolute path
            if (!pattern.matcher(href).matches()) {
                if (dataKey.isRelativeExclude()) {
                    // Exclude if relative path
                    return;
                }
            } else {
                
                // Get domain name / host
                Optional<String> host = ServletUtil.getHost(href);
                if (host.isEmpty()) {
                    return;
                }
                List<String> excludes = dataKey.getExcludes();
                if (excludes != null && !excludes.isEmpty()) {
                    
                    // Exclude if current host is included
                    if (excludes.contains(host.get())) {
                        return;
                    }
                }
            }
            String target = dataKey.getTarget();
            if (StringUtils.isEmpty(target)) {
                target = "";
            }
            // Set target property
            attributes.replaceValue("target", target);
        }
    }

    static AttributeProviderFactory factory() {
        return new IndependentAttributeProviderFactory() {
            @Override
            public @NotNull AttributeProvider apply(@NotNull LinkResolverContext linkResolverContext) {
                // Get dataHolder here
                return new LinkTargetAttributeProvider(linkResolverContext.getOptions());
            }
        };
    }
}

Configuration parameters can also be obtained through dataholder.get (datakey) in the version. Now, it is not recommended to use it. Here, it is recommended to use the form of linkResolverContext.getOptions()

Register Provider

The custom Provider needs to be registered through HtmlRenderer.Builder.attributeProviderFactory to use

public class LinkTargetExtensions implements HtmlRenderer.HtmlRendererExtension {
    // Define configuration parameters
    // And set the default value
    public static final DataKey<LinkTargetProperties> LINK_TARGET = new DataKey<>("LINK_TARGET", new LinkTargetProperties());
    @Override
    public void rendererOptions(@NotNull MutableDataHolder mutableDataHolder) {

    }

    @Override
    public void extend(HtmlRenderer.@NotNull Builder builder, @NotNull String s) {
        builder.attributeProviderFactory(LinkTargetAttributeProvider.factory());
    }

    public static LinkTargetExtensions create() {
        return new LinkTargetExtensions();
    }
}

Markdown tool class

public class MarkdownUtil{
    private static final MutableDataSet OPTIONS = new MutableDataSet(
        PegdownOptionsAdapter.flexmarkOptions(
            true,
            // All features
            Extensions.ALL,
            // Custom Link Target extension
            LinkTargetExtensions.create()
        ))
        .set(HtmlRenderer.SOFT_BREAK, "<br/>");
    
    // Resolver
    private static final Parser PARSER = Parser.builder(OPTIONS).build();

    // Renderer 
    private static final HtmlRenderer htmlRender = HtmlRenderer.builder(OPTIONS).build();
    
     /**
     * Render Markdown 
     * @param markdown File
     * @param JDK8 Of the Consumer for dynamically changing the configuration parameters of LinkTargetAttributeProvider
     * @return html
     */
    public static String renderHtml(String markdown, Consumer<Document> accept) {
        if (Util.isEmpty(markdown)) {
            return "";
        }
        Document document = PARSER.parse(markdown);
        if (accept != null) {
            accept.accept(document);
        }
        return htmlRender.render(document);
    }
}

Use example

public class TestMarkdownRender(){
    public static void main(String[] args) {
        String markdown = "[Test 1](http://www.itlangzi.com/test1 'test 1') [test 2](/test2 'test 2') [test 3](https://www.google.com/test3 'test 3') ";

        System.out.println(MarkdownUtil.renderHtml(markdown, doc -> {
            doc.set(LinkTargetExtensions.LINK_TARGET, new LinkTargetProperties(
                // Domain name to filter
                Arrays.asList("www.itlangzi.com","www.baidu.com"), 
                // Value of target property
                "_target", 
                // Exclude relative paths
                true
            ));
        }));
    }
}

Result

It's not easy to build bricks. Pay more attention

Original link IT prodigal blog > flexmark Java markdown add target attribute to link

Keywords: Programming Java Attribute Spring Google

Added by mcccy005 on Sat, 02 May 2020 22:44:19 +0300