Soks 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. data/README.txt +5 -4
  2. data/bin/soks-create-wiki.rb +153 -19
  3. data/contrib/easyprompt.rb +58 -0
  4. data/contrib/easyprompt_licence.txt +504 -0
  5. data/contrib/redcloth-2.0.11.rb +3 -1
  6. data/lib/authenticators.rb +18 -2
  7. data/lib/soks-helpers.rb +207 -157
  8. data/lib/soks-model.rb +131 -114
  9. data/lib/soks-servlet.rb +54 -35
  10. data/lib/soks-storage.rb +134 -0
  11. data/lib/soks-upgrade-0.0.2.rb +70 -0
  12. data/lib/soks-utils.rb +129 -19
  13. data/lib/soks-view.rb +136 -62
  14. data/lib/soks.rb +3 -1
  15. data/{template → templates/default}/attachment/logo.png +0 -0
  16. data/templates/default/attachment/logo.tiff +0 -0
  17. data/templates/default/attachment/newpage.js +41 -0
  18. data/templates/default/attachment/print_stylesheet.css +7 -0
  19. data/templates/default/attachment/rss.png +0 -0
  20. data/{template → templates/default}/attachment/stylesheet.css +44 -17
  21. data/templates/default/banned_titles.txt +31 -0
  22. data/templates/default/content/Bug%3A%20In%20a%20list%20of%20links%2C%20the%20last%20link%20is%20sometimes%20not%20linked.textile +10 -0
  23. data/templates/default/content/Bug%3A%20Symbols%20are%20not%20always%20correctly%20rendered%20in%20html.textile +3 -0
  24. data/templates/default/content/Bug%3A%20Uploads%20are%20not%20password%20protected.textile +3 -0
  25. data/templates/default/content/How%20to%20administrate%20this%20wiki.textile +62 -0
  26. data/templates/default/content/How%20to%20change%20the%20way%20this%20wiki%20looks.textile +30 -0
  27. data/templates/default/content/How%20to%20export%20a%20site%20from%20this%20wiki.textile +60 -0
  28. data/{template → templates/default}/content/How%20to%20hack%20soks.textile +3 -2
  29. data/{template → templates/default}/content/How%20to%20import%20a%20site%20from%20instiki.textile +1 -1
  30. data/templates/default/content/How%20to%20use%20this%20wiki.textile +27 -0
  31. data/templates/default/content/List%20of%20changes.textile +35 -0
  32. data/{template → templates/default}/content/Picture%20of%20a%20pair%20of%20soks.textile +0 -0
  33. data/{template → templates/default}/content/Soks%20Licence.textile +0 -0
  34. data/templates/default/content/home%20page.textile +17 -0
  35. data/templates/default/start.rb +94 -0
  36. data/templates/default/version.txt +1 -0
  37. data/{template → templates/default}/views/Page_content.rhtml +0 -0
  38. data/templates/default/views/Page_edit.rhtml +61 -0
  39. data/templates/default/views/Page_meta.rhtml +40 -0
  40. data/templates/default/views/Page_print.rhtml +6 -0
  41. data/templates/default/views/Page_revisions.rhtml +19 -0
  42. data/templates/default/views/Page_rss.rhtml +55 -0
  43. data/{template → templates/default}/views/Page_search_results.rhtml +1 -1
  44. data/templates/default/views/Page_view.rhtml +4 -0
  45. data/templates/default/views/UploadPage_edit.rhtml +38 -0
  46. data/templates/default/views/frame.rhtml +41 -0
  47. data/templates/default/views/messages.yaml +6 -0
  48. data/templates/instiki/attachment/header_backdrop.png +0 -0
  49. data/templates/instiki/attachment/instiki_style_sheet.css +199 -0
  50. data/templates/instiki/attachment/logo.tiff +0 -0
  51. data/templates/instiki/attachment/logotext.png +0 -0
  52. data/templates/instiki/attachment/newpage.js +41 -0
  53. data/templates/instiki/attachment/rss.png +0 -0
  54. data/templates/instiki/banned_titles.txt +31 -0
  55. data/templates/instiki/content/AutomaticSummary.textile +24 -0
  56. data/templates/instiki/content/How%20to%20export%20a%20site%20from%20this%20wiki.textile +60 -0
  57. data/templates/instiki/content/How%20to%20hack%20soks.textile +61 -0
  58. data/templates/instiki/content/How%20to%20import%20a%20site%20from%20instiki.textile +13 -0
  59. data/{template → templates/instiki}/content/Improving%20the%20style%20of%20this%20wiki.textile +2 -2
  60. data/templates/instiki/content/Known%20bugs.textile +8 -0
  61. data/templates/instiki/content/List%20of%20changes.textile +34 -0
  62. data/templates/instiki/content/Picture%20of%20a%20pair%20of%20soks.textile +1 -0
  63. data/templates/instiki/content/Pointers%20on%20adjusting%20the%20settings.textile +62 -0
  64. data/templates/instiki/content/Pointers%20on%20how%20to%20use%20this%20wiki.textile +27 -0
  65. data/templates/instiki/content/Recent%20Blog%20Entries.textile +3 -0
  66. data/templates/instiki/content/Recent%20Changes%20to%20This%20Site.textile +48 -0
  67. data/templates/instiki/content/Site%20Index.textile +16 -0
  68. data/templates/instiki/content/Soks%20Licence.textile +64 -0
  69. data/{template → templates/instiki}/content/home%20page.textile +9 -4
  70. data/templates/instiki/start.rb +85 -0
  71. data/templates/instiki/version.txt +1 -0
  72. data/templates/instiki/views/Page_content.rhtml +1 -0
  73. data/templates/instiki/views/Page_edit.rhtml +8 -0
  74. data/templates/instiki/views/Page_meta.rhtml +34 -0
  75. data/templates/instiki/views/Page_print.rhtml +6 -0
  76. data/templates/instiki/views/Page_revisions.rhtml +17 -0
  77. data/templates/instiki/views/Page_rss.rhtml +55 -0
  78. data/templates/instiki/views/Page_search_results.rhtml +18 -0
  79. data/templates/instiki/views/Page_view.rhtml +2 -0
  80. data/templates/instiki/views/UploadPage_edit.rhtml +16 -0
  81. data/templates/instiki/views/frame.rhtml +90 -0
  82. data/templates/instiki/views/messages.yaml +6 -0
  83. data/templates/rails/attachment/2colheader.css +77 -0
  84. data/templates/rails/attachment/basics.css +98 -0
  85. data/templates/rails/attachment/header_backdrop.png +0 -0
  86. data/templates/rails/attachment/logo.tiff +0 -0
  87. data/templates/rails/attachment/logotext.png +0 -0
  88. data/templates/rails/attachment/newpage.js +41 -0
  89. data/templates/rails/attachment/rss.png +0 -0
  90. data/templates/rails/banned_titles.txt +31 -0
  91. data/templates/rails/content/AutomaticSummary.textile +24 -0
  92. data/templates/rails/content/How%20to%20export%20a%20site%20from%20this%20wiki.textile +60 -0
  93. data/templates/rails/content/How%20to%20hack%20soks.textile +61 -0
  94. data/templates/rails/content/How%20to%20import%20a%20site%20from%20instiki.textile +13 -0
  95. data/templates/rails/content/Improving%20the%20style%20of%20this%20wiki.textile +30 -0
  96. data/templates/rails/content/Known%20bugs.textile +8 -0
  97. data/templates/rails/content/List%20of%20changes.textile +34 -0
  98. data/templates/rails/content/Picture%20of%20a%20pair%20of%20soks.textile +1 -0
  99. data/templates/rails/content/Pointers%20on%20adjusting%20the%20settings.textile +62 -0
  100. data/templates/rails/content/Pointers%20on%20how%20to%20use%20this%20wiki.textile +27 -0
  101. data/templates/rails/content/Recent%20Blog%20Entries.textile +3 -0
  102. data/templates/rails/content/Recent%20Changes%20to%20This%20Site.textile +48 -0
  103. data/templates/rails/content/Site%20Index.textile +16 -0
  104. data/templates/rails/content/Soks%20Licence.textile +64 -0
  105. data/templates/rails/content/home%20page.textile +23 -0
  106. data/templates/rails/start.rb +85 -0
  107. data/templates/rails/version.txt +1 -0
  108. data/templates/rails/views/Page_content.rhtml +1 -0
  109. data/templates/rails/views/Page_edit.rhtml +61 -0
  110. data/templates/rails/views/Page_meta.rhtml +38 -0
  111. data/templates/rails/views/Page_print.rhtml +6 -0
  112. data/templates/rails/views/Page_revisions.rhtml +19 -0
  113. data/templates/rails/views/Page_rss.rhtml +55 -0
  114. data/templates/rails/views/Page_search_results.rhtml +19 -0
  115. data/templates/rails/views/Page_view.rhtml +3 -0
  116. data/templates/rails/views/UploadPage_edit.rhtml +38 -0
  117. data/templates/rails/views/frame.rhtml +60 -0
  118. data/templates/rails/views/messages.yaml +6 -0
  119. metadata +122 -28
  120. data/template/content/How%20to%20export%20a%20site%20from%20this%20wiki.textile +0 -5
  121. data/template/content/Pointers%20on%20adjusting%20the%20settings.textile +0 -39
  122. data/template/content/Pointers%20on%20how%20to%20use%20this%20wiki.textile +0 -21
  123. data/template/content/Recent%20Changes%20to%20This%20Site.textile +0 -203
  124. data/template/start.rb +0 -74
  125. data/template/views/AttachmentPage_edit.rhtml +0 -36
  126. data/template/views/ImagePage_edit.rhtml +0 -36
  127. data/template/views/Page_edit.rhtml +0 -34
  128. data/template/views/Page_print.rhtml +0 -5
  129. data/template/views/Page_revisions.rhtml +0 -18
  130. data/template/views/Page_rss.rhtml +0 -34
  131. data/template/views/Page_view.rhtml +0 -3
  132. data/template/views/frame.rhtml +0 -34
