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
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'cl_wiki/configuration'
|
2
|
+
|
3
|
+
filename = File.join(File.dirname(__FILE__), '..', '..', 'config', 'clwiki.yml')
|
4
|
+
|
5
|
+
conf_hash = YAML::load(::File.open(filename))[Rails.env]
|
6
|
+
conf_hash['wiki_path'] = ::File.expand_path(conf_hash['wiki_path'], Rails.root)
|
7
|
+
$wiki_conf = ClWiki::Configuration.new(conf_hash)
|
8
|
+
$wiki_path = $wiki_conf.wiki_path
|
9
|
+
$wiki_conf
|
data/config/routes.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
ClWiki::Engine.routes.draw do
|
2
|
+
root to: 'page#show'
|
3
|
+
|
4
|
+
# legacy CGI
|
5
|
+
match '/clwikicgi.rb', to: 'page#show', via: [:get], as: 'legacy'
|
6
|
+
|
7
|
+
get '/find' => 'page#find', as: 'page_find'
|
8
|
+
post '/find' => 'page#find'
|
9
|
+
|
10
|
+
get '/recent' => 'page#recent', as: 'recent'
|
11
|
+
|
12
|
+
get '/:page_name' => 'page#show', as: 'page_show'
|
13
|
+
get '/:page_name/edit' => 'page#edit', as: 'page_edit'
|
14
|
+
post '/:page_name' => 'page#update'
|
15
|
+
end
|
data/lib/cl_wiki.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'cl_wiki/engine'
|
2
|
+
|
3
|
+
module ClWiki
|
4
|
+
=begin
|
5
|
+
http://edgeguides.rubyonrails.org/engines.html#inside-an-engine
|
6
|
+
|
7
|
+
Some engines choose to use this file to put global configuration options for their
|
8
|
+
engine. It's a relatively good idea, and so if you want to offer configuration
|
9
|
+
options, the file where your engine's module is defined is perfect for that. Place
|
10
|
+
the methods inside the module and you'll be good to go.
|
11
|
+
=end
|
12
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/index'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
$defaultConfFile = 'clwiki.yml'
|
5
|
+
|
6
|
+
module ClWiki
|
7
|
+
class Configuration
|
8
|
+
|
9
|
+
USE_INDEX_NO = 0
|
10
|
+
USE_INDEX_DRB = 1
|
11
|
+
USE_INDEX_LOCAL = 2
|
12
|
+
|
13
|
+
attr_accessor :wiki_path, :cgifn, :indexPort, :cssHref, :template, :useGmt,
|
14
|
+
:publishTag, :url_prefix, :global_edits, :cgifn_from_rss, :stats_name,
|
15
|
+
:index_log_fn, :page_update_format
|
16
|
+
attr_reader :custom_formatter_load_path
|
17
|
+
|
18
|
+
def wait_on_threads
|
19
|
+
# Ruby kills any threads as soon as the main process is done. Any
|
20
|
+
# threads created should be registered here. The last
|
21
|
+
# line of the CGI script should call out to wait_on_threads to make
|
22
|
+
# sure nothing running async in the background is terminated too early
|
23
|
+
@threads.each do |thread|
|
24
|
+
thread.join
|
25
|
+
end if !@threads.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def wait_on_thread(thread)
|
29
|
+
@threads = [] if !@threads
|
30
|
+
@threads << thread
|
31
|
+
end
|
32
|
+
|
33
|
+
def useIndex
|
34
|
+
@useIndex
|
35
|
+
end
|
36
|
+
|
37
|
+
def useIndex=(value)
|
38
|
+
@useIndex = value.to_i
|
39
|
+
end
|
40
|
+
|
41
|
+
def edit_rows
|
42
|
+
@edit_rows
|
43
|
+
end
|
44
|
+
|
45
|
+
def edit_rows=(value)
|
46
|
+
@edit_rows = value.to_i
|
47
|
+
end
|
48
|
+
|
49
|
+
def edit_cols
|
50
|
+
@edit_cols
|
51
|
+
end
|
52
|
+
|
53
|
+
def edit_cols=(value)
|
54
|
+
@edit_cols = value.to_i
|
55
|
+
end
|
56
|
+
|
57
|
+
def useIndexForPageExists
|
58
|
+
@useIndexForPageExists
|
59
|
+
end
|
60
|
+
|
61
|
+
def useIndexForPageExists=(value)
|
62
|
+
if value.class == String
|
63
|
+
@useIndexForPageExists = (value =~ /true/i)
|
64
|
+
else
|
65
|
+
@useIndexForPageExists = value
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def access_log_index
|
70
|
+
@access_log_index
|
71
|
+
end
|
72
|
+
|
73
|
+
def access_log_index=(value)
|
74
|
+
if value.class == String
|
75
|
+
@access_log_index = (value =~ /true/i)
|
76
|
+
else
|
77
|
+
@access_log_index = value
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def override_access_log_index
|
82
|
+
@orig_access_log_index_value = @access_log_index
|
83
|
+
@access_log_index = false
|
84
|
+
end
|
85
|
+
|
86
|
+
def restore_access_log_index
|
87
|
+
@access_log_index = @orig_access_log_index_value if @orig_access_log_index_value
|
88
|
+
end
|
89
|
+
|
90
|
+
def editable
|
91
|
+
@editable
|
92
|
+
end
|
93
|
+
|
94
|
+
def editable=(value)
|
95
|
+
if value.class == String
|
96
|
+
@editable = (value =~ /true/i)
|
97
|
+
else
|
98
|
+
@editable = value
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def showSourceLink
|
103
|
+
@showSourceLink
|
104
|
+
end
|
105
|
+
|
106
|
+
def showSourceLink=(value)
|
107
|
+
if value.class == String
|
108
|
+
@showSourceLink = (value =~ /true/i)
|
109
|
+
else
|
110
|
+
@showSourceLink = value
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.load(filename=$defaultConfFile)
|
115
|
+
$wiki_conf = self.new(YAML::load(::File.open(filename)))
|
116
|
+
$wiki_path = $wiki_conf.wiki_path
|
117
|
+
$wiki_conf
|
118
|
+
end
|
119
|
+
|
120
|
+
def initialize(hash={})
|
121
|
+
default_hash.merge(hash).each do |k, v|
|
122
|
+
instance_variable_set(:"@#{k.to_s}", v)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def default_hash
|
127
|
+
{
|
128
|
+
:url_prefix => '/',
|
129
|
+
:indexPort => ClWiki::Indexer.defaultPort,
|
130
|
+
:cgifn => 'clwikicgi.rb',
|
131
|
+
:default_recent_changes_name => "Recent Changes",
|
132
|
+
:recent_changes_name => "Recent Changes",
|
133
|
+
:stats_name => "Hit Counts",
|
134
|
+
:useGmt => false,
|
135
|
+
:publishTag => nil,
|
136
|
+
:useIndexForPageExists => false,
|
137
|
+
:showSourceLink => false,
|
138
|
+
:cgifn_from_rss => 'blogki.rb',
|
139
|
+
:edit_rows => 25,
|
140
|
+
:edit_cols => 80,
|
141
|
+
:access_log_index => false,
|
142
|
+
:index_log_fn => nil,
|
143
|
+
:custom_formatter_load_path => []
|
144
|
+
}
|
145
|
+
end
|
146
|
+
|
147
|
+
def default_recent_changes_name=(value)
|
148
|
+
if @recent_changes_name == @default_recent_changes_name
|
149
|
+
@recent_changes_name = value
|
150
|
+
end
|
151
|
+
@default_recent_changes_name = default_recent_changes_name
|
152
|
+
end
|
153
|
+
|
154
|
+
def default_recent_changes_name
|
155
|
+
@default_recent_changes_name
|
156
|
+
end
|
157
|
+
|
158
|
+
def recentChangesName=(value)
|
159
|
+
@recent_changes_name = value
|
160
|
+
@recent_changes_name = @default_recent_changes_name if @recent_changes_name.empty?
|
161
|
+
end
|
162
|
+
|
163
|
+
alias recent_changes_name= recentChangesName=
|
164
|
+
|
165
|
+
def recentChangesName
|
166
|
+
@recent_changes_name
|
167
|
+
end
|
168
|
+
|
169
|
+
alias recent_changes_name recentChangesName
|
170
|
+
end
|
171
|
+
end
|
data/lib/cl_wiki/file.rb
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
$wikiPageExt = '.txt'
|
5
|
+
|
6
|
+
module ClWiki
|
7
|
+
class File
|
8
|
+
attr_reader :name, :fileExt, :wikiRootPath, :pagePath, :modTimeAtLastRead
|
9
|
+
attr_accessor :clientLastReadModTime
|
10
|
+
|
11
|
+
def initialize(fullPageName, wikiRootPath, fileExt=$wikiPageExt, autocreate=true)
|
12
|
+
# fullPageName must start with / ?
|
13
|
+
@wikiRootPath = wikiRootPath
|
14
|
+
fullPageName = ClWiki::Util.convertToNativePath(fullPageName)
|
15
|
+
fullPageName.ensure_slash_prefix
|
16
|
+
@pagePath, @name = ::File.split(fullPageName)
|
17
|
+
@pagePath = '/' if @pagePath == '.'
|
18
|
+
@fileExt = fileExt
|
19
|
+
@metadata = {}
|
20
|
+
if autocreate
|
21
|
+
if file_exists?
|
22
|
+
readFile
|
23
|
+
else
|
24
|
+
writeToFile(default_content, false)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def content_is_default?
|
30
|
+
@contents.to_s == default_content
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete
|
34
|
+
File.delete(fullPathAndName) if File.exists?(fullPathAndName)
|
35
|
+
end
|
36
|
+
|
37
|
+
def default_content
|
38
|
+
"Describe " + @name + " here."
|
39
|
+
end
|
40
|
+
|
41
|
+
def file_exists?
|
42
|
+
FileTest.exists?(fullPathAndName)
|
43
|
+
end
|
44
|
+
|
45
|
+
def fullPath
|
46
|
+
res = ::File.expand_path(::File.join(@wikiRootPath, @pagePath))
|
47
|
+
raise 'no dirs in fullPath' if res.split('/').empty?
|
48
|
+
res
|
49
|
+
end
|
50
|
+
|
51
|
+
def fullPathAndName
|
52
|
+
::File.expand_path(@name + @fileExt, fullPath)
|
53
|
+
end
|
54
|
+
|
55
|
+
def fileName
|
56
|
+
raise Exception, 'ClWikiFile.fileName is deprecated, use fullPathAndName'
|
57
|
+
# fullPathAndName
|
58
|
+
end
|
59
|
+
|
60
|
+
def content
|
61
|
+
@contents
|
62
|
+
end
|
63
|
+
|
64
|
+
def content=(newContent)
|
65
|
+
writeToFile(newContent)
|
66
|
+
end
|
67
|
+
|
68
|
+
def writeToFile(content, checkModTime=true)
|
69
|
+
if checkModTime
|
70
|
+
# refactor, bring raiseIfMTimeNotEqual back into this class
|
71
|
+
ClWiki::Util.raiseIfMTimeNotEqual(@modTimeAtLastRead, fullPathAndName)
|
72
|
+
unless @clientLastReadModTime.nil?
|
73
|
+
ClWiki::Util.raiseIfMTimeNotEqual(@clientLastReadModTime, fullPathAndName)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
make_dirs(fullPath)
|
78
|
+
ding_mtime
|
79
|
+
::File.open(fullPathAndName, 'w+') do |f|
|
80
|
+
f.print(metadata_to_write)
|
81
|
+
f.print(content)
|
82
|
+
end
|
83
|
+
::File.utime(@metadata['mtime'], @metadata['mtime'], fullPathAndName)
|
84
|
+
readFile
|
85
|
+
end
|
86
|
+
|
87
|
+
def ding_mtime
|
88
|
+
@metadata['mtime'] = Time.now
|
89
|
+
end
|
90
|
+
|
91
|
+
def metadata_to_write
|
92
|
+
@metadata.collect { |k, v| "#{k}: #{v}" }.join("\n") + "\n\n\n"
|
93
|
+
end
|
94
|
+
|
95
|
+
def make_dirs(dir)
|
96
|
+
# need to commit each dir as we make it, which is why we just don't
|
97
|
+
# call File::makedirs. Core code copied from ftools.rb
|
98
|
+
parent = ::File.dirname(dir)
|
99
|
+
return if parent == dir or FileTest.directory? dir
|
100
|
+
make_dirs parent unless FileTest.directory? parent
|
101
|
+
if ::File.basename(dir) != ""
|
102
|
+
Dir.mkdir dir, 0755
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def readFile
|
107
|
+
::File.open(fullPathAndName, 'r') do |f|
|
108
|
+
@modTimeAtLastRead = f.mtime
|
109
|
+
raw_lines = f.readlines
|
110
|
+
metadata_lines, content = split_metadata(raw_lines)
|
111
|
+
read_metadata(metadata_lines)
|
112
|
+
apply_metadata
|
113
|
+
@contents = content
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def split_metadata(raw_lines)
|
118
|
+
start_index = 0
|
119
|
+
raw_lines.each_with_index do |ln, index|
|
120
|
+
if ln.chomp.empty?
|
121
|
+
next_line = raw_lines[index+1]
|
122
|
+
if next_line.nil? || next_line.chomp.empty?
|
123
|
+
start_index = index + 2
|
124
|
+
break
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
[raw_lines[0..start_index-3], raw_lines[start_index..-1]]
|
129
|
+
end
|
130
|
+
|
131
|
+
def read_metadata(lines)
|
132
|
+
@metadata = {}
|
133
|
+
lines.each do |ln|
|
134
|
+
key, value = ln.split(': ')
|
135
|
+
@metadata[key] = value
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def apply_metadata
|
140
|
+
@modTimeAtLastRead = Time.parse(@metadata['mtime']) if @metadata.keys.include? 'mtime'
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Util
|
145
|
+
def self.raiseIfMTimeNotEqual(mtime_to_compare, file_name)
|
146
|
+
# reading the instance .mtime appears to take Windows DST into account,
|
147
|
+
# whereas the static File.mtime(filename) method does not
|
148
|
+
current_mtime = ::File.open(file_name) do |f|
|
149
|
+
f.mtime
|
150
|
+
end
|
151
|
+
if mtime_to_compare != current_mtime
|
152
|
+
raise FileModifiedSinceRead, "File has been modified since it was last read."
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.convertToNativePath(path)
|
157
|
+
newpath = path.gsub(/\//, ::File::SEPARATOR)
|
158
|
+
newpath = newpath.gsub(/\\/, ::File::SEPARATOR)
|
159
|
+
return newpath
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
class FileError < Exception
|
164
|
+
end
|
165
|
+
|
166
|
+
class FileModifiedSinceRead < FileError
|
167
|
+
end
|
168
|
+
|
169
|
+
class FileMustUseWriteNewContent < FileError
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module ClWiki
|
2
|
+
class FindInFile
|
3
|
+
FULL_SEARCH = 0
|
4
|
+
FILE_NAME_ONLY = 1
|
5
|
+
|
6
|
+
attr_reader :find_path, :files
|
7
|
+
|
8
|
+
def initialize(find_path)
|
9
|
+
@find_path = find_path
|
10
|
+
end
|
11
|
+
|
12
|
+
def find(search_text, scope = FULL_SEARCH)
|
13
|
+
recursive_find_path = ::File.join(@find_path, '**', '*')
|
14
|
+
regex = /#{search_text}/i
|
15
|
+
@files = Dir[recursive_find_path].grep(regex)
|
16
|
+
if scope == FULL_SEARCH
|
17
|
+
Dir[recursive_find_path].each do |path_filename|
|
18
|
+
if ::File.stat(path_filename).file?
|
19
|
+
f = ::File.open(path_filename)
|
20
|
+
begin
|
21
|
+
@files << path_filename if f.grep(regex) != []
|
22
|
+
ensure
|
23
|
+
f.close unless f.nil?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
@files.collect! { |fn| fn.sub(@find_path + '/', '') }
|
29
|
+
@files.uniq!
|
30
|
+
@files.length
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class FormatBlockquote < ClWiki::CustomFormatter
|
2
|
+
def FormatBlockquote.match_re
|
3
|
+
/\[\].*\[\/\]/m
|
4
|
+
end
|
5
|
+
|
6
|
+
def FormatBlockquote.format_content(content, page)
|
7
|
+
if content
|
8
|
+
content.gsub!(/\[\]/, "<blockquote>")
|
9
|
+
content.gsub!(/\[\/\]/, "</blockquote>")
|
10
|
+
content
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
ClWiki::CustomFormatters.instance.register(FormatBlockquote)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class FormatGraphVizDiGraph < ClWiki::CustomFormatter
|
2
|
+
def FormatGraphVizDiGraph.match_re
|
3
|
+
/digraph.*\}/m
|
4
|
+
end
|
5
|
+
|
6
|
+
def FormatGraphVizDiGraph.format_content(content, page)
|
7
|
+
content.sub!(/digraph.*\}/m,
|
8
|
+
'<a href="dot.rb?fn=' + page.fileFullPathAndName + '">' +
|
9
|
+
'<img src="dot.rb?fn=' + page.fileFullPathAndName + '">' +
|
10
|
+
'</a>'
|
11
|
+
)
|
12
|
+
content
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ClWiki::CustomFormatters.instance.register(FormatGraphVizDiGraph)
|