Pimki 1.7.092 → 1.8.092

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/README-PIMKI +182 -178
  2. data/app/controllers/wiki.rb +950 -942
  3. data/app/models/chunks/category.rb +33 -33
  4. data/app/models/chunks/category_test.rb +21 -21
  5. data/app/models/chunks/chunk.rb +20 -20
  6. data/app/models/chunks/engines.rb +48 -48
  7. data/app/models/chunks/include.rb +1 -1
  8. data/app/models/chunks/match.rb +1 -1
  9. data/app/models/chunks/nowiki.rb +1 -1
  10. data/app/models/chunks/nowiki_test.rb +5 -0
  11. data/app/models/chunks/todo.rb +1 -0
  12. data/app/models/chunks/wiki.rb +130 -130
  13. data/app/models/page.rb +124 -124
  14. data/app/models/revision.rb +92 -92
  15. data/app/models/web.rb +314 -316
  16. data/app/models/wiki_content.rb +2 -2
  17. data/app/models/wiki_service.rb +170 -166
  18. data/app/models/wiki_words.rb +28 -28
  19. data/app/views/error.rhtml +37 -37
  20. data/app/views/navigation.rhtml +1 -1
  21. data/app/views/static_style_sheet.rhtml +10 -5
  22. data/app/views/top.rhtml +1 -1
  23. data/app/views/wiki/adv_search.rhtml +61 -61
  24. data/app/views/wiki/bliki.rhtml +7 -6
  25. data/app/views/wiki/bliki_edit.rhtml +26 -37
  26. data/app/views/wiki/bliki_new.rhtml +58 -64
  27. data/app/views/wiki/bliki_revision.rhtml +5 -3
  28. data/app/views/wiki/edit.rhtml +44 -44
  29. data/app/views/wiki/edit_menu.rhtml +26 -19
  30. data/app/views/wiki/edit_web.rhtml +303 -305
  31. data/app/views/wiki/glossary.rhtml +35 -27
  32. data/app/views/wiki/list.rhtml +175 -174
  33. data/app/views/wiki/list.rhtml.bak +175 -0
  34. data/app/views/wiki/mind.rhtml +70 -70
  35. data/app/views/wiki/new.rhtml +34 -32
  36. data/app/views/wiki/published.rhtml +34 -49
  37. data/app/views/wiki/revision.rhtml +88 -87
  38. data/app/views/wiki/rollback.rhtml +36 -35
  39. data/app/views/wiki/todo.rhtml +2 -2
  40. data/app/views/wiki_words_help.rhtml +8 -8
  41. data/libraries/action_controller_servlet.rb +202 -202
  42. data/libraries/madeleine_service.rb +162 -162
  43. data/pimki.rb +181 -181
  44. metadata +11 -12
  45. data/README +0 -172
  46. data/app/models/chunks/acronym.rb +0 -19
  47. data/app/views/wiki/test.rhtml +0 -25
  48. data/libraries/secure_web_controller_server.rb +0 -106
