java.lang.runtimeexception 不能获取链接_flexmark-java markdown给链接添加target属性

❝ flexmark-java 是 java 版的 Markdown 转换工具,基本支持 Markdown 所有的语法,而且扩展性也不错;本文主要是通过扩展形式给链接添加 target 属性本文的扩展还将支持 Spring Properties 来动态配置, 支持域名排除、支持相对路径排除、支持自定义 target 属性的值. ❞

定义Properties配置类 LinkTargetProperties

@Configuration@ConfigurationProperties(prefix = "markdown.link")public class LinkTargetProperties{    /**     * 排除添加 target 属性的链接     */    private List excludes;    /**     * target 属性的值     */    private String target = "_target";    /**     * 相对路径排除     */    private boolean relativeExclude = true;        // get 和 set 方法省略}

实现 AttributeProvider的类 LinkTargetAttributeProvider

扩展 flexmark-java 主要是通过实现 AttributeProvider 进行修改

public class LinkTargetAttributeProvider implements AttributeProvider {    // 用于获取配置的数据    private final DataHolder dataHolder;    // 绝对路径正则匹配    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         if (node instanceof Link && part == AttributablePart.LINK) {            // 获取 href 标签            Attribute hrefAttr = attributes.get("href");            if (hrefAttr == null) {                return;            }            // 值也不能为空            String href = hrefAttr.getValue();            if (StringUtils.isEmpty(href)) {                return;            }                        // 获取配置参数            // 注意此处不能直接使用 Spring Boot 的依赖注入            // 但可以使用ApplicatonContext.getBean的形式获取            LinkTargetProperties dataKey = FlexmarkExtensions.LINK_TARGET.get(this.dataHolder);                        // 判断是否是绝对路径            if (!pattern.matcher(href).matches()) {                if (dataKey.isRelativeExclude()) {                    // 如果是相对路径,则排除                    return;                }            } else {                                // 获取域名/host                Optional host = ServletUtil.getHost(href);                if (host.isEmpty()) {                    return;                }                List excludes = dataKey.getExcludes();                if (excludes != null && !excludes.isEmpty()) {                                        // 如果包含当前的host则排除                    if (excludes.contains(host.get())) {                        return;                    }                }            }            String target = dataKey.getTarget();            if (StringUtils.isEmpty(target)) {                target = "";            }            // 设置target 属性            attributes.replaceValue("target", target);        }    }    static AttributeProviderFactory factory() {        return new IndependentAttributeProviderFactory() {            @Override            public @NotNull AttributeProvider apply(@NotNull LinkResolverContext linkResolverContext) {                // 在此处获取dataHolder                return new LinkTargetAttributeProvider(linkResolverContext.getOptions());            }        };    }}

在旧版本中也可以通过 DataHoler.get(DataKey) 获取配置参数,现在已经不推荐使用了,这里推荐使用 linkResolverContext.getOptions()的形式

注册 Provider

自定义的Provider需要通过 HtmlRenderer.Builder.attributeProviderFactory 的方式注册才能使用

public class LinkTargetExtensions implements HtmlRenderer.HtmlRendererExtension {    // 定义配置参数    // 并设置默认值    public static final DataKey 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 工具类

public class MarkdownUtil{    private static final MutableDataSet OPTIONS = new MutableDataSet(        PegdownOptionsAdapter.flexmarkOptions(            true,            // 所有的特性            Extensions.ALL,            // 自定义的 Link Target 扩展            LinkTargetExtensions.create()        ))        .set(HtmlRenderer.SOFT_BREAK, "
"); // 解析器 private static final Parser PARSER = Parser.builder(OPTIONS).build(); // 渲染器 private static final HtmlRenderer htmlRender = HtmlRenderer.builder(OPTIONS).build(); /** * 渲染 Markdown * @param markdown 文档 * @param JDK8的Consumer的,用于动态改变 LinkTargetAttributeProvider的配置参数 * @return html */ public static String renderHtml(String markdown, Consumer accept) { if (Util.isEmpty(markdown)) { return ""; } Document document = PARSER.parse(markdown); if (accept != null) { accept.accept(document); } return htmlRender.render(document); }}

使用示例

public class TestMarkdownRender(){    public static void main(String[] args) {        String markdown = "[测试1](http://www.itlangzi.com/test1 '测试1') [测试2](/test2 '测试2') [测试3](https://www.google.com/test3 '测试3')";        System.out.println(MarkdownUtil.renderHtml(markdown, doc -> {            doc.set(LinkTargetExtensions.LINK_TARGET, new LinkTargetProperties(                // 需要过滤的域名                Arrays.asList("www.itlangzi.com","www.baidu.com"),                 // target 属性的值                "_target",                 // 排除相对路径                true            ));        }));    }}

结果

83800ecc126ce8b3a25ec6d17f80e02a.png

「码砖不易,多多关注」

原文链接 IT浪子の博客 > flexmark-java markdown给链接添加target属性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值