[英]Is it possible to parse a stylesheet with Nokogiri?
I've spent my requisite two hours Googling this, and I can not find any good answers, so let's see if humans can beat Google computers.我已经花了我必要的两个小时在谷歌上搜索这个,我找不到任何好的答案,所以让我们看看人类是否可以击败谷歌计算机。
I want to parse a stylesheet in Ruby so that I can apply those styles to elements in my document (to make the styles inlined).我想在 Ruby 中解析一个样式表,以便我可以将这些样式应用于文档中的元素(以使样式内联)。 So, I want to take something like
所以,我想采取类似
<style>
.mystyle {
color:white;
}
</style>
And be able to extract it into a Nokogiri object of some sort.并且能够将其提取为某种 Nokogiri 对象。
The Nokogiri class "CSS::Parser" (http://nokogiri.rubyforge.org/nokogiri/Nokogiri/CSS/Parser.html ) certainly has a promising name, but I can't find any documentation on what it is or how it works, so I have no idea if it can do what I'm after here. Nokogiri 类“CSS::Parser”(http://nokogiri.rubyforge.org/nokogiri/Nokogiri/CSS/Parser.html )当然有一个有前途的名字,但我找不到任何关于它是什么或如何的文档它有效,所以我不知道它是否可以做到我在这里所追求的。
My end goal is to be able to write code something like:我的最终目标是能够编写如下代码:
a_web_page = Nokogiri::HTML(html_page_as_string)
parsed_styles = Nokogiri::CSS.parse(html_page_as_string)
parsed_styles.each do |style|
existing_inlined_style = a_web_page.css(style.declaration) || ''
a_web_page.css(style.declaration)['css'] = existing_inlined_style + style.definition
end
Which would extract styles from a stylesheet and add them all as inlined styles to my document.这将从样式表中提取样式并将它们作为内联样式添加到我的文档中。
Nokogiri can't parse CSS stylesheets. Nokogiri 无法解析 CSS 样式表。
The CSS::Parser
that you came across parses CSS expressions .您遇到的
CSS::Parser
解析 CSS表达式。 It is used whenever you traverse a HTML tree by CSS selectors rather than XPath (this is a cool feature of Nokogiri).每当您通过 CSS 选择器而不是 XPath 遍历 HTML 树时,就会使用它(这是 Nokogiri 的一个很酷的功能)。
There is a Ruby CSS parser , though.不过,有一个 Ruby CSS parser 。 You can use it together with Nokogiri to achieve what you want.
您可以将它与 Nokogiri 一起使用来实现您想要的。
require "nokogiri"
require "css_parser"
html = Nokogiri::HTML(html_string)
css = CssParser::Parser.new
css.add_block!(css_string)
css.each_selector do |selector, declarations, specificity|
html.css(selector).each do |element|
style = element.attributes["style"]&.value || ""
element.set_attribute('style', [style, declarations].compact.join(" "))
end
end
@molf definitely had a great start there, but it still required debugging a handful of problems to get it working in production. @mlf 在那里肯定有一个很好的开始,但它仍然需要调试一些问题才能让它在生产中工作。 Here is the current, tested version of this:
这是当前的经过测试的版本:
html = Nokogiri::HTML(html_string)
css = CssParser::Parser.new
css.add_block!(html_string) # Warning: This line modifies the string passed into it. In potentially bad ways. Make sure the string has been duped and stored elsewhere before passing this.
css.each_selector do |selector, declarations, specificity|
next unless selector =~ /^[\d\w\s\#\.\-]*$/ # Some of the selectors given by css_parser aren't actually selectors.
begin
elements = html.css(selector)
elements.each do |match|
match["style"] = [match["style"], declarations].compact.join(" ")
end
rescue
logger.info("Couldn't parse selector '#{selector}'")
end
end
html_with_inline_styles = html.to_s
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.