olelo 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
data/bin/olelo CHANGED
@@ -28,7 +28,7 @@ opts = OptionParser.new do |opts|
28
28
  options[:host] = host
29
29
  end
30
30
 
31
- opts.on('-s', '--server SERVER', 'serve using SERVER (webrick/mongrel)') do |server|
31
+ opts.on('-s', '--server SERVER', 'serve using SERVER (webrick/mongrel/thin)') do |server|
32
32
  options[:server] = server
33
33
  end
34
34
 
data/config.ru CHANGED
@@ -99,6 +99,7 @@ use Rack::MethodOverride
99
99
  use Rack::CommonLogger, LoggerOutput.new(logger)
100
100
  use Rack::RelativeRedirect
101
101
  use Olelo::Middleware::ForceEncoding
102
+ use Rack::Head
102
103
  run Olelo::Application.new
103
104
 
104
105
  logger.info "Olelo started in #{Olelo::Config['production'] ? 'production' : 'development'} mode"
@@ -21,6 +21,7 @@ production: true
21
21
  sidebar_page: 'Sidebar'
22
22
 
23
23
  # Use a different base directory as root to support installation in user homes
24
+ # e.g. /wiki
24
25
  base_path: '/'
25
26
 
26
27
  # Main cache store. Uncomment this!
@@ -13,7 +13,7 @@ module Olelo
13
13
 
14
14
  has_around_hooks :request, :routing, :action, :title, :footer, :login_buttons,
15
15
  :edit_buttons, :attributes_buttons, :upload_buttons
16
- has_hooks :auto_login, :render, :menu, :head, :script
16
+ has_hooks :auto_login, :render, :menu, :head
17
17
 
18
18
  def self.reserved_path?(path)
19
19
  path = '/' + path.cleanpath
@@ -32,7 +32,7 @@ module Olelo
32
32
  # Executed before each request
33
33
  before :routing do
34
34
  User.current = User.find(session[:olelo_user])
35
- if !User.current
35
+ unless User.current
36
36
  invoke_hook(:auto_login)
37
37
  User.current ||= User.anonymous(request)
38
38
  end
@@ -148,7 +148,7 @@ module Olelo
148
148
  raise NotFound
149
149
  end
150
150
  @version = @diff.to
151
- cache_control version: @version
151
+ cache_control etag: @version.to_s
152
152
  render :changes
153
153
  end
154
154
 
@@ -158,8 +158,7 @@ module Olelo
158
158
  @page_nr = [params[:page].to_i, 1].max
159
159
  @history = page.history((@page_nr - 1) * per_page, per_page)
160
160
  @page_count = @page_nr + @history.length / per_page
161
- @history = @history[0...per_page]
162
- cache_control version: page.version
161
+ cache_control etag: page.etag
163
162
  render :history
164
163
  end
165
164
 
@@ -269,7 +268,7 @@ module Olelo
269
268
  get '/(:path)', tail: true do
270
269
  begin
271
270
  @page = Page.find!(params[:path])
272
- cache_control version: page.version
271
+ cache_control etag: page.etag
273
272
  show_page
274
273
  rescue NotFound
275
274
  redirect build_path(params[:path], action: :new)
@@ -278,7 +277,7 @@ module Olelo
278
277
 
279
278
  get '/version/:version(/:path)' do
280
279
  @page = Page.find!(params[:path], params[:version])
281
- cache_control version: page.version
280
+ cache_control etag: page.etag
282
281
  show_page
283
282
  end
284
283
 
data/lib/olelo/helper.rb CHANGED
@@ -17,14 +17,6 @@ module Olelo
17
17
  def render_block(name)
18
18
  with_hooks(name) { yield }.join.html_safe
19
19
  end
20
-
21
- def include_or_define_block(name, content = nil, &block)
22
- if block_given? || content
23
- define_block(name, content, &block)
24
- else
25
- include_block(name)
26
- end
27
- end
28
20
  end
29
21
 
30
22
  module FlashHelper
@@ -242,11 +234,6 @@ module Olelo
242
234
  last_modified = last_modified.try(:to_time) || last_modified
243
235
  last_modified = last_modified.try(:httpdate) || last_modified
244
236
 
245
- if options[:version]
246
- options[:etag] = options[:version].cache_id
247
- options[:last_modified] = options[:version].date
248
- end
249
-
250
237
  if User.logged_in?
251
238
  # Always private mode if user is logged in
252
239
  options[:private] = true
@@ -309,31 +296,38 @@ module Olelo
309
296
  end
310
297
 
311
298
  def footer(content = nil, &block)
312
- include_or_define_block(:footer, content, &block)
299
+ if block_given? || content
300
+ define_block(:footer, content, &block)
301
+ else
302
+ include_block(:footer)
303
+ end
313
304
  end
314
305
 
315
306
  def title(content = nil, &block)
316
- include_or_define_block(:title, content, &block)
307
+ if block_given? || content
308
+ define_block(:title, content, &block)
309
+ else
310
+ include_block(:title)
311
+ end
317
312
  end
318
313
 
319
314
  def head
320
- @@theme_link ||=
315
+ @@js_css_links ||=
321
316
  begin
322
317
  file = File.join(Config['themes_path'], Config['theme'], 'style.css')
323
- path = build_path "static/themes/#{Config['theme']}/style.css?#{File.mtime(file).to_i}"
324
- %{<link rel="stylesheet" href="#{escape_html path}" type="text/css"/>}
325
- end
326
- @@script_link ||=
327
- begin
328
- path = build_path "static/script.js?#{File.mtime(File.join(Config['app_path'], 'static', 'script.js')).to_i}"
329
- %{<script src="#{escape_html path}" type="text/javascript"></script>}
318
+ css_path = build_path "static/themes/#{Config['theme']}/style.css?#{File.mtime(file).to_i}"
319
+ js_path = build_path "static/script.js?#{File.mtime(File.join(Config['app_path'], 'static', 'script.js')).to_i}"
320
+ %{<link rel="stylesheet" href="#{escape_html css_path}" type="text/css"/>
321
+ <script src="#{escape_html js_path}" type="text/javascript"></script>}
330
322
  end
