我可以用 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
我有一个 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