require 'cgi'
require 'date'
class String
def escapeLineBreaks
self.gsub(/\\/,"\\s").gsub(/\n/,"\\n").gsub(/\r/,"")
end
def unescapeLineBreaks
self.gsub(/\\n/,"\n").gsub(/\\s/,"\\").gsub(/\r/,"")
end
def encodeHTML
CGI.escapeHTML(self)
end
def decodeHTML
CGI.unescapeHTML(self)
end
end
class Tiddler
@@main_fields = %w[tiddler modifier modified created tags].map{|f| f.to_sym}
@@ts = Time.now
def self.get_time
# so they are nicely ordered in Timeline
@@ts += 60
@@ts.utc.strftime("%Y%m%d%H%M%S")
end
@@defaults = {
:modified => Tiddler.get_time,
:created => Tiddler.get_time,
:modifier => 'MonkeyPirate',
:tags => '',
:tiddler => '',
}
def with_defaults(fields,file_name)
@@defaults.merge({:tiddler=>name_from_file(file_name)}).merge(fields)
end
attr_accessor :fields, :body, :raw
def initialize
end
def from_div(div)
@raw = div
@fields = {}
match_data = div.match(/<div([^>]+)>([^<]+)<\/div>/)
field_string = match_data[1]
@body = match_data[2].unescapeLineBreaks.decodeHTML
field_string.scan(/ (\w+)="([^"]+)"/) do |name,value|
@fields[name.to_sym] = value
end
self
end
def from_scratch(body,fields={})
@fields = with_defaults(fields)
@body = body
@raw = ""
self
end
def name_from_file(file_name)
if (file_name)
file_name.split("/").last.split(".").first
else
''
end
end
def from_file(file_name,fields={})
@raw = ""
@body = File.read(file_name)
@body.gsub!(/\$\$date\$\$/,File.stat(file_name).mtime.strftime('%d-%b-%Y'))
@body.gsub!(/\$\$version\$\$/,File.stat(file_name).mtime.strftime('%Y.%m.%d')[1..-1].gsub(/0/,''))
@fields = with_defaults(fields,file_name)
{:tiddler=>name_from_file(file_name)}.update(@fields) # guess name from file
@fields[:modified] = Tiddler.get_time
case File.extname(file_name)
when ".js"
@fields[:tags] = "systemConfig"
when ".html"
@fields[:tags] = "html"
when ".css"
@fields[:tags] = "css"
end
case File.basename(file_name)
when "MptwUpgradeURL.tiddler"
@fields[:tags] = "feed"
end
self
end
def append_content(new_content)
@body += new_content
end
def to_div
"<div"+
(@@main_fields.inject("") do |output,field|
%{#{output} #{field}="#{@fields[field]}"}
end)+
(@fields.keys.map{|f|f.to_s}.sort.reject{|f|@@main_fields.include?(f)}.inject("") do |output,field|
%{#{output} #{field}="#{@fields[field]}"}
end)+
">#{@body.escapeLineBreaks.encodeHTML}</div>"
end
end
class TiddlyWiki
attr_accessor :orig_tiddlers, :tiddlers
def initialize(&block)
@tiddlers = []
if block
instance_eval &block
end
end
def source_file(file_name)
@empty_file = file_name
@raw = File.read(@empty_file)
@orig_tiddlers = [12]#get_orig_tiddlers
end
@@store_regexp = /^(.*<div id="storeArea">\n?)(.*\n)(<\/div>.*)$/m
def pre_store
@raw.sub(@@store_regexp,'\1')
end
def store
@raw.sub(@@store_regexp,'\2')
end
def post_store
@raw.sub(@@store_regexp,'\3')
end
def tiddler_divs
store.to_a
end
def get_orig_tiddlers
tiddler_divs.inject([]) do |tiddlers,tiddler_div|
tiddlers << Tiddler.new.from_div(tiddler_div)
end
end
def tiddler_titles
@tiddlers.map do |t|
t.fields[:tiddler]
end
end
def add_tiddler(tiddler)
@tiddlers << tiddler
tiddler
end
def add_tiddler_from_file(file_name)
add_tiddler Tiddler.new.from_file("#{file_name}")
end
def add_tiddlers(file_names)
file_names.reject{|f| f.match(/^#/)}.each do |f|
add_tiddler_from_file(f)
end
end
def get_tiddler(tiddler_title)
@tiddlers.select{|t| t.fields[:tiddler] == tiddler_title}.first
end
def to_s
"#{pre_store}#{store_to_s}#{post_store}"
end
def store_to_s
@tiddlers.sort_by{|t| t.fields[:tiddler]}.inject(""){ |out,t|out << t.to_div << "\n"}
end
def store_to_file(file_name)
File.open(file_name,"w") { |f| f << "<xmp><div id=\"storeArea\">\n#{store_to_s}</div></xmp>" }
puts "Wrote store only to '#{file_name}'"
end
def to_file(file_name)
File.open(file_name,"w") { |f| f << to_s }
puts "Wrote tw file to '#{file_name}'"
end
def package_as(file_name,package_file_names)
new_tiddler = add_tiddler Tiddler.new.from_file(file_name)
new_tiddler.append_content(package(package_file_names))
end
def package(file_names)
"//{{{\nmerge(config.shadowTiddlers,{\n\n"+
((file_names.map do |f|
Tiddler.new.from_file(f)
end).map do |t|
t.fields[:tiddler] + ":[\n " +
t.body.dump.gsub(/\\t/,"\t").gsub(/\\n/,"\",\n \"") + "\n].join(\"\\n\")"
end).join(",\n\n")+
"\n\n});\n//}}}\n"
end
end
def make_tw(&block)
TiddlyWiki.new(&block)
end