# -*- mode: ruby; -*-
# Stream of Conciousness v.1.0beta1
# rsayers@robsayers.com
class StreamOfConsciousness
attr_accessor :settings, :sideitems
def initialize
require 'cgi'
require 'ftools' if RUBY_VERSION.to_f < 1.9
require 'erb'
settings={}
@pageno=1
@entries=[]
@categories=[]
@sideitems=[]
@plugins=[]
@templates={}
@cgi=CGI.new
@cgi.header
@mode=''
@path_info=[]
@path_info=@cgi.path_info.to_s.split('/')
@path_info.shift
@path_info << '/' if @path_info.last.nil?
if @path_info.last.match(/\d+$/)
@pageno=@path_info.pop.to_i
end
@path_info << '/' if @path_info.last.nil?
eval(File.read('blog.conf.rb')) if File.exists?('blog.conf.rb')
if (settings.nil?) then
@settings = {
:blog_title => "Blog Title",
# What's this blog's description (for outgoing RSS feed)?
:blog_description => "A Stream of Consciousness Blog",
# What's this blog's primary language (for outgoing RSS feed)?
:blog_language => "en",
# Where are this blog's entries kept?
:datadir => "/home/username/blogdata",
#What directory will static pages be served from?
:pagedir => "/home/username/pagedata",
:pagevar => "pages",
# What's my preferred base URL for this blog (leave blank for automatic)?
:url => "http://www.mysite.com",
# How many entries should I show on the home page?
:num_entries => 10,
# What file extension signifies a blosxom entry?
:file_extension => "txt",
# What is the default flavour?
:default_flavour => "html",
:plugindir => "/home/username/plugins",
:themedir => "/home/username/theme"
}
else
@settings=settings
end
@templates[:header]=%(
<%=@settings[:blog_title]%>
<%=do_hook('html_head') %>
)
@templates[:footer]=%(
)
@templates[:sidebar]=%(
<%unless @sideitems.nil? %>
<% @sideitems.each do |item| %>
<%=item['title']%>
<%=item['content'].call %>
<% end %>
<% end %>)
@templates[:rss]=%(
<%=@settings[:blog_title]%>
<%=@settings[:url]%>
<%=@settings[:blog_description]%>
<%=@entries.first.date%>
Stream of Consciousness
<% @entries.each do |post| %>
-
<%= post.title %>
<%= @settings[:url] %><%= post.category %>/<%= post.filename %>
]]>
<%=post.date%>
<%=@settings[:url]%><%=post.category%>/<%=post.filename%>
<% end %>
)
@templates[:layout]=%(
<%=template :header%>
<%=block.call if block_given? %>
<%=template :sidebar %>
<%=template :footer%>
)
@templates[:navigation]=%(
<%if @pageno > 1 then%>
<<Prev
<%end;if @pageno < @numpages then %>
Next >>
<%end%>
)
@templates[:page]=%()
@templates[:entry]=%()
@templates[:css]=%(
* { font-family: Helvetica; }
a { text-decoration: none; border-bottom: 1px dashed #929292;color:#929292; }
body { padding-left: 10px; }
#header { margin-bottom: 10px; width: 800px; border-top:5px solid black; background-color: #eeeeee}
#left { width: 600px; float:left;}
#content { width: 800px;}
#right {float:right;text-align:center }
#right ul { list-style: none; }
#right ul li { background-color: #eeeeee;width:170px;margin-left:-50px; border-bottom:1px solid black;text-align:left; border-left:2px solid black; padding-left: 10px }
#right ul li a { color: black; text-decoration:none; border-bottom: 0}
.postbody { text-align: justify;font-size:11pt; font-family: times; letter-spacing: 1px; margin-bottom:10px; }
#footer { clear: both; }
#blogtitle { font-size: 18pt; font-weight:bold; }
#blogsubtitle { clear:both; display:block; font-family:Times; font-style: italic}
.title { font-weight: bold; float:left;}
.date {float: right; color: #929292}
.postbody{border-top: 2px solid #929292; clear:both;}
.postfooter { text-align: center; margin-bottom:20px;font-weight:bold }
#footer { text-align: center; width:800px; background-color:#eeeeee;border-bottom:5px solid black}
#nav { text-align: center; margin-bottom:10px; }
pre,code {width:500px;overflow:auto; font-family:courier; font-size:11pt;letter-spacing:0px; background-color:#eeeeee}
hr { display:none})
load_plugins
load_templates
get_categories
get_pages
@numpages=1
# Default Side items, page and category lists
if (File.exist?(@settings[:pagedir])) then
@sideitems << {'title'=>'Pages','content'=>lambda{
r=''
return r
}}
end
@sideitems << {'title'=>'Categories','content'=>lambda{
r=''
@categories.each do |c|
r+= "#{c} "
end
r+=' '
return r
}}
do_hook('sideitems')
end
def dispatch
output=''
if @path_info.last.match('.*\.xml$') then
@mode='xml'
@cgi.header('Content-type: text/xml')
@path_info.pop
get_entries @path_info.join('/')
puts template :rss
elsif @path_info[0]=='pages'
@mode='page'
get_page
puts template(:layout) {
@entry=@entries.first
template(:page)
}
elsif @path_info.last.match('.*\.html$') then
@mode='view'
filename=@path_info.join('/')
filename.gsub!('.html','.txt')
if File.exist?(@settings[:datadir]+'/'+filename) then
get_entry(filename)
output=''
@entry=@entries.first
puts template(:layout) {
output << do_hook("before_single_entry")
output << template(:entry)
output << do_hook("after_single_entry")
output
}
else
error "Error: the requested entry was not found"
end
else
@mode='list'
if File.exist?( @settings[:datadir]+'/'+@path_info.join('/') ) then
get_entries @path_info.join('/')
do_hook('before_list_entry')
puts template(:layout) {
@entries.each do |e|
@entry=e
output << template(:entry)
end
output << template(:navigation)
output
}
else
error "Error: the specified path was not found"
end
end
end
def load_plugins
plugin_hook=''
code=lambda{}
return if !File.exist?(@settings[:plugindir])
Dir.chdir(@settings[:plugindir])
list=Dir.glob(File.join("**","*.rb"))
list.each do |f|
eval(File.read(@settings[:plugindir]+'/'+f))
@plugins << { :hook => plugin_hook, :code => code }
end
end
def load_templates
return if !File.exist?(@settings[:themedir])
Dir.chdir(@settings[:themedir])
list=Dir.glob(File.join("**","*.rhtml"))
list.each do |f|
name=f.gsub('.rhtml','').to_sym
@templates[name]=File.read(@settings[:themedir]+'/'+f)
end
end
def template(name,&block)
tpl=ERB.new(@templates[name])
tpl.result(binding)
end
def do_hook(hook)
@plugins.each do |p|
if p[:hook]==hook then
return p[:code].call
end
end
""
end
def get_entry(filename)
@entries << load_entry(@settings[:datadir]+'/'+filename)
end
def get_page
filename=@settings[:pagedir]+ '/' + @path_info.last
filename.gsub!('.html','.txt')
@entries << load_entry(filename)
end
def get_categories
@categories=[]
@categories << '/'
Dir.chdir(@settings[:datadir])
list=Dir.glob(File.join("**","*"))
list.each do |e|
@categories << '/'+e if FileTest.directory?(@settings[:datadir] + '/' + e)
end
@categories.sort!
end
def get_pages
@pages=[]
if (File.exist?(@settings[:pagedir])) then
Dir.chdir(@settings[:pagedir])
list=Dir.glob(File.join("**","*.txt"))
list.each do |e|
@pages << {'filename'=>e.gsub('.txt','.html'),'title'=>File.open(e).readline}
end
end
end
def error(msg)
puts template(:layout) {
msg
}
end
def load_entry(filename)
File.open(filename,"r:iso-8859-1:utf-8") do |f|
title=f.readline
body=f.read.gsub("\r","").gsub("\n"," ")
date=f.mtime
category="page"
category=get_cat_from_file(filename) if @mode != "page"
tmp,filename=File.split(filename)
Entry.new(title,body,date,category,filename)
end
end
def get_cat_from_file(filename)
fullpath=File.expand_path(filename)
tmp,category=fullpath.split(@settings[:datadir])
category,file=File.split(category)
category
end
def get_entries(category='/')
begin
Dir.chdir(@settings[:datadir] + '/' + category )
rescue
end
list=Dir.glob(File.join("**","*.#{@settings[:file_extension]}"))
list.each do |post|
@entries << load_entry(post)
end
@entries.sort! { |x,y| y.date <=> x.date }
start = (@pageno.to_i * @settings[:num_entries].to_i) - @settings[:num_entries].to_i
start = 0 if @pageno == 1
@numpages=(@entries.length.to_f / @settings[:num_entries].to_f).ceil
@entries=@entries[start,@settings[:num_entries].to_i]
do_hook('load_entries');
end
end
class Entry
attr_accessor :title, :body, :date, :category, :filename
def initialize(title,body,date,category,filename)
@title=title
@body=body
@date=date
@category=category
@filename=filename.gsub('.txt','.html')
end
end
settings={}
blog=StreamOfConsciousness.new
blog.dispatch