我可以用 Nokogiri 解析 SLIM 文件吗?

Can I parse a SLIM file with Nokogiri?

我有一个 Rails 应用程序,我正在尝试实现所见即所得编辑器 (mercury),以便用户可以更新站点的静态页面。

用户可能是超级用户,或者是我希望更新我的网站的某种人。该页面类似于 index.slim.html 页面。要更新的内容是静态内容(不存储在数据库中)。

我正在使用 Mercury

要更新的内容是这样的:

      hr
        #header_content data-mercury='full'
          p.lead Ratione, quasi, enim voluptates porro voluptas quaerat recusandae reprehenderit vitae aliquid earum ex quo assumenda doloremque ea dolores maxime error suscipit exercitationem.

我将以下数据提交给 Rails 控制器:

{"content"=>{"header_content"=>{"type"=>"full", "data"=>{}, "value"=>"<p class=\"lead\">\n                  Ratione, quasi, enim voluptates porro voluptas quaerat recusandae reprehenderit vitae aliquid earum ex quo assumenda doloremque ea dolores maxime error suscipit exercitationem.\n                </p>", "snippets"=>{}}}, "_method"=>"PUT", "controller"=>"pages", "action"=>"mercury_update", "id"=>"index", "page"=>{"content"=>{"header_content"=>{"type"=>"full", "data"=>{}, "value"=>"<p class=\"lead\">\n                  Ratione, quasi, enim voluptates porro voluptas quaerat recusandae reprehenderit vitae aliquid earum ex quo assumenda doloremque ea dolores maxime error suscipit exercitationem.\n                </p>", "snippets"=>{}}}}}

或者印得更漂亮一点:

page to update:
  "index" 
path to this page:
  app/views/pages/index.html.slim

Content:
  Html ID:
    header_content
  html:
    <p class="lead">
                  Ratione, quasi, enim voluptates porro voluptas quaerat recusandae reprehenderit vitae aliquid earum ex quo assumenda doloremque ea dolores maxime error suscipit exercitationem.
                </p>

因此,ID 为 header_content<div> 需要将其内容替换为那里的 HTML。

我怎样才能让 Nokogiri 找到那个 ID,更新内容(在 Slim 中)并保存它?我是否需要对任何需要此功能的页面不使用 Slim?

这不是最好的解决方案,但它满足了我的需要:

def get_match(text, key)
  return_hash = {}
  replace_lines = []
  line_num = 0  
  indent = -1
  matched_line = -1
  last_line = text.count-1
  text.each do |line| 
    line_num += 1
    if line.include? key
      indent = line.index(/[^ ]/)
      return_hash[:matched_line] = {:line_number => line_num, :line_text => line, :leading_spaces => indent}
      after_match = text[line_num..-1]
      i = indent
      after_line_num = line_num
      after_match.each do |l|
        after_line_num +=1
        i = l.index(/[^ ]/)
        if i <= indent
            break
        else
            replace_lines.append({:line_number=> after_line_num, :line_text => l, :leading_spaces => i})
        end

      end 
      return_hash[:replace_lines] = replace_lines
      break
    end
   end
   return_hash
 end


def new_slim_page_content (old_page_content, new_content, key)
    #run first function here
    matches = get_match(old_page_content, key)

    #create two temp files... convert html 2 slim
    input_file = Tempfile.new('input')
    input_file.write(new_content)
    input_file.close
    output_file = Tempfile.new('output')
    output_file.close

    # Can I do this without using system call?
    `html2slim "#{input_file.path}" "#{output_file.path}"`

    #put output_file contents in variable and delete temp files
    output_file.open
    output = output_file.read
    input_file.unlink
    output_file.unlink

    #delete old lines
    matched_line = matches[:matched_line][:line_number] - 1 #returns line number, want index
    replace_lines = matches[:replace_lines]
    replace_lines.each do |line|
        old_page_content.delete_at(matched_line + 1) #the next index
    end

    #create new lines
    output = output.split("\n")
    initial_offset = (" " * (matches[:matched_line][:leading_spaces] +2)) 
    output.map! { |line| initial_offset + line + "\n"}
    old_page_content.insert(matched_line + 1, output).flatten!
    old_page_content = old_page_content.join
end


text = []
path_to_page = 'C:/dev/best_in_show/app/views/pages/index.html.slim'

File.open(path_to_page, 'r') do |f|
    f.each_line do |line|
        text.append(line)
    end
end

new_text =  "<p class=\"lead\">test</p>"
key = "#header_content"
new_page = new_slim_page_content(text, new_text, key)
 File.open(path_to_page, 'w') do |f|
    f.write(new_page)
 end