@@ -529,7 +529,9 @@ class RedCloth < String
529
529
  end unless pre
530
530
  end
531
531
 
532
- line.gsub!( /^(?!\t|<\/?div|<\/?pre|<\/?notextile|<\/?code|$| )(.*)/, "\t<p>\\1</p>" ) unless pre
532
+ # line.gsub!( /^(?!\t|<\/?div|<\/?pre|<\/?notextile|<\/?code|$| )(.*)/, "\t<p>\\1</p>" ) unless pre
533
+
534
+ line.gsub!( /^(?!\t|<\/?div|<\/?pre|<\/?notextile|<\/?code| )(.*)/, "\t<p>\\1</p>" ) unless pre
533
535
 
534
536
  line.gsub!( "<br />", "\n" ) if pre
535
537
  pre = false if line =~ /<\/(pre|notextile)>/i
@@ -5,7 +5,23 @@ require 'base64'
5
5
 
6
6
  module WEBrick
7
7
  module HTTPAuth
8
- class NotAuthentication
8
+
9
+ class NoAuthenticationRequired
10
+
11
+ def authenticate(req, res)
12
+ req.user = req.meta_vars["HTTP_X_FORWARDED_FOR"] || req.meta_vars["REMOTE_ADDR"]
13
+ end
14
+ end
15
+
16
+ class NotPermitted
17
+
18
+ def authenticate(req, res)
19
+ raise WEBrick::HTTPStatus::Unauthorized
20
+ end
21
+
22
+ end
23
+
24
+ class AskForUserName
9
25
 
