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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a05ff0b1a136c335b3f6167e0f9012108bd49c5bf92fe94b11d4f93844d8510f
4
- data.tar.gz: d466ab9845678b7e3ee806248d880135946b8ec0015b3e3c932a7cc186164ed2
3
+ metadata.gz: 19d12f7ee8fbce5a07c527e9a05dd90703f5ff5f91fdb66c728295fc9c565539
4
+ data.tar.gz: 72daa353d7a40ebc6774c6b2a99aa665fa0483d53e40dd16af34cd22838a7c59
5
5
  SHA512:
6
- metadata.gz: ef48b158dde373c1063c343d8d276c46507b7db98d02a80de076c9387cd1e345b9b707af6ab1740fb25cf2f566013ca715fbed23aafbac6b96758c34be14051c
7
- data.tar.gz: 64baf2efec9c90eb5c61f09e35d82eefc9466742dbdea00c835858c76172c15f8d8d9507ff4f0ed84a95b50dd46f0cb28920f8dbcab78f175f520b3a99a1d340
6
+ metadata.gz: 46b443d65f1bdc2403b33690e67310d07361e5b159cee18ed480932a8003685b8e6eb35004e0c18473c726c24a434fcc1b562ebca8eeac1d4555119ae988a973
7
+ data.tar.gz: ccf1ac19ed5f3f8f1b9ee7a013a27777f5183287ca80d3124409e2a07e642818b2da6b8368fe82738d0d9f5b6f36d566eeb338bd1fb2e61588747c9743497c8b
@@ -0,0 +1,7 @@
1
+ module CLabs
2
+ class WikiDiffFormatter
3
+ def self.format_diff(diff)
4
+ "<b>Diff</b><br><pre>\n#{CGI.escapeHTML(diff)}\n</pre><br><hr=width\"50%\">"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # to create your own custom footer, see any of the files in the ./footer
2
+ # directory and imitate.
3
+
4
+ module ClWiki
5
+ class CustomFooter
6
+ end
7
+ end
@@ -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,7 @@
1
+ # to create your own custom formatter, see any of the files in the ./format
2
+ # directory and imitate.
3
+
4
+ module ClWiki
5
+ class CustomFormatter
6
+ end
7
+ 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,5 @@
1
+ module ClWiki
2
+ class FileError < RuntimeError
3
+
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module ClWiki
2
+ class FileModifiedSinceRead < FileError
3
+ end
4
+ 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(/ /, '&nbsp;')
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(/ /, '&nbsp;')
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
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ClWiki
4
- VERSION = '3.2.2'
4
+ VERSION = '3.2.3'
5
5
  end
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.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