Riki Wiki

riki: ruby wiki (a wiki written in ruby) or ruby icky (a ruby rehash of IckyWiki)

when i discovered the ShortestWikiContest, i thought "since RubyLanguage is so cool, i bet it can be used to write a complete wiki in under two hours and less than fifty lines". riki is the result. it may not the kind of code you'd want running a RealWiki, but it does implement AutomaticLinkGeneration, ContentEditableByAll, BackLinks, and most TextFormattingRules.

there is lots of room for improvement here (perhaps most importantly: complete TextFormattingRules as well as RecentChanges) which i may get to in time. or perhaps you, dear reader, will fill them in for me down below.


 $ cat riki.rb | wc
         40     146    1850
 $ cat riki.rb
 #!/usr/bin/env ruby
 require 'cgi' # riki.rb ShortestWikiContest submission by BrandtKurowski
 if ENV['PATH_INFO'] !~ /^\/(\w+)\/(\w+)$/
   puts "Location: riki.cgi/view/HomePage\n\n" and exit
 end
 operation, page, text = $1, $2, CGI.new['t'].shift
 data = File.exist?('../riki/data') ?
   File.open('../riki/data') do |file| Marshal.load(file) end : Hash.new('')
 if text
   data[page] = text
   File.open('../riki/data','w') do |file| Marshal.dump(data, file) end
 end
 puts "Content-type: text/html\n\n<html><head><title>"
 case operation
 when 'edit'
   puts %Q{#{page}</title><body><form action="../view/#{page}" method="post">
     <h1>#{page}</h1><textarea rows="10" name="t">#{data[page]}</textarea>
     <hr><input type="submit" value="Save"></form></body></html>}
 when 'search'
   list = data.reject {|name, text| text !~ page}.keys.collect { |name|
     %Q{<li><a href="../view/#{name}">#{name}</a>} }
   puts %Q{Search for #{page}</title><body><h1>Search Results</h1><hr>
     Searching for <em>#{page}</em><ul>#{list}</ul><hr></body></html>}
 else
   [ ['&','&amp;'], ['<','&lt;'], ['>','&gt;'], [/(\r?\n){2}/, '<p>\\&' ],
     [/(.*?)/, '<strong>\\1</strong>' ],
     [/(.*?)/, '<em>\\1</em>' ], [/^----/, '<hr>'],
     [/http:\/\/\S*/, '<a href="\\&">\\&</a>' ],
   ].each do |wiki, html| data[page].gsub!(wiki, html) end
   nil while data[page].gsub!(/^(\t*)\t([^\t]*?)$/, "<ul>\n\\1<li>\\2</ul>")
   nil while data[page].gsub!(/<\/ul>\s*<ul>/, '')
   data[page].gsub!(/(<li>\s*)+/, '<li>')
   data[page].gsub!(/([A-Z][a-z]+){2,}/) do |name|
     data.has_key?(name) ? %Q{<a href="../view/#{name}">#{name}</a>} :
                  %Q{#{name}<a href="../edit/#{name}">?</a>}
   end
   puts %Q{#{page}</title><body><h1><a href="../search/#{page}">#{page}</a>
     </h1><hr>#{data[page]}<hr><a href="../edit/#{page}">Edit #{page}</a>
     </body></html>}
 end


CategoryWikiImplementation CategoryRuby


EditText of this page (last edited September 11, 2003) or FindPage with title or text search