10
26
  include WEBrick::HTTPAuth::Authenticator
11
27
 
@@ -36,7 +52,7 @@ module WEBrick
36
52
  end
37
53
  end
38
54
 
39
- class OnePasswordAuthentication
55
+ class SiteWidePassword
40
56
  include Authenticator
41
57
 
42
58
  AuthScheme = "Basic"
data/lib/soks-helpers.rb CHANGED
@@ -3,8 +3,8 @@ require 'net/smtp'
3
3
 
4
4
  class AutomaticUpdateCrossLinks
5
5
 
6
- def initialize( wiki )
7
- @wiki = wiki
6
+ def initialize( wiki, view, banned_titles = [] )
7
+ @wiki, @view, @banned_titles = wiki, view, banned_titles
8
8
  @wiki.watch_for( :page_created ) { |event, page| new_page( page ) }
9
9
  @wiki.watch_for( :page_deleted ) { |event, page| delete_page( page ) }
10
10
  @wiki.watch_for( :page_revised ) { |event, page| page_revised( page ) }
@@ -12,208 +12,199 @@ class AutomaticUpdateCrossLinks
12
12
  end
13
13
 
14
14
  def new_page( page )
15
- @wiki.rollingmatch[ page.name ] = page
15
+ return if title_banned? page.name
16
+ @view.rollingmatch[ page.name ] = page
16
17
  titleregex = Regexp.new( page.name, Regexp::IGNORECASE )
