JS, HTML. Google prettify. Как динамически вставить предварительно проверенный HTML-код в contenteditable div на html-странице

Я пишу мессенджер, и моя цель - добавить возможность вставлять код и выделять его, как это делается в переполнении стека. Я использую библиотеку prettify от Google. Вот часть HTML:

<div id="test" style="margin-left: auto; margin-right: auto; overflow-y: scroll;" contenteditable="true"
                 placeholder="Type your message" name="message" ng-model="message">
            </div>

и функция js:

$scope.pasteHtmlAtCaret = function () {
            document.getElementById('test').focus();
            var sel, range;
            if (window.getSelection) {
                // IE9 and non-IE
                sel = window.getSelection();
                if (sel.getRangeAt && sel.rangeCount) {
                    range = sel.getRangeAt(0);

                    // Range.createContextualFragment() would be useful here but is
                    // only relatively recently standardized and is not supported in
                    // some browsers (IE9, for one)
                    var el = document.createElement("div");
                    //var el = document.getElementById('test');

                    /*var text = sel.toString().replace(/</g, "&lt;");
                    text = text.replace(/>/g, "&gt;");
                    text = text.replace(/&/g, "&amp;");*/

                    el.innerHTML = "<pre class=prettyprint linenums><code>" + sel.toString() + '</code></pre></br>';

                    range.deleteContents();

                    var frag = document.createDocumentFragment(), node, lastNode;
                    while ((node = el.firstChild)) {
                        lastNode = frag.appendChild(node);
                    }
                    var firstNode = frag.firstChild;
                    range.insertNode(frag);
                    prettyPrint();
                    // Preserve the selection
                    if (lastNode) {
                        range = range.cloneRange();
                        range.setStartAfter(lastNode);
                        range.setStartBefore(firstNode);

                        sel.removeAllRanges();
                        sel.addRange(range);
                    }
                }
            } else if ((sel = document.selection) && sel.type != "Control") {
                var originalRange = sel.createRange();
                originalRange.collapse(true);
                sel.createRange().pasteHTML(html);

                range = sel.createRange();
                range.setEndPoint("StartToStart", originalRange);
                range.select();
            }
        }

Как видите, я уже пытался разместить &lt; (в комментариях) и другие символы вместо символов <,>, &. Однако они отображаются в виде кода js, а не как символы. Не могли бы вы сказать мне, пожалуйста, как я могу вставить предварительно подтвержденный HTML-код в мой блок div (или, возможно, другой контейнер).

Возможно, вы могли бы также сказать мне, как сделать prettify показывать номера строк, потому что они не показаны прямо сейчас (они воспринимаются как другой класс как-то)

1 ответ

Решение

Afaict, вы создаете <pre class=prettyprint>, но библиотека prettify никогда не вызывается.

Я думаю, что вы можете просто использовать PR.prettyPrintOne и передайте исходный код HTML. Вы правы, что вы должны бежать &, <, а также > во-первых, поскольку он принимает HTML, а не простой исходный код.

PR.prettyPrintOne доступно при загрузке <script src=".../prettify.js"></script> но не при загрузке <script src=".../run_prettify.js"></script>,


/*var text = sel.toString().replace(/</g, "&lt;");
text = text.replace(/>/g, "&gt;");
text = text.replace(/&/g, "&amp;");*/

Здесь есть ошибка. Вы должны сделать .replace(/&/g, "&amp;") во-первых, потому что

"<".replace(/</g, "&lt;").replace(/&/g, "&amp;") === "&amp;lt;"

в то время как

"<".replace(/&/g, "&amp;").replace(/</g, "&lt;") === "&lt;"

Замена порядка имеет значение, когда некоторые из строк замещения также соответствуют шаблонам:)

function htmlEscape(s) {
  return (String(s).replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;"));
}
Другие вопросы по тегам