323
+ # Add base path to root page to fix links in history browsing and for wikis with base_path
331
324
  base_path = if page && page.root?
332
325
  url = request.base_url
326
+ url << Config['base_path'] if Config['base_path'] != '/'
333
327
  url << '/' << 'version'/page.tree_version if !page.head?
334
328
  %{<base href="#{escape_html url}/"/>}.html_safe
335
329
  end
336
- [base_path, @@theme_link, @@script_link, *invoke_hook(:head)].join.html_safe
330
+ [base_path, @@js_css_links, *invoke_hook(:head)].join.html_safe
337
331
  end
338
332
 
339
333
  def session
@@ -1,3 +1,4 @@
1
+ # From ActionPack
1
2
  module Olelo
2
3
  module Middleware
3
4
  class UAHeader
data/lib/olelo/page.rb CHANGED
@@ -39,8 +39,8 @@ module Olelo
39
39
 
40
40
  attr_reader :path, :tree_version
41
41
 
42
- def initialize(path, tree_version = nil, parent = nil)
43
- @path, @tree_version, @parent = path.to_s.cleanpath.freeze, tree_version, parent
42
+ def initialize(path, tree_version = nil, etag = nil, parent = nil)
43
+ @path, @etag, @tree_version, @parent = path.to_s.cleanpath.freeze, etag, tree_version, parent
44
44
  Page.check_path(@path)
45
45
  end
46
46
 
@@ -67,7 +67,10 @@ module Olelo
67
67
  path = path.to_s.cleanpath
68
68
  check_path(path)
69
69
  tree_version = repository.get_version(tree_version) unless Version === tree_version
70
- Page.new(path, tree_version) if tree_version && repository.path_exists?(path, tree_version)
70
+ if tree_version
71
+ etag = repository.path_etag(path, tree_version)
72
+ Page.new(path, tree_version, etag) if etag
73
+ end
71
74
  end
72
75
 
73
76
  # Throws if not found
@@ -88,6 +91,13 @@ module Olelo
88
91
  mime.text? || mime == EMPTY_MIME || mime == DIRECTORY_MIME
89
92
  end
90
93
 
94
+ def etag
95
+ unless new?
96
+ @etag ||= repository.path_etag(path, tree_version)
97
+ "#{head? ? 1 : 0}-#{@etag}"
98
+ end
99
+ end
100
+
91
101
  def next_version
92
102
  init_versions
93
103
  @next_version
@@ -208,7 +218,7 @@ module Olelo
208
218
  []
209
219
  else
210
220
  repository.get_children(path, tree_version).sort.map do |name|
211
- Page.new(path/name, tree_version, self)
221
+ Page.new(path/name, tree_version, nil, self)
212
222
  end
213
223
  end
214
224
  end
@@ -41,10 +41,6 @@ module Olelo
41
41
  def ==(other)
42
42
  other.to_s == id
43
43
  end
44
-
45
- def cache_id
46
- "#{@id}-#{@head}"
47
- end
48
44
  end
49
45
 
50
46
  # Difference between versions
@@ -131,13 +127,13 @@ module Olelo
131
127
  raise NotImplementedError
132
128
  end
133
129
 
134
- # Check if path exists
130
+ # Check if path exists and return etag
135
131
  #
136
132
  # @param [String] path
137
133
  # @param [String, Version] version
138
- # @return [Boolean]
134
+ # @return [String]
139
135
  # @api public
140
- def path_exists?(path, version)
136
+ def path_etag(path, version)
141
137
  raise NotImplementedError
142
138
  end
143
139
 
data/lib/olelo/routing.rb CHANGED
@@ -32,8 +32,7 @@ module Olelo
32
32
 
33
33
  catch(:forward) do
34
34
  with_hooks(:request) { perform! }
35
- status, header, body = response.finish
36
- return [status, header, request.head? ? [] : body]
35
+ return response.finish
37
36
  end
38
37
 
39
38
  @app ? @app.call(env) : error!(NotFound.new(@request.path_info))
@@ -195,7 +194,6 @@ module Olelo
195
194
 
196
195
  def get(path, patterns = {}, &block)
197
196
  add_route('GET', path, patterns, &block)
198
- add_route('HEAD', path, patterns, &block)
199
197
  end
200
198
 
201
199
  def put(path, patterns = {}, &block)
data/lib/olelo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Olelo
2
- VERSION = '0.9.6'
2
+ VERSION = '0.9.7'
3
3
  end
@@ -146,7 +146,7 @@ end
146
146
  # Plug-in the aspect subsystem
147
147
  module ::Olelo::PageHelper
148
148
  def render_page(page)
149
- Cache.cache("include-#{page.path}-#{page.version.cache_id}", update: no_cache?, defer: true) do |context|
149
+ Cache.cache("include-#{page.path}-#{page.etag}", update: no_cache?, defer: true) do |context|
150
150
  begin
151
151
  context = Context.new(page: page, params: {included: true})
152
152
  Aspect.find!(page, layout: true).call(context, page)
@@ -162,7 +162,7 @@ class ::Olelo::Application
162
162
  def show_page
163
163
  params[:aspect] ||= 'subpages' if params[:path].to_s.ends_with? '/'
164
164
  @selected_aspect, layout, header, content =