17
18
  @wiki.each { |name, linkedpage |
18
- unless name[0,10] == 'Site Index'
19
- @wiki.refresh_redcloth( linkedpage ) if linkedpage.textile =~ titleregex
20
- end
19
+ @view.refresh_redcloth( linkedpage ) if linkedpage.textile =~ titleregex
21
20
  }
22
21
  end
23
22
 
24
23
  def delete_page( page )
25
- @wiki.rollingmatch.delete( page.name )
26
- page.links_to.each { |linkedpage| @wiki.refresh_redcloth( linkedpage ) }
24
+ @view.rollingmatch.delete( page.name )
25
+ page.links_to.each { |linkedpage| @view.refresh_redcloth( linkedpage ) }
27
26
  end
28
27
 
29
28
  def page_revised( page )
30
29
  page.inserted_into.each { |including_page|
31
- @wiki.refresh_redcloth( including_page )
30
+ @view.refresh_redcloth( including_page )
32
31
  }
33
32
  end
34
33
 
35
34
  def update_all_pages
36
- @wiki.each { |pagename, page| @wiki.rollingmatch[ page.name ] = page }
37
- @wiki.each { |pagename, page| @wiki.refresh_redcloth( page ) }
38
- end
39
- end
40
-
41
- class AutomaticRecentChanges
42
-
43
- IGNORED_AUTHORS = /^Automatic/
44
-
45
- def initialize( wiki, lines = 200, pagename = "Recent Changes to This Site", author = "AutomaticRecentChanges" )
46
- @wiki, @lines, @pagename, @author = wiki, lines, pagename, author
47
- @wiki.watch_for( :page_revised ) { |event, page, revision| revised( page, revision ) }
48
- end
49
-
50
- def revised( page, revision )
51
- unless ( revision.author =~ IGNORED_AUTHORS )
52
- add_recent_change( page, revision )
53
- end
54
- end
55
-
56
- def add_recent_change( page, revision )
57
- changes_content = "On #{revision.created_at.strftime('%Y %b %d')}, #{revision.author} made these changes to [[#{page}]]:\n"
58
- revision.changes.each do |change_group| change_group.each do |change|
59
- next if change[2] == ""
60
- changes_content << case change[0]
61
- # Note, +/- reversed because diffs stored as diff from CURRENT version
62
- when "-" ; "| #{change[1]} | -<notextile>#{change[2]}</notextile>- |\n"
63
- when "+" ; "| #{change[1]} | <notextile>#{change[2]}</notextile> |\n"
64
- end
65
- end end
66
- changes_content << "\n"
67
- changes_content << @wiki.page( @pagename ).content.first_lines( @lines ) unless @wiki.page( @pagename ).empty?
68
- @wiki.revise( @pagename , changes_content, @author)
69
- end
70
- end
71
-
72
- class AutomaticOnePageIndex
73
-
74
- def initialize( wiki, pagename = "Site Index", author = "AutomaticIndex" )
75
- @wiki, @pagename, @author = wiki, pagename, author
76
- @wiki.watch_for( :page_created, :page_deleted ) { update_index }
77
- update_index
78
- end
79
-
80
- def update_index
81
- index = @wiki.sort_by{ |name, page| page.name_for_index.capitalize }.map{ |name, page| "* [[ #{page} ]]\n" }
82
- @wiki.revise( @pagename, "h1. Index\n\n#{index}", @author )
83
- end
84
- end
85
-
86
- class AutomaticMultiPageIndex < AutomaticOnePageIndex
87
-
88
- def update_index
89
- buckets = separate_pages_by_first_character
90
- link_bar = link_bar_from_buckets( buckets )
91
- buckets.each do |firstcharacter, pages|
92
- index = pages.sort_by{ |page| page.name_for_index.capitalize }.map{ |page| "* [[ #{page} ]]\n" }
93
- @wiki.revise( "#{@pagename} #{firstcharacter}", "h1. Site Index #{firstcharacter}\n\n#{link_bar}\n\n#{index}", @author )
94
- end
95
- @wiki.revise( @pagename, "h1. Site Index\n\n#{link_bar}", @author )
96
- end
97
-
98
- def separate_pages_by_first_character
99
- buckets = Hash.new
100
- @wiki.each do |name, page|
101
- ( buckets[ page.name_for_index[0,1].upcase ] ||= [] ) << page
102
- end
103
- buckets
104
- end
105
-
106
- def link_bar_from_buckets( buckets )
107
- buckets.keys.sort.map { |letter| "[[ #{letter} : #{@pagename} #{letter} ]]\n" }.join(' ')
108
- end
109
- end
110
-
111
- class FiniteUniqueList
112
- include Enumerable
113
-
114
- attr_accessor :max_size
115
-
116
- def initialize( max_size = nil )
117
- @max_size = max_size
118
- @list = Array.new
119
- end
120
-
121
- def add( item )
122
- remove( item )
123
- @list << item
124
- remove_excess_items
125
- end
126
-
127
- def remove( item )
128
- @list.delete( item )
35
+ @wiki.each { |pagename, page| @view.rollingmatch[ page.name ] = page unless title_banned?( page.name )}
36
+ @wiki.each { |pagename, page| @view.refresh_redcloth( page ) }
129
37
  end
