clwiki 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +31 -0
- data/Rakefile +53 -0
- data/app/assets/javascripts/cl_wiki/application.js +29 -0
- data/app/assets/stylesheets/cl_wiki/application.css +103 -0
- data/app/controllers/cl_wiki/application_controller.rb +4 -0
- data/app/controllers/cl_wiki/page_controller.rb +106 -0
- data/app/helpers/cl_wiki/application_helper.rb +4 -0
- data/app/views/cl_wiki/page/edit.html.erb +8 -0
- data/app/views/cl_wiki/page/find.html.erb +27 -0
- data/app/views/cl_wiki/page/recent.html.erb +4 -0
- data/app/views/cl_wiki/page/recent.rss.builder +18 -0
- data/app/views/cl_wiki/page/show.html.erb +1 -0
- data/app/views/layouts/cl_wiki/application.html.erb +14 -0
- data/config/clwiki.yml +73 -0
- data/config/initializers/clwiki.rb +9 -0
- data/config/routes.rb +15 -0
- data/lib/cl_wiki.rb +12 -0
- data/lib/cl_wiki/configuration.rb +171 -0
- data/lib/cl_wiki/engine.rb +5 -0
- data/lib/cl_wiki/file.rb +171 -0
- data/lib/cl_wiki/find_in_file.rb +33 -0
- data/lib/cl_wiki/format/format.blockquote.rb +15 -0
- data/lib/cl_wiki/format/format.graphviz.digraph.rb +16 -0
- data/lib/cl_wiki/format/format.opml.rb +105 -0
- data/lib/cl_wiki/format/format.pre.blockquote.rb +15 -0
- data/lib/cl_wiki/format/format.simpletable.rb +25 -0
- data/lib/cl_wiki/index.rb +455 -0
- data/lib/cl_wiki/page.rb +516 -0
- data/lib/cl_wiki/tools/cron.reminders.rb +241 -0
- data/lib/cl_wiki/tools/movepages.rb +27 -0
- data/lib/cl_wiki/tools/pagestomove.txt +56 -0
- data/lib/cl_wiki/tools/rublog/clWiki.rb +62 -0
- data/lib/cl_wiki/tools/rublog/readme.txt +2 -0
- data/lib/cl_wiki/tools/singlepage.rb +58 -0
- data/lib/cl_wiki/tools/test/singlepagetest.rb +9 -0
- data/lib/cl_wiki/tools/thunderbird.rb +23 -0
- data/lib/cl_wiki/version.rb +3 -0
- data/test/dummy/README.rdoc +259 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +16 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +37 -0
- data/test/dummy/config/boot.rb +9 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +34 -0
- data/test/dummy/config/environments/production.rb +81 -0
- data/test/dummy/config/environments/test.rb +36 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/locale.rb +7 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +5 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/log/development.log +1963 -0
- data/test/dummy/log/test.log +1340 -0
- data/test/dummy/public/404.html +27 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +26 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/17ea26cbf693e610505bdc24be534847 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/1883f3d938430da389005555d27c0bad +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/1b9132b83b822937e80ef987f7da1760 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/259fb44b87b29348087957b4937a1953 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/37f8e4f0491b6401433af823dfb471d9 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/48d7a2c40083020f9e7d97d4d73f26fa +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/4b0bfb6eb9d6983eb9defa58dd96dae4 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/4da11f1195532cd7b80f2dde7cf843d5 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/57347ee373d74c87e1515a059c701085 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/61b40e54192bf61d97ce2aef71e7d694 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/633b01c5a65fcd6457baf30d1cc94148 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/6ad8bb345cc43acfca78c043b7bfefae +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/87a335a43cb68a253dea2b6c0269a4d6 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/8a38b2f4390e68175dae4b4b1c144e2e +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/8ddc1a668acec35c2707ebc47768f59c +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/8f5ab7b6f73a1e9f16421b299134e39a +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/9835aec4bc0277b8f02d0e86c977fdba +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/ae4f771558859f9c120a0f22328e8521 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/afed0eaa6fcf7a263498a08a5cc02cf0 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/be786e5567855cdc6817603725fd1b8d +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/bf9b02df32690fb2a936818715d611f3 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/c2bf9d91a6a2786263b9912b948f435d +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/ce4c918439a53cb89d02313ed990d5de +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/d9c791f08c547f30854ad746a89b0bb5 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/ddc3a7b5173ff5c911a53004b56e4305 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/dfed1391742203d15f08cb07173bccba +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/e282b6bdaa0e070754f8558b9de5e417 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/f0e957c30443ade693f73ff470f0f894 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/f6b3cbb9c04d5af74d780464c9a34ee5 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/fb41fedee86fd2d10ddd938bf5d68eb7 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/1883f3d938430da389005555d27c0bad +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/48d7a2c40083020f9e7d97d4d73f26fa +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/61b40e54192bf61d97ce2aef71e7d694 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/8f5ab7b6f73a1e9f16421b299134e39a +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/9835aec4bc0277b8f02d0e86c977fdba +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/ae4f771558859f9c120a0f22328e8521 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/be786e5567855cdc6817603725fd1b8d +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/c2bf9d91a6a2786263b9912b948f435d +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/ce4c918439a53cb89d02313ed990d5de +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/e282b6bdaa0e070754f8558b9de5e417 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/f0e957c30443ade693f73ff470f0f894 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/f6b3cbb9c04d5af74d780464c9a34ee5 +0 -0
- data/test/dummy/tmp/testrep/FooBar.txt +1 -0
- data/test/dummy/tmp/testrep/FrontPage.txt +1 -0
- data/test/dummy/tmp/testrep/QuuxBaz.txt +1 -0
- data/test/dummy/wikirep/AboutClWiki.txt +31 -0
- data/test/dummy/wikirep/ChrisMorris.txt +4 -0
- data/test/dummy/wikirep/DotTest.txt +6 -0
- data/test/dummy/wikirep/FooBar.txt +4 -0
- data/test/dummy/wikirep/FooBarQuux.txt +4 -0
- data/test/dummy/wikirep/FrontPage.txt +14 -0
- data/test/dummy/wikirep/HtmlAreaTest.txt +4 -0
- data/test/dummy/wikirep/PreTagsTest.txt +27 -0
- data/test/dummy/wikirep/TheMan.txt +4 -0
- data/test/helpers/wiki_helper_test.rb +4 -0
- data/test/lib/clwiki/clwiki_test_helper.rb +3 -0
- data/test/lib/clwiki/file_test.rb +93 -0
- data/test/lib/clwiki/find_in_file_test.rb +111 -0
- data/test/lib/clwiki/index_test.rb +32 -0
- data/test/lib/clwiki/page_test.rb +239 -0
- data/test/lib/clwiki/test_base.rb +25 -0
- data/test/test_helper.rb +15 -0
- metadata +312 -0
data/lib/cl_wiki/page.rb
ADDED
@@ -0,0 +1,516 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'singleton'
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + '/file'
|
5
|
+
require File.dirname(__FILE__) + '/find_in_file'
|
6
|
+
|
7
|
+
$FIND_PAGE_NAME = "Find"
|
8
|
+
$FIND_RESULTS_NAME = "Find Results"
|
9
|
+
|
10
|
+
module ClWiki
|
11
|
+
class Page
|
12
|
+
attr_reader :content, :mtime, :name, :full_name, :pagePath, :raw_content,
|
13
|
+
:fileFullPathAndName
|
14
|
+
|
15
|
+
@@wikiIndexClient = nil
|
16
|
+
|
17
|
+
#Refactor clwikifile out of here into a storage class that will
|
18
|
+
# require in the appropriate storage file clwikifile, clwikisql
|
19
|
+
|
20
|
+
# refactor away wikiPath ... should be taken care of elsewhere, otherwise
|
21
|
+
# ClWiki must know it, and it should be storage independent
|
22
|
+
def initialize(fullName, wiki_path=$wiki_path)
|
23
|
+
@full_name = fullName
|
24
|
+
@wiki_path = wiki_path
|
25
|
+
@wikiFile = ClWiki::File.new(@full_name, @wiki_path)
|
26
|
+
@pagePath = @wikiFile.pagePath
|
27
|
+
@name = @wikiFile.name
|
28
|
+
end
|
29
|
+
|
30
|
+
# <pre> text in 1.13.2 had extra line feeds, because the \n were xformed to
|
31
|
+
# <br>\n, which results in two line feeds when rendered by Mozilla.
|
32
|
+
# The change a few versions ago inside convert_newline_to_br which started
|
33
|
+
# converting \n to <br>\n is the culprit here. I did this for more readable
|
34
|
+
# html, but that does screw up <pre> sections, so it's put back now.
|
35
|
+
def convert_newline_to_br
|
36
|
+
newcontent = ""
|
37
|
+
insideHtmlTags = false
|
38
|
+
@content.each_line do |substr|
|
39
|
+
insideHtmlTags = true if (substr =~ /#{$HTML_START}/)
|
40
|
+
insideHtmlTags = false if (substr =~ /#{$HTML_END}/)
|
41
|
+
if ((!ClWiki::PageFormatter.only_html(substr)) or (substr == "\n")) and !insideHtmlTags
|
42
|
+
newcontent = newcontent + substr.gsub(/\n/, "<br>")
|
43
|
+
else
|
44
|
+
newcontent = newcontent + substr
|
45
|
+
end
|
46
|
+
end
|
47
|
+
@content = newcontent
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.wikiIndexClient
|
51
|
+
@@wikiIndexClient = ClWikiIndexClient.new if !@@wikiIndexClient
|
52
|
+
@@wikiIndexClient
|
53
|
+
end
|
54
|
+
|
55
|
+
def read_raw_content
|
56
|
+
@raw_content = @wikiFile.content.join.gsub(/\r\n/, "\n")
|
57
|
+
read_page_attributes
|
58
|
+
ClWiki::Page.wikiIndexClient.add_hit(@full_name) if $wiki_conf.access_log_index
|
59
|
+
end
|
60
|
+
|
61
|
+
def content_never_edited?
|
62
|
+
@wikiFile.content_is_default?
|
63
|
+
end
|
64
|
+
|
65
|
+
def delete
|
66
|
+
@wikiFile.delete
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.read_file_full_path_and_name(full_name, wiki_path=$wiki_path)
|
70
|
+
wiki_file = ClWikiFile.new(full_name, wiki_path, $wikiPageExt, false)
|
71
|
+
wiki_file.fullPathAndName
|
72
|
+
end
|
73
|
+
|
74
|
+
def read_page_attributes
|
75
|
+
wikiFile = @wikiFile # ClWikiFile.new(@fullName, @wikiPath)
|
76
|
+
@mtime = wikiFile.modTimeAtLastRead
|
77
|
+
@fileFullPathAndName = wikiFile.fullPathAndName
|
78
|
+
end
|
79
|
+
|
80
|
+
def read_raw_content_with_forwarding(full_page_name)
|
81
|
+
stack = []
|
82
|
+
history = []
|
83
|
+
content = ''
|
84
|
+
final_page_name = full_page_name
|
85
|
+
stack.push(full_page_name)
|
86
|
+
while !stack.empty?
|
87
|
+
this_pg_name = stack.pop
|
88
|
+
if history.index(this_pg_name)
|
89
|
+
pg_content = '-= CIRCULAR FORWARDING DETECTED =-'
|
90
|
+
else
|
91
|
+
pg = ClWiki::Page.new(this_pg_name)
|
92
|
+
pg.read_raw_content
|
93
|
+
pg_content = pg.raw_content
|
94
|
+
fwd_full_page_name = get_forward_ref(pg_content)
|
95
|
+
if fwd_full_page_name
|
96
|
+
pg_content = "Auto forwarded from #{this_pg_name.strip_slash_prefix}<br><br>#{fwd_full_page_name}<br><br>"
|
97
|
+
stack.push fwd_full_page_name
|
98
|
+
else
|
99
|
+
final_page_name = this_pg_name
|
100
|
+
end
|
101
|
+
end
|
102
|
+
content << pg_content << "\n"
|
103
|
+
history << this_pg_name
|
104
|
+
end
|
105
|
+
[content, final_page_name]
|
106
|
+
end
|
107
|
+
|
108
|
+
def read_content(include_header_and_footer=true, include_diff=false)
|
109
|
+
read_page_attributes
|
110
|
+
@content, final_page_name = read_raw_content_with_forwarding(@full_name)
|
111
|
+
process_custom_renderers
|
112
|
+
convert_newline_to_br
|
113
|
+
f = ClWiki::PageFormatter.new(@content, final_page_name)
|
114
|
+
@content = "<div class='wikiBody'>#{f.formatLinks}</div>"
|
115
|
+
if include_header_and_footer
|
116
|
+
@content = get_header + @content + get_footer
|
117
|
+
end
|
118
|
+
@content = CLabs::WikiDiffFormatter.format_diff(@wikiFile.diff) + @content if include_diff
|
119
|
+
@content
|
120
|
+
end
|
121
|
+
|
122
|
+
def process_custom_renderers
|
123
|
+
root_dirs = [::File.join(::File.dirname(__FILE__), 'format')] + $wiki_conf.custom_formatter_load_path
|
124
|
+
root_dirs.each do |root_dir|
|
125
|
+
Dir[::File.join(root_dir, 'format.*')].each do |fn|
|
126
|
+
require fn
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
ClWiki::CustomFormatters.instance.process_formatters(@content, self)
|
131
|
+
end
|
132
|
+
|
133
|
+
def get_header
|
134
|
+
f = ClWiki::PageFormatter.new(nil, @full_name)
|
135
|
+
f.header(@full_name, self)
|
136
|
+
end
|
137
|
+
|
138
|
+
def get_footer
|
139
|
+
f = ClWiki::PageFormatter.new(nil, @full_name)
|
140
|
+
f.footer(self)
|
141
|
+
end
|
142
|
+
|
143
|
+
def get_forward_ref(content)
|
144
|
+
content_ary = content.split("\n")
|
145
|
+
res = (content_ary.collect { |ln| ln.strip.empty? ? nil : ln }.compact.length == 1)
|
146
|
+
if res
|
147
|
+
res = content_ary[0] =~ /^see (.*)/i
|
148
|
+
end
|
149
|
+
|
150
|
+
if res
|
151
|
+
page_name = $1
|
152
|
+
f = ClWiki::PageFormatter.new(content, @full_name)
|
153
|
+
res = f.is_wiki_name?(page_name)
|
154
|
+
if res
|
155
|
+
res = ClWiki::Page.page_exists?(page_name)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
if res
|
159
|
+
page_name
|
160
|
+
else
|
161
|
+
nil
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def update_content(newcontent, mtime)
|
166
|
+
wikiFile = @wikiFile # ClWikiFile.new(@fullName, @wikiPath)
|
167
|
+
wikiFile.clientLastReadModTime = mtime
|
168
|
+
wikiFile.content = newcontent
|
169
|
+
if $wiki_conf.useIndex != ClWiki::Configuration::USE_INDEX_NO
|
170
|
+
wikiIndexClient = ClWiki::IndexClient.new
|
171
|
+
wikiIndexClient.reindex_page(@full_name)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.page_exists?(page_name)
|
176
|
+
if ($wiki_conf.useIndex != ClWiki::Configuration::USE_INDEX_NO) &&
|
177
|
+
($wiki_conf.useIndexForPageExists)
|
178
|
+
res = ClWiki::Page.wikiIndexClient.page_exists?(page_name)
|
179
|
+
else
|
180
|
+
wiki_file = ClWiki::File.new(page_name, $wiki_path, $wikiPageExt, false)
|
181
|
+
res = wiki_file.file_exists?
|
182
|
+
end
|
183
|
+
res
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
class PageFormatter
|
188
|
+
attr_accessor :content
|
189
|
+
|
190
|
+
def initialize(content=nil, aFullName=nil)
|
191
|
+
@content = content
|
192
|
+
self.fullName = aFullName
|
193
|
+
@wikiIndex = nil
|
194
|
+
end
|
195
|
+
|
196
|
+
def fullName=(value)
|
197
|
+
@full_name = value
|
198
|
+
if @full_name
|
199
|
+
@full_name = @full_name[1..-1] if @full_name[0..1] == '//'
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def fullName
|
204
|
+
@full_name
|
205
|
+
end
|
206
|
+
|
207
|
+
def header(full_page_name, page = nil)
|
208
|
+
search_text = ::File.basename(full_page_name)
|
209
|
+
page_path, page_name = ::File.split(full_page_name)
|
210
|
+
page_path = '/' if page_path == '.'
|
211
|
+
dirs = page_path.split('/')
|
212
|
+
dirs = dirs[1..-1] if !dirs.empty? && dirs[0].empty?
|
213
|
+
full_dirs = (0..dirs.length-1).each { |i| full_dirs[i] = ('/' + dirs[0..i].join('/')) }
|
214
|
+
head = '<div class=\'wikiHeader\'>'
|
215
|
+
if (full_page_name != $FIND_PAGE_NAME) and
|
216
|
+
(full_page_name != $FIND_RESULTS_NAME) and
|
217
|
+
(full_page_name != $wiki_conf.recent_changes_name) and
|
218
|
+
(full_page_name != $wiki_conf.stats_name)
|
219
|
+
head << "<span class='pageName'><a href='find?search_text=#{search_text}'>#{page_name}</a></span><br/>"
|
220
|
+
full_dirs.each do |dir|
|
221
|
+
head << '<span class=\'pageTag\'>'
|
222
|
+
head << "<a href=#{cgifn}?page=#{dir}>#{File.split(dir)[-1]}</a></span>"
|
223
|
+
end
|
224
|
+
head << '<br/>'
|
225
|
+
head << "<span class='wikiPageData'>#{page_update_time(page)}</span><br/>" if page
|
226
|
+
else
|
227
|
+
head << '<span class=\'pageName\'>' + full_page_name + '</span>'
|
228
|
+
end
|
229
|
+
head << '</div>'
|
230
|
+
end
|
231
|
+
|
232
|
+
def page_update_time(page)
|
233
|
+
mod_time = page.mtime
|
234
|
+
if mod_time
|
235
|
+
update_format = $wiki_conf.page_update_format.gsub(/ /, ' ')
|
236
|
+
mod_time.strftime(update_format)
|
237
|
+
else
|
238
|
+
''
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def process_custom_footers(page)
|
243
|
+
Dir[::File.dirname(__FILE__) + '/footer/footer.*'].each do |fn|
|
244
|
+
require fn
|
245
|
+
end
|
246
|
+
|
247
|
+
ClWiki::CustomFooters.instance.process_footers(page)
|
248
|
+
end
|
249
|
+
|
250
|
+
def footer(page)
|
251
|
+
return '' if !page.is_a? ClWiki::Page # blogki does this
|
252
|
+
|
253
|
+
custom_footer = process_custom_footers(page)
|
254
|
+
|
255
|
+
wiki_name = page.full_name
|
256
|
+
|
257
|
+
# refactor string constants
|
258
|
+
footer = "<div class='wikiFooter'>"
|
259
|
+
footer << "<ul>"
|
260
|
+
if (wiki_name != $FIND_PAGE_NAME) and
|
261
|
+
(wiki_name != $FIND_RESULTS_NAME) and
|
262
|
+
(wiki_name != $wiki_conf.recent_changes_name) and
|
263
|
+
(wiki_name != $wiki_conf.stats_name)
|
264
|
+
if $wiki_conf.editable
|
265
|
+
footer << ("<li><span class='wikiAction'><a href='" + wiki_name.strip_slash_prefix + "/edit'>Edit</a></span></li>")
|
266
|
+
end
|
267
|
+
end
|
268
|
+
footer << "<li><span class='wikiAction'><a href='find'>Find</a></span></li>"
|
269
|
+
footer << "<li><span class='wikiAction'><a href='recent'>Recent</a></span></li>"
|
270
|
+
# footer << "<li><span class='wikiAction'><a href=#{cgifn}?about=true>About</a></span></li>" if wiki_name == "/FrontPage"
|
271
|
+
footer << "</ul></div>"
|
272
|
+
return custom_footer << footer
|
273
|
+
end
|
274
|
+
|
275
|
+
def src_url
|
276
|
+
"file://#{ClWiki::Page.read_file_full_path_and_name(@full_name)}"
|
277
|
+
end
|
278
|
+
|
279
|
+
def reload_url(with_global_edit_links=false)
|
280
|
+
result = "#{full_url}?page=#{@full_name}"
|
281
|
+
if with_global_edit_links
|
282
|
+
result << "&globaledits=true"
|
283
|
+
else
|
284
|
+
result << "&globaledits=false"
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def mailto_url
|
289
|
+
"mailto:?Subject=wikifyi:%20#{@full_name}&Body=#{reload_url}"
|
290
|
+
end
|
291
|
+
|
292
|
+
def gsubWords
|
293
|
+
@content.gsub(/<.+?>|<\/.+?>|\w+/) { |word| yield word }
|
294
|
+
end
|
295
|
+
|
296
|
+
def convert_relative_wikinames_to_absolute
|
297
|
+
# do not go ahead without testing here
|
298
|
+
#formatLinks do |word|
|
299
|
+
# if isWikiName?(word)
|
300
|
+
#end
|
301
|
+
|
302
|
+
# problem here is we should obey the NoWikiLinks and Html tag rules,
|
303
|
+
# and those variables aren't being yielded right now. If we change
|
304
|
+
# how the yield works, it affects the indexer. And we can't just
|
305
|
+
# tack on additional yield params and have existing code that only
|
306
|
+
# pays attention to the first keep working:
|
307
|
+
#
|
308
|
+
# irb(main):001:0> def test
|
309
|
+
# irb(main):002:1> yield 1,2,3
|
310
|
+
# irb(main):003:1> end
|
311
|
+
# nil
|
312
|
+
# irb(main):004:0> test do |a|
|
313
|
+
# irb(main):005:1* puts a
|
314
|
+
# irb(main):006:1> end
|
315
|
+
# 1
|
316
|
+
# 2
|
317
|
+
# 3
|
318
|
+
end
|
319
|
+
|
320
|
+
def formatLinks
|
321
|
+
no_wiki_link_in_effect = false
|
322
|
+
inside_html_tags = false
|
323
|
+
|
324
|
+
gsubWords do |word|
|
325
|
+
if (word[0, 1] == '<') and (word[-1, 1] == '>')
|
326
|
+
# refactor to class,local constant, instead of global
|
327
|
+
if word =~ /#{'<NoWikiLinks>'}/i
|
328
|
+
no_wiki_link_in_effect = true
|
329
|
+
word = ''
|
330
|
+
# refactor to class,local constant, instead of global
|
331
|
+
elsif word =~ /#{'</NoWikiLinks>'}/i
|
332
|
+
no_wiki_link_in_effect = false
|
333
|
+
word = ''
|
334
|
+
end
|
335
|
+
|
336
|
+
if word =~ /#{'<html>'}/i
|
337
|
+
inside_html_tags = true
|
338
|
+
word = ''
|
339
|
+
elsif word =~ /#{'</html>'}/i
|
340
|
+
inside_html_tags = false
|
341
|
+
word = ''
|
342
|
+
end
|
343
|
+
elsif is_wiki_name?(word)
|
344
|
+
if !no_wiki_link_in_effect and !inside_html_tags
|
345
|
+
# code smell here y'all
|
346
|
+
word = convertToLink(word) if !block_given?
|
347
|
+
end
|
348
|
+
end
|
349
|
+
if block_given?
|
350
|
+
yield word
|
351
|
+
else
|
352
|
+
word
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def self.only_html(str)
|
358
|
+
onlyOneTag = /\A[^<]*<[^<>]*>[^>]*\z/
|
359
|
+
headerTagLine = /\A\s*<h.>.*<\/h.>\s*\z/
|
360
|
+
(str =~ onlyOneTag) || (str =~ headerTagLine)
|
361
|
+
# str.scan(/<.*>/).to_s == str.chomp
|
362
|
+
end
|
363
|
+
|
364
|
+
def starts_with_path_char(path)
|
365
|
+
(path[0..0] == '/') || (path[0..1] == '//')
|
366
|
+
end
|
367
|
+
|
368
|
+
def cgifn
|
369
|
+
$wiki_conf.cgifn if $wiki_conf
|
370
|
+
end
|
371
|
+
|
372
|
+
def full_url
|
373
|
+
($wiki_conf.url_prefix + cgifn) if $wiki_conf
|
374
|
+
end
|
375
|
+
|
376
|
+
def convertToLink(page_name)
|
377
|
+
if ClWiki::Page.page_exists?(page_name)
|
378
|
+
"<a href='#{page_name.strip_slash_prefix}'>#{page_name.strip_slash_prefix}</a>"
|
379
|
+
else
|
380
|
+
if $wiki_conf.useIndex == ClWiki::Configuration::USE_INDEX_NO
|
381
|
+
finder = FindInFile.new($wiki_path)
|
382
|
+
finder.find(page_name, FindInFile::FILE_NAME_ONLY)
|
383
|
+
hits = finder.files.collect { |f| f.sub($wikiPageExt, '') }
|
384
|
+
else
|
385
|
+
@wikiIndex = ClWiki::IndexClient.new if @wikiIndex.nil?
|
386
|
+
titles_only = true
|
387
|
+
hits = @wikiIndex.search(page_name, titles_only)
|
388
|
+
hits = GlobalHitReducer.reduce_to_exact_if_exists(page_name, hits)
|
389
|
+
end
|
390
|
+
|
391
|
+
case hits.length
|
392
|
+
when 0
|
393
|
+
result = page_name
|
394
|
+
when 1
|
395
|
+
result = "<a href='#{hits[0]}'>#{page_name}</a>"
|
396
|
+
else
|
397
|
+
result = "<a href='find?search_text=#{page_name}'>#{page_name}</a>"
|
398
|
+
end
|
399
|
+
|
400
|
+
if ($wiki_conf.editable) && ((hits.length == 0) || ($wiki_conf.global_edits))
|
401
|
+
result << "<a href='#{page_name}/edit'>?</a>"
|
402
|
+
end
|
403
|
+
result
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
def is_wiki_name?(string)
|
408
|
+
all_wiki_names = true
|
409
|
+
names = string.split(/[\\\/]/)
|
410
|
+
|
411
|
+
# if first character is a slash, then split puts an empty string into names[0]
|
412
|
+
names.delete_if { |name| name.empty? }
|
413
|
+
all_wiki_names = false if names.empty?
|
414
|
+
names.each do |name|
|
415
|
+
all_wiki_names =
|
416
|
+
(
|
417
|
+
all_wiki_names and
|
418
|
+
|
419
|
+
# the number of all capitals followed by a lowercase is greater than 1
|
420
|
+
(name.scan(/[A-Z][a-z]/).length > 1) and
|
421
|
+
|
422
|
+
# the first letter is capitalized or slash
|
423
|
+
(
|
424
|
+
(name[0, 1] == name[0, 1].capitalize) or (name[0, 1] == '/') or (name[0, 1] == "\\")
|
425
|
+
) and
|
426
|
+
|
427
|
+
# there are no non-word characters in the string (count is 0)
|
428
|
+
# ^[\w|\\|\/] is read:
|
429
|
+
# _____________[_____ _^_ ____\w_________ _| __\\______ _| ___\/________]
|
430
|
+
# characters that are not word characters or back-slash or forward-slash
|
431
|
+
# (the not negates the *whole* character set (stuff in brackets))
|
432
|
+
(name.scan(/[^\w\\\/]/).length == 0)
|
433
|
+
)
|
434
|
+
end
|
435
|
+
return all_wiki_names
|
436
|
+
end
|
437
|
+
end
|
438
|
+
class CustomFooters
|
439
|
+
include Singleton
|
440
|
+
|
441
|
+
def register(class_ref)
|
442
|
+
@footers ||= []
|
443
|
+
@footers << class_ref
|
444
|
+
end
|
445
|
+
|
446
|
+
def process_footers(page)
|
447
|
+
content = ''
|
448
|
+
@footers.each do |f|
|
449
|
+
content << f.footer_html(page)
|
450
|
+
end if @footers
|
451
|
+
return content
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
# to create your own custom footer, see any of the files in the ./footer
|
456
|
+
# directory and imitate.
|
457
|
+
class CustomFooter
|
458
|
+
end
|
459
|
+
|
460
|
+
class CustomFormatters
|
461
|
+
include Singleton
|
462
|
+
|
463
|
+
def register(class_ref)
|
464
|
+
@formatters ||= []
|
465
|
+
@formatters << class_ref
|
466
|
+
end
|
467
|
+
|
468
|
+
def process_formatters(content, page)
|
469
|
+
@formatters.each do |f|
|
470
|
+
if content =~ f.match_re
|
471
|
+
content.gsub!(f.match_re) { |match| f.format_content(match, page) }
|
472
|
+
end
|
473
|
+
end if @formatters
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
# to create your own custom formatter, see any of the files in the ./format
|
478
|
+
# directory and imitate.
|
479
|
+
class CustomFormatter
|
480
|
+
end
|
481
|
+
|
482
|
+
class GlobalHitReducer
|
483
|
+
def GlobalHitReducer.reduce_to_exact_if_exists(term, hits)
|
484
|
+
reduced = hits.dup
|
485
|
+
reduced.delete_if do |hit|
|
486
|
+
parts = hit.split('/')
|
487
|
+
exact = (parts[-1] =~ /^#{term}$/i)
|
488
|
+
!exact
|
489
|
+
end
|
490
|
+
|
491
|
+
if !reduced.empty?
|
492
|
+
reduced
|
493
|
+
else
|
494
|
+
hits
|
495
|
+
end
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
module CLabs
|
501
|
+
class WikiDiffFormatter
|
502
|
+
def WikiDiffFormatter.format_diff(diff)
|
503
|
+
"<b>Diff</b><br><pre>\n#{CGI.escapeHTML(diff)}\n</pre><br><hr=width\"50%\">"
|
504
|
+
end
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
class String
|
509
|
+
def ensure_slash_prefix
|
510
|
+
self[0..0] != '/' ? "/#{self}" : self
|
511
|
+
end
|
512
|
+
|
513
|
+
def strip_slash_prefix
|
514
|
+
self.gsub(/^\//, '')
|
515
|
+
end
|
516
|
+
end
|