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

时间:2015-04-13 14:09:55

标签: ruby-on-rails ruby nokogiri

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

用户将是超级用户,或某种我想要更新我的网站的人。该页面将类似于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为<div>的{​​{1}}需要将其内容替换为HTML。

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

1 个答案:

答案 0 :(得分:0)

它不是最好的解决方案,但它能满足我的需求:

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