Можно ли проанализировать таблицу стилей с помощью Nokogiri? - PullRequest
9 голосов
/ 31 мая 2010

Я потратил необходимые два часа на поиски в Google, и не могу найти хороших ответов, поэтому давайте посмотрим, смогут ли люди побить компьютеры Google.

Я хочу проанализировать таблицу стилей в Ruby, чтобы я мог применить эти стили к элементам в моем документе (чтобы сделать стили встроенными). Итак, я хочу взять что-то вроде

<style>
.mystyle {
  color:white;
}
</style>

И иметь возможность извлечь его в какой-нибудь объект Нокогири.

Класс Nokogiri "CSS :: Parser" (http://nokogiri.rubyforge.org/nokogiri/Nokogiri/CSS/Parser.html), безусловно, имеет многообещающее имя, но я не могу найти никакой документации о том, что это такое или как это работает, поэтому я понятия не имею, может ли это делай то, что я после здесь.

Моя конечная цель - написать что-то вроде:

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

Что позволило бы извлечь стили из таблицы стилей и добавить их все как встроенные стили в мой документ.

Ответы [ 2 ]

15 голосов
/ 31 мая 2010

Nokogiri не может разобрать таблицы стилей CSS.

CSS::Parser, с которым вы столкнулись, разбирает CSS выражения . Он используется всякий раз, когда вы пересекаете дерево HTML с помощью селекторов CSS, а не XPath (это классная функция из Nokogiri).

Существует Ruby CSS-парсер . Вы можете использовать его вместе с 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|
  element = html.css(selector)
  element["style"] = [element["style"], declarations].compact.join(" ")
end
3 голосов
/ 07 июня 2010

@ molf определенно отлично начал там, но все еще требовалось отладить несколько проблем, чтобы заставить его работать в производстве. Вот текущая, проверенная версия этого:

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 
...