- 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