clwiki 3.2.2 → 3.2.3
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.
- checksums.yaml +4 -4
- data/lib/cl_wiki/c_labs/wiki_diff_formatter.rb +7 -0
- data/lib/cl_wiki/custom_footer.rb +7 -0
- data/lib/cl_wiki/custom_footers.rb +18 -0
- data/lib/cl_wiki/custom_formatter.rb +7 -0
- data/lib/cl_wiki/custom_formatters.rb +22 -0
- data/lib/cl_wiki/file.rb +0 -94
- data/lib/cl_wiki/file_error.rb +5 -0
- data/lib/cl_wiki/file_modified_since_read.rb +4 -0
- data/lib/cl_wiki/metadata.rb +60 -0
- data/lib/cl_wiki/page.rb +0 -245
- data/lib/cl_wiki/page_formatter.rb +190 -0
- data/lib/cl_wiki/util.rb +30 -0
- data/lib/cl_wiki/version.rb +1 -1
- data/lib/cl_wiki_lib.rb +19 -0
- metadata +11 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 19d12f7ee8fbce5a07c527e9a05dd90703f5ff5f91fdb66c728295fc9c565539
|
4
|
+
data.tar.gz: 72daa353d7a40ebc6774c6b2a99aa665fa0483d53e40dd16af34cd22838a7c59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46b443d65f1bdc2403b33690e67310d07361e5b159cee18ed480932a8003685b8e6eb35004e0c18473c726c24a434fcc1b562ebca8eeac1d4555119ae988a973
|
7
|
+
data.tar.gz: ccf1ac19ed5f3f8f1b9ee7a013a27777f5183287ca80d3124409e2a07e642818b2da6b8368fe82738d0d9f5b6f36d566eeb338bd1fb2e61588747c9743497c8b
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ClWiki
|
2
|
+
class CustomFooters
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
def register(class_ref)
|
6
|
+
@footers ||= []
|
7
|
+
@footers << class_ref
|
8
|
+
end
|
9
|
+
|
10
|
+
def process_footers(page)
|
11
|
+
String.new.tap do |content|
|
12
|
+
@footers&.each do |f|
|
13
|
+
content << f.footer_html(page)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ClWiki
|
2
|
+
class CustomFormatters
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
def register(class_ref)
|
6
|
+
@formatters ||= []
|
7
|
+
@formatters << class_ref
|
8
|
+
end
|
9
|
+
|
10
|
+
def unregister(class_ref)
|
11
|
+
@formatters.delete(class_ref)
|
12
|
+
end
|
13
|
+
|
14
|
+
def process_formatters(content, page)
|
15
|
+
@formatters&.each do |f|
|
16
|
+
if content&.match?(f.match_re)
|
17
|
+
content.gsub!(f.match_re) { |match| f.format_content(match, page) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/cl_wiki/file.rb
CHANGED
@@ -121,98 +121,4 @@ module ClWiki
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
end
|
124
|
-
|
125
|
-
class Metadata
|
126
|
-
def self.split_file_contents(content)
|
127
|
-
idx = content =~ /\n{3}/m
|
128
|
-
metadata = []
|
129
|
-
|
130
|
-
if idx
|
131
|
-
metadata = content[0..(idx - 1)].split(/\n/)
|
132
|
-
valid_metadata?(metadata) ? content = content[(idx + 3)..-1] : metadata = []
|
133
|
-
end
|
134
|
-
[self.new(metadata), content]
|
135
|
-
end
|
136
|
-
|
137
|
-
def self.valid_metadata?(lines)
|
138
|
-
lines.map { |ln| ln.scan(/\A(\w+):?/) }.flatten.
|
139
|
-
map { |k| supported_keys.include?(k) }.uniq == [true]
|
140
|
-
end
|
141
|
-
|
142
|
-
def self.supported_keys
|
143
|
-
%w[mtime encrypted owner]
|
144
|
-
end
|
145
|
-
|
146
|
-
def initialize(lines = [])
|
147
|
-
@hash = {}
|
148
|
-
@keys = Metadata.supported_keys
|
149
|
-
parse_lines(lines)
|
150
|
-
end
|
151
|
-
|
152
|
-
def [](key)
|
153
|
-
@hash[key]
|
154
|
-
end
|
155
|
-
|
156
|
-
def []=(key, value)
|
157
|
-
raise "Unexpected key: #{key}" unless @keys.include?(key)
|
158
|
-
|
159
|
-
@hash[key] = value
|
160
|
-
end
|
161
|
-
|
162
|
-
def has?(key)
|
163
|
-
@hash.key?(key)
|
164
|
-
end
|
165
|
-
|
166
|
-
def to_s
|
167
|
-
@hash.collect { |k, v| "#{k}: #{v}" }.join("\n") + "\n\n\n"
|
168
|
-
end
|
169
|
-
|
170
|
-
def to_h
|
171
|
-
@hash
|
172
|
-
end
|
173
|
-
|
174
|
-
private
|
175
|
-
|
176
|
-
def parse_lines(lines)
|
177
|
-
lines.each do |ln|
|
178
|
-
key, value = ln.split(': ')
|
179
|
-
@hash[key] = value.chomp if @keys.include?(key)
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
class Util
|
185
|
-
def self.raise_if_mtime_not_equal(mtime_to_compare, file_name)
|
186
|
-
# reading the instance .mtime appears to take Windows DST into account,
|
187
|
-
# whereas the static File.mtime(filename) method does not
|
188
|
-
current_mtime = ::File.open(file_name, &:mtime)
|
189
|
-
compare_read_times!(mtime_to_compare, current_mtime)
|
190
|
-
end
|
191
|
-
|
192
|
-
def self.compare_read_times!(a, b)
|
193
|
-
# ignore usec
|
194
|
-
a = Time.new(a.year, a.month, a.day, a.hour, a.min, a.sec)
|
195
|
-
b = Time.new(b.year, b.month, b.day, b.hour, b.min, b.sec)
|
196
|
-
if a != b
|
197
|
-
raise FileModifiedSinceRead, "File has been modified since it was last read. #{dump_time(a)} != #{dump_time(b)}"
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
def self.dump_time(time)
|
202
|
-
String.new.tap do |s|
|
203
|
-
s << time.to_s
|
204
|
-
s << ".#{time.usec}" if time.respond_to?(:usec)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
def self.convert_to_native_path(path)
|
209
|
-
path.gsub(%r{/}, ::File::SEPARATOR).gsub(/\\/, ::File::SEPARATOR)
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
class FileError < RuntimeError
|
214
|
-
end
|
215
|
-
|
216
|
-
class FileModifiedSinceRead < FileError
|
217
|
-
end
|
218
124
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module ClWiki
|
2
|
+
class Metadata
|
3
|
+
def self.split_file_contents(content)
|
4
|
+
idx = content =~ /\n{3}/m
|
5
|
+
metadata = []
|
6
|
+
|
7
|
+
if idx
|
8
|
+
metadata = content[0..(idx - 1)].split(/\n/)
|
9
|
+
valid_metadata?(metadata) ? content = content[(idx + 3)..-1] : metadata = []
|
10
|
+
end
|
11
|
+
[self.new(metadata), content]
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.valid_metadata?(lines)
|
15
|
+
lines.map { |ln| ln.scan(/\A(\w+):?/) }.flatten.
|
16
|
+
map { |k| supported_keys.include?(k) }.uniq == [true]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.supported_keys
|
20
|
+
%w[mtime encrypted owner]
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(lines = [])
|
24
|
+
@hash = {}
|
25
|
+
@keys = Metadata.supported_keys
|
26
|
+
parse_lines(lines)
|
27
|
+
end
|
28
|
+
|
29
|
+
def [](key)
|
30
|
+
@hash[key]
|
31
|
+
end
|
32
|
+
|
33
|
+
def []=(key, value)
|
34
|
+
raise "Unexpected key: #{key}" unless @keys.include?(key)
|
35
|
+
|
36
|
+
@hash[key] = value
|
37
|
+
end
|
38
|
+
|
39
|
+
def has?(key)
|
40
|
+
@hash.key?(key)
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
@hash.collect { |k, v| "#{k}: #{v}" }.join("\n") + "\n\n\n"
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_h
|
48
|
+
@hash
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def parse_lines(lines)
|
54
|
+
lines.each do |ln|
|
55
|
+
key, value = ln.split(': ')
|
56
|
+
@hash[key] = value.chomp if @keys.include?(key)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/cl_wiki/page.rb
CHANGED
@@ -149,249 +149,4 @@ module ClWiki
|
|
149
149
|
ClWiki::MemoryIndexer.instance.page_exists?(page_name)
|
150
150
|
end
|
151
151
|
end
|
152
|
-
|
153
|
-
class PageFormatter
|
154
|
-
FIND_PAGE_NAME = 'Find'
|
155
|
-
FIND_RESULTS_NAME = 'Find Results'
|
156
|
-
|
157
|
-
attr_reader :full_name
|
158
|
-
attr_accessor :content
|
159
|
-
|
160
|
-
def initialize(content = nil, full_name = nil)
|
161
|
-
@content = content
|
162
|
-
self.full_name = full_name
|
163
|
-
@wiki_index = nil
|
164
|
-
end
|
165
|
-
|
166
|
-
def full_name=(value)
|
167
|
-
@full_name = value
|
168
|
-
if @full_name
|
169
|
-
@full_name = @full_name[1..-1] if @full_name[0..1] == '//'
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def header(full_page_name, page = nil)
|
174
|
-
search_text = ::File.basename(full_page_name)
|
175
|
-
page_path, page_name = ::File.split(full_page_name)
|
176
|
-
page_path = '/' if page_path == '.'
|
177
|
-
dirs = page_path.split('/')
|
178
|
-
dirs = dirs[1..-1] if !dirs.empty? && dirs[0].empty?
|
179
|
-
full_dirs = (0..dirs.length - 1).each { |i| full_dirs[i] = ('/' + dirs[0..i].join('/')) }
|
180
|
-
head = String.new("<div class='wikiHeader'>")
|
181
|
-
head << core_footer_links(full_page_name, -1).sub('wikiFooter', 'wikiFooter wikiFooterFloat')
|
182
|
-
if [FIND_PAGE_NAME, FIND_RESULTS_NAME].include?(full_page_name)
|
183
|
-
head << "<span class='pageName'>#{full_page_name}</span>"
|
184
|
-
else
|
185
|
-
head << "<span class='pageName'><a href='find?search_text=#{search_text}'>#{page_name}</a></span><br/>"
|
186
|
-
full_dirs.each do |dir|
|
187
|
-
head << "'<span class='pageTag'>'"
|
188
|
-
head << "<a href=#{cgifn}?page=#{dir}>#{File.split(dir)[-1]}</a></span>"
|
189
|
-
end
|
190
|
-
head << '<br/>'
|
191
|
-
head << "<span class='wikiPageData'>#{page_update_time(page)}</span><br/>" if page
|
192
|
-
end
|
193
|
-
head << '</div>'
|
194
|
-
end
|
195
|
-
|
196
|
-
def page_update_time(page)
|
197
|
-
mod_time = page.mtime
|
198
|
-
if mod_time
|
199
|
-
update_format = $wiki_conf.page_update_format.gsub(/ /, ' ')
|
200
|
-
mod_time.strftime(update_format)
|
201
|
-
else
|
202
|
-
''
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
def process_custom_footers(page)
|
207
|
-
Dir["#{::File.dirname(__FILE__)}/footer/footer.*"].sort.each do |fn|
|
208
|
-
require fn
|
209
|
-
end
|
210
|
-
|
211
|
-
ClWiki::CustomFooters.instance.process_footers(page)
|
212
|
-
end
|
213
|
-
|
214
|
-
def footer(page)
|
215
|
-
return String.new unless page.is_a? ClWiki::Page
|
216
|
-
custom_footer = process_custom_footers(page)
|
217
|
-
custom_footer << core_footer_links(page.page_name)
|
218
|
-
end
|
219
|
-
|
220
|
-
def core_footer_links(wiki_name, tab_index=0)
|
221
|
-
# refactor string constants
|
222
|
-
footer = String.new("<div class='wikiFooter'>")
|
223
|
-
footer << '<ul>'
|
224
|
-
if $wiki_conf.editable
|
225
|
-
unless [FIND_PAGE_NAME, FIND_RESULTS_NAME].include?(wiki_name)
|
226
|
-
footer << "<li><span class='wikiAction'><a href='#{wiki_name}/edit' tabindex=#{tab_index}>Edit</a></span></li>"
|
227
|
-
end
|
228
|
-
end
|
229
|
-
footer << "<li><span class='wikiAction'><a href='find' tabindex=#{tab_index}>Find</a></span></li>"
|
230
|
-
if $wiki_conf.publishTag
|
231
|
-
footer << "<li><span class='wikiAction'><a href='recent' tabindex=#{tab_index}>Recent</a></span></li>"
|
232
|
-
else
|
233
|
-
footer << "<li><span class='wikiAction'><a href='FrontPage' tabindex=#{tab_index}>Home</a></span></li>"
|
234
|
-
end
|
235
|
-
footer << '</ul></div>'
|
236
|
-
footer
|
237
|
-
end
|
238
|
-
|
239
|
-
def src_url
|
240
|
-
"file://#{ClWiki::Page.read_file_full_path_and_name(@full_name)}"
|
241
|
-
end
|
242
|
-
|
243
|
-
def reload_url(with_global_edit_links = false)
|
244
|
-
result = "#{full_url}?page=#{@full_name}"
|
245
|
-
result << (with_global_edit_links ? '&globaledits=true' : '&globaledits=false')
|
246
|
-
end
|
247
|
-
|
248
|
-
def mailto_url
|
249
|
-
"mailto:?Subject=wikifyi:%20#{@full_name}&Body=#{reload_url}"
|
250
|
-
end
|
251
|
-
|
252
|
-
def gsub_words
|
253
|
-
@content.gsub(%r{<.+?>|</.+?>|\w+}) { |word| yield word }
|
254
|
-
end
|
255
|
-
|
256
|
-
def format_links
|
257
|
-
no_wiki_link_in_effect = false
|
258
|
-
inside_html_tags = false
|
259
|
-
|
260
|
-
gsub_words do |word|
|
261
|
-
if (word[0, 1] == '<') && (word[-1, 1] == '>')
|
262
|
-
# refactor to class,local constant, instead of global
|
263
|
-
if /<NoWikiLinks>/i.match?(word)
|
264
|
-
no_wiki_link_in_effect = true
|
265
|
-
word = ''
|
266
|
-
# refactor to class,local constant, instead of global
|
267
|
-
elsif /<\/NoWikiLinks>/i.match?(word)
|
268
|
-
no_wiki_link_in_effect = false
|
269
|
-
word = ''
|
270
|
-
end
|
271
|
-
|
272
|
-
if /<html>/i.match?(word)
|
273
|
-
inside_html_tags = true
|
274
|
-
word = ''
|
275
|
-
elsif /<\/html>/i.match?(word)
|
276
|
-
inside_html_tags = false
|
277
|
-
word = ''
|
278
|
-
end
|
279
|
-
elsif is_wiki_name?(word)
|
280
|
-
if !no_wiki_link_in_effect && !inside_html_tags
|
281
|
-
# code smell here y'all
|
282
|
-
word = convert_to_link(word) unless block_given?
|
283
|
-
end
|
284
|
-
end
|
285
|
-
if block_given?
|
286
|
-
yield word
|
287
|
-
else
|
288
|
-
word
|
289
|
-
end
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
def self.only_html(str)
|
294
|
-
only_one_tag = /\A[^<]*<[^<>]*>[^>]*\z/
|
295
|
-
header_tag_line = %r{\A\s*<h.>.*</h.>\s*\z}
|
296
|
-
(str =~ only_one_tag) || (str =~ header_tag_line)
|
297
|
-
# str.scan(/<.*>/).to_s == str.chomp
|
298
|
-
end
|
299
|
-
|
300
|
-
def starts_with_path_char(path)
|
301
|
-
(path[0..0] == '/') || (path[0..1] == '//')
|
302
|
-
end
|
303
|
-
|
304
|
-
def cgifn
|
305
|
-
$wiki_conf&.cgifn
|
306
|
-
end
|
307
|
-
|
308
|
-
def full_url
|
309
|
-
($wiki_conf.url_prefix + cgifn) if $wiki_conf
|
310
|
-
end
|
311
|
-
|
312
|
-
def convert_to_link(page_name)
|
313
|
-
if ClWiki::Page.page_exists?(page_name)
|
314
|
-
"<a href='#{page_name}'>#{page_name}</a>"
|
315
|
-
else
|
316
|
-
@wiki_index ||= ClWiki::MemoryIndexer.instance
|
317
|
-
hits = @wiki_index.search(page_name, titles_only: true)
|
318
|
-
|
319
|
-
result = case hits.length
|
320
|
-
when 0
|
321
|
-
page_name
|
322
|
-
when 1
|
323
|
-
"<a href='#{hits[0]}'>#{page_name}</a>"
|
324
|
-
else
|
325
|
-
"<a href='find?search_text=#{page_name}'>#{page_name}</a>"
|
326
|
-
end
|
327
|
-
|
328
|
-
if $wiki_conf.editable && (hits.empty? || $wiki_conf.global_edits)
|
329
|
-
result << "<a href='#{page_name}/edit'>?</a>"
|
330
|
-
end
|
331
|
-
result
|
332
|
-
end
|
333
|
-
end
|
334
|
-
|
335
|
-
def is_wiki_name?(string)
|
336
|
-
return false if string.empty?
|
337
|
-
|
338
|
-
/\A[0-9]*[A-Z][a-z]\w*?[A-Z][a-z]\w*\z/.match?(string)
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
|
-
class CustomFooters
|
343
|
-
include Singleton
|
344
|
-
|
345
|
-
def register(class_ref)
|
346
|
-
@footers ||= []
|
347
|
-
@footers << class_ref
|
348
|
-
end
|
349
|
-
|
350
|
-
def process_footers(page)
|
351
|
-
String.new.tap do |content|
|
352
|
-
@footers&.each do |f|
|
353
|
-
content << f.footer_html(page)
|
354
|
-
end
|
355
|
-
end
|
356
|
-
end
|
357
|
-
end
|
358
|
-
|
359
|
-
# to create your own custom footer, see any of the files in the ./footer
|
360
|
-
# directory and imitate.
|
361
|
-
class CustomFooter
|
362
|
-
end
|
363
|
-
|
364
|
-
class CustomFormatters
|
365
|
-
include Singleton
|
366
|
-
|
367
|
-
def register(class_ref)
|
368
|
-
@formatters ||= []
|
369
|
-
@formatters << class_ref
|
370
|
-
end
|
371
|
-
|
372
|
-
def unregister(class_ref)
|
373
|
-
@formatters.delete(class_ref)
|
374
|
-
end
|
375
|
-
|
376
|
-
def process_formatters(content, page)
|
377
|
-
@formatters&.each do |f|
|
378
|
-
if content&.match?(f.match_re)
|
379
|
-
content.gsub!(f.match_re) { |match| f.format_content(match, page) }
|
380
|
-
end
|
381
|
-
end
|
382
|
-
end
|
383
|
-
end
|
384
|
-
|
385
|
-
# to create your own custom formatter, see any of the files in the ./format
|
386
|
-
# directory and imitate.
|
387
|
-
class CustomFormatter
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
|
-
module CLabs
|
392
|
-
class WikiDiffFormatter
|
393
|
-
def self.format_diff(diff)
|
394
|
-
"<b>Diff</b><br><pre>\n#{CGI.escapeHTML(diff)}\n</pre><br><hr=width\"50%\">"
|
395
|
-
end
|
396
|
-
end
|
397
152
|
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
module ClWiki
|
2
|
+
class PageFormatter
|
3
|
+
FIND_PAGE_NAME = 'Find'
|
4
|
+
FIND_RESULTS_NAME = 'Find Results'
|
5
|
+
|
6
|
+
attr_reader :full_name
|
7
|
+
attr_accessor :content
|
8
|
+
|
9
|
+
def initialize(content = nil, full_name = nil)
|
10
|
+
@content = content
|
11
|
+
self.full_name = full_name
|
12
|
+
@wiki_index = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def full_name=(value)
|
16
|
+
@full_name = value
|
17
|
+
if @full_name
|
18
|
+
@full_name = @full_name[1..-1] if @full_name[0..1] == '//'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def header(full_page_name, page = nil)
|
23
|
+
search_text = ::File.basename(full_page_name)
|
24
|
+
page_path, page_name = ::File.split(full_page_name)
|
25
|
+
page_path = '/' if page_path == '.'
|
26
|
+
dirs = page_path.split('/')
|
27
|
+
dirs = dirs[1..-1] if !dirs.empty? && dirs[0].empty?
|
28
|
+
full_dirs = (0..dirs.length - 1).each { |i| full_dirs[i] = ('/' + dirs[0..i].join('/')) }
|
29
|
+
head = String.new("<div class='wikiHeader'>")
|
30
|
+
head << core_footer_links(full_page_name, -1).sub('wikiFooter', 'wikiFooter wikiFooterFloat')
|
31
|
+
if [FIND_PAGE_NAME, FIND_RESULTS_NAME].include?(full_page_name)
|
32
|
+
head << "<span class='pageName'>#{full_page_name}</span>"
|
33
|
+
else
|
34
|
+
head << "<span class='pageName'><a href='find?search_text=#{search_text}'>#{page_name}</a></span><br/>"
|
35
|
+
full_dirs.each do |dir|
|
36
|
+
head << "'<span class='pageTag'>'"
|
37
|
+
head << "<a href=#{cgifn}?page=#{dir}>#{File.split(dir)[-1]}</a></span>"
|
38
|
+
end
|
39
|
+
head << '<br/>'
|
40
|
+
head << "<span class='wikiPageData'>#{page_update_time(page)}</span><br/>" if page
|
41
|
+
end
|
42
|
+
head << '</div>'
|
43
|
+
end
|
44
|
+
|
45
|
+
def page_update_time(page)
|
46
|
+
mod_time = page.mtime
|
47
|
+
if mod_time
|
48
|
+
update_format = $wiki_conf.page_update_format.gsub(/ /, ' ')
|
49
|
+
mod_time.strftime(update_format)
|
50
|
+
else
|
51
|
+
''
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def process_custom_footers(page)
|
56
|
+
Dir["#{::File.dirname(__FILE__)}/footer/footer.*"].sort.each do |fn|
|
57
|
+
require fn
|
58
|
+
end
|
59
|
+
|
60
|
+
ClWiki::CustomFooters.instance.process_footers(page)
|
61
|
+
end
|
62
|
+
|
63
|
+
def footer(page)
|
64
|
+
return String.new unless page.is_a? ClWiki::Page
|
65
|
+
custom_footer = process_custom_footers(page)
|
66
|
+
custom_footer << core_footer_links(page.page_name)
|
67
|
+
end
|
68
|
+
|
69
|
+
def core_footer_links(wiki_name, tab_index = 0)
|
70
|
+
# refactor string constants
|
71
|
+
footer = String.new("<div class='wikiFooter'>")
|
72
|
+
footer << '<ul>'
|
73
|
+
if $wiki_conf.editable
|
74
|
+
unless [FIND_PAGE_NAME, FIND_RESULTS_NAME].include?(wiki_name)
|
75
|
+
footer << "<li><span class='wikiAction'><a href='#{wiki_name}/edit' tabindex=#{tab_index}>Edit</a></span></li>"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
footer << "<li><span class='wikiAction'><a href='find' tabindex=#{tab_index}>Find</a></span></li>"
|
79
|
+
if $wiki_conf.publishTag
|
80
|
+
footer << "<li><span class='wikiAction'><a href='recent' tabindex=#{tab_index}>Recent</a></span></li>"
|
81
|
+
else
|
82
|
+
footer << "<li><span class='wikiAction'><a href='FrontPage' tabindex=#{tab_index}>Home</a></span></li>"
|
83
|
+
end
|
84
|
+
footer << '</ul></div>'
|
85
|
+
footer
|
86
|
+
end
|
87
|
+
|
88
|
+
def src_url
|
89
|
+
"file://#{ClWiki::Page.read_file_full_path_and_name(@full_name)}"
|
90
|
+
end
|
91
|
+
|
92
|
+
def reload_url(with_global_edit_links = false)
|
93
|
+
result = "#{full_url}?page=#{@full_name}"
|
94
|
+
result << (with_global_edit_links ? '&globaledits=true' : '&globaledits=false')
|
95
|
+
end
|
96
|
+
|
97
|
+
def mailto_url
|
98
|
+
"mailto:?Subject=wikifyi:%20#{@full_name}&Body=#{reload_url}"
|
99
|
+
end
|
100
|
+
|
101
|
+
def gsub_words
|
102
|
+
@content.gsub(%r{<.+?>|</.+?>|\w+}) { |word| yield word }
|
103
|
+
end
|
104
|
+
|
105
|
+
def format_links
|
106
|
+
no_wiki_link_in_effect = false
|
107
|
+
inside_html_tags = false
|
108
|
+
|
109
|
+
gsub_words do |word|
|
110
|
+
if (word[0, 1] == '<') && (word[-1, 1] == '>')
|
111
|
+
# refactor to class,local constant, instead of global
|
112
|
+
if /<NoWikiLinks>/i.match?(word)
|
113
|
+
no_wiki_link_in_effect = true
|
114
|
+
word = ''
|
115
|
+
# refactor to class,local constant, instead of global
|
116
|
+
elsif /<\/NoWikiLinks>/i.match?(word)
|
117
|
+
no_wiki_link_in_effect = false
|
118
|
+
word = ''
|
119
|
+
end
|
120
|
+
|
121
|
+
if /<html>/i.match?(word)
|
122
|
+
inside_html_tags = true
|
123
|
+
word = ''
|
124
|
+
elsif /<\/html>/i.match?(word)
|
125
|
+
inside_html_tags = false
|
126
|
+
word = ''
|
127
|
+
end
|
128
|
+
elsif is_wiki_name?(word)
|
129
|
+
if !no_wiki_link_in_effect && !inside_html_tags
|
130
|
+
# code smell here y'all
|
131
|
+
word = convert_to_link(word) unless block_given?
|
132
|
+
end
|
133
|
+
end
|
134
|
+
if block_given?
|
135
|
+
yield word
|
136
|
+
else
|
137
|
+
word
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.only_html(str)
|
143
|
+
only_one_tag = /\A[^<]*<[^<>]*>[^>]*\z/
|
144
|
+
header_tag_line = %r{\A\s*<h.>.*</h.>\s*\z}
|
145
|
+
(str =~ only_one_tag) || (str =~ header_tag_line)
|
146
|
+
# str.scan(/<.*>/).to_s == str.chomp
|
147
|
+
end
|
148
|
+
|
149
|
+
def starts_with_path_char(path)
|
150
|
+
(path[0..0] == '/') || (path[0..1] == '//')
|
151
|
+
end
|
152
|
+
|
153
|
+
def cgifn
|
154
|
+
$wiki_conf&.cgifn
|
155
|
+
end
|
156
|
+
|
157
|
+
def full_url
|
158
|
+
($wiki_conf.url_prefix + cgifn) if $wiki_conf
|
159
|
+
end
|
160
|
+
|
161
|
+
def convert_to_link(page_name)
|
162
|
+
if ClWiki::Page.page_exists?(page_name)
|
163
|
+
"<a href='#{page_name}'>#{page_name}</a>"
|
164
|
+
else
|
165
|
+
@wiki_index ||= ClWiki::MemoryIndexer.instance
|
166
|
+
hits = @wiki_index.search(page_name, titles_only: true)
|
167
|
+
|
168
|
+
result = case hits.length
|
169
|
+
when 0
|
170
|
+
page_name
|
171
|
+
when 1
|
172
|
+
"<a href='#{hits[0]}'>#{page_name}</a>"
|
173
|
+
else
|
174
|
+
"<a href='find?search_text=#{page_name}'>#{page_name}</a>"
|
175
|
+
end
|
176
|
+
|
177
|
+
if $wiki_conf.editable && (hits.empty? || $wiki_conf.global_edits)
|
178
|
+
result << "<a href='#{page_name}/edit'>?</a>"
|
179
|
+
end
|
180
|
+
result
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def is_wiki_name?(string)
|
185
|
+
return false if string.empty?
|
186
|
+
|
187
|
+
/\A[0-9]*[A-Z][a-z]\w*?[A-Z][a-z]\w*\z/.match?(string)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
data/lib/cl_wiki/util.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module ClWiki
|
2
|
+
class Util
|
3
|
+
def self.raise_if_mtime_not_equal(mtime_to_compare, file_name)
|
4
|
+
# reading the instance .mtime appears to take Windows DST into account,
|
5
|
+
# whereas the static File.mtime(filename) method does not
|
6
|
+
current_mtime = ::File.open(file_name, &:mtime)
|
7
|
+
compare_read_times!(mtime_to_compare, current_mtime)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.compare_read_times!(a, b)
|
11
|
+
# ignore usec
|
12
|
+
a = Time.new(a.year, a.month, a.day, a.hour, a.min, a.sec)
|
13
|
+
b = Time.new(b.year, b.month, b.day, b.hour, b.min, b.sec)
|
14
|
+
if a != b
|
15
|
+
raise FileModifiedSinceRead, "File has been modified since it was last read. #{dump_time(a)} != #{dump_time(b)}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.dump_time(time)
|
20
|
+
String.new.tap do |s|
|
21
|
+
s << time.to_s
|
22
|
+
s << ".#{time.usec}" if time.respond_to?(:usec)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.convert_to_native_path(path)
|
27
|
+
path.gsub(%r{/}, ::File::SEPARATOR).gsub(/\\/, ::File::SEPARATOR)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/cl_wiki/version.rb
CHANGED
data/lib/cl_wiki_lib.rb
CHANGED
@@ -4,6 +4,25 @@ require File.expand_path('cl_wiki/configuration', __dir__)
|
|
4
4
|
require File.expand_path('cl_wiki/user_base', __dir__)
|
5
5
|
require File.expand_path('cl_wiki/public_user', __dir__)
|
6
6
|
require File.expand_path('cl_wiki/memory_indexer', __dir__)
|
7
|
+
|
8
|
+
require File.expand_path('cl_wiki/file_error', __dir__)
|
9
|
+
require File.expand_path('cl_wiki/file_modified_since_read', __dir__)
|
7
10
|
require File.expand_path('cl_wiki/file', __dir__)
|
11
|
+
|
12
|
+
require File.expand_path('cl_wiki/util', __dir__)
|
13
|
+
|
14
|
+
require File.expand_path('cl_wiki/custom_footer', __dir__)
|
15
|
+
require File.expand_path('cl_wiki/custom_footers', __dir__)
|
16
|
+
require File.expand_path('cl_wiki/custom_formatter', __dir__)
|
17
|
+
require File.expand_path('cl_wiki/custom_formatters', __dir__)
|
18
|
+
|
19
|
+
Dir[File.join(__dir__, 'cl_wiki', 'format', '*.rb')].each do |fn|
|
20
|
+
require fn
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
require File.expand_path('cl_wiki/metadata', __dir__)
|
25
|
+
require File.expand_path('cl_wiki/page_formatter', __dir__)
|
26
|
+
|
8
27
|
require File.expand_path('cl_wiki/page', __dir__)
|
9
28
|
require File.expand_path('cl_wiki/version', __dir__)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clwiki
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.
|
4
|
+
version: 3.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- chrismo
|
@@ -82,18 +82,28 @@ files:
|
|
82
82
|
- config/initializers/clwiki.rb
|
83
83
|
- config/routes.rb
|
84
84
|
- lib/cl_wiki.rb
|
85
|
+
- lib/cl_wiki/c_labs/wiki_diff_formatter.rb
|
85
86
|
- lib/cl_wiki/configuration.rb
|
87
|
+
- lib/cl_wiki/custom_footer.rb
|
88
|
+
- lib/cl_wiki/custom_footers.rb
|
89
|
+
- lib/cl_wiki/custom_formatter.rb
|
90
|
+
- lib/cl_wiki/custom_formatters.rb
|
86
91
|
- lib/cl_wiki/engine.rb
|
87
92
|
- lib/cl_wiki/file.rb
|
93
|
+
- lib/cl_wiki/file_error.rb
|
94
|
+
- lib/cl_wiki/file_modified_since_read.rb
|
88
95
|
- lib/cl_wiki/format/format_blockquote.rb
|
89
96
|
- lib/cl_wiki/format/format_graphviz_di_graph.rb
|
90
97
|
- lib/cl_wiki/format/format_opml.rb
|
91
98
|
- lib/cl_wiki/format/format_pre_blockquote.rb
|
92
99
|
- lib/cl_wiki/format/format_simple_table.rb
|
93
100
|
- lib/cl_wiki/memory_indexer.rb
|
101
|
+
- lib/cl_wiki/metadata.rb
|
94
102
|
- lib/cl_wiki/page.rb
|
103
|
+
- lib/cl_wiki/page_formatter.rb
|
95
104
|
- lib/cl_wiki/public_user.rb
|
96
105
|
- lib/cl_wiki/user_base.rb
|
106
|
+
- lib/cl_wiki/util.rb
|
97
107
|
- lib/cl_wiki/version.rb
|
98
108
|
- lib/cl_wiki_lib.rb
|
99
109
|
- lib/tasks/index.rake
|