@@ -1,125 +1,125 @@
1
- require "date"
2
- require "page_lock"
3
- require "revision"
4
- require "wiki_words"
5
- require "chunks/wiki"
6
-
7
- class Page
8
- include PageLock
9
-
10
- CONTINOUS_REVISION_PERIOD = 30 * 60 # 30 minutes
11
-
12
- attr_accessor :name, :last_visited, :viewed
13
- attr_reader :revisions, :web
14
-
15
- def initialize(web, name, content, created_at, author)
16
- @web, @name, @revisions = web, name, []
17
- revise(content, created_at, author)
18
- end
19
-
20
- def revise(content, created_at, author, edit_type='default')
21
- case edit_type
22
- when 'major'
23
- revise_major(content, created_at, author)
24
-
25
- when 'minor'
26
- if !@revisions.empty? # sanity check
27
- revise_minor(content, created_at, author)
28
- else
29
- revise_major(content, created_at, author)
30
- end
31
-
32
- when 'default'
33
- if !@revisions.empty? && continous_revision?(created_at, author)
34
- revise_minor(content, created_at, author)
35
- else
36
- revise_major(content, created_at, author)
37
- end
38
-
39
- else
40
- revise_major(content, created_at, author)
41
- end
42
-
43
- web.refresh_pages_with_references(name) if @revisions.length == 1
44
- end
45
-
46
- def rollback(revision_number, created_at, author_ip = nil)
47
- roll_back_revision = @revisions[revision_number].dup
48
- revise(roll_back_revision.content, created_at, Author.new(roll_back_revision.author, author_ip))
49
- end
50
-
51
- def revisions?
52
- revisions.length > 1
53
- end
54
-
55
- def revised_on
56
- created_on
57
- end
58
-
59
- def pretty_revised_on
60
- DateTime.new(revised_on.year, revised_on.mon, revised_on.day).strftime "%B %e, %Y"
61
- end
62
-
63
- def in_category?(cat)
64
- cat.nil? || cat.empty? || categories.include?(cat)
65
- end
66
-
67
- def categories
68
- display_content.find_chunks(Category).map { |cat| cat.list }.flatten
69
- end
70
-
71
- def authors
72
- revisions.collect { |rev| rev.author }
73
- end
74
-
75
- def references
76
- web.select.pages_that_reference(name)
77
- end
78
-
79
- def bliki_references
80
- web.select_bliki.pages_that_reference(name)
81
- end
82
-
83
- # Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
84
- def plain_name
85
- WikiWords.separate(name, web.brackets_only)
86
- end
87
-
88
- def link(options = {})
89
- web.make_link(name, nil, options)
90
- end
91
-
92
- def author_link(options = {})
93
- web.make_link(author, nil, options)
94
- end
95
-
96
- def last_visited() @last_visited || revisions.last.created_at end
97
- def viewed() @viewed ||= 0 end
98
-
99
- def has_todos?
100
- not display_content.find_chunks(Todo).empty?
101
- end
102
-
103
- private
104
- def continous_revision?(created_at, author)
105
- @revisions.last.author == author && @revisions.last.created_at + CONTINOUS_REVISION_PERIOD > created_at
106
- end
107
-
108
- # Forward method calls to the current revision, so the page responds to all revision calls
109
- def method_missing(method_symbol)
110
- revisions.last.send(method_symbol)
111
- end
112
-
113
- def revise_minor(content, created_at, author) #{{{
114
- @revisions.last.created_at = created_at
115
- @revisions.last.content = content
116
- @revisions.last.clear_display_cache
117
- end #}}}
118
-
119
- def revise_major(content, created_at, author) #{{{
120
- @revisions << Revision.new(self, @revisions.length, content, created_at, author)
121
- end #}}}
122
-
123
- end
124
-
1
+ require "date"
2
+ require "page_lock"
3
+ require "revision"
4
+ require "wiki_words"
5
+ require "chunks/wiki"
6
+
7
+ class Page
8
+ include PageLock
9
+
10
+ CONTINOUS_REVISION_PERIOD = 30 * 60 # 30 minutes
11
+
12
+ attr_accessor :name, :last_visited, :viewed
13
+ attr_reader :revisions, :web
14
+
15
+ def initialize(web, name, content, created_at, author)
16
+ @web, @name, @revisions = web, name, []
17
+ revise(content, created_at, author)
18
+ end
19
+
20
+ def revise(content, created_at, author, edit_type='default')
21
+ case edit_type
22
+ when 'major'
23
+ revise_major(content, created_at, author)
24
+
25
+ when 'minor'
26
+ if !@revisions.empty? # sanity check
27
+ revise_minor(content, created_at, author)
28
+ else
29
+ revise_major(content, created_at, author)
30
+ end
31
+
32
+ when 'default'
33
+ if !@revisions.empty? && continous_revision?(created_at, author)
34
+ revise_minor(content, created_at, author)
35
+ else
36
+ revise_major(content, created_at, author)
37
+ end
38
+
39
+ else
40
+ revise_major(content, created_at, author)
41
+ end
42
+
43
+ web.refresh_pages_with_references(name) if @revisions.length == 1
44
+ end
45
+
46
+ def rollback(revision_number, created_at, author_ip = nil)
47
+ roll_back_revision = @revisions[revision_number].dup
48
+ revise(roll_back_revision.content, created_at, Author.new(roll_back_revision.author, author_ip))
49
+ end
50
+
51
+ def revisions?
52
+ revisions.length > 1
53
+ end
54
+
55
+ def revised_on
56
+ created_on
57
+ end
58
+
59
+ def pretty_revised_on
60
+ DateTime.new(revised_on.year, revised_on.mon, revised_on.day).strftime "%B %e, %Y"
61
+ end
62
+
63
+ def in_category?(cat)
64
+ cat.nil? || cat.empty? || categories.include?(cat)
65
+ end
66
+
67
+ def categories
68
+ display_content.find_chunks(Category).map { |cat| cat.list }.flatten
69
+ end
70
+
71
+ def authors
72
+ revisions.collect { |rev| rev.author }
73
+ end
74
+
75
+ def references
76
+ web.select.pages_that_reference(name)
77
+ end
78
+
79
+ def bliki_references
80
+ web.select_bliki.pages_that_reference(name)
81
+ end
82
+
83
+ # Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
84
+ def plain_name
85
+ WikiWords.separate(name, web.brackets_only)
86
+ end
87
+
88
+ def link(options = {})
89
+ web.make_link(name, nil, options)
90
+ end
91
+
92
+ def author_link(options = {})
93
+ web.make_link(author, nil, options)
94
+ end
95
+
96
+ def last_visited() @last_visited || revisions.last.created_at end
97
+ def viewed() @viewed ||= 0 end
98
+
99
+ def has_todos?
100
+ not display_content.find_chunks(Todo).empty?
101
+ end
102
+
103
+ private
104
+ def continous_revision?(created_at, author)
105
+ @revisions.last.author == author && @revisions.last.created_at + CONTINOUS_REVISION_PERIOD > created_at
106
+ end
107
+
108
+ # Forward method calls to the current revision, so the page responds to all revision calls
109
+ def method_missing(method_symbol)
110
+ revisions.last.send(method_symbol)
111
+ end
112
+
113
+ def revise_minor(content, created_at, author) #{{{
114
+ @revisions.last.created_at = created_at
115
+ @revisions.last.content = content
116
+ @revisions.last.clear_display_cache
117
+ end #}}}
118
+
119
+ def revise_major(content, created_at, author) #{{{
120
+ @revisions << Revision.new(self, @revisions.length, content, created_at, author)
121
+ end #}}}
122
+
123
+ end
124
+
125
125
  # jEdit :folding=indent:collapseFolds=1:
