Обрезка строк HTML без разрыва тегов HTML - PullRequest
7 голосов
/ 06 мая 2009

Как написать функцию, которая может вырезать строку с тегами HTML в строку N-длины, не нарушая теги HTML при этом.

Возвращаемая строка не должна содержать ровно N символов. Он может обрезать его до или после тега, который находится на краю N-длинной строки.

Visit <a href="www.htz.hr">Croatia</a> this summer.

CutIt(9) должен вернуться

Visit

или

Visit <a href="www.htz.hr">Croatia</a>

Ответы [ 7 ]

5 голосов
/ 03 марта 2016
function trimHtml(html, options) {

    options = options || {};

    var limit = options.limit || 100,
        preserveTags = (typeof options.preserveTags !== 'undefined') ? options.preserveTags : true,
        wordBreak = (typeof options.wordBreak !== 'undefined') ? options.wordBreak : false,
        suffix = options.suffix || '...',
        moreLink = options.moreLink || '';

    var arr = html.replace(/</g, "\n<")
        .replace(/>/g, ">\n")
        .replace(/\n\n/g, "\n")
        .replace(/^\n/g, "")
        .replace(/\n$/g, "")
        .split("\n");

    var sum = 0,
        row, cut, add,
        tagMatch,
        tagName,
        tagStack = [],
        more = false;

    for (var i = 0; i < arr.length; i++) {

        row = arr[i];
        // count multiple spaces as one character
        rowCut = row.replace(/[ ]+/g, ' ');

        if (!row.length) {
            continue;
        }

        if (row[0] !== "<") {

            if (sum >= limit) {
                row = "";
            } else if ((sum + rowCut.length) >= limit) {

                cut = limit - sum;

                if (row[cut - 1] === ' ') {
                    while(cut){
                        cut -= 1;
                        if(row[cut - 1] !== ' '){
                            break;
                        }
                    }
                } else {

                    add = row.substring(cut).split('').indexOf(' ');

                    // break on halh of word
                    if(!wordBreak) {
                        if (add !== -1) {
                            cut += add;
                        } else {
                            cut = row.length;
                        }
                    }
                }

                row = row.substring(0, cut) + suffix;

                if (moreLink) {
                    row += '<a href="' + moreLink + '" style="display:inline">»</a>';
                }

                sum = limit;
                more = true;
            } else {
                sum += rowCut.length;
            }
        } else if (!preserveTags) {
            row = '';
        } else if (sum >= limit) {

            tagMatch = row.match(/[a-zA-Z]+/);
            tagName = tagMatch ? tagMatch[0] : '';

            if (tagName) {
                if (row.substring(0, 2) !== '</') {

                    tagStack.push(tagName);
                    row = '';
                } else {

                    while (tagStack[tagStack.length - 1] !== tagName && tagStack.length) {
                        tagStack.pop();
                    }

                    if (tagStack.length) {
                        row = '';
                    }

                    tagStack.pop();
                }
            } else {
                row = '';
            }
        }

        arr[i] = row;
    }

    return {
        html: arr.join("\n").replace(/\n/g, ""),
        more: more
    };
}

if (typeof module !== 'undefined' && module.exports) {
    module.exports = trimHtml;
}


использование

var html = '<div><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p><p>Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. </p><p>Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. </p><p>Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.</p></div>';
var trim = trimHtml(html, { limit: 200 });


// **returns object**


{
   html: '<div><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
   sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p><p>Ut
   enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut...
   </p></div>',
   more: true // indicates if limit is reached
}

ПРИМЕР РАБОТЫ

2 голосов
/ 07 мая 2009

Я решил проблему, поэтому вот код в C #;

static string CutIt(string s, int limit)
{
    if (s.Length < limit) return s;

    int okIndex = 0;
    bool inClosingTag = false;
    int numOpenTags = 0;

    for (int i = 0; i < limit; i++)
    {
        if (s[i]=='<')
        {
            if (s[i+1]=='/')
            {
                inClosingTag = true;    
            }
            else
            {
                numOpenTags++;   
            }
        }
        if (s[i]=='>')
        {
            if (s[i-1]=='/')
            {
                numOpenTags--;
            }
            if (inClosingTag)
            {
                numOpenTags--;
            }
        }

        if (numOpenTags == 0) okIndex = i;

    }
    return s.Substring(0, okIndex + 1);
}
1 голос
/ 06 мая 2009
static string CutIt(string s, int limit)
{
  s = s.Substring(0, limit);
  int openMark = s.LastIndexOf('<');
  if (openMark != -1)
  {
    int closeMark = s.LastIndexOf('>');
    if (openMark > closeMark)
    {
      s = s.Substring(0, openMark);
    }
  }
  return s.Trim();
}

public static void Main()
{
  Console.WriteLine(
    CutIt("Visit <a href=\"www.htz.hr\">Croatia</a> this summer.", 9)
  ); // prints "Visit"
}
1 голос
/ 06 мая 2009

Это может быть излишним, но попробуйте поискать AWK , он может делать такие вещи довольно легко, поскольку сосредоточен вокруг обработки текста.

Вы также можете написать собственный скрипт разбора, например

string s = "Visit <a href="www.htz.hr">Croatia</a> this summer."

result = ""

slice_limit = 9

i= 0

j = 0

in_tag = false

while i < slice_limit and j < s.size do

  if s[j] == "<" then in_tag = true

  if in_tag and s[i]==">" then in_tag = false

  if !in_tag then i++

  result += s[j]

end

... или что-то в этом роде (не проверял, но это дает вам идею).

РЕДАКТИРОВАТЬ : Вам также нужно будет добавить что-то, чтобы определить, закрыт тег или нет (просто добавьте флаг, такой как in_tag, и смешайте его с некоторым регулярным выражением, и оно должно работать) Надеюсь, что это поможет

РЕДАКТИРОВАТЬ2 : если вы указали язык, который хотите использовать, это может быть полезно. JavaScript?

0 голосов
/ 19 августа 2014

Вот решение JavaScript: trimHtml

0 голосов
/ 06 мая 2009

В javascript вы можете использовать свойство textContent элементов DOM для получения этого.

HTML

<p id='mytext'>Hey <a href="#">Visit Croatia</a> today</p>

Javascript

var el = document.getElementById("mytext");
console.log( el.textContent );
//alert( el.textContent ); // if you don't have firebug.
0 голосов
/ 06 мая 2009

Когда я столкнулся с такой проблемой (для RSS-канала), я просто вызвал strip_tags перед тем, как вырезать мою строку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...