Соответствие вывода PegDown+JSoup выходу PageDown

Я пытаюсь проанализировать и очистить уценку на стороне клиента и сервера.

  • На стороне клиента я использую PageDown в качестве редактора уценки. Это именно то, что использует Stackru, и поставляется с отличным окном предварительного просмотра. В этом окне предварительного просмотра отображается очищенный HTML, поэтому он удаляет такие вещи, как <div> теги.

  • На стороне сервера я использую PegDown и JSoup для анализа и очистки уценки.

Тем не менее, я нахожу случаи, когда результаты этих двух не совпадают. Например:

Входная уценка: how are <div>tags</div> treated?

Вывод страницы: <p>how are tags treated?</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> теги?

Моя конечная цель состоит в том, чтобы просто выполнить синтаксический анализ / очистку на стороне сервера, чтобы получить достаточно похожие результаты с синтаксическим анализом / очисткой на стороне клиента. Если есть лучшие способы сделать это, я открыт для предложений. Мне действительно все равно, если результаты этих двух точно совпадают, но такие вещи, как дополнительные <p> теги будут очень заметны для пользователей, поэтому я пытаюсь устранить это главное отличие.

Дополнительный вопрос: есть ли список HTML-тегов и атрибутов, которые PageDown может выводить?

Изменить: я также пытался использовать дезинфицирующее средство OWASP, но я получаю очень похожие результаты: <div> теги удалены, но <p> теги "исправлены" описанным выше способом, что приводит к тому, что HTML отличается от дезинфицирующего средства PageDown.

1 ответ

Решение

как настроить JSoup так, чтобы он просто удалял теги

вместо добавления дополнительных тегов

?

Спецификации HTML 5 запрещают использование div элемент внутри p элемент. Jsoup соблюдает эти спецификации, поэтому есть два p элементы в окончательной HTML-строке.

Чтобы лучше понять, почему это происходит, давайте посмотрим, как Jsoup#clean работает в три этапа:

  1. Разбор грязного HTML
  2. Настройте результирующее дерево в соответствии со спецификациями HTML 5
  3. Удалить запрещенные теги

На шаге 2 первый <p> тег закрывается непосредственно перед открытием div, Второй p на этом же шаге тоже получает свой открывающий тег. Поскольку Jsoup не знает, где начинается законное содержание этого абзаца, он ограничивает содержание второго абзаца строгой суммой (то есть ничем).

Действия в шагах 1 и 2 создают новый HTML-код, удовлетворяющий спецификациям HTML 5. На шаге 3 div теперь можно удалить.

Моя конечная цель состоит в том, чтобы просто выполнить синтаксический анализ / очистку на стороне сервера, чтобы получить достаточно похожие результаты с синтаксическим анализом / очисткой на стороне клиента.

Чтобы избежать других случаев, подобных тому, который был обнаружен здесь, вы должны использовать одну и ту же систему как на стороне клиента, так и на стороне сервера. Поскольку Pagedown написан на Javascript, вы можете попробовать запустить его внутри серверного движка Javascript.

Назвать несколько:

  • Нашорн (встроенная 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) {
   // ...
}

СМОТРИТЕ ТАКЖЕ

Другие вопросы по тегам