@@ -1,92 +1,92 @@
1
-
2
-
3
- require "diff/diff"
4
-
5
- require "wiki_content"
6
- require "chunks/wiki"
7
-
8
- require "date"
9
- require "author"
10
- require "page"
11
-
12
- class Revision
13
- attr_accessor :page, :number, :content, :created_at, :author
14
-
15
- def initialize(page, number, content, created_at, author)
16
- @page, @number, @created_at, @author = page, number, created_at, author
17
- self.content = content
18
- end
19
-
20
- # Ensure that the wiki content is parsed when ever it is updated.
21
- def content=(content)
22
- @content = content
23
- end
24
-
25
- def created_on
26
- Date.new(@created_at.year, @created_at.mon, @created_at.day)
27
- end
28
-
29
- def pretty_created_at
30
- # Must use DateTime because Time doesn't support %e on at least some platforms
31
- DateTime.new(
32
- @created_at.year, @created_at.mon, @created_at.day, @created_at.hour, @created_at.min
33
- ).strftime "%B %e, %Y %H:%M"
34
- end
35
-
36
- def next_revision
37
- page.revisions[number + 1]
38
- end
39
-
40
- def previous_revision
41
- number - 1 >= 0 && page.revisions[number - 1]
42
- end
43
-
44
- # Returns an array of all the WikiWords present in the content of this revision.
45
- def wiki_words
46
- unless @wiki_words_cache
47
- wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
48
- # BlikiLinks are used to link outside the wiki, so are not WikiLinks.
49
- wiki_chunks.reject! { |chunk| chunk.kind_of? WikiChunk::BlikiLink }
50
- @wiki_words_cache = wiki_chunks.map { |c| ( c.escaped_text ? nil : c.page_name ) }.compact.uniq
51
- end
52
- @wiki_words_cache
53
- end
54
-
55
- # Returns an array of all the WikiWords present in the content of this revision.
56
- # that already exists as a page in the web.
57
- def existing_pages
58
- wiki_words.select { |wiki_word| page.web.pages[wiki_word] }
59
- end
60
-
61
- # Returns an array of all the WikiWords present in the content of this revision
62
- # that *doesn't* already exists as a page in the web.
63
- def unexisting_pages
64
- wiki_words - existing_pages
65
- end
66
-
67
- # Explicit check for new type of display cache with find_chunks method.
68
- # Ensures new version works with older snapshots.
69
- def display_content
70
- unless @display_cache && @display_cache.respond_to?(:find_chunks)
71
- @display_cache = WikiContent.new(self)
72
- end
73
- @display_cache
74
- end
75
-
76
- def display_diff
77
- previous_revision ? HTMLDiff.diff(previous_revision.display_content, display_content) : display_content
78
- end
79
-
80
- def clear_display_cache
81
- @display_cache = @published_cache = @wiki_words_cache = nil
82
- end
83
-
84
- def display_published
85
- @published_cache ||= WikiContent.new(self, {:mode => :publish})
86
- end
87
-
88
- def display_content_for_export
89
- WikiContent.new(self, {:mode => :export} )
90
- end
91
-
92
- end
1
+
2
+
3
+ require "diff/diff"
4
+
5
+ require "wiki_content"
6
+ require "chunks/wiki"
7
+
8
+ require "date"
9
+ require "author"
10
+ require "page"
11
+
12
+ class Revision
13
+ attr_accessor :page, :number, :content, :created_at, :author
14
+
15
+ def initialize(page, number, content, created_at, author)
16
+ @page, @number, @created_at, @author = page, number, created_at, author
17
+ self.content = content
18
+ end
19
+
20
+ # Ensure that the wiki content is parsed when ever it is updated.
21
+ def content=(content)
22
+ @content = content
23
+ end
24
+
25
+ def created_on
26
+ Date.new(@created_at.year, @created_at.mon, @created_at.day)
27
+ end
28
+
29
+ def pretty_created_at
30
+ # Must use DateTime because Time doesn't support %e on at least some platforms
31
+ DateTime.new(
32
+ @created_at.year, @created_at.mon, @created_at.day, @created_at.hour, @created_at.min
33
+ ).strftime "%B %e, %Y %H:%M"
34
+ end
35
+
36
+ def next_revision
37
+ page.revisions[number + 1]
38
+ end
39
+
40
+ def previous_revision
41
+ number - 1 >= 0 && page.revisions[number - 1]
42
+ end
43
+
44
+ # Returns an array of all the WikiWords present in the content of this revision.
45
+ def wiki_words
46
+ unless @wiki_words_cache
47
+ wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
48
+ # BlikiLinks are used to link outside the wiki, so are not WikiLinks.
49
+ wiki_chunks.reject! { |chunk| chunk.kind_of? WikiChunk::BlikiLink }
50
+ @wiki_words_cache = wiki_chunks.map { |c| ( c.escaped_text ? nil : c.page_name ) }.compact.uniq
51
+ end
52
+ @wiki_words_cache
53
+ end
54
+
55
+ # Returns an array of all the WikiWords present in the content of this revision.
56
+ # that already exists as a page in the web.
57
+ def existing_pages
58
+ wiki_words.select { |wiki_word| page.web.pages[wiki_word] }
59
+ end
60
+
61
+ # Returns an array of all the WikiWords present in the content of this revision
62
+ # that *doesn't* already exists as a page in the web.
63
+ def unexisting_pages
64
+ wiki_words - existing_pages
65
+ end
66
+
67
+ # Explicit check for new type of display cache with find_chunks method.
68
+ # Ensures new version works with older snapshots.
69
+ def display_content
70
+ unless @display_cache && @display_cache.respond_to?(:find_chunks)
71
+ @display_cache = WikiContent.new(self)
72
+ end
73
+ @display_cache
74
+ end
75
+
76
+ def display_diff
77
+ previous_revision ? HTMLDiff.diff(previous_revision.display_content, display_content) : display_content
78
+ end
79
+
80
+ def clear_display_cache
81
+ @display_cache = @published_cache = @wiki_words_cache = nil
82
+ end
83
+
84
+ def display_published
85
+ @published_cache ||= WikiContent.new(self, {:mode => :publish})
86
+ end
87
+
88
+ def display_content_for_export
89
+ WikiContent.new(self, {:mode => :export} )
90
+ end
91
+
92
+ end
@@ -1,317 +1,315 @@
1
- require "cgi"
2
- require "page"
3
- require "page_set"
4
- require "wiki_words"
5
- require "zip/zip"
6
-
7
- class Web
8
- attr_accessor :pages, :name, :address, :password, :menu_type, :menu_content, :rendered_menu, :menu_limit, :menu_category
9
- attr_accessor :markup, :color, :safe_mode, :additional_style, :published, :default_to_published, :brackets_only, :count_pages
10
- attr_accessor :mind_map_size, :symbols_map, :links_map, :enable_dclick_edit, :check_pass_on_edit, :enable_menu
11
-
12
- # Mind Map defaults
13
- attr_accessor :mm_prog, :mm_graph_type, :mm_show_missing, :mm_show_authors, :mm_show_leaves, :mm_selected_categories
14
-
15
- @@BLIKI_TEMPLATE = "Try a weekly worksheet:\n\n| / | *Morning* | *Afternoon* |\n" +
16
- "| *Mon* | - | - |\n| *Tue* | - | - |\n| *Wed* | - | - |\n" +
17
- "| *Thu* | - | - |\n| *Fri* | - | - |\n"
18
-
19
- def bliki
20
- @bliki ||= Hash.new
21
- end
22
-
23
- def initialize(name, address, password = nil)
24
- @name, @address, @password, @safe_mode = name, address, password, false
25
- @pages = {}
26
- end
27
-
28
- def add_page(page)
29
- @pages[page.name] = page
30
- end
31
-
32
- def remove_pages(pages_to_be_removed)
33
- pages.delete_if { |page_name, page| pages_to_be_removed.include?(page) }
34
- end
35
-
36
- def revised_on
37
- pages.values.sort_by { |page| [page.created_at] }.reverse.first.created_at
38
- end
39
-
40
- def select(&accept)
41
- PageSet.new(self, @pages.values, accept)
42
- end
43
-
44
- def select_bliki(&accept)
45
- PageSet.new(self, bliki.values, accept)
46
- end
47
-
48
- def revised_on
49
- select.most_recent_revision
50
- end
51
-
52
- def authors
53
- select.authors
54
- end
55
-
56
- def categories
57
- select.map { |page| page.categories }.flatten.uniq.sort
58
- end
59
-
60
- # Create a link for the given page name and link text based
61
- # on the render mode in options and whether the page exists
62
- # in the this web.
63
- def make_link(name, text = nil, options = {})
64
- page = pages[name]
65
- text = text || WikiWords.separate(name)
66
- link = CGI.escape(name)
67
-
68
- case options[:mode]
69
- when :export
70
- if page then "<a class=\"existingWikiWord\" href=\"#{link}.html\">#{text}</a>"
71
- else "<span class=\"newWikiWord\">#{text}</span>" end
72
- when :publish
73
- if page then "<a class=\"existingWikiWord\" href=\"../published/#{link}\">#{text}</a>"
74
- else "<span class=\"newWikiWord\">#{text}</span>" end
75
- else
76
- if page then "<a class=\"existingWikiWord\" href=\"../show/#{link}\">#{text}</a>"
77
- else "<span class=\"newWikiWord\">#{text}<a href=\"../show/#{link}\">?</a></span>" end
78
- end
79
- end
80
-
81
-
82
- # Clears the display cache for all the pages with references to
83
- def refresh_pages_with_references(page_name)
84
- select.pages_that_reference(page_name).each { |page|
85
- page.revisions.each { |revision| revision.clear_display_cache }
86
- }
87
- end
88
-
89
- def refresh_revisions
90
- select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
91
- select_bliki.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
92
- end
93
-
94
- # Default values
95
- def markup() @markup || :textile end
96
- def color() @color || "008B26" end
97
- def brackets_only() @brackets_only || false end
98
- def count_pages() @count_pages || false end
99
- def enable_menu() @enable_menu || true end
100
- def menu_content() @menu_content || nil end
101
- def menu_limit() @menu_limit || 20 end
102
- def default_to_published() @default_to_published || false end
103
- def menu_type()
104
- (@menu_type.nil? || @menu_type.empty?) ? 'linkers' : @menu_type
105
- end
106
- def mind_map_size() (@mind_map_size == '0,0' ? '6,5' : @mind_map_size) end
107
- def mm_prog() @mm_prog || 'neato' end
108
- def mm_graph_type() @mm_graph_type || 'normal' end
109
- def mm_show_missing() @mm_show_missing || false end
110
- def mm_show_authors() @mm_show_authors || false end
111
- def mm_show_leaves() @mm_show_leaves || true end
112
- def mm_selected_categories() @mm_selected_categories || [] end
113
-
114
- # create a Mind Map graph and return the PNG and HTML map files generated
115
- def create_mind_map(prog, missing, show_authors, show_leaves, selected_categories, mm_size)
116
- dotFile = File.expand_path("#{WikiService.storage_path}/graph.dot")
117
- mapFile = File.expand_path("#{WikiService.storage_path}/graph.map")
118
- pngFile = File.expand_path("#{WikiService.storage_path}/map.png")
119
-
120
- File.open(dotFile, "w") do |file|
121
-
122
- # Graph properties:
123
- output_graph_header_to file, mm_size
124
-
125
- # Links and node properties:
126
- nodes = filter_categories(pages.values, selected_categories)
127
- auths = authors # avoid repeated selects
128
- unless show_authors
129
- nodes.delete_if { |entry|
130
- auths.include? entry.name
131
- }
132
- end
133
- unless show_leaves
134
- nodes.delete_if { |page|
135
- (page.wiki_words - [missing].flatten).size == 0
136
- }
137
- end
138
-
139
- # Page Special nodes properties:
140
- file.puts %{"Home Page" [color=\"##{color}\",style=bold];} if nodes.map{ |p| p.name }.include? "HomePage"
141
-
142
- nodes.each do |page|
143
- file.puts %{"#{page.plain_name}" [URL=\"../show/#{page.name}\"];}
144
- page.references.each do |referer|
145
- unless page.name == referer.name or not nodes.include? referer
146
- unless !show_authors and auths.include? referer.name
147
- file.puts %{"#{referer.plain_name}" -> "#{page.plain_name}";}
148
- end
149
- end
150
- end
151
- end
152
-
153
- # find missing pages:
154
- if missing
155
- shown_missing = []
156
- nodes.each do |page|
157
- missing.each do |wanted|
158
- if page.content =~ /#{wanted}/
159
- file.puts %{"#{page.plain_name}" -> "#{WikiWords.separate wanted}";}
160
- shown_missing << wanted
161
- end
162
- end
163
- end
164
- shown_missing.each do |wanted|
165
- file.puts %{"#{WikiWords.separate wanted}" [URL="/#{@address}/show/#{wanted}", fontsize=10,style=filled,color=grey];}
166
- end
167
- end
168
-
169
- output_graph_footer_to file
170
- end
171
-
172
- call_graphviz(prog, dotFile, mapFile, pngFile)
173
-
174
- [pngFile, mapFile]
175
- end
176
-
177
- def create_author_graph(prog, selected_categories, mm_size)
178
- dotFile = File.expand_path("#{WikiService.storage_path}/graph.dot")
179
- mapFile = File.expand_path("#{WikiService.storage_path}/graph.map")
180
- pngFile = File.expand_path("#{WikiService.storage_path}/map.png")
181
-
182
- File.open(dotFile, "w") do |file|
183
-
184
- # Graph properties:
185
- output_graph_header_to file, mm_size
186
-
187
- # Links and node properties:
188
- auths = authors # avoid repeated selects
189
- auths.each do |auth|
190
- file.puts %{"#{auth}" [style=filled,color=grey,URL="../show/#{auth}"];}
191
- end
192
-
193
- nodes = pages.values.reject { |entry| auths.include? entry.name }
194
- nodes = filter_categories(nodes, selected_categories)
195
- nodes.each do |page|
196
- file.puts %{"#{page.plain_name}" [URL="../show/#{page.name}"];}
197
- page.authors.each do |auth|
198
- file.puts %{"#{auth}" -> "#{page.plain_name}";}
199
- end
200
- end
201
-
202
- output_graph_footer_to file
203
- end
204
-
205
- call_graphviz(prog, dotFile, mapFile, pngFile)
206
-
207
- [pngFile, mapFile]
208
- end
209
-
210
- def create_category_graph(prog, show_authors, selected_categories, mm_size) #{{{
211
- dotFile = File.expand_path("#{WikiService.storage_path}/graph.dot")
212
- mapFile = File.expand_path("#{WikiService.storage_path}/graph.map")
213
- pngFile = File.expand_path("#{WikiService.storage_path}/map.png")
214
-
215
- File.open(dotFile, "w") do |file|
216
- # Graph properties:
217
- output_graph_header_to file, mm_size
218
-
219
- # Page Special nodes properties:
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}"];}
223
- end
224
-
225
- # Links and node properties:
226
- nodes = filter_categories(pages.values, selected_categories)
227
- auths = authors # avoid repeated selects
228
- unless show_authors
229
- nodes.delete_if { |entry|
230
- auths.include? entry.name
231
- }
232
- end
233
- nodes.each do |page|
234
- file.puts %{"#{page.plain_name}" [URL=\"../show/#{page.name}\"];}
235
- page.categories.each do |category|
236
- file.puts %{"#{category}" -> "#{page.plain_name}";}
237
- end
238
- end
239
-
240
- output_graph_footer_to file
241
- end
242
-
243
- call_graphviz(prog, dotFile, mapFile, pngFile)
244
-
245
- [pngFile, mapFile]
246
- end #}}}
247
-
248
- def output_graph_header_to file, mm_size
249
- file.puts "digraph G {"
250
- file.puts "size=\"#{mm_size}\";" if mm_size
251
- file.puts 'ratio=fill;'
252
- file.puts 'concentrate=true;'
253
- file.puts 'node [fontsize=10,fontname="Tahoma"];'
254
- file.puts 'edge [len=1.5];'
255
- end
256
-
257
- def output_graph_footer_to file
258
- file.puts "}"
259
- end
260
-
261
- def filter_categories(pages, selected_categories) #{{{
262
- nodes = pages
263
- unless selected_categories.empty?
264
- nodes = pages.reject { |page| (page.categories & selected_categories).empty? }
265
- if selected_categories.include? 'none'
266
- nodes += pages.select { |page| page.categories.empty? }
267
- end
268
- end
269
- nodes
270
- end #}}}
271
-
272
- def call_graphviz(prog, dotFile, mapFile, pngFile)
273
- system("#{prog} -Tcmap \"#{dotFile}\" -o \"#{mapFile}\"")
274
- system("#{prog} -Tpng \"#{dotFile}\" -o \"#{pngFile}\"")
275
- end
276
-
277
- ## Bliki methods
278
-
279
- def add_bliki_entry(page)
280
- bliki[page.name] = page
281
- end
282
-
283
- def bliki_entries_by_date
284
- bliki.values.sort_by { |page| page.revisions.first.created_at }.reverse
285
- end
286
-
287
- def bliki_entries_by_name
288
- pages.values.sort_by { |page| [page.name] }
289
- end
290
-
291
- def bliki_entries_that_match(regexp)
292
- bliki.values.select { |page| page.content =~ /#{regexp}/i }
293
- end
294
-
295
- def bliki_entries_that_reference(page_name)
296
- bliki.values.select { |page| page.wiki_words.include?(page_name) }
297
- end
298
-
299
- def bliki_entries_authored_by(author)
300
- bliki.values.select { |page| page.authors.include?(author) }
301
- end
302
-
303
- ## End bliki methods
304
-
305
- private
306
- # Returns an array of all the wiki words in any current revision
307
- def wiki_words
308
- pages.values.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
309
- end
310
-
311
- # Returns an array of all the page names on this web
312
- def page_names
313
- pages.keys
314
- end
315
- end
316
-
1
+ require "cgi"
2
+ require "page"
3
+ require "page_set"
4
+ require "wiki_words"
5
+ require "zip/zip"
6
+
7
+ class Web
8
+ attr_accessor :pages, :name, :address, :password, :menu_type, :menu_content, :rendered_menu, :menu_limit, :menu_category
9
+ attr_accessor :markup, :color, :safe_mode, :additional_style, :published, :default_to_published, :brackets_only, :count_pages
10
+ attr_accessor :mind_map_size, :symbols_map, :links_map, :enable_dclick_edit, :check_pass_on_edit, :enable_menu
11
+
12
+ # Mind Map defaults
13
+ attr_accessor :mm_prog, :mm_graph_type, :mm_show_missing, :mm_show_authors, :mm_show_leaves, :mm_selected_categories
14
+
15
+ @@BLIKI_TEMPLATE = "Try a weekly worksheet:\n\n| / | *Morning* | *Afternoon* |\n" +
16
+ "| *Mon* | - | - |\n| *Tue* | - | - |\n| *Wed* | - | - |\n" +
17
+ "| *Thu* | - | - |\n| *Fri* | - | - |\n"
18
+
19
+ def bliki
20
+ @bliki ||= Hash.new
21
+ end
22
+
23
+ def initialize(name, address, password = nil)
24
+ @name, @address, @password, @safe_mode = name, address, password, false
25
+ @pages = {}
26
+ end
27
+
28
+ def add_page(page)
29
+ @pages[page.name] = page
30
+ end
31
+
32
+ def remove_pages(pages_to_be_removed)
33
+ pages.delete_if { |page_name, page| pages_to_be_removed.include?(page) }
34
+ end
35
+
36
+ def revised_on
37
+ pages.values.sort_by { |page| [page.created_at] }.reverse.first.created_at
38
+ end
39
+
40
+ def select(&accept)
41
+ PageSet.new(self, @pages.values, accept)
42
+ end
43
+
44
+ def select_bliki(&accept)
45
+ PageSet.new(self, bliki.values, accept)
46
+ end
47
+
48
+ def revised_on
49
+ select.most_recent_revision
50
+ end
51
+
52
+ def authors
53
+ select.authors
54
+ end
55
+
56
+ def categories
57
+ select.map { |page| page.categories }.flatten.uniq.sort
58
+ end
59
+
60
+ # Create a link for the given page name and link text based
61
+ # on the render mode in options and whether the page exists
62
+ # in the this web.
63
+ def make_link(name, text = nil, options = {})
64
+ page = pages[name]
65
+ text = text || WikiWords.separate(name)
66
+ link = CGI.escape(name)
67
+
68
+ case options[:mode]
69
+ when :export
70
+ if page then "<a class=\"existingWikiWord\" href=\"#{link}.html\">#{text}</a>"
71
+ else "<span class=\"newWikiWord\">#{text}</span>" end
72
+ when :publish
73
+ if page then "<a class=\"existingWikiWord\" href=\"../published/#{link}\">#{text}</a>"
74
+ else "<span class=\"newWikiWord\">#{text}</span>" end
75
+ else
76
+ if page then "<a class=\"existingWikiWord\" href=\"../show/#{link}\">#{text}</a>"
77
+ else "<span class=\"newWikiWord\">#{text}<a href=\"../show/#{link}\">?</a></span>" end
78
+ end
79
+ end
80
+
81
+
82
+ # Clears the display cache for all the pages with references to
83
+ def refresh_pages_with_references(page_name)
84
+ select.pages_that_reference(page_name).each { |page|
85
+ page.revisions.each { |revision| revision.clear_display_cache }
86
+ }
87
+ end
88
+
89
+ def refresh_revisions
90
+ select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
91
+ select_bliki.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
92
+ end
93
+
94
+ # Default values
95
+ def markup() @markup || :textile end
96
+ def color() @color || "008B26" end
97
+ def brackets_only() @brackets_only || false end
98
+ def count_pages() @count_pages || false end
99
+ def menu_content() @menu_content || nil end
100
+ def menu_limit() @menu_limit || 20 end
101
+ def default_to_published() @default_to_published || false end
102
+ def menu_type()
103
+ (@menu_type.nil? || @menu_type.empty?) ? 'linkers' : @menu_type
104
+ end
105
+ def mind_map_size() (@mind_map_size == '0,0' ? '6,5' : @mind_map_size) end
106
+ def mm_prog() @mm_prog || 'neato' end
107
+ def mm_graph_type() @mm_graph_type || 'normal' end
108
+ def mm_show_missing() @mm_show_missing || false end
109
+ def mm_show_authors() @mm_show_authors || false end
110
+ def mm_selected_categories() @mm_selected_categories || [] end
111
+
112
+ # create a Mind Map graph and return the PNG and HTML map files generated
113
+ def create_mind_map(prog, missing, show_authors, show_leaves, selected_categories, mm_size)
114
+ dotFile = File.expand_path("#{WikiService.storage_path}/graph.dot")
115
+ mapFile = File.expand_path("#{WikiService.storage_path}/graph.map")
116
+ pngFile = File.expand_path("#{WikiService.storage_path}/map.png")
117
+
118
+ File.open(dotFile, "w") do |file|
119
+
120
+ # Graph properties:
121
+ output_graph_header_to file, mm_size
122
+
123
+ # Links and node properties:
124
+ nodes = filter_categories(pages.values, selected_categories)
125
+ auths = authors # avoid repeated selects
126
+ unless show_authors
127
+ nodes.delete_if { |entry|
128
+ auths.include? entry.name
129
+ }
130
+ end
131
+ unless show_leaves
132
+ nodes.delete_if { |page|
133
+ (page.wiki_words - [missing].flatten).size == 0
134
+ }
135
+ end
136
+
137
+ # Page Special nodes properties:
138
+ file.puts %{"Home Page" [color=\"##{color}\",style=bold];} if nodes.map{ |p| p.name }.include? "HomePage"
139
+
140
+ nodes.each do |page|
141
+ file.puts %{"#{page.plain_name}" [URL=\"../show/#{page.name}\"];}
142
+ page.references.each do |referer|
143
+ unless page.name == referer.name or not nodes.include? referer
144
+ unless !show_authors and auths.include? referer.name
145
+ file.puts %{"#{referer.plain_name}" -> "#{page.plain_name}";}
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ # find missing pages:
152
+ if missing
153
+ shown_missing = []
154
+ nodes.each do |page|
155
+ missing.each do |wanted|
156
+ if page.content =~ /#{wanted}/
157
+ file.puts %{"#{page.plain_name}" -> "#{WikiWords.separate wanted}";}
158
+ shown_missing << wanted
159
+ end
160
+ end
161
+ end
162
+ shown_missing.each do |wanted|
163
+ file.puts %{"#{WikiWords.separate wanted}" [URL="/#{@address}/show/#{wanted}", fontsize=10,style=filled,color=grey];}
164
+ end
165
+ end
166
+
167
+ output_graph_footer_to file
168
+ end
169
+
170
+ call_graphviz(prog, dotFile, mapFile, pngFile)
171
+
172
+ [pngFile, mapFile]
173
+ end
174
+
175
+ def create_author_graph(prog, selected_categories, mm_size)
176
+ dotFile = File.expand_path("#{WikiService.storage_path}/graph.dot")
177
+ mapFile = File.expand_path("#{WikiService.storage_path}/graph.map")
178
+ pngFile = File.expand_path("#{WikiService.storage_path}/map.png")
179
+
180
+ File.open(dotFile, "w") do |file|
181
+
182
+ # Graph properties:
183
+ output_graph_header_to file, mm_size
184
+
185
+ # Links and node properties:
186
+ auths = authors # avoid repeated selects
187
+ auths.each do |auth|
188
+ file.puts %{"#{auth}" [style=filled,color=grey,URL="../show/#{auth}"];}
189
+ end
190
+
191
+ nodes = pages.values.reject { |entry| auths.include? entry.name }
192
+ nodes = filter_categories(nodes, selected_categories)
193
+ nodes.each do |page|
194
+ file.puts %{"#{page.plain_name}" [URL="../show/#{page.name}"];}
195
+ page.authors.each do |auth|
196
+ file.puts %{"#{auth}" -> "#{page.plain_name}";}
197
+ end
198
+ end
199
+
200
+ output_graph_footer_to file
201
+ end
202
+
203
+ call_graphviz(prog, dotFile, mapFile, pngFile)
204
+
205
+ [pngFile, mapFile]
206
+ end
207
+
208
+ def create_category_graph(prog, show_authors, selected_categories, mm_size) #{{{
209
+ dotFile = File.expand_path("#{WikiService.storage_path}/graph.dot")
210
+ mapFile = File.expand_path("#{WikiService.storage_path}/graph.map")
211
+ pngFile = File.expand_path("#{WikiService.storage_path}/map.png")
212
+
213
+ File.open(dotFile, "w") do |file|
214
+ # Graph properties:
215
+ output_graph_header_to file, mm_size
216
+
217
+ # Page Special nodes properties:
218
+ categs = selected_categories.empty? ? categories : selected_categories
219
+ categs.each do |category|
220
+ file.puts %{"#{category}" [fontsize=20,style=filled,color=grey,comment="#{category}",URL="../list/?category=#{category}"];}
221
+ end
222
+
223
+ # Links and node properties:
224
+ nodes = filter_categories(pages.values, selected_categories)
225
+ auths = authors # avoid repeated selects
226
+ unless show_authors
227
+ nodes.delete_if { |entry|
228
+ auths.include? entry.name
229
+ }
230
+ end
231
+ nodes.each do |page|
232
+ file.puts %{"#{page.plain_name}" [URL=\"../show/#{page.name}\"];}
233
+ page.categories.each do |category|
234
+ file.puts %{"#{category}" -> "#{page.plain_name}";}
235
+ end
236
+ end
237
+
238
+ output_graph_footer_to file
239
+ end
240
+
241
+ call_graphviz(prog, dotFile, mapFile, pngFile)
242
+
243
+ [pngFile, mapFile]
244
+ end #}}}
245
+
246
+ def output_graph_header_to file, mm_size
247
+ file.puts "digraph G {"
248
+ file.puts "size=\"#{mm_size}\";" if mm_size
249
+ file.puts 'ratio=fill;'
250
+ file.puts 'concentrate=true;'
251
+ file.puts 'node [fontsize=10,fontname="Tahoma"];'
252
+ file.puts 'edge [len=1.5];'
253
+ end
254
+
255
+ def output_graph_footer_to file
256
+ file.puts "}"
257
+ end
258
+
259
+ def filter_categories(pages, selected_categories) #{{{
260
+ nodes = pages
261
+ unless selected_categories.empty?
262
+ nodes = pages.reject { |page| (page.categories & selected_categories).empty? }
263
+ if selected_categories.include? 'none'
264
+ nodes += pages.select { |page| page.categories.empty? }
265
+ end
266
+ end
267
+ nodes
268
+ end #}}}
269
+
270
+ def call_graphviz(prog, dotFile, mapFile, pngFile)
271
+ system("#{prog} -Tcmap \"#{dotFile}\" -o \"#{mapFile}\"")
272
+ system("#{prog} -Tpng \"#{dotFile}\" -o \"#{pngFile}\"")
273
+ end
274
+
275
+ ## Bliki methods
276
+
277
+ def add_bliki_entry(page)
278
+ bliki[page.name] = page
279
+ end
280
+
281
+ def bliki_entries_by_date
282
+ bliki.values.sort_by { |page| page.revisions.first.created_at }.reverse
283
+ end
284
+
285
+ def bliki_entries_by_name
286
+ pages.values.sort_by { |page| [page.name] }
287
+ end
288
+
289
+ def bliki_entries_that_match(regexp)
290
+ bliki.values.select { |page| page.content =~ /#{regexp}/i }
291
+ end
292
+
293
+ def bliki_entries_that_reference(page_name)
294
+ bliki.values.select { |page| page.wiki_words.include?(page_name) }
295
+ end
296
+
297
+ def bliki_entries_authored_by(author)
298
+ bliki.values.select { |page| page.authors.include?(author) }
299
+ end
300
+
301
+ ## End bliki methods
302
+
303
+ private
304
+ # Returns an array of all the wiki words in any current revision
305
+ def wiki_words
306
+ pages.values.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
307
+ end
308
+
309
+ # Returns an array of all the page names on this web
310
+ def page_names
311
+ pages.keys
312
+ end
313
+ end
314
+
317
315
  # jEdit :folding=indent:collapseFolds=1: