# YarWiki =begin # ERGO rename image_path # ERGO is there a plugin_path system? ERGO make the Test on the page_name test the page. ERGO add wiki pages to wiki folder ERGO add redirection instructions ERGO click should assert that it clicked ERGO TDA we could use instance_eval and get rid of the excess rjs's ERGO the [+] for a test case title shall inplace edit it and offer to clone or delete it The [+] for setup shall offer to clone the page ERGO better outer tags for index.rhtml and system to replace with your layout ERGO rename that to wiki.rhtml ERGO put the document title in a little stretcher above the testing iframe ERGO assert_match, deny_match ERGO [f8] shall launch testage if any ERGO name our action wiki, so we can share a controller. # ERGO the status bar should advise of test progress # the test_frame should reflect the current page's src & title # ERGO Of all the world's languages, English # is the ugliest and the beautifulest. # ERGO the editor should test on # ERGO disable this for nodes it won't work for # ERGO why we need the require...environment.rb?? =end require 'pathname' require RAILS_ROOT + '/config/environment.rb' unless defined? YAML class YarWiki def initialize(page_name = 'FrontPage') @page_name = page_name @@wiki_path ||= File.expand_path(File.join(RAILS_ROOT, 'wiki')) Dir.mkdir(@@wiki_path) unless File.directory?(@@wiki_path) @yaml_path = File.join(@@wiki_path, page_name + '.yaml') @y = YAML::parse_file(yaml_path) if File.exist?(yaml_path) end attr_reader :page_name, :yaml_path, :x, :y attr_writer :x class ::String def to_ypath return $1.gsub(':', '//') if self =~ /node(:.*)/ return self end def to_id(prefix = '') prefix += '_' unless prefix.blank? return prefix + 'node' + to_ypath.gsub('//', ':') end end def self.maybe_install_startup_files #:nodoc: %w( FrontPage RecentChanges ).each do |page_name| yar = YarWiki.new(page_name) next if File.exist?(yar.yaml_path) source = File.join(RAILS_ROOT, "vendor/plugins/yar_wiki/wiki/#{page_name}.yaml") FileUtils.copy_file(source, yar.yaml_path) end image_path = File.join(RAILS_ROOT, 'public/images/wiki') Dir.mkdir(image_path) unless File.directory?(image_path) target = File.join(image_path, 'skyRamp.png') unless File.exist?(target) source = File.join(RAILS_ROOT, "vendor/plugins/yar_wiki/wiki/skyRamp.png") FileUtils.copy_file(source, target) end end def render_page(context) x = Builder::XmlMarkup.new skyRamp = "background-image: url(#{context.image_path 'wiki/skyRamp.png'}); " # sky Blue = #87CEEB # height: 60; x.div :style => 'width: 50%; height: 50px; font-size: 150%; ' + 'font-weight: bold; float: left; ' + skyRamp do x << '  ' x.text! page_name end x.div :style => 'width: 50%; height: 50px; font-size: 150%; ' + 'font-weight: bold; float: left; ' + skyRamp, :id => 'title_bar' do x << ' ' end x.div :style => 'width: 100%; height: 80%; ' + 'background-color: #F5F5DC; ' + 'overflow: auto; ' + 'unicode-bidi: bidi-override; ' + 'direction: rtl; ' + 'float: left;', :id => :wiki_panel do x.div :dir => 'ltr' do format_yaml(context, x) end end # ERGO add a test for whatever effect required the {} x.div(:id => :test_panel, :style => 'display: none; float: right; height: 80%'){} x.div(:id => :transcript){} x.target! end #-- # ERGO the editor must prevent shenanigans in the titles # ERGO use this default more #++ def save_page(contents = @y.emit) File.open(yaml_path, 'w'){|f| f.write(contents) } initialize(page_name) end def get_uri(concepts) return @page.url_for(concepts) if @page rescue '/wiki/edit_node' end # CONSIDER debug the test's mock version of url_for, and take this crud out! def ondblclick(ypath) %(var ypath = "#{ypath}"; var div = document.getElementById(ypath); ajax = new Ajax.Updater(ypath, "#{get_uri :controller => :wiki, :action => :edit_node}", { asynchronous:true, evalScripts:true, method:"get", parameters:"page_name=#{page_name}&ypath="+ypath+ "&width="+div.offsetWidth+ "&height="+div.offsetHeight }); ).gsub("\n", '').squeeze(' ') end def format_wiki(x, line) line.gsub(/(\b(?:[A-Z][a-z]+){2,}\b)|(.*)/) do |q| case q when /^(?:[A-Z][a-z]+){2,}$/ x.a :href => q, :id => 'link_' + q do x.text! q end when /.+/ x.text! q end end # x.text! line end def format_scalar(str, ypath) @x.div :id => ypath, :class => :editable, :ondblclick => ondblclick(ypath) do str.value.split("\n").each do |line| if line =~ /^(\s+)(.*)/ @x << ' ' * $1.size line = $2 end format_wiki(@x, line) @x.br end end end def format_test_link(ypath, linkie, title) linker = 'title_' + ypath options = { :url => { :action => 'display_iframe', :page_name => page_name, :ypath => ypath.to_ypath }, :loading => "ajax = new Effect.Highlight('#{linker}');" } html = { :id => 'link_' + ypath } @x << @page.link_to_remote(linkie, options, html) @x.text! title end def get_color(ypath) color = get_node_string(ypath.to_ypath + '//color') color = 'wiki_' + color unless color.blank? end def format_tuple(hash, ypath) key = hash.keys.first.value ypath += ':' + key @x.table :id => 'bar_' + ypath, :width => '100%' do @x.tr do @x.td :id => 'title_' + ypath, :width => '5%', :class => get_color(ypath) do @x.strong do if key =~ /^(test)(.*)/ format_test_link(ypath, $1, $2) else @x.text! key end end @x.text! ': ' end @x.td :align => :right do @x.span :style => 'color:grey; font-size: 50%' do @x.a :href => '#', :onclick => "ajax = new Effect.Highlight('#{ypath}');" + ondblclick(ypath) + '; return false;' do @x.text! '[+]' end end end @x.td(:width => '5%') end end item = hash.values.first send("format_#{item.kind}".to_sym, item, ypath) end # that calls format_seq or format_scalar #-- # ERGO tell rdoc maintainers that was a valid : # ERGO obviously: productize the ability to show and hide yaml lines # ERGO www.johnbrownfineart.com #++ def format_each(seq, ypath) seq.children.each do |kid| if kid.value.instance_of? Array format_each(kid, ypath) else next if kid.value.keys.first.value == 'color' @x.li{ format_tuple(kid.value, ypath) } end end end def format_seq(seq, ypath) @x.ul{ format_each(seq, ypath) } end def format_yaml(page, x) if File.exist?(yaml_path) @x = x @page = page format_seq(@y, 'node' ) else @x.span(yaml_path + ' not found') end end def get_node(ypath) nodes = @y.select(ypath) return nil unless nodes and nodes.size > 0 return nodes.first end def get_node_string(ypath) node = get_node(ypath) return '' unless node return(node.value or '') end def select_value(key_path, value_path) setup = get_node_string('//setup' + value_path) value = get_node_string(key_path + value_path) return [setup, value].reject(&:blank?).join("\n") || '' end def get_rjs #:stopdoc: ahp = ActionView::Helpers::PrototypeHelper #:nodoc: ahp::JavaScriptGenerator.new(self) do |rjs| return rjs end #:startdoc: end def escape_javascript(javascript) (javascript || '').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" } end #-- # ERGO don't pass a test until the last assertion passes # ERGO double-clicking on a text item TDA zilches the current editor #++ def eval_rjs(ypath, script, session = {}) #:stopdoc: rjs = get_rjs ahp = ActionView::Helpers::PrototypeHelper #:nodoc: form = ahp::JavaScriptGenerator::Form.new(rjs) rjs.instance_eval(script) was_debug = ActionView::Base.debug_rjs ActionView::Base.debug_rjs = false js = "function report(diagnostic) { var transcript = window.parent.document.getElementById('transcript'); transcript.innerHTML += diagnostic; onComplete(); }" js += "function onComplete() { window.parent.location.href = 'javascript:void(find_faults(\"#{page_name}\",\"#{ypath}\"))'; }" js.gsub!(/\n/, '').squeeze!(' ') js += rjs.to_s js += 'onComplete();' #File.open('curious.js'+Time.now().to_f.to_s, 'w'){|f| f.write(js) } js = 'update_iframe("' + escape_javascript(js) + '");' return js ensure ActionView::Base.debug_rjs = was_debug #:startdoc: end end #:stopdoc: # ERGO how to get this f---er out of the RDoc??? ZAP = ActionView::Helpers::PrototypeHelper unless defined?(ZAP) #:nodoc: class ZAP::JavaScriptGenerator #:nodoc: #:startdoc: class Form def initialize(rjs) @rjs = rjs end # ERGO ability to pick form by name def method_missing(symbol, arg = nil) name = symbol.id2name if name =~ /(.+)=$/ return @rjs[$1].value = arg else return @rjs[name] end # ERGO what the returns are for? end end def click(button, &block) onload(&block) # self << 'alert(test_frame.onload);' self << "document.getElementById('#{button}').click();" end def submit(form, &block) # ERGO use this or lose it onload(&block) self << "document.getElementById('#{form}').submit();" end def surf(page, &block) onload(&block) self << "window.location.href = #{page};" end def h(q) #:nodoc: ERB::Util::html_escape(q) end def assert(javascript) diagnostic = "failed: #{h javascript}
" self << "if (!(#{javascript})) report(\"#{diagnostic}\");" end def assert_ajax(target) target = target.inspect.inspect.gsub(/^"/, '').gsub(/"$/, '') self << "{ var handler = { onComplete: function(request) {" + "if (#{target}.test(request.url)) {" + "Ajax.Responders.unregister(handler); " yield self << "} } }; Ajax.Responders.register(handler); }" end def onload(&block) return unless block self << 'var test_frame = window.parent.document.getElementById("test_frame");' self << "test_frame.onload = function() {" self << 'var test_frame = window.parent.document.getElementById("test_frame");' self << 'test_frame.onload = function() {};' block.call self << "}; " end end module YarWikiActions include REXML def index YarWiki.maybe_install_startup_files render :file => File.join(File.dirname(__FILE__), 'wiki.rhtml') end def find_faults yar = YarWiki.new(params[:page_name]) y = YAML.parse_file(yar.yaml_path) ypath = params[:ypath] color_path = ypath + '//color' color = y.select(color_path) render :update do |rjs| if color.size > 0 # ERGO TDA that line new_color = /fault/.match(params[:transcript]) ? 'red' : 'green' if color.first.value != new_color color.first.value = new_color yar.save_page(y.emit) # ERGO TDA this line # rjs[color_path.to_id ].replace_html(new_color) rjs[ypath.to_id('title')].className = 'wiki_'+new_color rjs[ypath.to_id('bar' )].className = 'wiki_'+new_color end end end end # TDA YarWiki count the assertions def update_yaml_node yar = YarWiki.new(params[:page_name]) y = YAML.parse_file(yar.yaml_path) ypath = params[:ypath] y.select(ypath)[0].value = params[:node_contents] yar.save_page(y.emit) render :nothing => true end def edit_node yar = YarWiki.new(params[:page_name]) y = YAML.parse_file(yar.yaml_path) x = Builder::XmlMarkup.new ypath = params[:ypath ].to_ypath w = params[:width ] h = params[:height] x.form :action => '/wiki/update_yaml_node', :id => 'edit_node_form' do x.input :type => :hidden, :name => :ypath, :value => ypath x.input :type => :hidden, :name => :page_name, :value => yar.page_name # ERGO you can click the page tag and go to the page w/o testing it action = url_for(:controller => :wiki, :action => :update_yaml_node) x.textarea :name => 'node_contents', :onkeydown => 'return editor_keydown(event, "' + action + '");', :style => "width: #{w}px; height: #{h}px" do x.text! y.select(ypath)[0].value end end render :text => x.target! end def display_iframe yar = YarWiki.new(params[:page_name]) ypath = params[:ypath] that = self render :update do |rjs| begin iframe = that.send(:test_iframe, yar, ypath) q = YAML::load_file(yar.yaml_path) rjs['wiki_panel'].set_style :width => '50%' rjs['test_panel'].set_style :width => '50%' rjs.replace_html 'test_panel', iframe rjs.replace_html 'transcript' rjs.show 'test_panel' path_code = ypath.to_id('bar') q.each do |k,v| if k =~ /^test/ other_node = ("//" + k).to_id('bar') # ERGO move the '//'+ inside nu_class = other_node == path_code ? yar.get_color(path_code) : '' rjs[other_node].className = nu_class end end rescue SyntaxError => e rjs.replace_html 'transcript', h(e.message) rescue => e # ERGO explain more, hilite problem in editor rjs.replace_html 'transcript', h(e.message) end end end private def test_iframe(yar, ypath) page = yar.select_value(ypath, '//page') script = yar.select_value(ypath, '//script') js = yar.eval_rjs(ypath, script, session) x = Builder::XmlMarkup.new page = '/' + page unless page =~ /^\// page = request.relative_url_root + page if request x.iframe :id => :test_frame, :src => page, :onload => js, :width => '100%', :height => '100%', :style => 'width: 100%; height: 100%' # ERGO need the style?? # ERGO