130
38
 
131
- def each
132
- @list.reverse_each { |item| yield item }
39
+ def title_banned?( title )
40
+ @banned_titles.include? title
133
41
  end
134
42
 
135
- def empty?; @list.empty? end
136
-
137
- private
138
-
139
- def remove_excess_items
140
- if @max_size
141
- while @list.size > @max_size
142
- @list.shift
143
- end
144
- end
145
- end
146
43
  end
147
44
 
148
45
  class AutomaticSummary
149
46
 
150
47
  DEFAULT_SETTINGS = {
151
- :regexp_for_pages => /.*/,
48
+ :regexp_for_title => /.*/, # These three regexps act as an AND
49
+ :regexp_for_author => nil,
50
+ :regexp_for_content => nil,
152
51
  :max_pages_to_show => nil,
153
52
  :pagename => 'Summary',
154
53
  :author => 'AutomaticSummary',
155
- :lines_to_include => nil,
54
+ :lines_to_include => nil, # Or pass a block
156
55
  :only_new_pages => false,
56
+ :sort_pages_by => :created_on, # Could be :revised_on or :score or :name or :name_for_index, or :author
57
+ :reverse_sort => false,
58
+ :include_metadata => false, # Includes author and time in summary
59
+ :summarise_revisions => false, # If true, then can contain several revisions for same page
60
+ :remove_deleted_pages => true, # If false will keep references to deleted pages
157
61
  }
158
62
 
159
63
  attr_reader :settings, :pages_in_summary
160
64
 
161
- def initialize( wiki, settings = {} )
162
- @wiki = wiki
163
- @settings = DEFAULT_SETTINGS.merge( settings )
164
- @pages_in_summary = FiniteUniqueList.new( @settings[:max_pages_to_show] )
165
- scan_for_pages_to_summarise
65
+ def initialize( wiki, settings = {}, &renderer )
66
+ @wiki, @settings, @renderer = wiki, DEFAULT_SETTINGS.merge( settings ), renderer
67
+ setup_list
68
+ scan_for_pages_to_summarise_in wiki
166
69
  render_summary
167
- @wiki.watch_for( @settings[:only_new_pages] ? :page_created : :page_revised ) { |event, page| check_whether_to_add_page( page ) }
168
- @wiki.watch_for( :page_deleted ) { |event, page| check_whether_to_remove_page( page ) }
70
+ start_watching_wiki wiki
169
71
  end
170
72
 
171
- def check_whether_to_add_page( page )
73
+ def check_whether_to_add_page( page, revision )
172
74
  return if page.name == @settings[:pagename]
