require 'nokogiri' module Trackman module Scaffold module ContentSaver def self.included(base) class << base attr_accessor :nodes_to_remove, :nodes_to_edit, :text_to_edit, :mappings end base.nodes_to_remove = {} base.nodes_to_edit = {} base.text_to_edit = {} if defined?(Rails) base.mappings = { :maintenance => '503', :maintenance_error => '503-error', :not_found => '404', :error => '500' } else base.mappings = {} end base.extend ClassMethods end module ClassMethods def edit selector, &block raise 'block parameter is mandatory' unless block_given? nodes_to_edit[selector] = block end def gsub pattern, replacement text_to_edit[pattern] = replacement end def remove selector, &predicate nodes_to_remove[selector] = predicate end end protected def remove_default_nodes doc nodes = [] nodes = nodes.concat doc.search('script').select{|n| n['src'] && n['src'].include?('/assets') && !n['src'].include?('application') } nodes = nodes.concat doc.search('link').select{|n| n['href'] && n['href'].include?('/assets') && !n['href'].include?('application') } nodes.each{|n| n.remove } doc end def remove_nodes doc self.class.nodes_to_remove.each do |selector, predicate| nodes = doc.search(selector) i = 0; unless predicate.nil? nodes = nodes.select { |n| r = predicate.call(n, i); i +=1;r } end nodes.each{|n| n.remove } end doc end def edit_nodes doc self.class.nodes_to_edit.each do |selector, block| doc.search(selector).each_with_index { |n, i| block.call(n, i) } end doc end def gsub_html text self.class.text_to_edit.each do |pattern, replacement| text.gsub! pattern, replacement end text end def xslt @xslt ||= Nokogiri::XSLT(File.open("#{File.dirname(__FILE__)}/pretty-print.xslt")) end def asset_pipeline_debug_mode? Object.const_defined?(:Rails) && Rails.respond_to?(:application) && Rails.application.config.assets.enabled && Rails.application.config.assets.debug end def new_content params={:keep_default_nodes => false} html = Nokogiri::HTML(response.body) edit_nodes html remove_default_nodes html unless params[:keep_default_nodes] remove_nodes html html = xslt.apply_to(html).to_s gsub_html(html) end def render_content response.body = new_content(:keep_default_nodes => asset_pipeline_debug_mode?) to_write = self.class.mappings[params[:action].to_sym] unless to_write.nil? path = "/public/#{to_write}.html" File.open(Rails.root.to_s + path, 'w') { |f| f.write(new_content) } end end end end end