module Golf module Filter class Upcase def self.transform(data) data.upcase end end end class Compiler require 'find' attr_accessor :golfpath def initialize(golfpath = '.') self.golfpath = "#{golfpath}/golfapp" puts "golf #{Golf::VERSION}: starting compiler in #{@golfpath}..." puts "golf #{Golf::VERSION}: is valid golfapp?: #{Golf::Compiler.valid?(@golfpath)}" puts "golf #{Golf::VERSION}: loading filters in #{golfpath}/filters" Dir["#{golfpath}/filters/*.rb"].each do |path| require path end end def self.valid?(dir) File.exists?("#{dir}/golfapp/components") end def generate_componentsjs "jQuery.golf.components=#{component_json};;jQuery.golf.res=#{res_json};;jQuery.golf.plugins=#{plugin_json};;jQuery.golf.scripts=#{script_json};;jQuery.golf.styles=#{style_json};;jQuery.golf.setupComponents();" end def component_json traverse_components end def res_json JSON.dump(compile_res(@golfpath)) end # compile_res: This function creates a hash representation of # the file structure relative to . The values are either # hashes (for directories) or strings (for files). The string # values are the path to the file relative to @golfpath. # # Example: compile_res("#{@golfpath}/dir1") # # @golfpath/ # |--dir1/ # | |--file1 # | |--file2 # | +--dir2/ # | |--file3 # | |--file4 # | +--dir3/ # | |--file5 # | +--file6 # +--dir4/ # # { # file1 => "dir1/file1", # file2 => "dir1/file2", # dir2 => { # file3 => "dir1/dir2/file3", # file4 => "dir1/dir2/file4" # dir3 => { # file5 => "dir1/dir2/dir3/file5", # file6 => "dir1/dir2/dir3/file6" # } # } # } # def compile_res(dir) results = {} mypath = dir.split('').last == "/" ? dir : dir+"/" myroot = @golfpath.split('').last == "/" ? @golfpath : @golfpath+"/" if File.exists?(mypath) Find.find(mypath) do |path| e = path.slice(mypath.length, path.length-mypath.length) r = path.slice(myroot.length, path.length-myroot.length) f = URI.escape(e) g = File.basename(e) h = File.dirname(r) == "." ? [] : File.dirname(r).split("/") if FileTest.directory?(path) next else r2 = results h.each { |i| if ! r2[i] r2[i] = {} end r2 = r2[i] } r2[g] = f end end end results end def plugin_json traverse("#{@golfpath}/plugins", "js") end def script_json traverse("#{@golfpath}/scripts", "js") end def style_json traverse("#{@golfpath}/styles", "css") end def traverse_components results = {} Dir["#{@golfpath}/components/**/*"].each do |path| name = package_name(path) valid_arr = path_valid_for_filtering?(path) next if FileTest.directory?(path) or !path.include?('.html') or path.include?('~') data = filtered_read(path) data_arr = extract_parts(data, path) results = results.merge({ name => { "name" => name, "html" => data_arr["html"], "css" => data_arr["css"], "js" => data_arr["js"] }}) end JSON.dump(results) end def traverse(dir, type) results = {} if File.exists?(dir) and File.directory?(dir) Dir["#{dir}/**/*.#{type}"].sort.reverse.each do |path| next if path.include?('~') name = path.split('/').last.gsub(".#{type}",'') data = filtered_read(path) results = results.merge({ name => { "name" => name, "#{type}" => data }}) end end JSON.dump(results) end def extract_parts(data, path) component_name = path.split('/').last component_dir = path.gsub(component_name, '') #load from file doc = Hpricot(data) arr = {} css = (doc/'//style').first if css arr["css"] = css.inner_html else arr["css"] = "" end js = (doc/'//script').first if js arr["js"] = js.inner_html else arr["js"] = "" end (doc/'//style').remove (doc/'//script').remove arr["html"] = doc.to_s #load from files, ".js.coffee", etc Dir["#{component_dir}/*"].each do |file_path| next if file_path.include?('~') valid_arr = path_valid_for_filtering?(file_path) if valid_arr filter_name = valid_arr[1] output_type = valid_arr[0] arr[output_type] = filtered_read(file_path) else extension = file_path.split('/').last.split('.').last arr[extension] = File.read(file_path) end end arr end def filtered_read(path) data = File.read(path) if path.split('.').last == 'html' data = filter_by_block(data) end data = filter_by_extension(data, path) data end def filter_by_block(data) doc = Hpricot(data) if doc unfiltered_elements = doc.search('//*[@filter]') if unfiltered_elements.count == 0 data else unfiltered_elements.each do |element| filter = element.attributes["filter"] filter_name = filter.capitalize.to_sym if Golf::Filter.constants.include?(filter_name) element.remove_attribute('filter') res = Golf::Filter.const_get(filter_name).transform(element.to_s) element.swap(res) end end return doc.to_s end else data end end def path_valid_for_filtering?(path) path_arr = path.split('/').last.split('.') if path_arr.count > 2 last_two = path_arr[path_arr.length - 2..path_arr.length] if last_two[0] == "js" or last_two[0] == "css" or last_two[0] == "html" last_two end end end def filter_by_extension(data, path) valid_arr = path_valid_for_filtering?(path) if valid_arr filter_name = valid_arr[1].capitalize.to_sym if Golf::Filter.constants.include?(filter_name) Golf::Filter.const_get(filter_name).transform(data) else data end else data end end def package_name(path) if path.include?('golfapp/components') path.match(/golfapp\/components\/(.*)/) component_path = $1 component_path.split('/')[0...-1].join('.') end end end end