]> git.rkrishnan.org Git - .emacs.d.git/blob - emacs/nxhtml/tests/in/blorgit.rb
submodulized .emacs.d setup
[.emacs.d.git] / emacs / nxhtml / tests / in / blorgit.rb
1 # blorgit --- blogging with org-mode
2 require 'rubygems'
3 require 'sinatra'
4 require 'backend/rewrite_content_disposition'
5 require 'yaml'
6 $global_config ||= YAML.load(File.read(File.join(File.dirname(__FILE__), 'blorgit.yml')))
7 $blogs_dir  ||= File.expand_path($global_config[:blogs_dir])
8 $url_prefix ||= $global_config[:url_prefix]
9 require 'backend/init.rb'
10
11 # Configuration (http://sinatra.rubyforge.org/book.html#configuration)
12 #--------------------------------------------------------------------------------
13 use RewriteContentDisposition, {"org" => "attachment"}
14 set(:public, $blogs_dir)
15 enable(:static)
16 set(:app_file, __FILE__)
17 set(:haml, { :format => :html5, :attr_wrapper  => '"' })
18 set(:url_prefix, $url_prefix)
19 use_in_file_templates!
20 mime(:org, 'text/org')
21
22 # Routes (http://sinatra.rubyforge.org/book.html#routes)
23 #--------------------------------------------------------------------------------
24 get('/') do
25   if config['index']
26     redirect(path_for(config['index']))
27   else
28     "It seems you haven't yet configured a blogs directory.  Try"+
29       " running <tt>rake new</tt> from the root. of your blorgit directory"
30   end
31 end
32
33 post(/^\/.search/) do
34   @query = params[:query]
35   @results = Blog.search(params[:query])
36   haml :results
37 end
38
39 get(/^\/\.edit\/(.*)?$/) do
40   pass unless config['editable']
41   path, format = split_format(params[:captures].first)
42   if @blog = Blog.find(path)
43     @title = @blog.title
44     @files = (Blog.files(path) or [])
45     haml :edit
46   else
47     "Nothing here to edit."
48   end
49 end
50
51 get(/^\/(.*)?$/) do
52   path, format = split_format(params[:captures].first)
53   @files = (Blog.files(path) or [])
54   @blog = Blog.find(path)
55   if @blog or File.directory?(Blog.expand(path))
56     if format == 'html'
57       @title = @blog ? @blog.title : path
58       haml :blog
59     elsif @blog
60       content_type(format)
61       attachment extension(@blog.path, format)
62       @blog.send("to_#{format}")
63     else
64       pass
65     end
66   elsif config['editable'] and extension(path, 'org').match(Blog.location_regexp)
67     pass if path.match(/^\./)
68     protected!
69     @path = path
70     haml :confirm_create
71   else
72     "Can't create a new page at #{path}"
73   end
74 end
75
76 post(/^\/(.*)?$/) do
77   path, format = split_format(params[:captures].first)
78   @blog = Blog.find(path)
79   if params[:comment]
80     pass unless (@blog and config['commentable'])
81     return "Sorry, review your math..." unless params[:checkout] == params[:captca]
82     @blog.add_comment(Comment.build(2, params[:title], params[:author], params[:body]))
83     @blog.save
84     redirect(path_for(@blog))
85   elsif config['editable']
86     protected!
87     if @blog and params[:edit]
88       @blog.body = params[:body]
89       @blog.change_log = params[:change_log] if params[:change_log]
90       @blog.save
91       redirect(path_for(@blog))
92     elsif extension(path, 'org').match(Blog.location_regexp)
93       @blog = Blog.new(:path => extension(path, 'org'),
94                        :body => "# -*- mode: org -*-\n#+TITLE: #{File.basename(path)}\n#+OPTIONS: toc:nil ^:nil\n\n")
95       @blog.save
96       redirect(path_for(@blog))
97     elsif path.match(/^\./)
98       pass
99     else
100       "Can't create a new page at #{path}"
101     end
102   else
103     pass
104   end
105 end
106
107 # Helpers (http://sinatra.rubyforge.org/book.html#helpers)
108 #--------------------------------------------------------------------------------
109 helpers do
110   def config
111     $local_config_file ||= File.join($blogs_dir, '.blorgit.yml')
112     $local_config ||= $global_config[:config].merge(File.exists?($local_config_file) ? YAML.load(File.read($local_config_file)) : {})
113     config_file = File.join(File.dirname(File.join($blogs_dir, (params[:captures] ? params[:captures].first : ''))), '.blorgit.yml')
114     $local_config.merge((File.exists?(config_file)) ? YAML.load(File.read(config_file)) : {})
115   end
116
117   def split_format(url) url.match(/(.+)\.(.+)/) ? [$1, $2] : [url, 'html'] end
118
119   def path_for(path, opts ={})
120     path = (path.class == Blog ? path.path : path)
121     File.join(options.url_prefix, extension(path, (opts[:format] or nil)))
122   end
123
124   def show(blog, options={}) haml("%a{ :href => '#{path_for(blog)}' } #{blog.title}", :layout => false) end
125
126   def comment(blog, parent_comment) end
127
128   def extension(path, format = nil) (path.match(/^(.+)\..+$/) ? $1 : path)+(format ? "."+format : '') end
129
130   def time_ago(from_time)
131     distance_in_minutes = (((Time.now - from_time.to_time).abs)/60).round
132     case distance_in_minutes
133     when 0..1            then 'about a minute'
134     when 2..44           then "#{distance_in_minutes} minutes"
135     when 45..89          then 'about 1 hour'
136     when 90..1439        then "about #{(distance_in_minutes.to_f / 60.0).round} hours"
137     when 1440..2879      then '1 day'
138     when 2880..43199     then "#{(distance_in_minutes / 1440).round} days"
139     when 43200..86399    then 'about 1 month'
140     when 86400..525599   then "#{(distance_in_minutes / 43200).round} months"
141     when 525600..1051199 then 'about 1 year'
142     else                      "over #{(distance_in_minutes / 525600).round} years"
143     end
144   end
145
146   # from http://www.sinatrarb.com/faq.html#auth
147   def protected!
148     response['WWW-Authenticate'] = %(Basic realm="username and password required") and \
149     throw(:halt, [401, "Not authorized\n"]) and \
150     return unless ((not config['auth']) or authorized?)
151   end
152
153   def authorized?
154     @auth ||=  Rack::Auth::Basic::Request.new(request.env)
155     @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == config['auth']
156   end
157
158 end
159
160 # HAML Templates (http://haml.hamptoncatlin.com/)
161 #--------------------------------------------------------------------------------
162 __END__
163 @@ layout
164 !!!
165 %html
166   %head
167     %meta{'http-equiv' => "content-type", :content => "text/html;charset=UTF-8"}
168     :javascript
169       function toggle(item) {
170         el = document.getElementById(item);
171         if(el.style.display == "none") { document.getElementById(item).style.display = "block" }
172         else { document.getElementById(item).style.display = "none" }
173         }
174     - if config['favicon']
175       %link{:rel => "icon", :type => "image/x-icon", :href => path_for(config['favicon'], :format => 'ico')}
176     %link{:rel => "stylesheet", :type => "text/css", :href => path_for(config['style'], :format => 'css')}
177     %title= "#{config['title']}: #{@title}"
178   %body
179     #container
180       #titlebar= render(:haml, :titlebar, :layout => false)
181       #insides
182         #sidebar= render(:haml, :sidebar, :locals => { :files => @files }, :layout => false)
183         #contents= yield
184
185 @@ titlebar
186 #title_pre
187 #title
188   %a{ :href => path_for(''), :title => 'home' }= config['title']
189 #title_post
190 #search= haml :search, :layout => false
191 - if @blog
192   #actions
193     %ul
194       - if config['editable']
195         %li
196           %a{ :href => path_for(File.join(".edit", @blog.path)), :title => "edit #{@title}" } edit
197       %li
198         %a{ :href => path_for(@blog, :format => 'org'), :title => 'download as org-mode' } .org
199       %li
200         %a{ :href => path_for(@blog, :format => 'tex'), :title => 'download as LaTeX' } .tex
201       %li
202         %a{ :href => path_for(@blog, :format => 'pdf'), :title => 'download as PDF' } .pdf
203 #title_separator
204
205 @@ sidebar
206 - if (config['recent'] and (config['recent'] > 0))
207   #recent= haml :recent, :layout => false
208 - if (config['dir_list'] and @files)
209   #dir= haml :dir, :locals => { :files => files }, :layout => false
210
211 @@ search
212 %form{ :action => path_for('.search'), :method => :post, :id => :search }
213   %ul
214     %li
215       %input{ :id => :query, :name => :query, :type => :text, :size => 12 }
216     %li
217       %input{ :id => :search, :name => :search, :value => :search, :type => :submit }
218
219 @@ recent
220 %label Recent
221 %ul
222   - Blog.all.sort_by(&:ctime).reverse[(0..(config['recent'] - 1))].each do |blog|
223     %li
224       %a{ :href => path_for(blog)}= blog.title
225
226 @@ dir
227 %label Directory
228 %ul
229   - files.each do |file|
230     %li
231       %a{ :href => path_for(file) + (File.directory?(Blog.expand(file)) ? "/" : "") }= File.basename(file)
232
233 @@ results
234 #results_list
235   %h1
236     Search Results for
237     %em= "/" + @query + "/"
238   %ul
239     - @results.sort_by{ |b,h| -h }.each do |blog, hits|
240       %li
241         %a{ :href => path_for(blog) }= blog.name
242         = "(#{hits})"
243
244 @@ edit
245 %h1= "Edit #{@title}"
246 %form{ :action => path_for(@blog), :method => :post, :id => :comment_form }
247   %textarea{ :id => :body, :name => :body, :rows => 28, :cols => 82 }= @blog.body
248   %br
249   Change log:
250   %input{ :id => :change_log, :name => :change_log, :type => :text }
251   %input{ :id => :submit, :name => :edit, :value => :update, :type => :submit }
252   %a{ :href => path_for(@blog) } Cancel
253
254 @@ blog
255 - if @blog
256   #blog_body= @blog.to_html
257   - if (config['commentable'] and (not @blog.commentable == 'disabled'))
258     #comments= render(:haml, :comments, :locals => {:comments => @blog.comments, :commentable => @blog.commentable}, :layout => false)
259 - else
260   #dir= haml :dir, :locals => { :files => @files }, :layout => false
261
262 @@ comments
263 #existing_commment
264   %label= "Comments (#{comments.size})"
265   %ul
266   - comments.each do |comment|
267     %li
268       %ul
269         %li
270           %label title
271           = comment.title
272         %li
273           %label author
274           = comment.author
275         %li
276           %label date
277           = time_ago(comment.date) + " ago"
278         %li
279           %label comment
280           %div= Blog.string_to_html(comment.body)
281 - unless commentable == 'closed'
282   #new_comment
283     %label{ :onclick => "toggle('comment_form');"} Post a new Comment
284     %form{ :action => path_for(@blog), :method => :post, :id => :comment_form, :style => 'display:none' }
285       - equation = "#{rand(10)} #{['+', '*', '-'].sort_by{rand}.first} #{rand(10)}"
286       %ul
287         %li
288           %label name
289           %input{ :id => :author, :name => :author, :type => :text }
290         %li
291           %label title
292           %input{ :id => :title, :name => :title, :type => :text, :size => 36 }
293         %li
294           %label comment
295           %textarea{ :id => :body, :name => :body, :rows => 8, :cols => 68 }
296         %li
297           %input{ :id => :checkout, :name => :checkout, :type => :hidden, :value => eval(equation) }
298           %span
299           %p to protect against spam, please answer the following
300           = equation + " = "
301           %input{ :id => :captca, :name => :captca, :type => :text, :size => 4 }
302         %li
303           %input{ :id => :submit, :name => :comment, :value => :comment, :type => :submit }
304
305 @@ confirm_create
306 %form{ :action => path_for(@path), :method => 'post', :id => 'creation_form'}
307   %label
308     Create a new page at
309     %em= @path
310     ?
311   %input{ :id => 'submit', :name => 'submit', :value => 'create', :type => 'submit' }
312   %a{ :href => path_for('/') } cancel
313