173
- if page.name=~ @settings[:regexp_for_pages]
174
- @pages_in_summary.add( page )
75
+ if summarise? page
76
+ @pages_in_summary.add( @settings[:summarise_revisions] ? revision : page )
175
77
  render_summary
176
78
  end
177
79
  end
178
80
 
179
- def check_whether_to_remove_page( page )
180
- render_summary if @pages_in_summary.remove( page )
81
+ def check_whether_to_remove_page( page, revision )
82
+ return unless @settings[:remove_deleted_pages]
83
+ render_summary if @pages_in_summary.remove( @settings[:summarise_revisions] ? revision : page )
181
84
  end
182
85
 
183
- def scan_for_pages_to_summarise
184
- @wiki.select do |name,page|
185
- name=~ @settings[:regexp_for_pages]
186
- end.sort_by do |name, page|
187
- (@settings[:only_new_pages] ? page.revision[0] : page).created_at
188
- end.each do |name, page|
189
- @pages_in_summary.add page
86
+ private
87
+
88
+ def summarise?( page )
89
+ return false if @settings[:regexp_for_title] && page.name !~ @settings[:regexp_for_title]
90
+ return false if @settings[:regexp_for_author] && page.author !~ @settings[:regexp_for_author]
91
+ return false if @settings[:regexp_for_content] && page.content !~ @settings[:regexp_for_content]
92
+ return true
93
+ end
94
+
95
+ def scan_for_pages_to_summarise_in( wiki )
96
+ wiki.each( @settings[:remove_deleted_pages] ) do |name,page|
97
+ next if page.name == @settings[:pagename]
98
+ next unless summarise? page
99
+ if @settings[:summarise_revisions]
100
+ page.revisions.each { |revision| @pages_in_summary.add revision }
101
+ else
102
+ @pages_in_summary.add page
103
+ end
190
104
  end
191
105
  end
192
106
 
193
107
  def render_summary
108
+ if @wiki.exists? @settings[:pagename]
109
+ old_page = @wiki.page( @settings[:pagename] )
110
+ if old_page.textile =~ /(.*?<automaticsummary>).*?(<\/automaticsummary>.*)/mi
111
+ content, tail = $1, $2
112
+ end
113
+ end
114
+ content ||= "h2. #{@settings[:pagename]}\n\np{font-size: x-small;}. #{@settings[:pagename]} was created automatically from pages whose title matches #{@settings[:regexp_for_title].inspect}.\n\n<automaticsummary>"
115
+ tail ||= "</automaticsummary>"
116
+ content << "\n\n"
194
117
  if @pages_in_summary.empty?
195
- @wiki.revise( @settings[:pagename], "No pages found to summarise" , @settings[:author] )
118
+ content << "No pages found to summarise"
119
+ elsif @renderer
120
+ @pages_in_summary.each { |page| content << @renderer.call(page) }
121
+ elsif @settings[:lines_to_include]
122
+ @pages_in_summary.each { |page| content << render_page(page) }
196
123
  else
197
- content = ""
198
- @pages_in_summary.each do |page|
199
- content << "<div class='subpage'>\n\n"
200
- content << render_page( page )
201
- content << "\n\np(more). [[(more) : #{page.name}]]\n\n"
202
- content << "</div>\n"
203
- end
204
- @wiki.revise( @settings[:pagename], content , @settings[:author] )
124
+ @pages_in_summary.each { |page| content << render_link_to(page) }
205
125
  end
126
+ content << "\n\n"
127
+ content << tail
128
+ @wiki.revise( @settings[:pagename], content , @settings[:author] )
206
129
  end
207
130
 
208
131
  def render_page( page )
