Подтвердить что ты не робот

Интерпретировать новые строки, как и s в уценке (стиль Github Markdown) в Ruby

Я использую markdown для комментариев на своем сайте, и хочу, чтобы пользователи могли создавать разрывы строк, нажимая enter вместо space space enter (см. этот мета-вопрос для более подробной информации об этой идее)

Как я могу это сделать в Ruby? Вы могли бы подумать, что Github Flavored Markdown будет именно тем, что мне нужно, но (удивительно), это довольно плохо.

Здесь их реализация:

# in very clear cases, let newlines become <br /> tags
text.gsub!(/^[\w\<][^\n]*\n+/) do |x|
  x =~ /\n{2}/ ? x : (x.strip!; x << "  \n")
end

Эта логика требует, чтобы строка начиналась с \w для строки в конце для создания <br>. Причина этого требования заключается в том, что вы не должны возиться со списками: (Но см. Приведенное ниже изменение, я даже не уверен, что это имеет смысл)

* we don't want a <br>
* between these two list items

Однако в этих случаях логика ломается:

[some](http://google.com)
[links](http://google.com)
*this line is in italics*
another line
> the start of a blockquote!
another line

I.e., во всех этих случаях в конце первой строки должен быть <br>, и все же GFM не добавляет один

Как ни странно, это корректно работает в javascript версии GFM.

Есть ли у кого-нибудь работающая реализация "новых строк в <br> s" в Ruby?

Изменить: он становится еще более запутанным!

Если вы проверите Gitub официальный репозиторий Github Flavored Markdown, вы найдете еще одну новую строку в <br> regex!:

# in very clear cases, let newlines become <br /> tags
text.gsub!(/(\A|^$\n)(^\w[^\n]*\n)(^\w[^\n]*$)+/m) do |x|
  x.gsub(/^(.+)$/, "\\1  ")
end

Я не знаю, что означает это регулярное выражение, но в вышеприведенных тестовых случаях оно не улучшается.

Кроме того,, это не похоже на оправдание "не возиться со списками", требующее, чтобы строки начинались со словных символов, для начала. I.e., стандартная семантика списка разметки не изменяется независимо от того, добавили ли вы 2 конечных пробела. Здесь:

  • item 1
  • item 2
  • item 3

В источнике этого вопроса есть два конечных пробела после "item 1", и все же, если вы посмотрите на HTML, нет лишнего <br>

Это заставляет меня думать, что лучшее регулярное выражение для преобразования строк в строку <br> справедливо:

text.gsub!(/^[^\n]+\n+/) do |x|
  x =~ /\n{2}/ ? x : (x.strip!; x << "  \n")
end

Мысли?

4b9b3361

Ответ 1

Я не уверен, поможет ли это, но я просто использую simple_format() из ActionView:: Helpers:: TextHelper

ActionView simple_format

my_text = "Here is some basic text...\n...with a line break."

simple_format(my_text)

output => "<p>Here is some basic text...\n<br />...with a line break.</p>"

Даже если это не соответствует вашим спецификациям, посмотрите на исходный код simple_format().gsub! методы могут помочь вам написать собственную версию требуемой уценки.

Ответ 2

Немного поздно, но, возможно, полезно для других людей. Я получил его на работу (но не полностью протестировал), предварительно обработав текст, используя регулярные выражения, например. Это отвратительно в результате отсутствия нулевой ширины lookbehinds, но хорошо.

# Append two spaces to a simple line, if it ends in newline, to render the
# markdown properly. Note: do not do this for lists, instead insert two newlines. Also, leave double newlines
# alone.
text.gsub! /^ ([\*\+\-]\s+|\d+\s+)? (.+?) (\ \ )? \r?\n (\r?\n|[\*\+\-]\s+|\d+\s+)? /xi do
  full, pre, line, spaces, post = $~.to_a
  if post != "\n" && pre.blank? && post.blank? && spaces.blank?
    "#{pre}#{line}  \n#{post}"
  elsif pre.present? || post.present?
    "#{pre}#{line}\n\n#{post}"
  else
    full
  end
end