Есть ли простой способ преобразовать HTML с несколькими <br /> тегами в соответствующие окружающие <p> теги в Javascript?

StackOverflow https://stackoverflow.com/questions/1275250

Вопрос

Допустим, у меня есть куча HTML, как показано ниже:

bla bla bla long paragraph here
<br/>
<br/>
bla bla bla more paragraph text
<br/>
<br/>

Есть ли простой способ с помощью Javascript преобразовать его в правильную семантику <p> метки?Например.:

<p>
  bla bla bla long paragraph here
</p>
<p>
  bla bla bla more paragraph text
</p>

Интервал между выводами не важен, в идеале он будет работать с любым интервалом между вводами.

Я думаю, что мог бы попробовать состряпать регулярное выражение, но прежде чем я это сделаю, я хотел убедиться, что я а) избегаю мира обид и б) там нет ничего другого - я пытался выполнить поиск в Google, но пока ничего не придумал.

Спасибо за любой совет!

Это было полезно?

Решение

Мне стало скучно.Я уверен, что необходимы оптимизации/настройки.Использует немного jQuery, чтобы творить чудеса.Работал в ФФ3.И ответ на ваш вопрос: не существует очень «простого» способа :)

$(function() {
  $.fn.pmaker = function() {
    var brs = 0;
    var nodes = [];

    function makeP()
    {
      // only bother doing this if we have nodes to stick into a P
      if (nodes.length) {
        var p = $("<p/>");
        p.insertBefore(nodes[0]);  // insert a new P before the content
        p.append(nodes); // add the children        
        nodes = [];
      }
      brs=0;
    }

    this.contents().each(function() {    
      if (this.nodeType == 3) // text node 
      {
        // if the text has non whitespace - reset the BR counter
        if (/\S+/.test(this.data)) {
          nodes.push(this);
          brs = 0;
        }
      } else if (this.nodeType == 1) {
        if (/br/i.test(this.tagName)) {
          if (++brs == 2) {
            $(this).remove(); // remove this BR from the dom
            $(nodes.pop()).remove(); // delete the previous BR from the array and the DOM
            makeP();
          } else {
            nodes.push(this);
          }
        } else if (/^(?:p)$/i.test(this.tagName)) {
          // these tags for the P break but dont scan within
          makeP();
        } else if (/^(?:div)$/i.test(this.tagName)) {
          // force a P break and scan within
          makeP();
          $(this).pmaker();
        } else {
          brs = 0; // some other tag - reset brs.
          nodes.push(this); // add the node 
          // specific nodes to not peek inside of - inline tags
          if (!(/^(?:b|i|strong|em|span|u)$/i.test(this.tagName))) {
            $(this).pmaker(); // peek inside for P needs            
          }
        } 
      } 
    });
    while ((brs--)>0) { // remove any extra BR's at the end
      $(nodes.pop()).remove();
    }
    makeP();
    return this;
  };

  // run it against something:
  $(function(){ 
    $("#worker").pmaker();
  });

И это была часть html, которую я тестировал:

<div id="worker">
bla bla bla long <b>paragraph</b> here
<br/>
<br/>
bla bla bla more paragraph text
<br/>
<br/>
this text should end up in a P
<div class='test'>
  and so should this
  <br/>
  <br/>
  and this<br/>without breaking at the single BR
</div>
and then we have the a "buggy" clause
<p>
  fear the real P!
</p>
and a trailing br<br/>
</div>

И результат:

<div id="worker"><p>
bla bla bla long <b>paragraph</b> here
</p>
<p>
bla bla bla more paragraph text
</p>
<p>
this text should end up in a P
</p><div class="test"><p>
  and so should this
  </p>
  <p>
  and this<br/>without breaking at the single BR
</p></div><p>
and then we have the a "buggy" clause
</p><p>
  fear the real P!
</p><p>
and a trailing br</p>
</div>

Другие советы

Сканируйте каждый из дочерних элементов + текст включающего элемента.Каждый раз, когда вы сталкиваетесь с элементом «br», создайте элемент «p» и добавьте к нему все ожидающие обработки.Вспеньте, промойте, повторите.

Не забудьте удалить материал, который вы перемещаете в новый элемент «p».

я нашел эта библиотека (prototype.js) быть полезным для такого рода вещей.

Я предполагаю, что вы на самом деле не разрешаете никаких других Иногда вам нужно сохранять отдельные разрывы строк (не все <br /> элементы плохие), и вы хотите включить только двойные экземпляры <br /> в разрывы абзацев.

Поступая таким образом, я бы:

  1. Удалите все разрывы строк
  2. Оберните все это в абзац
  3. Заменить <br /><br /> с </p>\n<p>
  4. Наконец, удалите все пустые <p></p> элементы, которые могли бы быть сгенерированы

Таким образом, код мог бы выглядеть примерно так:

var ConvertToParagraphs = function(text) {
    var lineBreaksRemoved = text.replace(/\n/g, "");
    var wrappedInParagraphs = "<p>" + lineBreaksRemoved + "</p>";
    var brsRemoved = wrappedInParagraphs.replace(/<br[^>]*>[\s]*<br[^>]*>/gi, "</p>\n<p>");
    var emptyParagraphsRemoved = brsRemoved.replace(/<p><\/p>/g, "");
    return emptyParagraphsRemoved;
}

Примечание: Я был чрезвычайно подробен, чтобы показать процессы, вы бы, конечно, упростили их.

Это превращает ваш образец:

bla bla bla long paragraph here
<br/>
<br/>
bla bla bla more paragraph text
<br/>
<br/>

В:

<p>bla bla bla long paragraph here</p>
<p>bla bla bla more paragraph text</p>

Но он делает это, не удаляя никаких <br /> элементы, которые вам действительно могут понадобиться.

Я бы сделал это в несколько этапов:

  1. Регулярное выражение:Преобразуйте все br-теги в разрывы строк.
  2. Регулярное выражение:Удалите все пустое пространство.
  3. Регулярное выражение:Преобразуйте несколько разрывов строк в одиночные.
  4. Используйте Array.split(' ') для результата.

Это должно дать массив со всеми «настоящими» абзацами (теоретически). Затем вы можете просто перебрать его и обернуть каждую строку p-тегами.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top