209
- if @settings[:lines_to_include]
210
- page.textile.first_lines( @settings[:lines_to_include] )
211
- else
212
- page.textile
213
- end
132
+ "<div class='subpage'>\n#[page.name} #{ @settings[:include_metadata] ? render_meta_data( page ) : "" }<br />\n\n#{page.textile.first_lines( @settings[:lines_to_include] ).close_unmatched_html}\n\np(more). [[(more) => #{page.name}]]\n\n</div>\n"
133
+ end
134
+
135
+ def render_link_to( page )
136
+ "* #{page.name} #{ @settings[:include_metadata] ? render_meta_data( page ) : "" }\n"
137
+ end
138
+
139
+ def render_meta_data( page )
140
+ "revised on #{page.revised_on.strftime('%Y %b %d %H:%M')} by #{page.author}"
141
+ end
142
+
143
+ def setup_list
144
+ @pages_in_summary = FiniteUniqueList.new( @settings[:max_pages_to_show],
145
+ @settings[:reverse_sort],
146
+ @settings[:sort_pages_by] )
214
147
  end
148
+
149
+ def start_watching_wiki( wiki )
150
+ wiki.watch_for( @settings[:only_new_pages] ? :page_created : :page_revised ) { |event, page, revision| check_whether_to_add_page( page, revision ) }
151
+ wiki.watch_for( :page_deleted ) { |event, page, revision| check_whether_to_remove_page( page, revision ) } if @settings[:remove_deleted_pages]
152
+ end
153
+
215
154
  end
216
155
 
156
+ class AutomaticRecentChanges
157
+
158
+ def initialize( wiki, changes = 200, pagename = "Recent Changes to This Site", author = "AutomaticRecentChanges" )
159
+ AutomaticSummary.new( wiki, { :pagename => pagename,
160
+ :author => author,
161
+ :only_new_pages => false,
162
+ :sort_pages_by => :revised_on,
163
+ :include_metadata => true,
164
+ :summarise_revisions => true,
165
+ :reverse_sort => true,
166
+ :remove_deleted_pages => false,
167
+ } )
168
+ end
169
+ end
170
+
171
+ class AutomaticOnePageIndex
172
+
173
+ def initialize( wiki, pagename = "Site Index", author = "AutomaticIndex" )
174
+ AutomaticSummary.new( wiki, { :pagename => pagename,
175
+ :author => author,
176
+ :only_new_pages => true,
177
+ :sort_pages_by => :name_for_index,
178
+ } )
179
+ end
180
+
181
+ end
182
+
183
+ class AutomaticMultiPageIndex
184
+
185
+ def initialize( wiki, pageroot = "Site Index", author = "AutomaticIndex" )
186
+ content = "h1. #{pageroot}\n\n"
187
+ ('A'..'Z').each do |letter|
188
+ AutomaticSummary.new( wiki, { :regexp_for_title => /^#{letter}.*/i,
189
+ :pagename => "#{pageroot} #{letter}",
190
+ :author => author,
191
+ :only_new_pages => true,
192
+ :sort_pages_by => :name_for_index,
193
+ } )
194
+ content << "* #{pageroot} #{letter}\n"
195
+ end
196
+ AutomaticSummary.new( wiki, { :regexp_for_title => /^[^A-Za-z].*/,
197
+ :pagename => "#{pageroot} Other",
198
+ :author => author,
199
+ :only_new_pages => true,
200
+ :sort_pages_by => :name_for_index,
201
+ } )
202
+ content << "* #{pageroot} Other\n"
203
+ wiki.revise( pageroot, content, author )
204
+ end
205
+
206
+ end
207
+
217
208
  class AutomaticCalendar
218
209
 
219
210
  attr_reader :month_pagename, :day_pagename
@@ -240,12 +231,13 @@ class AutomaticCalendar
240
231
  1.upto( 31 ) do |day_no|
241
232
  day = time_for( month, day_no )
242
233
  break if day.month > month
243
- content << "| [[ #{day_no} : #{day_pagename( day )} ]] "
234
+ content << "| [[ #{day_no} => #{day_pagename( day )} ]] "
244
235
  content << "|\n" if day.wday == 6
245
236
  end
246
237
  day.wday.upto( 5 ) { content << "| . " }
247
238
  content << "|\n"
248
- content << "\n\n< #{month_pagename( month-1 )} #{month_pagename( month+1 )} >\n"
239
+ content << "\n\n< #{month_pagename( month-1 )} #{month_pagename( month+1 )} >\n"
240
+ content << "</div>"
249
241
  end
250
242
 
251
243
  def time_for( month, day = 1 )
@@ -290,10 +282,10 @@ class AutomaticUpcomingEvents
290
282
  content = "<div class='upcomingevents'>\n"
