Нокогири CSS нормализация - PullRequest
2 голосов
/ 14 ноября 2011

У меня есть некоторые атрибуты, такие как:

<span style="font:22px Arial">...</span>

и другие, такие как:

<span style="font-size:22px;font-family:Arial">...</span>

Теперь я могу получить атрибут стиля с помощью nokogiri, но мне нужна следующая информация:

  • семейство шрифтов
  • размер шрифта
  • цвет
  • текст-отделка
  • начертание шрифта
  • стиль шрифта

Некоторые атрибуты, такие как цвет, легко получить, но некоторые другие, такие как размер шрифта, требуют некоторой обработки строки css.

Прежде чем копаться в моем собственном решении, мне было интересно, сможет ли nokogiri или, возможно, специализированный гем css нормализовать строку css и позволить мне запросить атрибуты css по одному. Было бы еще удобнее, если бы я мог получить вычисленный CSS (например, элемент без размера шрифта внутри элемента с размером шрифта 10 дал бы мне 10, когда я спрашиваю размер шрифта для дочернего элемента) , но эту последнюю часть легко реализовать с помощью хеша и стека, так что это не очень важно.

Ответы [ 3 ]

1 голос
/ 14 ноября 2011

Нет, Nokogiri не имеет таких возможностей для этого. Вам нужен эквивалент JavaScript getComputedStyle(), реализованный в Ruby, для которого потребуется библиотека Ruby, которая знает, как анализировать HTML и CSS, и применять правила CSS к документу HTML.

Редактировать : Вы можете попробовать использовать JRuby вместе с Celerity для браузера без головы.

1 голос
/ 14 ноября 2011

Хм. Парсер JavaScript DOM мог бы сделать это красиво, но я не знаю, сможет ли Ruby. css_parser gem может быть отправной точкой, но я не знаю, может ли он обрабатывать встроенные стили ...

И, конечно же, встроенные стили, подобные этим, являются злом, отчасти потому, что их трудно нормализовать. Замените на таблицу стилей как можно скорее, если это ваша собственная разметка.

0 голосов
/ 08 декабря 2011

Попробовав много разных вещей, я закончил писать свое собственное решение с нуля.

Для дальнейшего использования вот как я это сделал:

  • используйте Nokogiri's doc.traverse чтобы просмотреть документ
  • каждый раз, когда я сталкиваюсь с текстовым узлом, я делаю что-то вроде parents = []; parent = node.parent; while parent do parents << parent; parent = parent.parent; end; result << {:text => node.text, :parents => parents}
  • наконец, для каждого фрагмента текста в моем массиве результатов, я переключаю родителейвручную анализируйте каждый узел, задавая стиль один за другим, например, шрифт font-size:

        css = node[:style]
        if not style[:font_size] # style is a hash applied to each text chunk, the first encountered parent that define it wins
            if node.name == 'font' and node[:size]
                style[:font_size] = node[:size].to_i * 5
            elsif css =~ /font-size:[^;\d]*(\d*)/
                style[:font_size] = $1.to_i
            elsif css =~ /font:[^;\d]*(\d*)/
                style[:font_size] = $1.to_i
            end
        end
    

Не было действительно сложно обработать все случаи браузера, простопринял системный подход.Окончательная реализация для font-size примерно в 5 раз длиннее (для обработки единиц ...).К сожалению, я не могу выпустить полный исходный код.Но я надеюсь, что это ответит на вопрос тех, кто приземлится на него.

...