lib/craft.rb in craft-0.0.1 vs lib/craft.rb in craft-0.0.2

- old
+ new

@@ -1,5 +1,91 @@ -require "craft/version" +require 'craft/version' +require 'nokogiri' -module Craft - # Your code goes here... +# Craft objects out of HTML and XML. +# +# Examples +# +# module Transformations +# IntegerTransform = lambda { |n| Integer n.text } +# end +# +# class Person < Craft +# include Transformations +# +# one :name, 'div.name' +# one :age, 'div.age', IntegerTransform +# many :friends, 'li.friend', Person +# end +# +class Craft + class << self + # We alias call to new so that crafted objects may nest themselves or other + # crafted objects as transformations. + alias call new + + # Define a method that extracts a collection of values from a parsed + # document. + # + # name - The Symbol name of the method. + # paths - One or more String XPath of CSS queries. An optional Proc + # transformation on the extracted value may be appended. If none is + # appended, the default transformation returns the stripped String + # value of the node. + # + # Returns an Array. + def many(name, *paths) + transform = pop_transformation paths + + define_method name do + @node.search(*paths).map { |node| transform.call node } + end + end + + # Define a method that extracts a single value from a parsed document. + # + # name - The Symbol name of the method. + # paths - One or more String XPath of CSS queries. An optional Proc + # transformation on the extracted value may be appended. If none is + # appended, the default transformation returns the stripped String + # value of the node. + # + # Returns an Object. + def one(name, *paths) + transform = pop_transformation paths + + define_method name do + transform.call @node.at(*paths) + end + end + + # Parse a document. + # + # body - A String HTML or XML document. + # + # Returns an instance of its self. + def parse(body) + new Nokogiri body + end + + private + + def pop_transformation(array) + if array.last.respond_to? :call + array.pop + else + Module.new do + def self.call(node) + node.text.strip if node + end + end + end + end + end + + # Craft a new object. + # + # node - A Nokogiri::XML::Node. + def initialize(node) + @node = node + end end