291
283
  Time.now.day.upto( Time.now.day+7 ) do |day|
292
284
  time = @calendar.time_for( Time.now.month, day )
293
- content << "| [[ #{relative_day( time ) } : #{@calendar.day_pagename( time )} ]] |"
285
+ content << "| [[ #{relative_day( time ) } => #{@calendar.day_pagename( time )} ]] |"
294
286
  content << (@wiki.exists?( @calendar.day_pagename(time) ) ? render_event( @calendar.day_pagename( time ) ) : "&nbsp; |\n")
295
287
  end
296
- content << "\n\np(more). [[(more) : #{@calendar.month_pagename}]]\n\n"
288
+ content << "\n\np(more). [[(more) => #{@calendar.month_pagename}]]\n\n"
297
289
  content << "</div>\n"
298
290
  @wiki.revise( "Upcoming Events", content , "AutomaticCalendar" )
299
291
  end
@@ -313,9 +305,67 @@ class AutomaticUpcomingEvents
313
305
  page = @wiki.page( name )
314
306
  headings = page.textile.select { |line| line =~ /^h\d\./ }
315
307
  headings = headings.map { |heading| heading.to_s[4..-1].strip }
316
- headings = [ page.textile[/.*?\n/] ] if headings.empty?
317
- content = "[[ #{headings.shift} : #{page.name} ]] |\n"
318
- headings.each { |heading| content << "| &nbsp; | [[ #{heading} : #{page.name} ]] |\n" }
308
+ headings = [ page.textile.first_lines(1) ] if headings.empty?
309
+ content = " [[ #{headings.shift} => #{page.name} ]] |\n"
310
+ headings.each { |heading| content << "| &nbsp; | [[ #{heading} => #{page.name} ]] |\n" }
319
311
  content
320
312
  end
321
313
  end
314
+
315
+ class AutomaticAuthorIndex
316
+
317
+ def initialize( wiki, create_author_pages = true, author_include_regexp = /.*/, author_exclude_regexp = /^Automatic.*/, pagename = "authors", author = "AutomaticAuthorIndexer", author_page_tail = "s pages" )
318
+ @wiki, @create_author_pages, @author_include_regexp, @author_exclude_regexp, @pagename, @author, @author_page_tail = wiki, create_author_pages, author_include_regexp, author_exclude_regexp, pagename, author, author_page_tail
319
+ @authors = []
320
+ find_all_authors( wiki )
321
+ @wiki.watch_for( :page_revised ) { |event, page, revision|
322
+ $stderr.puts "Got a page revised message in AutomaticAuthorIndex"
323
+ add_author( revision ) }
324
+ end
325
+
326
+ def add_author( revision )
327
+ return if @authors.include? revision.author
328
+ return unless revision.author =~ @author_include_regexp
329
+ return unless revision.author !~ @author_exclude_regexp
330
+ @authors << revision.author
331
+ @authors.sort!
332
+ create_author_page_for(revision.author) if @create_author_pages
333
+ render_author_index
334
+ end
335
+
336
+ def find_all_authors( wiki )
337
+ wiki.each do |name, page|
338
+ page.revisions.each do |revision|
339
+ add_author( revision )
340
+ end
341
+ end
342
+ end
343
+
344
+ def render_author_index
345
+ content = "h1. Index of Authors\n\n"
346
+ @authors.each do |author|
347
+ content << "* #{author}"
348
+ if @create_author_pages
349
+ content << " #{author}#{@author_page_tail}"
350
+ end
351
+ content << "\n"
352
+ end
353
+ @wiki.revise( @pagename, content, @author )
354
+ end
355
+
356
+
357
+ def create_author_page_for( author )
358
+ AutomaticSummary.new( @wiki, { :pagename => "#{author}#{@author_page_tail}" ,
359
+ :regexp_for_author => /#{author}/,
360
+ :author => @author,
361
+ :only_new_pages => false,
362
+ :sort_pages_by => :revised_on,
363
+ :include_metadata => true,
364
+ :summarise_revisions => true,
365
+ :reverse_sort => true,
366
+ :remove_deleted_pages => false,
367
+ } )
368
+ end
369
+
370
+ end
371
+