Soks 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.txt +4 -0
- data/lib/helpers/default-helpers.rb +94 -56
- data/lib/helpers/mail2wiki-helper.rb +8 -6
- data/lib/soks-servlet.rb +19 -16
- data/lib/soks-storage.rb +6 -7
- data/lib/soks-utils.rb +26 -0
- data/lib/soks-view.rb +4 -4
- data/lib/soks.rb +2 -1
- data/templates/default/attachment/newpage.js +2 -2
- data/templates/default/attachment/stylesheet.css +14 -3
- data/templates/default/content/A%20page%20with%20an%20umlaut%20%F6%20in%20its%20title.textile +1 -0
- data/templates/default/content/All%20News.textile +18 -1
- data/templates/default/content/Bil%20Kleb.textile +1 -0
- data/templates/default/content/Bil.textile +1 -0
- data/templates/default/content/Bill%20Wood.textile +3 -0
- data/templates/default/content/Bug%3A%20Does%20not%20make%20use%20of%20if%2Dmodified%2Dsince%20r.textile +1 -0
- data/templates/default/content/Bug%3A%20Type%20a%20title%20here.textile +31 -0
- data/templates/default/content/How%20to%20use%20the%20keyboard%20shortcuts.textile +4 -2
- data/templates/default/content/Latest%20News.textile +19 -2
- data/templates/default/content/List%20of%20changes.textile +43 -0
- data/templates/default/content/New%20Recent%20Changes%20class.textile +10 -0
- data/templates/default/content/News%3A%20Version%200%2E0%2E6%20Released.textile +13 -0
- data/templates/default/content/Planned%20Features.textile +9 -8
- data/templates/default/content/README.textile +4 -0
- data/templates/default/content/Recent%20Changes%20to%20This%20Site.textile +282 -205
- data/templates/default/content/Skorgu.textile +3 -0
- data/templates/default/content/ctrl%2Dn.textile +1 -1
- data/templates/default/content/sandbox.textile +20 -0
- data/templates/default/start.rb +15 -5
- data/templates/default/version.txt +1 -1
- data/templates/default/views/Page_edit.rhtml +6 -3
- data/templates/default/views/frame.rhtml +3 -2
- data/test/test_soks-storage.rb +69 -0
- data/test/test_soks-utils.rb +84 -0
- data/test/test_soks-view.rb +43 -0
- metadata +14 -11
- data/templates/default/content/Attached%20ruby%20logo.textile +0 -1
- data/templates/default/content/Attached%20test%20thing.textile +0 -1
- data/templates/default/content/Known%20bugs.textile +0 -18
- data/templates/default/content/Picture%20of%20Type%20a%20title%20here.textile +0 -1
- data/templates/default/content/Picture%20of%20a%20logo%20for%20the%20ruby%20language.textile +0 -1
- data/templates/default/content/Picture%20of%20powered%20by%20ruby%20logo.textile +0 -1
- data/templates/default/content/Recent%20News.textile +0 -9
- data/templates/default/content/Type%20a%20title%20here.textile +0 -1
data/README.txt
CHANGED
@@ -44,6 +44,8 @@ h2. UPGRADE
|
|
44
44
|
|
45
45
|
If you already have a previous version of soks then to upgrade, run @soks-create-wiki.rb --destination-dir=path/to/your/wiki@ and it will guide you through the upgrade.
|
46
46
|
|
47
|
+
Note that if you were using the multi page index class before, you will need to manually delete all the old index pages (@rm content/Site%20Index*@). The new pages will be created automatically.
|
48
|
+
|
47
49
|
h2. FEATURES
|
48
50
|
|
49
51
|
# Runs on its own webrick server (no independent web server required)
|
@@ -62,11 +64,13 @@ I suspect there are many, as befits its version number. In particular it has:
|
|
62
64
|
* Does not permit browsers to cache pages
|
63
65
|
* Not user friendly in the way it handles simultaneous edits of a page (last person to save wins)
|
64
66
|
* Some bugs in layout and formatting of text.
|
67
|
+
* RSS feed does not completely validate
|
65
68
|
|
66
69
|
See http://www.soks.org/wiki/KnownBugs for details.
|
67
70
|
|
68
71
|
h2. RELEASES
|
69
72
|
|
73
|
+
# 2005 Mar 21 - soks-0.0.7 - Fifth public release (alpha)
|
70
74
|
# 2005 Mar 15 - soks-0.0.6 - Fourth public release (alpha)
|
71
75
|
# 2005 Feb 12 - soks-0.0.5 - Third public release (alpha)
|
72
76
|
# 2005 Jan 24 - soks-0.0.4 - Second public release (alpha)
|
@@ -48,9 +48,12 @@ end
|
|
48
48
|
class AutomaticSummary
|
49
49
|
|
50
50
|
DEFAULT_SETTINGS = {
|
51
|
-
:regexp_for_title => /.*/, # These
|
51
|
+
:regexp_for_title => /.*/, # These six regexps act as an AND, with the exclude three acting as NOT their contents
|
52
52
|
:regexp_for_author => nil,
|
53
53
|
:regexp_for_content => nil,
|
54
|
+
:regexp_to_exclude_title => nil,
|
55
|
+
:regexp_to_exclude_author => nil,
|
56
|
+
:regexp_to_exclude_content => nil,
|
54
57
|
:max_pages_to_show => nil,
|
55
58
|
:pagename => 'Summary',
|
56
59
|
:author => 'AutomaticSummary',
|
@@ -61,6 +64,7 @@ class AutomaticSummary
|
|
61
64
|
:include_metadata => false, # Includes author and time in summary
|
62
65
|
:summarise_revisions => false, # If true, then can contain several revisions for same page
|
63
66
|
:remove_deleted_pages => true, # If false will keep references to deleted pages
|
67
|
+
:merge_revisions => false, # If true, repeats with the same author will be merged
|
64
68
|
}
|
65
69
|
|
66
70
|
attr_reader :settings, :pages_in_summary
|
@@ -70,53 +74,72 @@ class AutomaticSummary
|
|
70
74
|
setup_list
|
71
75
|
scan_for_pages_to_summarise_in wiki
|
72
76
|
render_summary
|
73
|
-
|
77
|
+
start_watching wiki
|
74
78
|
end
|
75
79
|
|
76
80
|
def check_whether_to_add_page( page, revision )
|
77
|
-
return
|
78
|
-
if
|
79
|
-
|
80
|
-
|
81
|
-
end
|
81
|
+
return unless summarise?( page )
|
82
|
+
remove_previous_revisions( page, revision ) if @settings[:merge_revisions]
|
83
|
+
@pages_in_summary.add( @settings[:summarise_revisions] ? revision : page )
|
84
|
+
render_summary
|
82
85
|
end
|
83
86
|
|
84
87
|
def check_whether_to_remove_page( page, revision )
|
85
88
|
return unless @settings[:remove_deleted_pages]
|
86
|
-
|
89
|
+
return unless summarise?( page )
|
90
|
+
return unless @pages_in_summary.remove( @settings[:summarise_revisions] ? revision : page )
|
91
|
+
render_summary
|
87
92
|
end
|
88
93
|
|
89
94
|
private
|
90
95
|
|
91
96
|
def summarise?( page )
|
97
|
+
return false if page.name == @settings[:pagename]
|
92
98
|
return false if @settings[:regexp_for_title] && page.name !~ @settings[:regexp_for_title]
|
93
99
|
return false if @settings[:regexp_for_author] && page.author !~ @settings[:regexp_for_author]
|
94
100
|
return false if @settings[:regexp_for_content] && page.content !~ @settings[:regexp_for_content]
|
101
|
+
return false if @settings[:regexp_to_exclude_title] && page.name =~ @settings[:regexp_to_exclude_title]
|
102
|
+
return false if @settings[:regexp_to_exclude_author] && page.author =~ @settings[:regexp_to_exclude_author]
|
103
|
+
return false if @settings[:regexp_to_exclude_content] && page.content =~ @settings[:regexp_to_exclude_content]
|
95
104
|
return true
|
96
105
|
end
|
97
106
|
|
98
107
|
def scan_for_pages_to_summarise_in( wiki )
|
99
108
|
wiki.each( @settings[:remove_deleted_pages] ) do |name,page|
|
100
|
-
next if page.name == @settings[:pagename]
|
101
|
-
next unless summarise? page
|
102
109
|
if @settings[:summarise_revisions]
|
103
|
-
page
|
110
|
+
scan_for_revisions_to_summarise_in( page )
|
104
111
|
else
|
112
|
+
next unless summarise? page
|
105
113
|
@pages_in_summary.add page
|
106
114
|
end
|
107
115
|
end
|
108
116
|
end
|
109
117
|
|
110
|
-
def
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
118
|
+
def scan_for_revisions_to_summarise_in( page )
|
119
|
+
page.revisions.each do |revision|
|
120
|
+
next unless summarise? revision
|
121
|
+
remove_previous_revisions( page, revision ) if @settings[:merge_revisions]
|
122
|
+
@pages_in_summary.add revision
|
116
123
|
end
|
117
|
-
|
118
|
-
|
119
|
-
|
124
|
+
end
|
125
|
+
|
126
|
+
def remove_previous_revisions( page, revision )
|
127
|
+
revision.number.downto(0) do |previous_number|
|
128
|
+
previous_revision = page.revisions.at( previous_number )
|
129
|
+
break unless previous_revision.author == revision.author
|
130
|
+
@pages_in_summary.remove( previous_revision )
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def render_summary
|
135
|
+
@wiki.page( @settings[:pagename] ).textile =~ /(.*?<automaticsummary>).*?(<\/automaticsummary>.*)/mi
|
136
|
+
top = $1 || "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>"
|
137
|
+
tail = $2 || "</automaticsummary>"
|
138
|
+
@wiki.revise( @settings[:pagename], top + render_list + tail , @settings[:author] )
|
139
|
+
end
|
140
|
+
|
141
|
+
def render_list
|
142
|
+
content = "\n\n"
|
120
143
|
if @pages_in_summary.empty?
|
121
144
|
content << "No pages found to summarise"
|
122
145
|
elsif @renderer
|
@@ -127,12 +150,10 @@ class AutomaticSummary
|
|
127
150
|
@pages_in_summary.each { |page| content << render_link_to(page) }
|
128
151
|
end
|
129
152
|
content << "\n\n"
|
130
|
-
content << tail
|
131
|
-
@wiki.revise( @settings[:pagename], content , @settings[:author] )
|
132
153
|
end
|
133
154
|
|
134
155
|
def render_page( page )
|
135
|
-
"<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"
|
156
|
+
"<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"
|
136
157
|
end
|
137
158
|
|
138
159
|
def render_link_to( page )
|
@@ -144,42 +165,57 @@ class AutomaticSummary
|
|
144
165
|
end
|
145
166
|
|
146
167
|
def setup_list
|
147
|
-
@pages_in_summary = FiniteUniqueList.new( @settings[:max_pages_to_show],
|
148
|
-
@settings[:reverse_sort],
|
149
|
-
@settings[:sort_pages_by] )
|
168
|
+
@pages_in_summary = FiniteUniqueList.new( @settings[:max_pages_to_show], @settings[:reverse_sort], @settings[:sort_pages_by] )
|
150
169
|
end
|
151
170
|
|
152
|
-
def
|
171
|
+
def start_watching( wiki )
|
153
172
|
wiki.watch_for( @settings[:only_new_pages] == true ? :page_created : :page_revised ) { |event, page, revision| check_whether_to_add_page( page, revision ) }
|
154
173
|
wiki.watch_for( :page_deleted ) { |event, page, revision| check_whether_to_remove_page( page, revision ) } if @settings[:remove_deleted_pages]
|
155
174
|
end
|
156
175
|
|
157
|
-
end
|
176
|
+
end
|
158
177
|
|
159
|
-
class AutomaticRecentChanges
|
178
|
+
class AutomaticRecentChanges < AutomaticSummary
|
179
|
+
|
180
|
+
def initialize( wiki, changes = 200, title_regexp = /.*/, pagename = "Recent Changes to This Site", author = "AutomaticRecentChanges", exclude_automatic_helpers = true, merge_revisions = true )
|
181
|
+
super( wiki, { :pagename => pagename,
|
182
|
+
:regexp_for_title => title_regexp,
|
183
|
+
:regexp_to_exclude_author => exclude_automatic_helpers && /^Automatic/i,
|
184
|
+
:max_pages_to_show => changes,
|
185
|
+
:author => author,
|
186
|
+
:only_new_pages => false,
|
187
|
+
:sort_pages_by => :revised_on,
|
188
|
+
:summarise_revisions => true,
|
189
|
+
:reverse_sort => true,
|
190
|
+
:remove_deleted_pages => false,
|
191
|
+
:merge_revisions => merge_revisions,
|
192
|
+
} )
|
193
|
+
end
|
160
194
|
|
161
|
-
def
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
195
|
+
def render_list
|
196
|
+
content = "<div class='recentchanges'>\n\nh2. Today\n\n"
|
197
|
+
previous_time = Time.now
|
198
|
+
@pages_in_summary.each do |revision|
|
199
|
+
unless revision.revised_on.same_day?( previous_time )
|
200
|
+
content << "\nh2. #{revision.revised_on.strftime('%a %d %b %Y')}\n\n"
|
201
|
+
previous_time = revision.revised_on
|
202
|
+
end
|
203
|
+
content << "* #{revision.revised_on.strftime('%H:%M')} - [[#{revision.name}]] revised by #{revision.author}\n"
|
204
|
+
end
|
205
|
+
content << "\n\n</div>"
|
172
206
|
end
|
207
|
+
|
173
208
|
end
|
174
209
|
|
175
210
|
class AutomaticOnePageIndex
|
176
211
|
|
177
212
|
def initialize( wiki, pagename = "Site Index", author = "AutomaticIndex" )
|
178
213
|
AutomaticSummary.new( wiki, { :pagename => pagename,
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
214
|
+
:regexp_to_exclude_title => /#{Regexp.escape(pagename)}/i,
|
215
|
+
:author => author,
|
216
|
+
:only_new_pages => true,
|
217
|
+
:sort_pages_by => :name_for_index,
|
218
|
+
} )
|
183
219
|
end
|
184
220
|
|
185
221
|
end
|
@@ -190,20 +226,22 @@ class AutomaticMultiPageIndex
|
|
190
226
|
content = "h1. #{pageroot}\n\n"
|
191
227
|
('A'..'Z').each do |letter|
|
192
228
|
AutomaticSummary.new( wiki, { :regexp_for_title => /^#{letter}.*/i,
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
229
|
+
:pagename => "#{pageroot} #{letter}.",
|
230
|
+
:regexp_to_exclude_title => /^#{Regexp.escape(pageroot)} ([a-z]|Other)\./i,
|
231
|
+
:author => author,
|
232
|
+
:only_new_pages => true,
|
233
|
+
:sort_pages_by => :name_for_index,
|
234
|
+
} )
|
235
|
+
content << "* #{pageroot} #{letter}.\n"
|
199
236
|
end
|
200
237
|
AutomaticSummary.new( wiki, { :regexp_for_title => /^[^A-Za-z].*/,
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
238
|
+
:pagename => "#{pageroot} Other.",
|
239
|
+
:regexp_to_exclude_title => /^#{Regexp.escape(pageroot)} ([a-z]|Other)\./i,
|
240
|
+
:author => author,
|
241
|
+
:only_new_pages => true,
|
242
|
+
:sort_pages_by => :name_for_index,
|
243
|
+
} )
|
244
|
+
content << "* #{pageroot} Other.\n"
|
207
245
|
wiki.revise( pageroot, content, author )
|
208
246
|
end
|
209
247
|
|
@@ -1,5 +1,12 @@
|
|
1
1
|
require 'net/imap'
|
2
2
|
|
3
|
+
# From Dave Burt on comp.lang.ruby
|
4
|
+
class String
|
5
|
+
def from_quoted_printable
|
6
|
+
self.gsub(/\r\n/, "\n").unpack("M").first
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
3
10
|
class Message
|
4
11
|
|
5
12
|
attr_reader :message_id, :subject, :sender_name, :sender_email, :date, :text
|
@@ -15,12 +22,7 @@ class Message
|
|
15
22
|
end
|
16
23
|
|
17
24
|
def plain_text_content_from_message( id )
|
18
|
-
text = @imap.fetch( id, 'BODY[1]' ).first.attr['BODY[1]']
|
19
|
-
text.gsub!(/\r\n/,"\n")
|
20
|
-
text.gsub!(/\r/,"\n")
|
21
|
-
text.gsub!(/=\n/,'')
|
22
|
-
#text.gsub!(/((?:=[0-9a-fA-F]{2})+)/n) { [$1.delete('=')].pack('H*') }
|
23
|
-
|
25
|
+
text = @imap.fetch( id, 'BODY[1]' ).first.attr['BODY[1]'].from_quoted_printable
|
24
26
|
text
|
25
27
|
end
|
26
28
|
|
data/lib/soks-servlet.rb
CHANGED
@@ -16,7 +16,8 @@ class WikiServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
16
16
|
doAttachment( request, response, request.path[1..-1] )
|
17
17
|
when /\/(\w+?)\/(.+)/ # If request of the form /verb/pagename then doVerb on this class
|
18
18
|
verb, pagename = $1, make_pagename_valid( $2 )
|
19
|
-
authenticate request, response
|
19
|
+
authenticate request, response
|
20
|
+
make_username_valid( request )
|
20
21
|
if self.respond_to?( "do#{verb.capitalize}" )
|
21
22
|
self.send( "do#{verb.capitalize}", request, response, pagename, request.user )
|
22
23
|
else
|
@@ -108,22 +109,21 @@ class WikiServlet < WEBrick::HTTPServlet::AbstractServlet
|
|
108
109
|
|
109
110
|
def upload_file_data( upload_data )
|
110
111
|
path = "#{$SETTINGS[:root_directory]}/attachment/"
|
111
|
-
filename = unique_filename( path , upload_data.filename )
|
112
|
+
filename = File.unique_filename( path , upload_data.filename )
|
112
113
|
File.open( File.join( path, filename ), 'wb' ) { |file| upload_data.list.each { |data| file << data } }
|
113
114
|
"/attachment/#{filename}"
|
114
115
|
end
|
115
116
|
|
116
|
-
def unique_filename( path, filename )
|
117
|
-
filename.gsub!(' ','') # Unfortunately no spaces permitted in redcloth links
|
118
|
-
return filename unless File.exist? File.join( path, filename ) # Leave as is, if doesn't exist
|
119
|
-
name, counter, extension = File.basename( filename, '.*'), 1, File.extname( filename )
|
120
|
-
counter += 1 while File.exist? File.join( path, "#{name}#{counter}#{extension}" )
|
121
|
-
return "#{name}#{counter}#{extension}"
|
122
|
-
end
|
123
|
-
|
124
117
|
# Certain characters cause problems in titles, so delete
|
125
118
|
def make_pagename_valid( pagename )
|
126
|
-
pagename.
|
119
|
+
pagename.to_valid_pagename
|
120
|
+
end
|
121
|
+
|
122
|
+
# Because the username is also used as a page title, also delete troublesome characters from them
|
123
|
+
# and make sure the name doesn't start with Automatic
|
124
|
+
def make_username_valid( request )
|
125
|
+
request.user = request.user.to_valid_pagename
|
126
|
+
request.user = "External #{request.user}" if request.user =~ /^Automatic/i
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
@@ -134,23 +134,26 @@ def start_wiki( settings = {}, &automatic_agents )
|
|
134
134
|
|
135
135
|
wiki = Wiki.new( "#{$SETTINGS[:root_directory]}/content" )
|
136
136
|
view = View.new( wiki, $SETTINGS[:name] )
|
137
|
-
|
137
|
+
|
138
138
|
Thread.new( automatic_agents, wiki, view ) do |block, wiki, view|
|
139
|
+
$LOG.info "Starting helper classes"
|
139
140
|
block.call( wiki, view )
|
141
|
+
$LOG.info "Finished starting helper classes"
|
140
142
|
end.priority = -2
|
141
143
|
|
142
144
|
server = WEBrick::HTTPServer.new( { :Port => $SETTINGS[:port],
|
143
|
-
|
144
|
-
|
145
|
+
:ServerType=> $SETTINGS[:server_type]
|
146
|
+
} )
|
145
147
|
|
146
148
|
server.mount("/", WikiServlet, view, $SETTINGS )
|
147
149
|
|
148
150
|
trap("INT") {
|
149
|
-
$
|
151
|
+
$LOG.warn "Trying to shutdown gracefully"
|
150
152
|
server.shutdown
|
151
153
|
wiki.shutdown
|
152
|
-
$
|
154
|
+
$LOG.info "Shutdown."
|
153
155
|
}
|
154
156
|
|
157
|
+
$LOG.warn "Starting server"
|
155
158
|
server.start
|
156
159
|
end
|
data/lib/soks-storage.rb
CHANGED
@@ -2,7 +2,7 @@ module WikiFlatFileStore
|
|
2
2
|
|
3
3
|
CONTENT_EXTENSION = '.textile'
|
4
4
|
REVISIONS_EXTENSION = '.yaml'
|
5
|
-
DEFAULT_AUTHOR = '
|
5
|
+
DEFAULT_AUTHOR = 'the import script'
|
6
6
|
|
7
7
|
def load_all_pages
|
8
8
|
move_files_if_names_are_not_url_encoded
|
@@ -64,9 +64,9 @@ module WikiFlatFileStore
|
|
64
64
|
revisions[ array[0] ] = Revision.new( page, *array ) }
|
65
65
|
}
|
66
66
|
rescue
|
67
|
-
$
|
67
|
+
$LOG.error "Error loading revisions with #{$!.to_s} in file #{page.name}"
|
68
68
|
end
|
69
|
-
revisions.each_with_index { |r,i| $
|
69
|
+
revisions.each_with_index { |r,i| $LOG.error "#{page.name} missing revision #{i}" unless r }
|
70
70
|
revisions
|
71
71
|
end
|
72
72
|
|
@@ -84,8 +84,8 @@ module WikiFlatFileStore
|
|
84
84
|
def move_files_if_names_are_not_url_encoded
|
85
85
|
Dir[ File.join( @folder, "*#{CONTENT_EXTENSION}" ) ].each do |filename|
|
86
86
|
basename = File.basename( filename, '.*')
|
87
|
-
next if basename.url_decode.url_encode == basename # All ok, so no worry
|
88
|
-
new_name = File.join( File.dirname(filename), basename.url_decode.url_encode
|
87
|
+
next if basename.url_decode.to_valid_pagename.url_encode == basename # All ok, so no worry
|
88
|
+
new_name = File.join( File.dirname(filename), File.unique_filename( File.dirname(filename), basename.url_decode.to_valid_pagename.url_encode + File.extname( filename) ) )
|
89
89
|
File.rename(filename, new_name )
|
90
90
|
end
|
91
91
|
end
|
@@ -102,14 +102,13 @@ module WikiFlatFileStore
|
|
102
102
|
|
103
103
|
# Appends the last revision onto the yaml file
|
104
104
|
def save_revisions( page )
|
105
|
-
$
|
105
|
+
$LOG.info "Saving revisions for #{page.name}"
|
106
106
|
File.open(filename_for_revisions( page.name ), 'a' ) do |file|
|
107
107
|
YAML.dump( page.revisions.last.to_a, file )
|
108
108
|
file.puts # Needed to ensure that documents are separated
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
-
|
113
112
|
def page_name_for( filename )
|
114
113
|
File.basename( filename, '.*').url_decode
|
115
114
|
end
|
data/lib/soks-utils.rb
CHANGED
@@ -143,6 +143,11 @@ class String
|
|
143
143
|
end
|
144
144
|
text
|
145
145
|
end
|
146
|
+
|
147
|
+
# Removes punctuation and spaces that can cause problems with page names
|
148
|
+
def to_valid_pagename
|
149
|
+
self.tr('\\\[]?{}&^`<>/','').strip
|
150
|
+
end
|
146
151
|
end
|
147
152
|
|
148
153
|
class FiniteUniqueList
|
@@ -217,3 +222,24 @@ class Numeric
|
|
217
222
|
end
|
218
223
|
end
|
219
224
|
|
225
|
+
class Time
|
226
|
+
|
227
|
+
# Checks whether two times are on the same day
|
228
|
+
def same_day?( other_time )
|
229
|
+
return false unless other_time.year == self.year
|
230
|
+
return false unless other_time.yday == self.yday
|
231
|
+
return true
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
class File
|
236
|
+
|
237
|
+
def self.unique_filename( path, filename )
|
238
|
+
filename.tr!(' ','') # Unfortunately no spaces permitted in redcloth links
|
239
|
+
return filename unless exist?( join( path, filename ) )# Leave as is, if doesn't exist
|
240
|
+
name, counter, extension = basename( filename, '.*'), 1, extname( filename )
|
241
|
+
counter += 1 while exist?( join( path, "#{name}#{counter}#{extension}" ) )
|
242
|
+
return "#{name}#{counter}#{extension}"
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
data/lib/soks-view.rb
CHANGED
@@ -71,7 +71,7 @@ class BruteMatch
|
|
71
71
|
|
72
72
|
def match( text )
|
73
73
|
@titles.each do |title|
|
74
|
-
regexp =
|
74
|
+
regexp = /\b#{Regexp.escape(title)}\b/i
|
75
75
|
page = @matches[ title ]
|
76
76
|
text.gsub!( regexp ) { |match| yield match, page }
|
77
77
|
end
|
@@ -222,7 +222,7 @@ class View
|
|
222
222
|
|
223
223
|
def view( pagename, view = 'view', person = nil )
|
224
224
|
page = @wiki.page pagename
|
225
|
-
|
225
|
+
renderedview = redcloth( page )
|
226
226
|
content_of_page = html( page.class, view, binding )
|
227
227
|
if should_frame? view
|
228
228
|
frame_erb.result binding
|
@@ -269,7 +269,7 @@ class View
|
|
269
269
|
end
|
270
270
|
|
271
271
|
def refresh_redcloth( page )
|
272
|
-
$
|
272
|
+
$LOG.info "Refreshing #{page}"
|
273
273
|
@redcloth_cache[page] = "" if page.textile.strip == ""
|
274
274
|
@redcloth_cache[ page ] = WikiRedCloth.new( self, page, page.textile ).to_html
|
275
275
|
end
|
@@ -289,7 +289,7 @@ class View
|
|
289
289
|
end
|
290
290
|
|
291
291
|
def erb_filename( klass, view )
|
292
|
-
$
|
292
|
+
$LOG.info "Looking for #{path_for( klass, view)}"
|
293
293
|
until File.exists?( path_for( klass, view ) )
|
294
294
|
if klass.superclass
|
295
295
|
klass = klass.superclass
|
data/lib/soks.rb
CHANGED
@@ -32,11 +32,12 @@ $SETTINGS = {
|
|
32
32
|
:dont_frame_templates => ['print','rss'],
|
33
33
|
:force_no_cache => false, # Adds headers to restrict the cacheing of pages
|
34
34
|
:redcloth_hard_breaks => false, # Set Redcloth to use hard breaks
|
35
|
+
:reload_erb_each_request => false, # False faster for production, true speeds development cycle
|
35
36
|
:server_type => WEBrick::SimpleServer, # Could be WEBrick::Daemon if you wish to fork
|
36
37
|
:authenticators => [ [ %r{/(view|rss|print|find|meta|attachment)/.*}, WEBrick::HTTPAuth::NoAuthenticationRequired.new ],
|
37
38
|
# [ %r{/upload/.*}, WEBrick::HTTPAuth::NotPermitted.new ],
|
38
39
|
# [ %r{/(edit|save)/home page}, WEBrick::HTTPAuth::SiteWidePassword.new('password','You need to enter the site wide password to edit the home page') ],
|
39
40
|
# [ %r{/(view|edit|save)/private.*},WEBrick::HTTPAuth::BasicAuth.new( :UserDB => htpasswd, :Realm => realm ) ], # See webrick documentation
|
40
41
|
[ %r{.*}, WEBrick::HTTPAuth::AskForUserName.new( 'No password, just enter a name') ]
|
41
|
-
]
|
42
|
+
]
|
42
43
|
}
|
@@ -42,9 +42,9 @@ function hotkey( event )
|
|
42
42
|
|
43
43
|
function validateTitle( proposed_title )
|
44
44
|
{
|
45
|
-
var illegalcharacters = /[\\\[\]
|
45
|
+
var illegalcharacters = /[\\\[\]\?<>&\^\/]/;
|
46
46
|
if (illegalcharacters.test( proposed_title ) == true )
|
47
47
|
{
|
48
|
-
alert( 'Unfortunately the characters \ [ ] ? < > & ^ in titles cause problems with Soks. Please try not to use them');
|
48
|
+
alert( 'Unfortunately the characters \ / [ ] ? < > & ^ in titles cause problems with Soks. Please try not to use them.');
|
49
49
|
}
|
50
50
|
}
|
@@ -159,6 +159,12 @@ pre.change {
|
|
159
159
|
height: 75%;
|
160
160
|
}
|
161
161
|
|
162
|
+
|
163
|
+
.help {
|
164
|
+
color: red;
|
165
|
+
text-align: center;
|
166
|
+
}
|
167
|
+
|
162
168
|
#tips h1 {
|
163
169
|
padding-left: 5px;
|
164
170
|
margin-top: 0px;
|
@@ -178,6 +184,10 @@ form.editpage {
|
|
178
184
|
display: inline;
|
179
185
|
}
|
180
186
|
|
187
|
+
fieldset {
|
188
|
+
border: none;
|
189
|
+
}
|
190
|
+
|
181
191
|
div.undochange {
|
182
192
|
border-top: solid 1px #AAAAAA;
|
183
193
|
margin-top: 10px;
|
@@ -199,7 +209,8 @@ div.undochange {
|
|
199
209
|
margin-top: 5px;
|
200
210
|
}
|
201
211
|
|
202
|
-
|
203
|
-
|
204
|
-
|
212
|
+
|
213
|
+
.recentchanges li, .recentchanges ul {
|
214
|
+
list-style-type: none;
|
215
|
+
padding-left: 5px;
|
205
216
|
}
|
@@ -0,0 +1 @@
|
|
1
|
+
Test whether this works.
|
@@ -4,6 +4,23 @@ p{font-size: x-small;}. All News was created automatically from pages whose titl
|
|
4
4
|
|
5
5
|
<automaticsummary>
|
6
6
|
|
7
|
-
|
7
|
+
<div class='subpage'>
|
8
|
+
[[ News: Version 0.0.6 Released ]] <br />
|
9
|
+
|
10
|
+
It gives me great pleasure to announce version 0.0.6 of Soks - Yet another ruby wiki. You can get it from http://rubyforge.org/frs/?group_id=481&release_id=1807 or, if you have gems, run @sudo gem install Soks@.
|
11
|
+
|
12
|
+
This release fixes quite a lot of bugs, provides a few more settings that can be tweaked, and the default 'look' has been toned down. See list of changes for details, and please take a note of the known bugs.
|
13
|
+
|
14
|
+
Thanks to all those that helped with bugs, suggestions and code.
|
15
|
+
|
16
|
+
Grateful for feedback at tamc@rubyforge.org
|
17
|
+
|
18
|
+
*WARNING;* This Bug: Internet Exploror 6.0 incompatibilities during page edits is really annoying for users of IE 6. Temporary fixes can be found on that page, and I will make a new release soon to fix.
|
19
|
+
|
20
|
+
|
21
|
+
p(more). [[(more) => News: Version 0.0.6 Released]]
|
22
|
+
|
23
|
+
</div>
|
24
|
+
|
8
25
|
|
9
26
|
</automaticsummary>
|
@@ -0,0 +1 @@
|
|
1
|
+
A steward of "FUN3D":http://fun3d.larc.nasa.gov software development at "NASA":http://www.larc.nasa.gov.
|
@@ -0,0 +1 @@
|
|
1
|
+
See Bil Kleb
|
@@ -0,0 +1 @@
|
|
1
|
+
Currently tells the browser to not cache any page. This is wasteful of bandwidth and increases server load. Should handle the if-modified-since request headers to return 'not modified' messages instead.
|
@@ -0,0 +1,31 @@
|
|
1
|
+
Please click in the box above and give a meaningful title, then fill out any information below that you can. It is all optional, and I'm grateful for whatever you provide.
|
2
|
+
|
3
|
+
* Your name:
|
4
|
+
* Soks version:
|
5
|
+
* Your operating system:
|
6
|
+
* Your version of ruby:
|
7
|
+
* Your browser:
|
8
|
+
|
9
|
+
And please describe the problem below:
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
And if you have any suggestions for the cause or a fix, please put it below:
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
Thank you *very* much
|
30
|
+
|
31
|
+
tamc
|
@@ -2,7 +2,7 @@ h1. Keyboard Shortcuts
|
|
2
2
|
|
3
3
|
Soks has a number of keyboard short cuts. Depending on your browser, only some of them will work:
|
4
4
|
|
5
|
-
* ctrl-n : New page. Will use whatever text you had selected as the title of the new page (definitely only works on a few browsers)
|
5
|
+
* ctrl-n : New page. Will use whatever text you had selected as the title of the new page (definitely only works on a few browsers[1])
|
6
6
|
* ctrl-e: Edit page, and if you are editing:
|
7
7
|
** ctrl-s saves the page
|
8
8
|
** ctrl-c cancels the editing
|
@@ -12,4 +12,6 @@ Soks has a number of keyboard short cuts. Depending on your browser, only some
|
|
12
12
|
* ctrl-i: Site Index
|
13
13
|
* ctrl-r: Recent changes to this site
|
14
14
|
|
15
|
-
Note
|
15
|
+
*Note:* On Linux/Firefox and WindowsXP/IE6.0, substitute "meta" or "alt" for "ctrl". And for WindowsXP/IE6.0, these will only move you to the link on the page -- you then have to hit enter to proceed.
|
16
|
+
|
17
|
+
fn1. Does not work on Linux/Firefox1.0 or WindowsXP/IE6.0
|