165
- Cache.cache("aspect-#{page.path}-#{page.version.cache_id}-#{build_query(params)}",
165
+ Cache.cache("aspect-#{page.path}-#{page.etag}-#{build_query(params)}",
166
166
  update: no_cache?, defer: true) do |cache|
167
167
  aspect = Aspect.find!(page, name: params[:aspect])
168
168
  cache.disable! if !aspect.cacheable?
@@ -172,6 +172,7 @@ class ::Olelo::Application
172
172
  context.header['Content-Type'] ||= page.mime.to_s if !aspect.layout?
173
173
  [aspect.name, aspect.layout?, context.header.to_hash, result]
174
174
  end
175
+
175
176
  self.response.header.merge!(header)
176
177
 
177
178
  @menu_versions = true
@@ -186,18 +187,15 @@ class ::Olelo::Application
186
187
 
187
188
  hook :menu do |menu|
188
189
  if menu.name == :actions && view_menu = menu[:view]
189
- Cache.cache("aspect-menu-#{page.path}-#{page.version.cache_id}-#{@selected_aspect}",
190
- update: no_cache?, defer: true) do
191
- aspects = Aspect.find_all(page).select {|a| !a.hidden? || a.name == @selected_aspect || a.name == page.attributes['aspect'] }.map do |a|
192
- [Locale.translate("aspect_#{a.name}", fallback: titlecase(a.name)), a]
193
- end.sort_by(&:first)
194
- aspects.select {|label, a| a.layout? }.map do |label, a|
195
- MenuItem.new(a.name, label: label, href: build_path(page, aspect: a.name), class: a.name == @selected_aspect ? 'selected' : nil)
196
- end +
197
- aspects.reject {|label, a| a.layout? }.map do |label, a|
198
- MenuItem.new(a.name, label: label, href: build_path(page, aspect: a.name), class: 'download')
199
- end
200
- end.each {|item| view_menu << item }
190
+ aspects = Aspect.find_all(page).select {|a| !a.hidden? || a.name == @selected_aspect || a.name == page.attributes['aspect'] }.map do |a|
191
+ [Locale.translate("aspect_#{a.name}", fallback: titlecase(a.name)), a]
192
+ end.sort_by(&:first)
193
+ aspects.select {|label, a| a.layout? }.each do |label, a|
194
+ view_menu << MenuItem.new(a.name, label: label, href: build_path(page, aspect: a.name), class: a.name == @selected_aspect ? 'selected' : nil)
195
+ end
196
+ aspects.reject {|label, a| a.layout? }.each do |label, a|
197
+ view_menu << MenuItem.new(a.name, label: label, href: build_path(page, aspect: a.name), class: 'download')
198
+ end
201
199
  end
202
200
  end
203
201
  end
data/plugins/blog/main.rb CHANGED
@@ -10,7 +10,7 @@ end
10
10
  Tags::Tag.define 'menu', optional: 'path', description: 'Show blog menu', dynamic: true do |context, attrs, content|
11
11
  page = Page.find(attrs[:path]) rescue nil
12
12
  if page
13
- Cache.cache("blog-#{page.path}-#{page.version.cache_id}", update: no_cache?(context.request.env), defer: true) do
13
+ Cache.cache("blog-#{page.path}-#{page.etag}", update: no_cache?(context.request.env), defer: true) do
14
14
  years = {}
15
15
  page.children.each do |child|
16
16
  (years[child.version.date.year] ||= [])[child.version.date.month] = true
@@ -1,4 +1,6 @@
1
1
  $(function() {
2
+ "use strict";
3
+
2
4
  var textarea = $('#edit-content');
3
5
  if (textarea.length == 1) {
4
6
  textarea.hide().before('<div id="ace-editor" style="position:relative; width:100%; height: 40em"/>');
@@ -1,10 +1,10 @@
1
1
  (function(){var e=function(){var g=typeof document.selection!=="undefined"&&typeof document.selection.createRange!=="undefined";return{getSelectionRange:function(a){var b,c,d;a.focus();if(typeof a.selectionStart!=="undefined"){b=a.selectionStart;c=a.selectionEnd}else if(g){b=document.selection.createRange();c=b.text.length;if(b.parentElement()!==a)throw"Unable to get selection range.";if(a.type==="textarea"){d=b.duplicate();d.moveToElementText(a);d.setEndPoint("EndToEnd",b);b=d.text.length-c}else{a=
2
2
  a.createTextRange();a.setEndPoint("EndToStart",b);b=a.text.length}c=b+c}else throw"Unable to get selection range.";return{start:b,end:c}},getSelectionStart:function(a){return this.getSelectionRange(a).start},getSelectionEnd:function(a){return this.getSelectionRange(a).end},setSelectionRange:function(a,b,c){var d;a.focus();if(typeof c==="undefined")c=b;if(typeof a.selectionStart!=="undefined")a.setSelectionRange(b,c);else if(g){d=a.value;a=a.createTextRange();c-=b+d.slice(b+1,c).split("\n").length-
3
- 1;b-=d.slice(0,b).split("\n").length-1;a.move("character",b);a.moveEnd("character",c);a.select()}else throw"Unable to set selection range.";},getSelectedText:function(a){var b=this.getSelectionRange(a);return a.value.substring(b.start,b.end)},insertText:function(a,b,c,d,h){d=d||c;var i=c+b.length,l=a.value.substring(0,c);d=a.value.substr(d);a.value=l+b+d;h===true?this.setSelectionRange(a,c,i):this.setSelectionRange(a,i)},replaceSelectedText:function(a,b,c){var d=this.getSelectionRange(a);this.insertText(a,
3
+ 1;b-=d.slice(0,b).split("\n").length-1;a.move("character",b);a.moveEnd("character",c);a.select()}else throw"Unable to set selection range.";},getSelectedText:function(a){var b=this.getSelectionRange(a);return a.value.substring(b.start,b.end)},insertText:function(a,b,c,d,h){d=d||c;var i=c+b.length,k=a.value.substring(0,c);d=a.value.substr(d);a.value=k+b+d;h===true?this.setSelectionRange(a,c,i):this.setSelectionRange(a,i)},replaceSelectedText:function(a,b,c){var d=this.getSelectionRange(a);this.insertText(a,
4
4
  b,d.start,d.end,c)},wrapSelectedText:function(a,b,c,d){b=b+this.getSelectedText(a)+c;this.replaceSelectedText(a,b,d)}}}();window.Selection=e})();
5
5
  (function(e){e.fn.extend({getSelectionRange:function(){return Selection.getSelectionRange(this[0])},getSelectionStart:function(){return Selection.getSelectionStart(this[0])},getSelectionEnd:function(){return Selection.getSelectionEnd(this[0])},getSelectedText:function(){return Selection.getSelectedText(this[0])},setSelectionRange:function(g,a){return this.each(function(){Selection.setSelectionRange(this,g,a)})},insertText:function(g,a,b,c){return this.each(function(){Selection.insertText(this,g,a,
6
6
  b,c)})},replaceSelectedText:function(g,a){return this.each(function(){Selection.replaceSelectedText(this,g,a)})},wrapSelectedText:function(g,a,b){return this.each(function(){Selection.wrapSelectedText(this,g,a,b)})}})})(jQuery);(function(e){var g={creole:{link:["[[","link text","]]"],bold:["**","bold text","**"],italic:["//","italic text","//"],ul:["* ","list item","",true],ol:["# ","list item","",true],h1:["= ","headline","",true],h2:["== ","headline","",true],h3:["=== ","headline","",true],sub:["~~","subscript","~~"],sup:["^^","superscript","^^"],del:["--","deleted text","--"],ins:["++","inserted text","++"],image:["{{","image","}}"],preformatted:["{{{","preformatted","}}}"]},markdown:{link:function(a){return(a=prompt("link target:",
7
7
  a))?["[","link text","]("+a+")"]:null},bold:["**","bold text","**"],italic:["*","italic text","*"],ul:["* ","list item","",true],ol:["1. ","list item","",true],h1:["","headline","\n========",true],h2:["","headline","\n--------",true],image:function(a){return(a=prompt("image path:",a))?["![","image alt text","]("+a+")"]:null},preformatted:[" ","preformatted","",true]},orgmode:{bold:["*","bold text","*"],italic:["/","italic text","/"],ul:["- ","list item",""],ol:["1. ","list item",""],h1:["* ","headline",
8
8
  ""],h2:["** ","headline",""],h3:["*** ","headline",""]},textile:{link:function(a){return(a=prompt("link target:",a))?['"',"link text",'":'+a]:null},bold:["*","bold text","*"],italic:["_","italic text","_"],ul:["* ","list item","",true],ol:["# ","list item","",true],h1:["h1. ","headline","",true],h2:["h2. ","headline","",true],h3:["h3. ","headline","",true],em:["_","emphasized text","_"],sub:["~","subscript","~"],sup:["^","superscript","^"],del:["-","deleted text","-"],ins:["+","inserted text","+"],
9
- image:["!","image","!"]}};e.fn.markupEditor=function(a){if(a=g[a]){var b=e('<ul class="button-bar" id="markup-editor"/>'),c=[];for(k in a)c.push(k);c.sort();for(var d=0;d<c.length;++d)b.append('<li><a href="#" id="markup-editor-'+c[d]+'">'+c[d]+"</a></li>");this.before(b);var h=this;e("a",b).click(function(){var i=a[this.id.substr(14)],l=h.getSelectedText();if(typeof i=="function")i=i(l);if(i){var f=h.getSelectionRange(),j=i[0],n=i[1],m=i[2];if(i[3]){h.setSelectionRange(f.start-1,f.start);if(f.start!==
10
- 0&&h.getSelectedText()!="\n")j="\n"+j;h.setSelectionRange(f.end,f.end+1);if(h.getSelectedText()!="\n")m+="\n"}if(f.start==f.end){h.insertText(j+n+m,f.start,f.start,false);h.setSelectionRange(f.start+j.length,f.start+j.length+n.length)}else h.insertText(j+l+m,f.start,f.end,false)}return false})}}})(jQuery);$(function(){var e=Olelo.page_mime;if(e=="application/x-empty"||e=="inode/directory")e=Olelo.default_mime;(e=/text\/x-(\w+)/.exec(e))&&$("#edit-content").markupEditor(e[1])});
9
+ image:["!","image","!"]}};e.fn.markupEditor=function(a){if(a=g[a]){var b=e('<ul class="button-bar" id="markup-editor"/>'),c=[];for(var d in a)c.push(d);c.sort();for(d=0;d<c.length;++d)b.append('<li><a href="#" id="markup-editor-'+c[d]+'">'+c[d]+"</a></li>");this.before(b);var h=this;e("a",b).click(function(){var i=a[this.id.substr(14)],k=h.getSelectedText();if(typeof i=="function")i=i(k);if(i){var f=h.getSelectionRange(),j=i[0],m=i[1],l=i[2];if(i[3]){h.setSelectionRange(f.start-1,f.start);if(f.start!==
10
+ 0&&h.getSelectedText()!="\n")j="\n"+j;h.setSelectionRange(f.end,f.end+1);if(h.getSelectedText()!="\n")l+="\n"}if(f.start==f.end){h.insertText(j+m+l,f.start,f.start,false);h.setSelectionRange(f.start+j.length,f.start+j.length+m.length)}else h.insertText(j+k+l,f.start,f.end,false)}return false})}}})(jQuery);$(function(){var e=Olelo.page_mime;if(e=="application/x-empty"||e=="inode/directory")e=Olelo.default_mime;(e=/text\/x-(\w+)/.exec(e))&&$("#edit-content").markupEditor(e[1])});
@@ -1,4 +1,6 @@
1
1
  (function($) {
2
+ "use strict";
3
+
2
4
  var markups = {
3
5
  creole: {
4
6
  link: ['[[', 'link text', ']]'],
@@ -97,7 +99,7 @@
97
99
  var list = $('<ul class="button-bar" id="markup-editor"/>');
98
100
 
99
101
  var buttons = [];
100
- for (k in markup) {
102
+ for (var k in markup) {
101
103
  buttons.push(k);
102
104
  }
103
105
  buttons.sort();
@@ -1,4 +1,6 @@
1
1
  $(function() {
2
+ "use strict";
3
+
2
4
  var mime = Olelo.page_mime;
3
5
  if (mime == 'application/x-empty' || mime == 'inode/directory') {
4
6
  mime = Olelo.default_mime;
@@ -1,15 +1,34 @@
1
1
  description 'Markdown nowiki filter'
2
2
 
3
+ # Embeds indented markdown text blocks in <notags> tags
4
+ # and adds <notags> around ``texts``
3
5
  Filter.create :markdown_nowiki do |context, content|
4
6
  output = ''
5
- until content.blank?
6
- case content
7
- when /(\A( {4}|\t).*)|(\A``.*?``)|(\A`[^`]*`)/
8
- output << "<notags>#{$&}</notags>"
9
- when /(\A[^`\n]+)|(\A\n+)/
10
- output << $&
7
+ block, state = nil, nil
8
+ content.each_line do |line|
9
+ if block
10
+ if line =~ /\A( {4}|\t)/
11
+ block << line
12
+ state = :in
13
+ elsif line =~ /\A\s*\Z/
14
+ block << line
15
+ state = :after if state == :in
16
+ elsif state == :after
17
+ output << "<notags>#{block}</notags>"
18
+ block = nil
19
+ else
20
+ block << line
21
+ line = block
22
+ block = nil
23
+ end
24
+ elsif line =~ /\A\s*\Z/
25
+ block, state = line, :before
26
+ end
27
+
28
+ unless block
29
+ output << line.gsub(/``.*?``|`[^`]*`/, '<notags>\0</notags>')
11
30
  end
12
- content = $'
13
31
  end
32
+ output << (state == :before ? block : "<notags>#{block}</notags>") if block
14
33
  output
15
34
  end
@@ -1,4 +1,6 @@
1
1
  $(function() {
2
+ "use strict";
3
+
2
4
  function initFancybox() {
3
5
  $('a.fancybox').each(function() {
4
6
  var href = this.href.replace(/aspect=\w+/g, '');
@@ -0,0 +1,30 @@
1
+ description 'Cache page fragments'
2
+ dependencies 'utils/cache'
3
+
4
+ class ::Olelo::Application
5
+ def cache_id
6
+ @cache_id ||= page ? "#{page.path}-#{page.etag}-#{build_query(params)}" : "#{request.path_info}-#{build_query(params)}"
7
+ end
8
+
9
+ redefine_method :menu do |name|
10
+ Cache.cache("menu-#{name}-#{cache_id}", update: no_cache?) do |cache|
11
+ super(name)
12
+ end
13
+ end
14
+
15
+ redefine_method :head do
16
+ Cache.cache("head-#{cache_id}", update: no_cache?) do |cache|
17
+ super()
18
+ end
19
+ end
20
+
21
+ redefine_method :footer do |content = nil, &block|
22
+ if block_given? || content
23
+ super(content, &block)
24
+ else
25
+ Cache.cache("footer-#{cache_id}", update: no_cache?) do |cache|
26
+ super()
27
+ end
28
+ end
29
+ end
30
+ end
@@ -24,9 +24,13 @@ class GitrbRepository < Repository
24
24
  end
25
25
 
26
26
  # @override
27
- def path_exists?(path, version)
27
+ def path_etag(path, version)
28
28
  check_path(path)
29
- !get_object(path, version).nil? rescue false
29
+ if id = get_object(path, version).id rescue nil
30
+ [id,
31
+ (get_object(path + CONTENT_EXT, version).id rescue nil),
32
+ (get_object(path + ATTRIBUTE_EXT, version).id rescue nil)].join('-')
33
+ end
30
34
  end
31
35
 
32
36
  # @override
@@ -73,7 +77,7 @@ class GitrbRepository < Repository
73
77
  if object
74
78
  content = object.data
75
79
  # Try to force utf-8 encoding and revert to old encoding if this doesn't work
76
- content.try_encoding(Encoding.default_encoding)
80
+ content.try_encoding(Encoding.default_external)
77
81
  else
78
82
  ''
79
83
  end
@@ -238,10 +238,14 @@ class RuggedRepository < Repository
238
238
  commit_to_version(@git.last_commit)
239
239
  end
240
240
 
241
- def path_exists?(path, version)
241
+ def path_etag(path, version)
242
242
  commit = @git.lookup(version.to_s)
243
243
  raise 'Not a commit' unless Rugged::Commit === commit
244
- path.blank? || commit.tree.path(path) != nil rescue nil
244
+ if oid = oid_by_path(commit, path)
245
+ [oid,
246
+ oid_by_path(commit, path + CONTENT_EXT),
247
+ oid_by_path(commit, path + ATTRIBUTE_EXT)].join('-')
248
+ end
245
249
  end
246
250
 
247
251
  def get_version(version = nil)
@@ -311,15 +315,17 @@ class RuggedRepository < Repository
311
315
  def get_children(path, version)
312
316
  commit = @git.lookup(version.to_s)
313
317
  raise 'Not a commit' unless Rugged::Commit === commit
314
- object = object_by_path(commit.tree, path)
315
- Rugged::Tree === object ? object.map {|e| e[:name].force_encoding(Encoding.default_external) }.reject {|name| reserved_name?(name) } : []
318
+ object = object_by_path(commit, path)
319
+ Rugged::Tree === object ? object.map do |e|
320
+ e[:name].force_encoding(Encoding.default_external)
321
+ end.reject {|name| reserved_name?(name) } : []
316
322
  end
317
323
 
318
324
  def get_content(path, version)
319
325
  commit = @git.lookup(version.to_s)
320
326
  raise 'Not a commit' unless Rugged::Commit === commit
321
- object = object_by_path(commit.tree, path)
322
- object = object_by_path(commit.tree, path + CONTENT_EXT) if Rugged::Tree === object
327
+ object = object_by_path(commit, path)
328
+ object = object_by_path(commit, path + CONTENT_EXT) if Rugged::Tree === object
323
329
  Rugged::Blob === object ? object.content.try_encoding(Encoding.default_external) : ''
324
330
  end
325
331
 
@@ -327,7 +333,7 @@ class RuggedRepository < Repository
327
333
  commit = @git.lookup(version.to_s)
328
334
  raise 'Not a commit' unless Rugged::Commit === commit
329
335
  path += ATTRIBUTE_EXT
330
- object = object_by_path(commit.tree, path)
336
+ object = object_by_path(commit, path)
331
337
  object ? YAML.load(object.content) : {}
332
338
  end
333
339
 
@@ -393,17 +399,23 @@ class RuggedRepository < Repository
393
399
  def path_changed?(c, path)
394
400
  return true if path.blank?
395
401
  ref1, ref2, ref3 = nil, nil, nil
396
- (c.parents.empty? && (ref1 ||= c.tree.path(path) rescue {})) || c.parents.any? do |parent|
397
- (ref1 ||= c.tree.path(path) rescue {}) != (parent.tree.path(path) rescue {}) ||
398
- (ref2 ||= c.tree.path(path + ATTRIBUTE_EXT) rescue {}) != (parent.tree.path(path + ATTRIBUTE_EXT) rescue {}) ||
399
- (ref3 ||= c.tree.path(path + CONTENT_EXT) rescue {}) != (parent.tree.path(path + CONTENT_EXT) rescue {})
402
+ (c.parents.empty? && (ref1 ||= oid_by_path(c, path))) || c.parents.any? do |parent|
403
+ (ref1 ||= oid_by_path(c, path)) != (oid_by_path(parent, path)) ||
404
+ (ref2 ||= oid_by_path(c, path + ATTRIBUTE_EXT)) != (oid_by_path(parent, path + ATTRIBUTE_EXT)) ||
405
+ (ref3 ||= oid_by_path(c, path + CONTENT_EXT)) != (oid_by_path(parent, path + CONTENT_EXT))
400
406
  end
401
407
  end
402
408
 
403
- def object_by_path(tree, path)
404
- return tree if path.blank?
405
- ref = tree.path(path)
406
- @git.lookup(ref[:oid])
409
+ def oid_by_path(commit, path)
410
+ return commit.tree_oid if path.blank?
411
+ commit.tree.path(path)[:oid]
412
+ rescue Rugged::IndexerError
413
+ nil
414
+ end
415
+
416
+ def object_by_path(commit, path)
417
+ return commit.tree if path.blank?
418
+ @git.lookup(commit.tree.path(path)[:oid])
407
419
  rescue Rugged::IndexerError
408
420
  nil
409
421
  end
@@ -1,6 +1,8 @@
1
1
  // Ajax Tree View
2
2
  // Written by Daniel Mendler, 2009
3
3
  (function($) {
4
+ "use strict";
5
+
4
6
  // Create treeview
5
7
  // $('div#id').treeView(...);
6
8
  $.fn.treeView = function(options) {
@@ -1,4 +1,6 @@
1
1
  $(function() {
2
+ "use strict";
3
+
2
4
  // Add treeview translations
3
5
  $.translations({
4
6
  en: {
@@ -1,6 +1,8 @@
1
1
  // Simple storage plugin
2
2
  // Written by Daniel Mendler
3
3
  (function($) {
4
+ "use strict";
5
+
4
6
  var storage = {}, data = {};
5
7
  try {
6
8
  if (window.localStorage) {
@@ -1,6 +1,8 @@
1
1
  // Very simple i18n plugin
2
2
  // Written by Daniel Mendler
3
3
  (function($) {
4
+ "use strict";
5
+
4
6
  var locale = null, translations = {};
5
7
  $.translations = function(t) {
6
8
  for (var lang in t) {
@@ -1,4 +1,6 @@
1
1
  (function($) {
2
+ "use strict";
3
+
2
4
  // Add treeview translations
3
5
  $.translations({
4
6
  en: {
@@ -1,4 +1,6 @@
1
1
  (function($) {
2
+ "use strict";
3
+
2
4
  $.fn.historyTable = function() {
3
5
  $('thead tr', this).prepend('<th class="compare"><button>&#177;</button></th>');
4
6
  $('tbody tr', this).each(function() {
@@ -3,6 +3,8 @@
3
3
  // $('#page_element').bind('pageLoaded', function() {});
4
4
  // Written by Daniel Mendler
5
5
  (function($) {
6
+ "use strict";
7
+
6
8
  $.fn.pagination = function(links) {
7
9
  var page = this;
8
10
 
@@ -1,6 +1,8 @@
1
1
  // Simple, unobtrusive tab widget
2
2
  // Written by Daniel Mendler
3
3
  (function($) {
4
+ "use strict";
5
+
4
6
  $.fn.tabWidget = function(options) {
5
7
  var store = options && options.store;
6
8
  var selected = null;
@@ -1,6 +1,8 @@
1
1
  // Replace timestamps with relative time
2
2
  // Written by Daniel Mendler
3
3
  (function($) {
4
+ "use strict";
5
+
4
6
  $.translations({
5
7
  en: {
6
8
  less_than_a_minute_ago: 'less than a minute ago',
@@ -1,6 +1,8 @@
1
1
  // Underline text in elements. Especially useful for accesskeys.
2
2
  // Written by Daniel Mendler
3
3
  (function($) {
4
+ "use strict";
5
+
4
6
  $.extend($.fn, {
5
7
  // Underline text
6
8
  underlineText: function(str) {
@@ -1,4 +1,6 @@
1
1
  (function($) {
2
+ "use strict";
3
+
2
4
  $.widget('ui.combobox', {
3
5
  _create: function() {
4
6
  var input = this.element;
@@ -1,6 +1,8 @@
1
1
  // Olelo bootstrap
2
2
  // Written by Daniel Mendler
3
3
  $(function() {
4
+ "use strict";
5
+
4
6
  $('html').removeClass('no-js').addClass('js');
5
7
  function pageLoaded() {
6
8
  $('#upload-path', this).each(function() {
data/test/request_test.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  require 'helper'
2
2
  require 'olelo/middleware/force_encoding'
3
3
  require 'olelo/middleware/degrade_mime_type'
4
+ require 'olelo/middleware/ua_header'
4
5
  require 'rack/relative_redirect'
5
- require 'rack/session/pool'
6
6
 
7
7
  class Bacon::Context
8
8
  include Rack::Test::Methods
@@ -74,7 +74,9 @@ describe 'requests' do
74
74
  use Rack::MethodOverride
75
75
  use Olelo::Middleware::ForceEncoding
76
76
  use Olelo::Middleware::DegradeMimeType
77
+ use Olelo::Middleware::UAHeader
77
78
  #use Rack::RelativeRedirect
79
+ use Rack::Head
78
80
  run Olelo::Application.new
79
81
  end
80
82
  end
data/views/show.slim CHANGED
@@ -1,7 +1,7 @@
1
1
  - title page.title
2
- = define_block :version_link do
3
- a.version href=build_path(page, version: page.version, force_version: true) title=page.version = page.version.short
4
2
  = footer do
3
+ = define_block :version_link do
4
+ a.version href=build_path(page, version: page.version, force_version: true) title=page.version = page.version.short
5
5
  == :version_by.t(version: blocks[:version_link], author: escape_html(page.version.author.name), date: date(page.version.date))
6
6
  - if !page.attributes['no_title']
7
7
  h1= title
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: olelo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.6
4
+ version: 0.9.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-05 00:00:00.000000000 Z
12
+ date: 2012-11-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
16
- requirement: !ruby/object:Gem::Requirement
16
+ requirement: &9838140 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,15 +21,10 @@ dependencies:
21
21
  version: 1.3.6
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ~>
28
- - !ruby/object:Gem::Version
29
- version: 1.3.6
24
+ version_requirements: *9838140
30
25
  - !ruby/object:Gem::Dependency
31
26
  name: slim
32
- requirement: !ruby/object:Gem::Requirement
27
+ requirement: &9836960 !ruby/object:Gem::Requirement
33
28
  none: false
34
29
  requirements:
35
30
  - - ~>
@@ -37,15 +32,10 @@ dependencies:
37
32
  version: 1.3.3
38
33
  type: :runtime
39
34
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ~>
44
- - !ruby/object:Gem::Version
45
- version: 1.3.3
35
+ version_requirements: *9836960
46
36
  - !ruby/object:Gem::Dependency
47
37
  name: creole
48
- requirement: !ruby/object:Gem::Requirement
38
+ requirement: &9835660 !ruby/object:Gem::Requirement
49
39
  none: false
50
40
  requirements:
51
41
  - - ~>
@@ -53,15 +43,10 @@ dependencies:
53
43
  version: 0.5.0
54
44
  type: :runtime
55
45
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: 0.5.0
46
+ version_requirements: *9835660
62
47
  - !ruby/object:Gem::Dependency
63
48
  name: nokogiri
64
- requirement: !ruby/object:Gem::Requirement
49
+ requirement: &9833880 !ruby/object:Gem::Requirement
65
50
  none: false
66
51
  requirements:
67
52
  - - ~>
@@ -69,15 +54,10 @@ dependencies:
69
54
  version: 1.5.5
70
55
  type: :runtime
71
56
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ~>
76
- - !ruby/object:Gem::Version
77
- version: 1.5.5
57
+ version_requirements: *9833880
78
58
  - !ruby/object:Gem::Dependency
79
59
  name: mimemagic
80
- requirement: !ruby/object:Gem::Requirement
60
+ requirement: &9832440 !ruby/object:Gem::Requirement
81
61
  none: false
82
62
  requirements:
83
63
  - - ~>
@@ -85,15 +65,10 @@ dependencies:
85
65
  version: 0.2.0
86
66
  type: :runtime
87
67
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ~>
92
- - !ruby/object:Gem::Version
93
- version: 0.2.0
68
+ version_requirements: *9832440
94
69
  - !ruby/object:Gem::Dependency
95
70
  name: rack
96
- requirement: !ruby/object:Gem::Requirement
71
+ requirement: &9829740 !ruby/object:Gem::Requirement
97
72
  none: false
98
73
  requirements:
99
74
  - - ~>
@@ -101,15 +76,10 @@ dependencies:
101
76
  version: 1.4.1
102
77
  type: :runtime
103
78
  prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
- requirements:
107
- - - ~>
108
- - !ruby/object:Gem::Version
109
- version: 1.4.1
79
+ version_requirements: *9829740
110
80
  - !ruby/object:Gem::Dependency
111
81
  name: redcarpet
112
- requirement: !ruby/object:Gem::Requirement
82
+ requirement: &9829040 !ruby/object:Gem::Requirement
113
83
  none: false
114
84
  requirements:
115
85
  - - ~>
@@ -117,15 +87,10 @@ dependencies:
117
87
  version: 2.2.2
118
88
  type: :runtime
119
89
  prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
- requirements:
123
- - - ~>
124
- - !ruby/object:Gem::Version
125
- version: 2.2.2
90
+ version_requirements: *9829040
126
91
  - !ruby/object:Gem::Dependency
127
92
  name: rugged
128
- requirement: !ruby/object:Gem::Requirement
93
+ requirement: &9828020 !ruby/object:Gem::Requirement
129
94
  none: false
130
95
  requirements:
131
96
  - - ~>
@@ -133,15 +98,10 @@ dependencies:
133
98
  version: 0.17.0.b7
134
99
  type: :runtime
135
100
  prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
- requirements:
139
- - - ~>
140
- - !ruby/object:Gem::Version
141
- version: 0.17.0.b7
101
+ version_requirements: *9828020
142
102
  - !ruby/object:Gem::Dependency
143
103
  name: evaluator
144
- requirement: !ruby/object:Gem::Requirement
104
+ requirement: &9826260 !ruby/object:Gem::Requirement
145
105
  none: false
146
106
  requirements:
147
107
  - - ~>
@@ -149,15 +109,10 @@ dependencies:
149
109
  version: 0.1.6
150
110
  type: :runtime
151
111
  prerelease: false
152
- version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
- requirements:
155
- - - ~>
156
- - !ruby/object:Gem::Version
157
- version: 0.1.6
112
+ version_requirements: *9826260
158
113
  - !ruby/object:Gem::Dependency
159
114
  name: rake
160
- requirement: !ruby/object:Gem::Requirement
115
+ requirement: &9824340 !ruby/object:Gem::Requirement
161
116
  none: false
162
117
  requirements:
163
118
  - - ! '>='
@@ -165,15 +120,10 @@ dependencies:
165
120
  version: 0.8.7
166
121
  type: :development
167
122
  prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
169
- none: false
170
- requirements:
171
- - - ! '>='
172
- - !ruby/object:Gem::Version
173
- version: 0.8.7
123
+ version_requirements: *9824340
174
124
  - !ruby/object:Gem::Dependency
175
125
  name: sass
176
- requirement: !ruby/object:Gem::Requirement
126
+ requirement: &9822920 !ruby/object:Gem::Requirement
177
127
  none: false
178
128
  requirements:
179
129
  - - ! '>='
@@ -181,15 +131,10 @@ dependencies:
181
131
  version: 3.1.0
182
132
  type: :development
183
133
  prerelease: false
184
- version_requirements: !ruby/object:Gem::Requirement
185
- none: false
186
- requirements:
187
- - - ! '>='
188
- - !ruby/object:Gem::Version
189
- version: 3.1.0
134
+ version_requirements: *9822920
190
135
  - !ruby/object:Gem::Dependency
191
136
  name: bacon
192
- requirement: !ruby/object:Gem::Requirement
137
+ requirement: &9822060 !ruby/object:Gem::Requirement
193
138
  none: false
194
139
  requirements:
195
140
  - - ~>
@@ -197,15 +142,10 @@ dependencies:
197
142
  version: 1.1.0
198
143
  type: :development
199
144
  prerelease: false
200
- version_requirements: !ruby/object:Gem::Requirement
201
- none: false
202
- requirements:
203
- - - ~>
204
- - !ruby/object:Gem::Version
205
- version: 1.1.0
145
+ version_requirements: *9822060
206
146
  - !ruby/object:Gem::Dependency
207
147
  name: rack-test
208
- requirement: !ruby/object:Gem::Requirement
148
+ requirement: &9812980 !ruby/object:Gem::Requirement
209
149
  none: false
210
150
  requirements:
211
151
  - - ~>
@@ -213,12 +153,7 @@ dependencies:
213
153
  version: 0.6.2
214
154
  type: :development
215
155
  prerelease: false
216
- version_requirements: !ruby/object:Gem::Requirement
217
- none: false
218
- requirements:
219
- - - ~>
220
- - !ruby/object:Gem::Version
221
- version: 0.6.2
156
+ version_requirements: *9812980
222
157
  description: Olelo is a git-based wiki which supports many markup languages, tags,
223
158
  embedded TeX and much more. It can be extended through plugins.
224
159
  email:
@@ -355,6 +290,7 @@ files:
355
290
  - plugins/misc/fancybox/script/01-jquery.easing.js
356
291
  - plugins/misc/fancybox/script/02-jquery.fancybox.js
357
292
  - plugins/misc/fancybox/script/init.js
293
+ - plugins/misc/fragment_cache.rb
358
294
  - plugins/misc/system.rb
359
295
  - plugins/misc/variables.rb
360
296
  - plugins/misc/webdav.rb
@@ -533,8 +469,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
533
469
  version: '0'
534
470
  requirements: []
535
471
  rubyforge_project: olelo
536
- rubygems_version: 1.8.23
472
+ rubygems_version: 1.8.15
537
473
  signing_key:
538
474
  specification_version: 3
539
475
  summary: Olelo is a git-based wiki.
540
476
  test_files: []
477
+ has_rdoc: