Javascript обрезает текст HTML

Есть ли у JavaScript способ обрезания HTML-текста без всех головных болей совпадающих меток и т.д.?

Спасибо.

Ответ 1

Там нет встроенного javascript. Там плагин jQuery, на который вы можете взглянуть.

Ответ 2

У меня была такая же проблема, и я закончил писать следующее, чтобы справиться с этим. Он обрезает HTML до длины, очищает любые теги начала и конца, которые, возможно, были отключены в конце, а затем закрывает все теги, оставшиеся незакрытыми:

function truncateHTML(text, length) {
    var truncated = text.substring(0, length);
    // Remove line breaks and surrounding whitespace
    truncated = truncated.replace(/(\r\n|\n|\r)/gm,"").trim();
    // If the text ends with an incomplete start tag, trim it off
    truncated = truncated.replace(/<(\w*)(?:(?:\s\w+(?:={0,1}(["']{0,1})\w*\2{0,1})))*$/g, '');
    // If the text ends with a truncated end tag, fix it.
    var truncatedEndTagExpr = /<\/((?:\w*))$/g;
    var truncatedEndTagMatch = truncatedEndTagExpr.exec(truncated);
    if (truncatedEndTagMatch != null) {
        var truncatedEndTag = truncatedEndTagMatch[1];
        // Check to see if there an identifiable tag in the end tag
        if (truncatedEndTag.length > 0) {
            // If so, find the start tag, and close it
            var startTagExpr = new RegExp(
                "<(" + truncatedEndTag + "\\w?)(?:(?:\\s\\w+(?:=([\"\'])\\w*\\2)))*>");
            var testString = truncated;
            var startTagMatch = startTagExpr.exec(testString);

            var startTag = null;
            while (startTagMatch != null) {
                startTag = startTagMatch[1];
                testString = testString.replace(startTagExpr, '');
                startTagMatch = startTagExpr.exec(testString);
            }
            if (startTag != null) {
                truncated = truncated.replace(truncatedEndTagExpr, '</' + startTag + '>');
            }
        } else {
            // Otherwise, cull off the broken end tag
            truncated = truncated.replace(truncatedEndTagExpr, '');
        }
    }
    // Now the tricky part. Reverse the text, and look for opening tags. For each opening tag,
    //  check to see that he closing tag before it is for that tag. If not, append a closing tag.
    var testString = reverseHtml(truncated);
    var reverseTagOpenExpr = /<(?:(["'])\w*\1=\w+ )*(\w*)>/;
    var tagMatch = reverseTagOpenExpr.exec(testString);
    while (tagMatch != null) {
        var tag = tagMatch[0];
        var tagName = tagMatch[2];
        var startPos = tagMatch.index;
        var endPos = startPos + tag.length;
        var fragment = testString.substring(0, endPos);
        // Test to see if an end tag is found in the fragment. If not, append one to the end
        //  of the truncated HTML, thus closing the last unclosed tag
        if (!new RegExp("<" + tagName + "\/>").test(fragment)) {
            truncated += '</' + reverseHtml(tagName) + '>';
        }
        // Get rid of the already tested fragment
        testString = testString.replace(fragment, '');
        // Get another tag to test
        tagMatch = reverseTagOpenExpr.exec(testString);
    }
    return truncated;
}

function reverseHtml(str) {
    var ph = String.fromCharCode(206);
    var result = str.split('').reverse().join('');
    while (result.indexOf('<') > -1) {
        result = result.replace('<',ph);
    }
    while (result.indexOf('>') > -1) {
        result = result.replace('>', '<');
    }
    while (result.indexOf(ph) > -1) {
        result = result.replace(ph, '>');
    }
    return result;
}

Ответ 3

Я знаю, что этот вопрос старый, но у меня недавно была такая же проблема. Я написал следующую библиотеку, которая безопасно обрезает действительный HTML: https://github.com/arendjr/text-clipper

Ответ 4

Там плагин mootools, который делает именно то, что вам нужно: mooReadAll в mouools forge

Ответ 5

Недавно я закончил функцию jQuery, чтобы сделать это, используя ширину и высоту контейнера. Протестируйте его и посмотрите, работает ли он для вас. Я еще не уверен в проблемах совместимости, ошибках или ограничениях, но я тестировал их в FF, Chrome и IE7.

Ответ 6

Если вам нужно более легкое решение в vanilla JS, это должно сработать, хотя в нем останутся пустые элементы, поэтому все зависит от того, заботитесь ли вы о них. Также обратите внимание, что он мутирует узлы на месте.

function truncateNode(node, limit) {
  if (node.nodeType === Node.TEXT_NODE) {
    node.textContent = node.textContent.substring(0, limit);
    return limit - node.textContent.length;
  }

  node.childNodes.forEach((child) => {
    limit = truncateNode(child, limit);
  });

  return limit;
}
const span = document.createElement('span');
span.innerHTML = '<b>foo</b><i>bar</i><u>baz</u>';
truncateNode(span, 5);
expect(span.outerHTML).toEqual('<span><b>foo</b><i>ba</i><u></u></span>');

Ответ 7

Я просмотрел интернет, ища ответ на этот вопрос сам, и в конце концов решил, что мне лучше просто написать функцию для выполнения усечения (в отличие от импорта библиотеки для этого. Мой пример использования был довольно узким ( усекая текст до определенного количества символов, я также удостоверяюсь, что эллипсы вставлены в конец ближайшего слова в эту позицию:

function truncate(str){
  if (str.length > 150){
    var pos = 125,  // truncate at 125 chars
    // Search for the word end.
        right = str.slice(pos).search(/\s/);         
        return '<div class="newString">' + str.substring(0, pos + right)+'<span style="display:inline;"class="read-more">... more</span>';
   }
   else{
     return str;     
   }
}