Преобразовать обычный текстовый список в HTML - PullRequest
3 голосов
/ 20 мая 2010

У меня есть простой текстовый список, подобный этому:

I am the first top-level list item
  I am his son
  Me too
Second one here
  His son
  His daughter
    I am the son of the one above
    Me too because of the indentation
  Another one

И я хотел бы превратить это в:

<ul>
  <li>I am the first top-level list-item
    <ul>
      <li>I am his son</li>
      <li>Me too</li>
    </ul>
  </li>
  <li>Second one here
    <ul>
      <li>His son</li>
      <li>His daughter
        <ul>
          <li>I am the son of the one above</li>
          <li>Me too because of the indentation</li>
        </ul>
      </li>
      <li>Another one</li>
    </ul>
  </li>
</ul>

Как можно поступить так?

Ответы [ 5 ]

5 голосов
/ 20 мая 2010

Я никогда не использовал ruby, но обычный алгоритм остался прежним:

  1. Создайте структуру данных следующим образом:
    Node => (Text => string, Children => array of Nodes)
  2. Читать строку
  3. Проверьте, больше ли отступ, чем текущий отступ
  4. Если да, добавьте строку к дочерним элементам текущего узла и вызовите метод рекурсивно с активным узлом. Продолжайте с 2.
  5. Проверьте, равен ли отступ текущему отступу.
  6. Если да, добавьте строку к активному узлу. Продолжайте с 2.
  7. Убедитесь, что отступ меньше текущего отступа.
  8. Если да, вернитесь из метода.
  9. Повторять до EOF.

Для вывода:

1. print <ul>
2. Take the first node, print <li>node.Text
3. If there are child nodes (count of node.Children > 0) recurse to 1.
4. print </li>
5. take next node, continue from 2.
6. print </ul>
1 голос
/ 08 сентября 2011

Старая тема, но ... Похоже, я нашел способ сделать HTML-код Гленна Джекмана действительным (избегайте <ul> с дочерним <ul>).
Я использую строки с отступом табуляции.

    require 'haml'
    class String
       def text2htmllist
         tabs = -1
         topUL=true
         addme=''

         haml = self.gsub(/^([\t]*)/) do |match|
           line_tabs = match.length

           if ( line_tabs > tabs )
                if topUL
                    repl = "#{match}#{addme}%ul\n"
                    topUL=false
                else
                    repl = "#{match}#{addme}%li\n"
                    addme += "\t"
                    repl += "#{match}#{addme}%ul\n"
                end
           else
              repl = ''
              addme = addme.gsub(/^[\t]/,'') if ( line_tabs < tabs ) #remove one \t 
           end
           tabs = line_tabs
           repl << "\t#{match}#{addme}%li "

         end
         puts haml
         Haml::Engine.new(haml).render
       end
    end #String class

    str = <<FIM
    I am the first top-level list item
        I am his son
        Me too
    Second one here
        His son
        His daughter
            I am the son of the one above
            Me too because of the indentation
        Another one
    FIM

    puts str.text2htmllist

Производит:

%ul
    %li I am the first top-level list item
    %li
        %ul
            %li I am his son
            %li Me too
    %li Second one here
    %li
        %ul
            %li His son
            %li His daughter
            %li
                %ul
                    %li I am the son of the one above
                    %li Me too because of the indentation
            %li Another one
<ul>
  <li>I am the first top-level list item</li>
  <li>
    <ul>
      <li>I am his son</li>
      <li>Me too</li>
    </ul>
  </li>
  <li>Second one here</li>
  <li>
    <ul>
      <li>His son</li>
      <li>His daughter</li>
      <li>
        <ul>
          <li>I am the son of the one above</li>
          <li>Me too because of the indentation</li>
        </ul>
      </li>
      <li>Another one</li>
    </ul>
  </li>
</ul>
1 голос
/ 20 мая 2010

преобразовать ввод в Haml , а затем отобразить его как HTML

require 'haml'

def text_to_html(input)
  indent = -1
  haml = input.gsub(/^( *)/) do |match|
    line_indent = $1.length
    repl = line_indent > indent ? "#{$1}%ul\n" : ''
    indent = line_indent
    repl << "  #{$1}%li "
  end
  Haml::Engine.new(haml).render
end

puts text_to_html(<<END)
I am the first top-level list item
  I am his son
  Me too
Second one here
  His son
  His daughter
    I am the son of the one above
    Me too because of the indentation
  Another one
END

Результаты в

<ul>
  <li>I am the first top-level list item</li>
  <ul>
    <li>I am his son</li>
    <li>Me too</li>
  </ul>
  <li>Second one here</li>
  <ul>
    <li>His son</li>
    <li>His daughter</li>
    <ul>
      <li>I am the son of the one above</li>
      <li>Me too because of the indentation</li>
    </ul>
    <li>Another one</li>
  </ul>
</ul>
1 голос
/ 20 мая 2010

Этот код работает должным образом, но заголовки печатаются в новой строке.

require "rubygems"
require "builder"

def get_indent(line)
  line.to_s =~ /(\s*)(.*)/
  $1.size
end

def create_list(lines, list_indent = -1, 
       b = Builder::XmlMarkup.new(:indent => 2, :target => $stdout))
  while not lines.empty?
    line_indent = get_indent lines.first

    if line_indent == list_indent
      b.li {
        b.text! lines.shift.strip + $/
        if get_indent(lines.first) > line_indent
          create_list(lines, line_indent, b)
        end
      }
    elsif line_indent < list_indent
      break
    else
      b.ul {
        create_list(lines, line_indent, b)
      }
    end
  end
end
0 голосов
/ 20 мая 2010

Вы, вероятно, могли бы сделать это, выполнив несколько простых операций поиска и замены. Такие программы, как TextWrangler на Mac, Notepad ++ в Windows и, возможно, gedit в Linux (не уверен, насколько хорошо его находка работает со сложными вещами), могут искать новые строки и заменять их другими вещами. Начните с материала самого высокого уровня и продолжайте свой путь (начните с материала без пробелов спереди и работайте). Вам, вероятно, придется немного поэкспериментировать, чтобы получить нужные вещи. Если это то, что вы хотите делать на регулярной основе, вы, вероятно, могли бы сделать небольшой сценарий, но я сомневаюсь, что это так.

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