javascript – 将PegDown JSoup输出与PageDown输出匹配

我试图在客户端和服务器端解析并清理markdown.

>在客户端,我使用PageDown作为降价编辑器.这正是StackOverflow使用的,它带有一个漂亮的预览框.此预览框显示已清理的html,因此它会删除像< div>这样的内容.标签.
>在服务器端,我使用PegDownJSoup来解析和清理降价.

但是,我发现两者的输出不一样的情况.例如:

输入降价:如何< div>标记< / div>如何治疗?

PageDown输出:< p>标签如何处理?< / p>

PegDown / JSoup输出:

<p>how are </p>tags treated?
<p></p>

我对JSoup没有任何想象力.这是我的代码:

public class Main {

    public static void main(String... args){

        PegDownProcessor pdp = new PegDownProcessor();

        String markdown = "how are <div>tags</div> treated?";

        String html = pdp.markdownToHtml(markdown);

        Whitelist whitelist = Whitelist.relaxed().removeTags("div");

        html = Jsoup.clean(html, whitelist);
        System.out.println(html);

        System.out.println("Done.");
    }
}

我理解为什么会发生这种情况,我不会惊讶于两个不同的系统会产生两种不同的输出.我的问题是:我如何设置JSoup,以便它只删除< div>标签而不是添加额外的< p>标签?

我的最终目标是简单地让服务器端解析/清理生成与客户端解析/清理相当类似的结果.如果有更好的方法,我愿意接受建议.我真的不在乎两者的输出是否完全相同,但是像extra< p>这样的东西.用户会非常注意标签,所以我试图消除这一主要差异.

额外问题:是否有PageDown可以输出的html标签和属性列表?

编辑:我也尝试过使用the OWASP sanitizer,但结果非常相似:< div>标签已删除,但< p>标签以上述方式“固定”,导致与PageDown的清洁剂不同的html.

最佳答案

how can I setup JSoup so that it simply removes the <div> tags instead of adding extra <p> tags?

HTML 5规范拒绝在p元素中使用div元素.
Jsoup尊重这些规范,这就是为什么最终的html字符串中有两个p元素.

为了更好地理解为什么会发生这种情况,让我们看看Jsoup#clean如何分三步工作:

>解析脏HTML
>调整结果树以符合HTML 5规范
>删除拒绝的标签

在步骤2中,第一个< p>标签在开始div之前关闭.第二个p也在同一步骤中获得了开始标记.由于Jsoup不知道该段的合法内容从何处开始,因此它将第二段的内容限制为严格的数量(即没有).

步骤1和2中的操作创建了满足HTML 5规范的新HTML代码.在步骤3中,现在可以删除div.

My end goal is to simply have the server-side parsing/sanitizing generate reasonably similar results to the client-side parsing/sanitizing.

为了避免像这里发现的其他情况,您应该在客户端和服务器端使用相同的系统.由于Pagedown是用Javascript编写的,因此您可以尝试在服务器端Javascript引擎中运行它.

仅举几例:

> Nashorn(内置Java 8)
>犀牛
> V8

示例代码

这是一个说明Nashorn使用的示例:

Caller.java

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval(new FileReader("script.js"));

Invocable invocable = (Invocable) engine;

Object result = invocable.invokeFunction("myFunction", "fooValue");

System.out.println(result);
System.out.println(result.getClass());

的script.js

function myFunction(foo) {
   // ...
}

也可以看看

> How to embed V8 in a Java application?
> List of HTML5 elements that can be nested inside P element?

点赞