How to extend NokoGiri or Taka in a similar but simpler fashion?

64 views
Skip to first unread message

Kristian Mandrup

unread,
May 1, 2010, 6:20:09 PM5/1/10
to taka-talk
I would like to extend Taka in a similar way as Taka extends Nokogiri

doc = Page::Model::HTML(File.open 'fixtures/test.html')

# iterate and execute an extension method 'my_method' on each element
for using the css selector!
doc.css('*').each do |elem|
puts elem.my_method
end

# my_extension.rb
module MyExtension
def my_method
"hello world!"
end
end

---
I'm trying to copy a simplified version of the Taka setup. I am
thinking something like the following would work?

I only need the extension to apply on tag elements (which can have css
style sapplied), such as XML::Element.

require 'my_extension'

module Page
module Model
class << self
def XML *args
doc = Nokogiri::XML(*args)
doc.extend(MyExtension
doc
end

def HTML *args
doc = Nokogiri::HTML(*args)
doc.extend(MyExtension)
doc.extend(Module.new {
def decorate(node)
node = super
node.extend(MyExtension
node
end
})
doc
end
end
end
end

Aaron Patterson

unread,
May 1, 2010, 7:02:05 PM5/1/10
to taka...@googlegroups.com
On Sat, May 1, 2010 at 3:20 PM, Kristian Mandrup <kman...@gmail.com> wrote:
> I would like to extend Taka in a similar way as Taka extends Nokogiri
>
> doc = Page::Model::HTML(File.open 'fixtures/test.html')
>
> # iterate and execute an extension method 'my_method' on each element
> for using the css selector!
> doc.css('*').each do |elem|
>  puts elem.my_method
> end
>
> # my_extension.rb
> module MyExtension
>  def my_method
>    "hello world!"
>  end
> end
>
> ---
> I'm trying to copy a simplified version of the Taka setup. I am
> thinking something like the following would work?
>
> I only need the extension to apply on tag elements (which can have css
> style sapplied), such as XML::Element.

Take a look at the decorators method on Nokogiri::XML::Document. I
can't remember the exact syntax off the top of my head, but you should
be able to do something like this:

module MyDecorator
...
end

doc = get_a_document_somehow()
doc.decorators[Nokogiri::XML::Element] << MyDecorator

And MyDecorator will be applied to all XML::Element tags.

--
Aaron Patterson
http://tenderlovemaking.com/

Kristian Mandrup

unread,
May 1, 2010, 9:11:39 PM5/1/10
to taka-talk
Perfect!

doc.decorators(Nokogiri::XML::Element) << CSS::Element
doc.decorate!

describe "HtmlCssDecorator" do
it "works" do
doc = Nokogiri::HTML(File.open 'fixtures/test.html')
doc = CSS::Model.apply_to(doc, :css_path => File.dirname(__FILE__)
+ "/fixtures/")

doc.css('*').each do |elem|
puts show(elem) if elem.declarations
end
end
end

def show(elem)
s = ""
return s if !elem.declarations
elem.declarations.each do |decl|
s += decl[1].to_s
end
s
end

--

I now have access to precisely the CSS styles that would apply in the
browser for each HTML element.
The stylesheets referenced by the HTML doc are loaded, parsed and the
styles merged using the specificity calculations as given by W3C.
Sweet!!!


On May 1, 7:02 pm, Aaron Patterson <aaron.patter...@gmail.com> wrote:
Reply all
Reply to author
Forward
0 new messages