Pimki 1.2.092 → 1.3.092
Sign up to get free protection for your applications and to get access to all the features.
- data/README-PIMKI +18 -0
- data/app/controllers/wiki.rb +42 -13
- data/app/models/chunks/engines.rb +16 -3
- data/app/models/chunks/literal.rb +1 -0
- data/app/models/chunks/todo.rb +3 -2
- data/app/models/chunks/uri.rb +1 -1
- data/app/models/chunks/wiki.rb +20 -8
- data/app/models/chunks/wiki_symbols.rb +22 -0
- data/app/models/revision_test.rb +2 -2
- data/app/models/web.rb +57 -33
- data/app/models/wiki_content.rb +13 -6
- data/app/models/wiki_service.rb +5 -1
- data/app/models/wiki_words.rb +10 -10
- data/app/views/static_style_sheet.rhtml +6 -0
- data/app/views/wiki/bliki.rhtml +1 -1
- data/app/views/wiki/bliki_revision.rhtml +41 -1
- data/app/views/wiki/edit_menu.rhtml +16 -3
- data/app/views/wiki/edit_web.rhtml +29 -0
- data/app/views/wiki/list.rhtml +14 -2
- data/app/views/wiki/mind.rhtml +30 -11
- data/app/views/wiki/search.rhtml +23 -1
- data/pimki.rb +23 -4
- metadata +7 -15
data/README-PIMKI
CHANGED
@@ -66,6 +66,24 @@ Command-line options:
|
|
66
66
|
Run "ruby pimki.rb --help"
|
67
67
|
|
68
68
|
History:
|
69
|
+
1.3.092 New features and bug fixes release
|
70
|
+
- Updated to RedCloth v3.0.0.
|
71
|
+
- Fixed problem with incorrect handling of some complex link formats and
|
72
|
+
<pre> tags. (Justin)
|
73
|
+
- Expanded search to look also in Bliki entries.
|
74
|
+
- Can now show diff between Bliki entry versions.
|
75
|
+
- Editing left-side menu is now password protected.
|
76
|
+
- Added capacity in Mind Map to filter displayed pages by category and/or
|
77
|
+
filter leaf nodes (i.e. pages that do not have links to other pages). This
|
78
|
+
cuts down on the anount of visual information to give a bit more topical
|
79
|
+
view of the web.
|
80
|
+
- Added custom symbols/elements: <:cbx> and <:cbxc> to display a checkbox
|
81
|
+
(and a checked checkbox).
|
82
|
+
- Added customization options through "Edit Web":
|
83
|
+
- Added capacity to set the prefered size of the Mind Map image.
|
84
|
+
- Customizable mapping of symbols/elements (in progress).
|
85
|
+
- Added capacity for custom link formats (in progress).
|
86
|
+
|
69
87
|
1.2.092 Bug-fix and minor enhancements release
|
70
88
|
- Fixed problem with free-content of menu. (Mark S)
|
71
89
|
- Fixed problem in persisting menu-type changes.
|
data/app/controllers/wiki.rb
CHANGED
@@ -61,17 +61,24 @@ class WikiController < ActionControllerServlet
|
|
61
61
|
@categories = web.categories
|
62
62
|
@category = @params["category"]
|
63
63
|
@pages_in_category = web.select { |page| page.in_category?(@category) }
|
64
|
+
@pages_without_category = web.select { |page| page.categories.length == 0 }
|
65
|
+
if @category == 'none'
|
66
|
+
@pages_in_category = @pages_without_category
|
67
|
+
end
|
64
68
|
@set_name = ( @categories.include?(@category) ? "category '#{@category}'" : "the web" )
|
65
69
|
@category_links = @categories.map do |c|
|
66
|
-
(@category == c ? "<span class=\"selected\"
|
70
|
+
(@category == c ? "<span class=\"selected\">[#{c}]</span>" : "<a href=\"?category=#{c}\">#{c}</a>")
|
67
71
|
end
|
68
72
|
end
|
69
73
|
|
70
74
|
def search
|
71
75
|
set_menu_pages
|
72
|
-
@query
|
76
|
+
@query = @params["query"]
|
73
77
|
rex = /#{@query}/i
|
74
78
|
@results = web.select { |page| rex.match(page.name) or rex.match(page.content) }
|
79
|
+
@bliki_results = web.bliki.values.select do |entry|
|
80
|
+
rex.match(entry.name) or rex.match(entry.content)
|
81
|
+
end
|
75
82
|
@results.length == 1 ? redirect_show(@results.first.name) : render
|
76
83
|
end
|
77
84
|
|
@@ -164,7 +171,10 @@ class WikiController < ActionControllerServlet
|
|
164
171
|
@params["password"].empty? ? nil : @params["password"],
|
165
172
|
@params["published"] ? true : false,
|
166
173
|
@params["brackets_only"] ? true : false,
|
167
|
-
@params["count_pages"] ? true : false
|
174
|
+
@params["count_pages"] ? true : false,
|
175
|
+
@params['mind_map_size'],
|
176
|
+
@params['symbols_map'],
|
177
|
+
@params['links_map']
|
168
178
|
)
|
169
179
|
|
170
180
|
redirect_show("HomePage", @params["address"])
|
@@ -240,6 +250,7 @@ class WikiController < ActionControllerServlet
|
|
240
250
|
@authors = web.authors
|
241
251
|
end #}}}
|
242
252
|
|
253
|
+
require 'pp'
|
243
254
|
def mind #{{{
|
244
255
|
parse_category
|
245
256
|
set_menu_pages
|
@@ -247,12 +258,24 @@ class WikiController < ActionControllerServlet
|
|
247
258
|
@prog = @req.query['draw_type'] || 'neato'
|
248
259
|
@graph_type = @req.query['graph_type'] || 'normal'
|
249
260
|
missing = @pages_in_category.wanted_pages if @req.query['missing']
|
250
|
-
show_authors = @req.query['show_authors'] == 'on'
|
261
|
+
show_authors = !@req.query.empty? && @req.query['show_authors'] == 'on'
|
262
|
+
show_leaves = @req.query.empty? || @req.query['show_leaves'] == 'on'
|
263
|
+
|
264
|
+
# TODO: fix handling of multiple-select for whole application
|
265
|
+
@selected_categories = @req.body.split('&').map { |pair|
|
266
|
+
pair.split('=') }.select { |k,v|
|
267
|
+
k == 'selected_categs' }.map { |k,v| v } if @req.body
|
268
|
+
@selected_categories ||= []
|
269
|
+
@selected_categories = [] if @selected_categories.include? 'all'
|
270
|
+
|
251
271
|
@pngFile = @mapFile = nil
|
252
272
|
case @graph_type
|
253
|
-
when 'normal' then @pngFile, @mapFile = web.create_mind_map(@prog, missing,
|
254
|
-
|
255
|
-
when '
|
273
|
+
when 'normal' then @pngFile, @mapFile = web.create_mind_map(@prog, missing,
|
274
|
+
show_authors, show_leaves, @selected_categories)
|
275
|
+
when 'author' then @pngFile, @mapFile = web.create_author_graph(@prog,
|
276
|
+
@selected_categories)
|
277
|
+
when 'category' then @pngFile, @mapFile = web.create_category_graph(@prog,
|
278
|
+
show_authors, @selected_categories)
|
256
279
|
end
|
257
280
|
end #}}}
|
258
281
|
|
@@ -264,6 +287,8 @@ class WikiController < ActionControllerServlet
|
|
264
287
|
end #}}}
|
265
288
|
|
266
289
|
def save_menu #{{{
|
290
|
+
redirect_show("HomePage") unless wiki.authenticate(@params["system_password"])
|
291
|
+
|
267
292
|
unless @req.query['action'] == 'Cancel Update'
|
268
293
|
type = @req.query['type']
|
269
294
|
content = @req.query['content']
|
@@ -316,7 +341,11 @@ class WikiController < ActionControllerServlet
|
|
316
341
|
redirect_action "edit/#{CGI.escape(page_name)}?msg=#{CGI.escape(e.message)}"
|
317
342
|
end
|
318
343
|
else
|
319
|
-
|
344
|
+
if page_name
|
345
|
+
redirect_action "new/#{CGI.escape(page_name)}"
|
346
|
+
else
|
347
|
+
redirect_show "HomePage"
|
348
|
+
end
|
320
349
|
end
|
321
350
|
end
|
322
351
|
|
@@ -400,7 +429,7 @@ class WikiController < ActionControllerServlet
|
|
400
429
|
|
401
430
|
def bliki_delete
|
402
431
|
wiki.delete_bliki_entry(web_address, page_name)
|
403
|
-
redirect_bliki
|
432
|
+
redirect_bliki
|
404
433
|
end
|
405
434
|
|
406
435
|
def bliki_edit
|
@@ -418,7 +447,7 @@ class WikiController < ActionControllerServlet
|
|
418
447
|
def cancel_bliki_edit
|
419
448
|
@page = wiki.read_bliki_entry(web_address, page_name)
|
420
449
|
@page.unlock if @page
|
421
|
-
redirect_bliki
|
450
|
+
redirect_bliki
|
422
451
|
end
|
423
452
|
|
424
453
|
def bliki_save
|
@@ -431,7 +460,7 @@ class WikiController < ActionControllerServlet
|
|
431
460
|
end
|
432
461
|
|
433
462
|
write_cookie("author", @params["author"])
|
434
|
-
redirect_bliki
|
463
|
+
redirect_bliki
|
435
464
|
end
|
436
465
|
|
437
466
|
def bliki_revision
|
@@ -471,8 +500,8 @@ class WikiController < ActionControllerServlet
|
|
471
500
|
redirect_path "/#{web}/show/#{CGI.escape(page)}"
|
472
501
|
end
|
473
502
|
|
474
|
-
def redirect_bliki
|
475
|
-
redirect_path "/#{
|
503
|
+
def redirect_bliki
|
504
|
+
redirect_path "/#{web_address}/bliki/"
|
476
505
|
end
|
477
506
|
|
478
507
|
def redirect_action(action, web = web_address)
|
@@ -8,16 +8,29 @@ module Engines
|
|
8
8
|
class Textile < Chunk::Abstract
|
9
9
|
def self.pattern() /^(.*)$/m end
|
10
10
|
def mask(content)
|
11
|
-
RedCloth.new(text,content.options[:engine_opts]).to_html
|
11
|
+
#RedCloth.new(text,content.options[:engine_opts]).to_html
|
12
|
+
rc = RedCloth.new(text,content.options[:engine_opts])
|
13
|
+
rc.rules = [:textile]
|
14
|
+
rc.to_html
|
12
15
|
end
|
13
16
|
def unmask(content) self end
|
14
17
|
end
|
15
18
|
|
16
19
|
class Markdown < Chunk::Abstract
|
17
20
|
def self.pattern() /^(.*)$/m end
|
18
|
-
|
19
|
-
|
21
|
+
|
22
|
+
if RedCloth::VERSION >= '3.0.0'
|
23
|
+
def mask(content)
|
24
|
+
rc = RedCloth.new(text,content.options[:engine_opts])
|
25
|
+
rc.rules = [:markdown]
|
26
|
+
rc.to_html
|
27
|
+
end
|
28
|
+
else
|
29
|
+
def mask(content)
|
30
|
+
BlueCloth.new(text,content.options[:engine_opts]).to_html
|
31
|
+
end
|
20
32
|
end
|
33
|
+
|
21
34
|
def unmask(content) self end
|
22
35
|
end
|
23
36
|
|
data/app/models/chunks/todo.rb
CHANGED
@@ -4,10 +4,11 @@ require 'parsedate'
|
|
4
4
|
|
5
5
|
# ToDo items.
|
6
6
|
class Todo < Chunk::Abstract
|
7
|
-
def self.pattern() /todo: (
|
7
|
+
def self.pattern() /todo: (.*?)(?=<br|\r|\n|\z)/i end
|
8
8
|
|
9
9
|
def initialize(match_data, revision)
|
10
10
|
super(match_data, revision)
|
11
|
+
@text = match_data[1]
|
11
12
|
end
|
12
13
|
|
13
14
|
def escaped_text() nil end
|
@@ -17,6 +18,6 @@ class Todo < Chunk::Abstract
|
|
17
18
|
# the style 'todo' is bright-red to be eye catching. It is not expected that
|
18
19
|
# there will be too many items on one page, but each is supposed to stand out.
|
19
20
|
# The ToDo special page differentiates between the 'todo' and 'todoFuture' styles.
|
20
|
-
"<span class=\"todo\"><strong>TODO:</strong> #{@text
|
21
|
+
"<span class=\"todo\"><strong>TODO:</strong> #{@text}</span>" )
|
21
22
|
end
|
22
23
|
end
|
data/app/models/chunks/uri.rb
CHANGED
@@ -22,7 +22,7 @@ class URIChunk < Chunk::Abstract
|
|
22
22
|
COUNTRY = '(?:au|at|be|ca|ch|de|dk|fr|hk|in|ir|it|jp|nl|no|pt|ru|se|sw|tv|tw|uk|us)'
|
23
23
|
|
24
24
|
# These are needed otherwise HOST will match almost anything
|
25
|
-
TLDS = "\\.(?:#{GENERIC}|#{COUNTRY})"
|
25
|
+
TLDS = "\\.(?:#{GENERIC}|#{COUNTRY})\b"
|
26
26
|
|
27
27
|
# Redefine USERINFO so that it must have non-zero length
|
28
28
|
USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})+"
|
data/app/models/chunks/wiki.rb
CHANGED
@@ -36,17 +36,20 @@ module WikiChunk
|
|
36
36
|
# The +page_name+ method returns the matched WikiWord.
|
37
37
|
class Word < WikiLink
|
38
38
|
def self.pattern
|
39
|
-
Regexp.new('(\\\\)?(' + WikiWords::WIKI_WORD_PATTERN + ')
|
40
|
-
end
|
39
|
+
Regexp.new('(\\\\)?(' + WikiWords::WIKI_WORD_PATTERN + ')(</a>)?', 0, "utf-8")
|
40
|
+
end # (chunk\d+chunk)?
|
41
41
|
|
42
42
|
attr_reader :page_name
|
43
43
|
|
44
44
|
def initialize(match_data, revision)
|
45
45
|
super(match_data, revision)
|
46
|
-
@escape = match_data[1]
|
47
|
-
@
|
46
|
+
@escape = match_data[1] || match_data[3]
|
47
|
+
# @chunk_text = match_data[2] || ''
|
48
|
+
@page_name = @link_text = match_data[2]
|
48
49
|
end
|
49
50
|
|
51
|
+
def mask(content) pre_mask + post_mask; end
|
52
|
+
def regexp() Regexp.new(pre_mask + post_mask) end
|
50
53
|
def escaped_text() (@escape.nil? ? nil : page_name) end
|
51
54
|
def link_text() WikiWords.separate(page_name) end
|
52
55
|
end
|
@@ -69,15 +72,20 @@ module WikiChunk
|
|
69
72
|
def initialize(match_data, revision)
|
70
73
|
super(match_data, revision)
|
71
74
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
+
# If the like is aliased, set the page name to the first bit
|
76
|
+
# and the link text to the second, otherwise set both to the
|
77
|
+
# contents of the double brackets.
|
75
78
|
if match_data[1] =~ ALIASED_LINK_PATTERN
|
76
79
|
@page_name, @link_text = $1, $2
|
77
80
|
else
|
78
81
|
@page_name, @link_text = match_data[1], match_data[1]
|
79
82
|
end
|
80
83
|
end
|
84
|
+
|
85
|
+
def mask(content) pre_mask + post_mask; end
|
86
|
+
def regexp() Regexp.new(pre_mask + post_mask) end
|
87
|
+
def escaped_text() (@escape.nil? ? nil : page_name) end
|
88
|
+
def link_text() WikiWords.separate(page_name) end
|
81
89
|
end
|
82
90
|
|
83
91
|
# This chunk handles [bliki[entry name]].
|
@@ -96,7 +104,11 @@ module WikiChunk
|
|
96
104
|
return self if content.sub!(regexp) { |match|
|
97
105
|
web = revision.page.web
|
98
106
|
entry = web.bliki[page_name]
|
99
|
-
|
107
|
+
if entry.nil?
|
108
|
+
"<span style='background:lightgrey;font-style:italic'>Unknown Bliki entry: '#{page_name}'</span>"
|
109
|
+
else
|
110
|
+
"<a class='existingWikiWord' href='/#{web.address}/bliki_revision/#{entry.name}?rev=#{entry.revisions.size-1}'>#{entry.name}</a>"
|
111
|
+
end
|
100
112
|
}
|
101
113
|
end
|
102
114
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
class WikiSymbol < Chunk::Abstract
|
3
|
+
def self.pattern() /<:(.*?)>/ end
|
4
|
+
|
5
|
+
attr_accessor :symbol_code
|
6
|
+
|
7
|
+
def initialize(match_data, revision)
|
8
|
+
super(match_data, revision)
|
9
|
+
@symbol_code = match_data[1]
|
10
|
+
end
|
11
|
+
|
12
|
+
def unmask(content)
|
13
|
+
tag = case symbol_code
|
14
|
+
when 'cbx' then '<input type="checkbox" disabled />'
|
15
|
+
when 'cbxc' then '<input type="checkbox" disabled checked />'
|
16
|
+
else symbol_code
|
17
|
+
end
|
18
|
+
|
19
|
+
return self if content.gsub!( Regexp.new(mask(content)), tag )
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
data/app/models/revision_test.rb
CHANGED
@@ -141,7 +141,7 @@ class RevisionTest < Test::Unit::TestCase
|
|
141
141
|
"DavidHeinemeierHansson"
|
142
142
|
)
|
143
143
|
|
144
|
-
|
144
|
+
@revision_with_code_block = Revision.new(
|
145
145
|
@mock_page,
|
146
146
|
1,
|
147
147
|
"This is a code block:\n def a_method(arg)\n return ThatWay\n\nNice!",
|
@@ -151,7 +151,7 @@ class RevisionTest < Test::Unit::TestCase
|
|
151
151
|
|
152
152
|
assert_equal "<h1>My Headline</h1>\n\n<p>that <span class=\"newWikiWord\">Smart Engine GUI<a href=\"../show/SmartEngineGUI\">?</a></span></p>", @revision.display_content
|
153
153
|
|
154
|
-
|
154
|
+
assert_equal "<p>This is a code block:</p>\n\n<pre><code>def a_method(arg)\nreturn ThatWay\n</code></pre>\n\n<p>Nice!</p>", @revision_with_code_block.display_content
|
155
155
|
end
|
156
156
|
|
157
157
|
def test_rdoc
|
data/app/models/web.rb
CHANGED
@@ -7,6 +7,7 @@ require "zip/zip"
|
|
7
7
|
class Web
|
8
8
|
attr_accessor :pages, :name, :address, :password, :menu_type, :menu_content, :rendered_menu, :menu_limit, :menu_category
|
9
9
|
attr_accessor :markup, :color, :safe_mode, :additional_style, :published, :brackets_only, :count_pages
|
10
|
+
attr_accessor :mind_map_size, :symbols_map, :links_map
|
10
11
|
|
11
12
|
@@BLIKI_TEMPLATE = "Try a weekly worksheet:\n\n| / | *Morning* | *Afternoon* |\n" +
|
12
13
|
"| *Mon* | - | - |\n| *Tue* | - | - |\n| *Wed* | - | - |\n" +
|
@@ -87,14 +88,16 @@ class Web
|
|
87
88
|
def color() @color || "008B26" end
|
88
89
|
def brackets_only() @brackets_only || false end
|
89
90
|
def count_pages() @count_pages || false end
|
90
|
-
def menu_content() @menu_content || ''
|
91
|
-
def menu_limit() @menu_limit || 20
|
91
|
+
def menu_content() @menu_content || '' end
|
92
|
+
def menu_limit() @menu_limit || 20 end
|
92
93
|
def menu_type()
|
93
94
|
(@menu_type.nil? || @menu_type.empty?) ? 'linkers' : @menu_type
|
94
95
|
end
|
96
|
+
def mind_map_size() (@mind_map_size == '0,0' ? '6,5' : @mind_map_size) end
|
97
|
+
|
95
98
|
|
96
99
|
# create a Mind Map graph and return the PNG and HTML map files generated
|
97
|
-
def create_mind_map(prog, missing, show_authors)
|
100
|
+
def create_mind_map(prog, missing, show_authors, show_leaves, selected_categories)
|
98
101
|
dotFile = File.expand_path("#{WikiService.storage_path}/graph.dot")
|
99
102
|
mapFile = File.expand_path("#{WikiService.storage_path}/graph.map")
|
100
103
|
pngFile = File.expand_path("#{WikiService.storage_path}/map.png")
|
@@ -103,28 +106,34 @@ class Web
|
|
103
106
|
|
104
107
|
# Graph properties:
|
105
108
|
file.puts "digraph G {"
|
106
|
-
file.puts
|
107
|
-
|
109
|
+
file.puts "size=\"#{mind_map_size}\";"
|
110
|
+
file.puts 'ratio=fill;'
|
108
111
|
file.puts 'concentrate=true;'
|
109
112
|
file.puts 'node [fontsize=10,fontname="Tahoma"];'
|
110
113
|
file.puts 'edge [len=1.5];'
|
111
114
|
|
112
|
-
# Page Special nodes properties:
|
113
|
-
file.puts "HomePage [color=\"##{color}\",style=bold];"
|
114
|
-
|
115
115
|
# Links and node properties:
|
116
|
-
nodes = pages.values
|
116
|
+
nodes = filter_categories(pages.values, selected_categories)
|
117
117
|
auths = authors # avoid repeated selects
|
118
|
-
unless show_authors
|
118
|
+
unless show_authors
|
119
119
|
nodes.delete_if { |entry|
|
120
120
|
auths.include? entry.name
|
121
121
|
}
|
122
122
|
end
|
123
|
+
unless show_leaves
|
124
|
+
nodes.delete_if { |page|
|
125
|
+
(page.wiki_words - [missing].flatten).size == 0
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
# Page Special nodes properties:
|
130
|
+
file.puts "HomePage [color=\"##{color}\",style=bold];" if nodes.map{ |p| p.name }.include? "HomePage"
|
131
|
+
|
123
132
|
nodes.each do |page|
|
124
133
|
file.puts "#{page.name} [URL=\"../show/#{page.name}\"];"
|
125
134
|
page.references.each do |referer|
|
126
|
-
unless page.name == referer.name
|
127
|
-
unless show_authors
|
135
|
+
unless page.name == referer.name or not nodes.include? referer
|
136
|
+
unless !show_authors and auths.include? referer.name
|
128
137
|
file.puts "#{referer.name} -> #{page.name};"
|
129
138
|
end
|
130
139
|
end
|
@@ -133,28 +142,29 @@ class Web
|
|
133
142
|
|
134
143
|
# find missing pages:
|
135
144
|
if missing
|
136
|
-
|
137
|
-
|
138
|
-
end
|
139
|
-
pages.values.each do |page|
|
145
|
+
shown_missing = []
|
146
|
+
nodes.each do |page|
|
140
147
|
missing.each do |wanted|
|
141
148
|
if page.content =~ /#{wanted}/
|
142
149
|
file.puts "#{page.name} -> #{wanted};"
|
150
|
+
shown_missing << wanted
|
143
151
|
end
|
144
152
|
end
|
145
153
|
end
|
154
|
+
shown_missing.each do |wanted|
|
155
|
+
file.puts "#{wanted} [URL=\"/#{@address}/show/#{wanted}\", fontsize=10,style=filled,color=grey];"
|
156
|
+
end
|
146
157
|
end
|
147
158
|
|
148
159
|
file.puts "}"
|
149
160
|
end
|
150
161
|
|
151
|
-
|
152
|
-
system("#{prog} -Tpng #{dotFile} -o #{pngFile}")
|
162
|
+
call_graphviz(prog, dotFile, mapFile, pngFile)
|
153
163
|
|
154
164
|
[pngFile, mapFile]
|
155
165
|
end
|
156
166
|
|
157
|
-
def create_author_graph(prog)
|
167
|
+
def create_author_graph(prog, selected_categories)
|
158
168
|
dotFile = File.expand_path("#{WikiService.storage_path}/graph.dot")
|
159
169
|
mapFile = File.expand_path("#{WikiService.storage_path}/graph.map")
|
160
170
|
pngFile = File.expand_path("#{WikiService.storage_path}/map.png")
|
@@ -163,7 +173,7 @@ class Web
|
|
163
173
|
|
164
174
|
# Graph properties:
|
165
175
|
file.puts "digraph G {"
|
166
|
-
file.puts
|
176
|
+
file.puts "size=\"#{mind_map_size}\";" if mind_map_size
|
167
177
|
#file.puts 'ratio=fill;'
|
168
178
|
file.puts 'concentrate=true;'
|
169
179
|
file.puts 'node [fontsize=10,fontname="Tahoma"];'
|
@@ -175,8 +185,8 @@ class Web
|
|
175
185
|
file.puts "#{auth} [style=filled,color=grey,URL=\"../show/#{auth}\"];"
|
176
186
|
end
|
177
187
|
|
178
|
-
nodes = pages.values
|
179
|
-
nodes
|
188
|
+
nodes = pages.values.reject { |entry| auths.include? entry.name }
|
189
|
+
nodes = filter_categories(nodes, selected_categories)
|
180
190
|
nodes.each do |page|
|
181
191
|
file.puts "#{page.name} [URL=\"../show/#{page.name}\"];"
|
182
192
|
page.authors.each do |auth|
|
@@ -187,13 +197,12 @@ class Web
|
|
187
197
|
file.puts "}"
|
188
198
|
end
|
189
199
|
|
190
|
-
|
191
|
-
system("#{prog} -Tpng #{dotFile} -o #{pngFile}")
|
200
|
+
call_graphviz(prog, dotFile, mapFile, pngFile)
|
192
201
|
|
193
202
|
[pngFile, mapFile]
|
194
203
|
end
|
195
204
|
|
196
|
-
def create_category_graph(prog, show_authors) #{{{
|
205
|
+
def create_category_graph(prog, show_authors, selected_categories) #{{{
|
197
206
|
dotFile = File.expand_path("#{WikiService.storage_path}/graph.dot")
|
198
207
|
mapFile = File.expand_path("#{WikiService.storage_path}/graph.map")
|
199
208
|
pngFile = File.expand_path("#{WikiService.storage_path}/map.png")
|
@@ -201,22 +210,22 @@ class Web
|
|
201
210
|
File.open(dotFile, "w") do |file|
|
202
211
|
# Graph properties:
|
203
212
|
file.puts "digraph G {"
|
204
|
-
file.puts
|
213
|
+
file.puts "size=\"#{mind_map_size}\";" if mind_map_size
|
205
214
|
#file.puts 'ratio=fill;'
|
206
215
|
file.puts 'concentrate=true;'
|
207
216
|
file.puts 'node [fontsize=10,fontname="Tahoma"];'
|
208
217
|
file.puts 'edge [len=1.5];'
|
209
218
|
|
210
219
|
# Page Special nodes properties:
|
211
|
-
|
212
|
-
|
213
|
-
file.puts "#{category} [fontsize=20,style=filled,color=grey,comment=\"#{category}\"];"
|
220
|
+
categs = selected_categories.empty? ? categories : selected_categories
|
221
|
+
categs.each do |category|
|
222
|
+
file.puts "#{category} [fontsize=20,style=filled,color=grey,comment=\"#{category}\",URL=\"../list/?category=#{category}\"];"
|
214
223
|
end
|
215
224
|
|
216
225
|
# Links and node properties:
|
217
|
-
nodes = pages.values
|
226
|
+
nodes = filter_categories(pages.values, selected_categories)
|
218
227
|
auths = authors # avoid repeated selects
|
219
|
-
unless show_authors
|
228
|
+
unless show_authors
|
220
229
|
nodes.delete_if { |entry|
|
221
230
|
auths.include? entry.name
|
222
231
|
}
|
@@ -231,11 +240,26 @@ class Web
|
|
231
240
|
file.puts "}"
|
232
241
|
end
|
233
242
|
|
234
|
-
|
235
|
-
system("#{prog} -Tpng #{dotFile} -o #{pngFile}")
|
243
|
+
call_graphviz(prog, dotFile, mapFile, pngFile)
|
236
244
|
|
237
245
|
[pngFile, mapFile]
|
238
246
|
end #}}}
|
247
|
+
|
248
|
+
def filter_categories(pages, selected_categories) #{{{
|
249
|
+
nodes = pages
|
250
|
+
unless selected_categories.empty?
|
251
|
+
nodes = pages.reject { |page| (page.categories & selected_categories).empty? }
|
252
|
+
if selected_categories.include? 'none'
|
253
|
+
nodes += pages.select { |page| page.categories.empty? }
|
254
|
+
end
|
255
|
+
end
|
256
|
+
nodes
|
257
|
+
end #}}}
|
258
|
+
|
259
|
+
def call_graphviz(prog, dotFile, mapFile, pngFile)
|
260
|
+
system("#{prog} -Tcmap \"#{dotFile}\" -o \"#{mapFile}\"")
|
261
|
+
system("#{prog} -Tpng \"#{dotFile}\" -o \"#{pngFile}\"")
|
262
|
+
end
|
239
263
|
|
240
264
|
## Bliki methods
|
241
265
|
|
data/app/models/wiki_content.rb
CHANGED
@@ -7,6 +7,7 @@ require 'chunks/wiki'
|
|
7
7
|
require 'chunks/literal'
|
8
8
|
require 'chunks/uri'
|
9
9
|
require 'chunks/nowiki'
|
10
|
+
require 'chunks/wiki_symbols'
|
10
11
|
|
11
12
|
# Wiki content is just a string that can process itself with a chain of
|
12
13
|
# actions. The actions can modify wiki content so that certain parts of
|
@@ -26,11 +27,11 @@ require 'chunks/nowiki'
|
|
26
27
|
# * :pre_engine_actions
|
27
28
|
# => A list of render actions or chunks to be processed before the
|
28
29
|
# markup engine is applied. By default this is:
|
29
|
-
# Category, Include, URIChunk, WikiChunk::Link
|
30
|
+
# Category, Include, URIChunk, WikiChunk::Link
|
30
31
|
# * :post_engine_actions
|
31
32
|
# => A list of render actions or chunks to apply after the markup
|
32
33
|
# engine. By default these are:
|
33
|
-
# Literal::Pre, Literal::Tags
|
34
|
+
# Literal::Pre, Literal::Tags, WikiChunk::Word
|
34
35
|
# ToDo items
|
35
36
|
# * :mode
|
36
37
|
# => How should the content be rendered? For normal display (:display),
|
@@ -43,8 +44,9 @@ class WikiContent < String
|
|
43
44
|
|
44
45
|
# Moved URIChunk from pre-engine to post-engine, as it clashed with the textile
|
45
46
|
# markup of "link":URL.
|
46
|
-
PRE_ENGINE_ACTIONS = [ NoWiki, Category, Include,
|
47
|
-
|
47
|
+
PRE_ENGINE_ACTIONS = [ NoWiki, Category, Include, Literal::Pre, WikiSymbol,
|
48
|
+
WikiChunk::Link, WikiChunk::BlikiLink ]
|
49
|
+
POST_ENGINE_ACTIONS = [ Literal::Tags, WikiChunk::Word, URIChunk, Todo ]
|
48
50
|
|
49
51
|
|
50
52
|
DEFAULT_OPTS = {
|
@@ -54,6 +56,11 @@ class WikiContent < String
|
|
54
56
|
:engine_opts => [],
|
55
57
|
:mode => [:display]
|
56
58
|
}
|
59
|
+
|
60
|
+
if RedCloth::VERSION >= '3.0.0'
|
61
|
+
# RedCloth v3 changes the default behaviour from not folding lines.
|
62
|
+
DEFAULT_OPTS[:engine_opts] = [:hard_breaks]
|
63
|
+
end
|
57
64
|
|
58
65
|
attr_reader :web, :options, :rendered
|
59
66
|
|
@@ -66,9 +73,9 @@ class WikiContent < String
|
|
66
73
|
# Deep copy of DEFAULT_OPTS to ensure that changes to PRE/POST_ENGINE_ACTIONS stay local
|
67
74
|
@options = Marshal.load(Marshal.dump(DEFAULT_OPTS)).update(options)
|
68
75
|
@options[:engine] = Engines::MAP[@web.markup] || Engines::Textile
|
69
|
-
@options[:engine_opts]
|
76
|
+
@options[:engine_opts] += (@web.safe_mode ? [:filter_html, :filter_styles] : [])
|
70
77
|
|
71
|
-
@options[:
|
78
|
+
@options[:post_engine_actions].delete(WikiChunk::Word) if @web.brackets_only
|
72
79
|
|
73
80
|
super(@revision.content)
|
74
81
|
|
data/app/models/wiki_service.rb
CHANGED
@@ -29,7 +29,8 @@ class WikiService < MadeleineService
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def update_web(old_address, new_address, name, markup, color, additional_style, safe_mode = false,
|
32
|
-
password = nil, published = false, brackets_only = false, count_pages = false
|
32
|
+
password = nil, published = false, brackets_only = false, count_pages = false,
|
33
|
+
mind_map_size="7,7", symbols_map=nil, links_map=nil)
|
33
34
|
if old_address != new_address
|
34
35
|
@webs[new_address] = @webs[old_address]
|
35
36
|
@webs.delete(old_address)
|
@@ -44,6 +45,9 @@ class WikiService < MadeleineService
|
|
44
45
|
|
45
46
|
web.password, web.published, web.brackets_only, web.count_pages =
|
46
47
|
password, published, brackets_only, count_pages
|
48
|
+
|
49
|
+
web.mind_map_size, web.symbols_map, web.links_map =
|
50
|
+
mind_map_size, symbols_map, links_map
|
47
51
|
end
|
48
52
|
|
49
53
|
def read_page(web_address, page_name)
|
data/app/models/wiki_words.rb
CHANGED
@@ -3,26 +3,26 @@
|
|
3
3
|
module WikiWords
|
4
4
|
# In order of appearance: Latin, greek, cyrillian, armenian
|
5
5
|
I18N_HIGHER_CASE_LETTERS =
|
6
|
-
"
|
7
|
-
"
|
8
|
-
"
|
9
|
-
"
|
6
|
+
"À�?ÂÃÄÅĀĄĂÆÇĆČĈĊĎ�?ÈÉÊËĒĘĚĔĖĜĞĠĢĤĦÌ�?Î�?ĪĨĬĮİIJĴĶ�?ĽĹĻĿÑŃŇŅŊÒÓÔÕÖØŌ�?ŎŒŔŘŖŚŠŞŜȘŤŢŦȚÙÚÛÜŪŮŰŬŨŲŴ�?ŶŸŹŽŻ" +
|
7
|
+
"ΑΒΓΔΕΖΗΘΙΚΛΜ�?ΞΟΠΡΣΤΥΦΧΨΩ" +
|
8
|
+
"ΆΈΉΊΌΎ�?ѠѢѤѦѨѪѬѮѰѲѴѶѸѺѼѾҀҊҌҎ�?ҒҔҖҘҚҜҞҠҢҤҦҨҪҬҮҰҲҴҶҸҺҼҾ�?ӃӅӇӉӋ�?�?ӒӔӖӘӚӜӞӠӢӤӦӨӪӬӮӰӲӴӸЖ" +
|
9
|
+
"ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀ�?ՂՃՄՅՆՇՈՉՊՋՌ�?�?�?ՑՒՓՔՕՖ"
|
10
10
|
|
11
11
|
I18N_LOWER_CASE_LETTERS =
|
12
|
-
"
|
13
|
-
"
|
14
|
-
"
|
15
|
-
"
|
12
|
+
"àáâãäå�?ąăæçć�?ĉċ�?đèéêëēęěĕėƒ�?ğġģĥħìíîïīĩĭįıijĵķĸłľĺļŀñńňņʼnŋòóôõöø�?ő�?œŕřŗśšş�?șťţŧțùúûüūůűŭũųŵýÿŷžżźÞþßſ�?ð" +
|
13
|
+
"άέήίΰαβγδεζηθικλμνξοπ�?ςστυφχψωϊϋό�?ώ�?" +
|
14
|
+
"абвгдежзийклмнопр�?туфхцчшщъыь�?ю�?�?ёђѓєѕіїјљћќ�?ўџѡѣѥѧѩѫѭѯѱѳѵѷѹѻѽѿ�?ҋ�?�?ґғҕҗҙқ�?ҟҡңҥҧҩҫҭүұҳҵҷҹһҽҿӀӂӄӆӈӊӌӎӑӓӕӗәӛ�?ӟӡӣӥӧөӫӭӯӱӳӵӹ" +
|
15
|
+
"աբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտր�?ւփքօֆև"
|
16
16
|
|
17
17
|
DIGITS = "0123456789"
|
18
18
|
|
19
|
-
WIKI_WORD_PATTERN = '[A-Z' + I18N_HIGHER_CASE_LETTERS + ']+[a-z' + I18N_LOWER_CASE_LETTERS + DIGITS + ']
|
19
|
+
WIKI_WORD_PATTERN = '[A-Z' + I18N_HIGHER_CASE_LETTERS + ']+[a-z' + I18N_LOWER_CASE_LETTERS + ']+[a-z' + I18N_LOWER_CASE_LETTERS + DIGITS + ']*[A-Z' + I18N_HIGHER_CASE_LETTERS + DIGITS + ']\w+'
|
20
20
|
|
21
21
|
def self.separate(wiki_word, ignore_separation = false)
|
22
22
|
if ignore_separation
|
23
23
|
wiki_word
|
24
24
|
else
|
25
|
-
wiki_word.gsub(/([a-z#{I18N_LOWER_CASE_LETTERS}])([A-Z#{I18N_HIGHER_CASE_LETTERS}#{DIGITS}])/u, '\1 \2').gsub(/(\d+)/u, ' \1 ')
|
25
|
+
wiki_word.gsub(/([a-z#{I18N_LOWER_CASE_LETTERS}]|[A-Z]{3,})([A-Z#{I18N_HIGHER_CASE_LETTERS}#{DIGITS}])/u, '\1 \2').gsub(/(\d+)/u, ' \1 ')
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -150,10 +150,16 @@ ol.setup li {
|
|
150
150
|
.diffdel {
|
151
151
|
background: pink;
|
152
152
|
}
|
153
|
+
del.diffmod {
|
154
|
+
background: pink;
|
155
|
+
}
|
153
156
|
|
154
157
|
.diffins {
|
155
158
|
background: lightgreen;
|
156
159
|
}
|
160
|
+
ins.diffmod {
|
161
|
+
background: lightgreen;
|
162
|
+
}
|
157
163
|
|
158
164
|
#TextileHelp table {
|
159
165
|
margin-bottom: 0;
|
data/app/views/wiki/bliki.rhtml
CHANGED
@@ -61,7 +61,7 @@
|
|
61
61
|
<ul>
|
62
62
|
<% @entries.each do |page| %>
|
63
63
|
<li><a href="../bliki_revision/<%= page.name %>?rev=<%= page.revisions.length - 1 %>" class="navlink" accesskey="R"><%= page.plain_name %></a>
|
64
|
-
<small>[<%= page.author_link %>, <%=page.revisions.first.created_at.strftime("%d-%b-%Y") %>]</small>
|
64
|
+
<small>[<%= page.author_link %>, <%=page.revisions.first.created_at.strftime("%d-%b-%Y") %>, <%= page.revisions.length %> revision(s)]</small>
|
65
65
|
</li>
|
66
66
|
<% end %>
|
67
67
|
</ul>
|
@@ -7,7 +7,21 @@
|
|
7
7
|
<th><small><%= @revision.pretty_created_at %></small></th>
|
8
8
|
</tr>
|
9
9
|
<tr>
|
10
|
-
<td colspan="2"
|
10
|
+
<td colspan="2">
|
11
|
+
<div id="revision">
|
12
|
+
<%= @revision.display_content %>
|
13
|
+
</div>
|
14
|
+
<div id="changes" style="display: none">
|
15
|
+
<p style="background: #eee; padding: 3px; border: 1px solid silver">
|
16
|
+
<small>
|
17
|
+
Showing changes from revision #<%= @page.number - 1 %> to #<%= @page.number %>:
|
18
|
+
<ins class="diffins">Added</ins> | <del class="diffdel">Removed</del>
|
19
|
+
</small>
|
20
|
+
</p>
|
21
|
+
|
22
|
+
<%= @revision.display_diff %>
|
23
|
+
</div>
|
24
|
+
</td>
|
11
25
|
</tr>
|
12
26
|
<tr style="background-color:efe">
|
13
27
|
<th colspan="2" align="right"><small><%= web.make_link(@revision.author, nil, {}) %></small></th>
|
@@ -46,6 +60,32 @@
|
|
46
60
|
| Referenced by: <%= @page.references.collect { |ref| "<a href='#{ref.name}'>#{ref.name}</a>" }.join(", ") %>
|
47
61
|
</small>
|
48
62
|
<% end %>
|
63
|
+
|
64
|
+
<% if @page.revisions.length > 1 %>
|
65
|
+
<span id="show_changes">
|
66
|
+
| <a href="#" onClick="toggleChanges(); return false;">See changes</a>
|
67
|
+
</span>
|
68
|
+
<span id="hide_changes" style="display: none">
|
69
|
+
| <a href="#" onClick="toggleChanges(); return false;">Hide changes</a>
|
70
|
+
</span>
|
71
|
+
<% end %>
|
72
|
+
|
49
73
|
</div>
|
50
74
|
|
75
|
+
<script language="Javascript">
|
76
|
+
function toggleChanges() {
|
77
|
+
if (document.getElementById("changes").style.display == "none") {
|
78
|
+
document.getElementById("changes").style.display = "block";
|
79
|
+
document.getElementById("revision").style.display = "none";
|
80
|
+
document.getElementById("show_changes").style.display = "none";
|
81
|
+
document.getElementById("hide_changes").style.display = "inline";
|
82
|
+
} else {
|
83
|
+
document.getElementById("changes").style.display = "none";
|
84
|
+
document.getElementById("revision").style.display = "block";
|
85
|
+
document.getElementById("show_changes").style.display = "inline";
|
86
|
+
document.getElementById("hide_changes").style.display = "none";
|
87
|
+
}
|
88
|
+
}
|
89
|
+
</script>
|
90
|
+
|
51
91
|
<%= sub_template "bottom" %>
|
@@ -26,10 +26,23 @@
|
|
26
26
|
<p><input type="radio" name="type" value="user" <%= 'checked' if @menu_type == 'user' %>>Or just write your own menu contents (as a regular Wiki page):
|
27
27
|
<textarea name="content" style="width: 400px; height: 300px"><%= @menu_content %></textarea>
|
28
28
|
</p>
|
29
|
-
|
29
|
+
|
30
|
+
<table width="400px">
|
31
|
+
<tr><td align="right">
|
32
|
+
<small>
|
33
|
+
Enter system password
|
34
|
+
<input style="font-size:small;" type="password" id="system_password" name="system_password">
|
35
|
+
and
|
30
36
|
<input type="submit" name='action' value="Update">
|
31
|
-
|
32
|
-
</
|
37
|
+
</small>
|
38
|
+
</tr></td>
|
39
|
+
<tr><td align="right">
|
40
|
+
<small>
|
41
|
+
...or forget changes and <input type="submit" name='action' value="Cancel Update">
|
42
|
+
</small>
|
43
|
+
</tr></td>
|
44
|
+
</table>
|
45
|
+
|
33
46
|
</form>
|
34
47
|
|
35
48
|
<%= sub_template "bottom" %>
|
@@ -72,6 +72,29 @@
|
|
72
72
|
<input type="checkbox" name="published"<%= " CHECKED" if @web.published %>> Publish this web
|
73
73
|
</div>
|
74
74
|
|
75
|
+
<h2 style="margin-bottom: 3px">Customise this PIM (<%= @web.name %>)</h2>
|
76
|
+
<div class="help">
|
77
|
+
Here are a few setting you can use to tweak the appearance of your Pimki.
|
78
|
+
</div>
|
79
|
+
<div class="inputBox">
|
80
|
+
Limit the size of the Mind Map image. Format is "width,height" in inches. Leave blank for no size limit.<br />
|
81
|
+
<input type="text" name="mind_map_size" id="mind_map_size" value="<%= web.mind_map_size %>">
|
82
|
+
|
83
|
+
<!--
|
84
|
+
|
85
|
+
<br /><br />
|
86
|
+
|
87
|
+
Extra special symbols. The format of the map is: "code=text" on separate lines. This will map an element of <i><:code></i> to <i>text</i>, e.g. <:cbx> is mapped to <input type="checkbox" disabled /><br />
|
88
|
+
<textarea name="symbols_map" id="symbols_map" style="width: 100%; height: 100px"></textarea>
|
89
|
+
|
90
|
+
<br /><br />
|
91
|
+
|
92
|
+
Extra special links. The format of the map is: "link_name=link_format" on separate lines. This will map an element of <i>[link_name[link_text]]</i> to your specified format. e.g. to use google's redirection enter: <pre>google=http://www.google.com/url?sa=D&q=#{link_text}</pre> and use as: <pre>[[!goggle http://pimki.rubyforge.org/]]</pre> to map to: <pre>http://www.google.com/url?sa=D&q=http://pimki.rubyforge.org/</pre><br />
|
93
|
+
<textarea name="links_map" id="links_map" style="width: 100%; height: 100px"></textarea>
|
94
|
+
|
95
|
+
-->
|
96
|
+
</div>
|
97
|
+
|
75
98
|
<p align="right">
|
76
99
|
<small>
|
77
100
|
Enter system password
|
@@ -131,6 +154,12 @@ function validateSetup() {
|
|
131
154
|
alert("The password and its verification doesn't match");
|
132
155
|
return false;
|
133
156
|
}
|
157
|
+
|
158
|
+
// if (document.getElementById('mind_map_size').value != "" &&
|
159
|
+
// !/^\d+,\d+$/.test(document.getElementById('mind_map_size').value)) {
|
160
|
+
// alert("The Mind Map size must be in the format of 'digit,digit'!");
|
161
|
+
// return false;
|
162
|
+
// }
|
134
163
|
|
135
164
|
return true;
|
136
165
|
}
|
data/app/views/wiki/list.rhtml
CHANGED
@@ -3,8 +3,20 @@
|
|
3
3
|
|
4
4
|
<% unless @categories.empty? %>
|
5
5
|
<div id="categories">
|
6
|
-
<strong>Categories</strong>:
|
7
|
-
|
6
|
+
<strong>Categories</strong>:
|
7
|
+
|
8
|
+
<% if @params["category"].nil? %>
|
9
|
+
[Any]
|
10
|
+
<% else %>
|
11
|
+
<a href=".">Any</a>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<% if @params["category"] == 'none' %>
|
15
|
+
[None]
|
16
|
+
<% else %>
|
17
|
+
<a href="?category=none">None</a>
|
18
|
+
<% end %>
|
19
|
+
|
8
20
|
<%= @category_links.join(', ') %>
|
9
21
|
</div>
|
10
22
|
<% end %>
|
data/app/views/wiki/mind.rhtml
CHANGED
@@ -10,26 +10,45 @@
|
|
10
10
|
<%= File.read(@mapFile) %>
|
11
11
|
</map>
|
12
12
|
|
13
|
-
<table border=0>
|
14
|
-
<form name="
|
13
|
+
<table border="0" width="100%">
|
14
|
+
<form name="mapOpts" id="mapOpts" action="../mind/" method="post">
|
15
|
+
<tr style="font-weight:bold;">
|
16
|
+
<td>Graph Type</td>
|
17
|
+
<td style="width:200px">Layout Type</td>
|
18
|
+
<td style="width:500px">Content Options</td>
|
19
|
+
<td>Categories</td>
|
20
|
+
</tr>
|
15
21
|
<tr>
|
22
|
+
<td style="vertical-align:top;" width="30%">
|
23
|
+
<input type="radio" name="graph_type" value="normal" <%= 'checked' if @graph_type == 'normal' %>>Draw Normal Graph<br>
|
24
|
+
<input type="radio" name="graph_type" value="author" <%= 'checked' if @graph_type == 'author' %>>Draw Authors Graph<br>
|
25
|
+
<input type="radio" name="graph_type" value="category" <%= 'checked' if @graph_type == 'category' %>>Draw Category Graph<br>
|
26
|
+
</td>
|
16
27
|
<td width="100" style="vertical-align:top;" >
|
17
28
|
<input type="radio" name="draw_type" value="neato" <% if @prog == 'neato' %> checked <% end %>>Neato<br>
|
18
29
|
<input type="radio" name="draw_type" value="dot" <% if @prog == 'dot' %> checked <% end %>>Dot</br>
|
19
30
|
<input type="radio" name="draw_type" value="circo" <% if @prog == 'circo' %> checked <% end %>>Circo</br>
|
20
31
|
<input type="radio" name="draw_type" value="twopi" <% if @prog == 'twopi' %> checked <% end %>>Twopi</br>
|
21
32
|
</td>
|
22
|
-
<td style="vertical-align:top;
|
23
|
-
<input type="
|
24
|
-
<input type="
|
25
|
-
<input type="
|
33
|
+
<td style="vertical-align:top;width:400px;">
|
34
|
+
<input type="checkbox" id="show_authors" name="show_authors" <%= 'checked' if @req.query['show_authors'] == 'on' %>>Show author pages<br>
|
35
|
+
<input type="checkbox" id="missing" name="missing" <%= 'checked' if @req.query['missing'] == 'on' %>>Show missing pages<br>
|
36
|
+
<input type="checkbox" id="show_leaves" name="show_leaves" <%= 'checked' if @req.query.empty? || @req.query['show_leaves'] == 'on' %>>Show leaf pages<br>
|
37
|
+
<!-- <input type="checkbox" id="limit_categs" name="limit_categs" <%= 'checked' if @req.query['limit_categ'] == 'on' %>>Limit to selected cetegories<br> -->
|
26
38
|
</td>
|
27
|
-
<td
|
28
|
-
<
|
29
|
-
|
30
|
-
|
39
|
+
<td>
|
40
|
+
<select id="selected_categs" name="selected_categs" size="4" style="width:120px;" multiple>
|
41
|
+
<option value="all" <%= 'selected' if @selected_categories.empty? %>><all categories></option>
|
42
|
+
<option value="none" <%= 'selected' if @selected_categories.include? 'none' %>><no categories></option>
|
43
|
+
<% for category in @categories %>
|
44
|
+
<option value="<%= category %>" <%= 'selected' if @selected_categories.include? category %>><%= category %></option>
|
45
|
+
<% end %>
|
46
|
+
</select>
|
31
47
|
</td>
|
32
|
-
|
48
|
+
</tr>
|
49
|
+
<tr>
|
50
|
+
<td colspan='4' align='center'><input type="submit" value="Redraw" name="Go"></td>
|
51
|
+
</tr>
|
33
52
|
</form>
|
34
53
|
</table>
|
35
54
|
|
data/app/views/wiki/search.rhtml
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
<% @title = @results.length > 0 ? "#{@results.length} pages contains \"#{@params["query"]}\"" : "No pages contains \"#{@query}\"" %><%= sub_template "top" %>
|
2
2
|
|
3
3
|
<% if @results.length > 0 %>
|
4
|
+
<h3>Matching Pages:</h3>
|
4
5
|
<ul>
|
5
6
|
<% for page in @results %>
|
6
7
|
<li><a href="../show/<%= page.name %>"><%= page.plain_name %></a><br />
|
@@ -17,7 +18,28 @@
|
|
17
18
|
</li>
|
18
19
|
<% end %>
|
19
20
|
</ul>
|
20
|
-
<%
|
21
|
+
<% end %>
|
22
|
+
<% if @bliki_results.length > 0 %>
|
23
|
+
<h3>Matching Bliki Entries:</h3>
|
24
|
+
<ul>
|
25
|
+
<% for entry in @bliki_results %>
|
26
|
+
<li><a href="../bliki_revision/<%= entry.name %>?rev=<%= entry.revisions.size-1 %>"><%= entry.name %></a><br />
|
27
|
+
<%
|
28
|
+
idxs = entry.content.scan(/.{0,30}#{@params["query"]}.{0,30}/im)
|
29
|
+
idxs.each do |i|
|
30
|
+
begin %>
|
31
|
+
...<%= i.to_s %>...<br /><%
|
32
|
+
rescue Exception => e
|
33
|
+
%><%= e.message %><%
|
34
|
+
end
|
35
|
+
end
|
36
|
+
%>
|
37
|
+
</li>
|
38
|
+
<% end %>
|
39
|
+
</ul>
|
40
|
+
<% end %>
|
41
|
+
|
42
|
+
<% if @results.length == 0 && @bliki_results.length == 0 %>
|
21
43
|
<p>Perhaps you should try expanding your query. Remember that Instiki searches for entire phrases, so if you search for "all that jazz" it will not match pages that contain these words in separation—only as a sentence fragment.</p>
|
22
44
|
|
23
45
|
<p>If you're a high-tech computer wizard, you might even want try constructing a regular expression. That's actually what Instiki uses, so go right ahead and flex your "[a-z]*Leet?RegExpSkill(s|z)"</p>
|
data/pimki.rb
CHANGED
@@ -10,15 +10,34 @@ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), "libraries")
|
|
10
10
|
begin
|
11
11
|
require 'rubygems'
|
12
12
|
require_gem 'madeleine'
|
13
|
-
require_gem '
|
13
|
+
require_gem 'RedCloth'
|
14
14
|
require_gem 'rubyzip'
|
15
|
-
require_gem 'bluecloth'
|
16
15
|
|
17
|
-
rescue LoadError
|
16
|
+
rescue LoadError => detail
|
18
17
|
# no rubygems, so load from the libraries directory
|
18
|
+
p detail
|
19
19
|
require 'redcloth'
|
20
|
-
require 'bluecloth'
|
20
|
+
require 'bluecloth'
|
21
21
|
end
|
22
|
+
|
23
|
+
### RedCloth Modifications:
|
24
|
+
# Remove the "caps" spanning:
|
25
|
+
RedCloth::GLYPHS.delete_if { |glyph| glyph[1] =~ /class=\"caps\"/ }
|
26
|
+
# Fix missing hard_break
|
27
|
+
if RedCloth::VERSION == '3.0.0'
|
28
|
+
class RedCloth #{{{
|
29
|
+
alias_method :old_clean_white_space, :clean_white_space
|
30
|
+
def clean_white_space text
|
31
|
+
old_clean_white_space text
|
32
|
+
hard_break text
|
33
|
+
end
|
34
|
+
end #}}}
|
35
|
+
else
|
36
|
+
# Redcloth v3.0.0 can handle markdown, so BlueCloth is only required if we
|
37
|
+
# have an earlier redcloth version.
|
38
|
+
require 'BlueCloth'
|
39
|
+
end
|
40
|
+
|
22
41
|
# }}}
|
23
42
|
|
24
43
|
# Handle command-line options: {{{
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.
|
2
|
+
rubygems_version: 0.8.3
|
3
3
|
specification_version: 1
|
4
4
|
name: Pimki
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.
|
7
|
-
date: 2004-12-
|
6
|
+
version: 1.3.092
|
7
|
+
date: 2004-12-26
|
8
8
|
summary: A Personal Information Manager (PIM) based on the Wiki technology of Instiki.
|
9
9
|
require_paths:
|
10
10
|
- libraries
|
11
|
-
author: Assaph Mehr (based on work by David Heinemeier Hansson)
|
12
11
|
email: assaph@gmail.com
|
13
12
|
homepage: http://pimki.rubyforge.org
|
14
13
|
rubyforge_project: pimki
|
@@ -25,6 +24,8 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
25
24
|
version: 0.0.0
|
26
25
|
version:
|
27
26
|
platform: ruby
|
27
|
+
authors:
|
28
|
+
- Assaph Mehr (based on work by David Heinemeier Hansson)
|
28
29
|
files:
|
29
30
|
- pimki.rb
|
30
31
|
- README
|
@@ -63,6 +64,7 @@ files:
|
|
63
64
|
- app/models/chunks/uri.rb
|
64
65
|
- app/models/chunks/uri_test.rb
|
65
66
|
- app/models/chunks/wiki.rb
|
67
|
+
- app/models/chunks/wiki_symbols.rb
|
66
68
|
- app/models/chunks/wiki_test.rb
|
67
69
|
- app/views/bottom.rhtml
|
68
70
|
- app/views/markdown_help.rhtml
|
@@ -130,22 +132,12 @@ dependencies:
|
|
130
132
|
- !ruby/object:Gem::Dependency
|
131
133
|
name: RedCloth
|
132
134
|
version_requirement:
|
133
|
-
version_requirements: !ruby/object:Gem::Version::Requirement
|
134
|
-
requirements:
|
135
|
-
-
|
136
|
-
- "~>"
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: 2.0.11
|
139
|
-
version:
|
140
|
-
- !ruby/object:Gem::Dependency
|
141
|
-
name: BlueCloth
|
142
|
-
version_requirement:
|
143
135
|
version_requirements: !ruby/object:Gem::Version::Requirement
|
144
136
|
requirements:
|
145
137
|
-
|
146
138
|
- ">="
|
147
139
|
- !ruby/object:Gem::Version
|
148
|
-
version: 0.0
|
140
|
+
version: 3.0.0
|
149
141
|
version:
|
150
142
|
- !ruby/object:Gem::Dependency
|
151
143
|
name: rubyzip
|