instiki 0.10.0 → 0.10.1

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.
Files changed (88) hide show
  1. data/CHANGELOG +174 -165
  2. data/README +68 -68
  3. data/app/controllers/admin_controller.rb +94 -94
  4. data/app/controllers/application.rb +135 -131
  5. data/app/controllers/file_controller.rb +129 -129
  6. data/app/controllers/wiki_controller.rb +354 -354
  7. data/app/helpers/application_helper.rb +68 -68
  8. data/app/models/author.rb +3 -3
  9. data/app/models/chunks/category.rb +33 -33
  10. data/app/models/chunks/chunk.rb +86 -86
  11. data/app/models/chunks/engines.rb +61 -54
  12. data/app/models/chunks/include.rb +41 -41
  13. data/app/models/chunks/literal.rb +31 -31
  14. data/app/models/chunks/nowiki.rb +28 -28
  15. data/app/models/chunks/test.rb +18 -18
  16. data/app/models/chunks/uri.rb +182 -182
  17. data/app/models/chunks/wiki.rb +141 -141
  18. data/app/models/file_yard.rb +58 -58
  19. data/app/models/page.rb +112 -112
  20. data/app/models/page_lock.rb +22 -22
  21. data/app/models/page_set.rb +89 -89
  22. data/app/models/revision.rb +123 -123
  23. data/app/models/web.rb +182 -176
  24. data/app/models/wiki_content.rb +207 -207
  25. data/app/models/wiki_service.rb +233 -233
  26. data/app/models/wiki_words.rb +23 -23
  27. data/app/views/admin/create_system.rhtml +83 -83
  28. data/app/views/admin/create_web.rhtml +69 -69
  29. data/app/views/admin/edit_web.rhtml +137 -136
  30. data/app/views/file/file.rhtml +18 -18
  31. data/app/views/file/import.rhtml +22 -22
  32. data/app/views/layouts/default.rhtml +86 -85
  33. data/app/views/markdown_help.rhtml +12 -12
  34. data/app/views/mixed_help.rhtml +6 -6
  35. data/app/views/navigation.rhtml +30 -30
  36. data/app/views/rdoc_help.rhtml +12 -12
  37. data/app/views/textile_help.rhtml +24 -24
  38. data/app/views/wiki/authors.rhtml +11 -11
  39. data/app/views/wiki/edit.rhtml +39 -39
  40. data/app/views/wiki/export.rhtml +12 -12
  41. data/app/views/wiki/feeds.rhtml +14 -14
  42. data/app/views/wiki/list.rhtml +64 -64
  43. data/app/views/wiki/locked.rhtml +23 -23
  44. data/app/views/wiki/login.rhtml +14 -14
  45. data/app/views/wiki/new.rhtml +31 -31
  46. data/app/views/wiki/page.rhtml +115 -115
  47. data/app/views/wiki/print.rhtml +14 -14
  48. data/app/views/wiki/published.rhtml +9 -9
  49. data/app/views/wiki/recently_revised.rhtml +26 -26
  50. data/app/views/wiki/revision.rhtml +103 -103
  51. data/app/views/wiki/rollback.rhtml +36 -36
  52. data/app/views/wiki/rss_feed.rhtml +22 -22
  53. data/app/views/wiki/search.rhtml +38 -38
  54. data/app/views/wiki/tex.rhtml +22 -22
  55. data/app/views/wiki/tex_web.rhtml +34 -34
  56. data/app/views/wiki/web_list.rhtml +18 -18
  57. data/app/views/wiki_words_help.rhtml +9 -9
  58. data/config/environment.rb +82 -82
  59. data/config/environments/development.rb +5 -5
  60. data/config/environments/production.rb +4 -4
  61. data/config/environments/test.rb +17 -17
  62. data/config/routes.rb +18 -18
  63. data/lib/active_record_stub.rb +31 -31
  64. data/lib/bluecloth_tweaked.rb +1127 -0
  65. data/lib/diff.rb +444 -444
  66. data/lib/instiki_errors.rb +14 -14
  67. data/lib/rdocsupport.rb +151 -151
  68. data/lib/redcloth_for_tex.rb +736 -736
  69. data/natives/osx/desktop_launcher/AppDelegate.h +18 -18
  70. data/natives/osx/desktop_launcher/AppDelegate.mm +109 -109
  71. data/natives/osx/desktop_launcher/Credits.html +15 -15
  72. data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/classes.nib +12 -12
  73. data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/info.nib +24 -24
  74. data/natives/osx/desktop_launcher/Info.plist +12 -12
  75. data/natives/osx/desktop_launcher/Instiki.xcode/project.pbxproj +592 -592
  76. data/natives/osx/desktop_launcher/Instiki_Prefix.pch +7 -7
  77. data/natives/osx/desktop_launcher/MakeDMG.sh +9 -9
  78. data/natives/osx/desktop_launcher/main.mm +14 -14
  79. data/natives/osx/desktop_launcher/version.plist +16 -16
  80. data/public/404.html +5 -5
  81. data/public/500.html +5 -5
  82. data/public/dispatch.rb +9 -9
  83. data/public/javascripts/edit_web.js +52 -52
  84. data/public/javascripts/prototype.js +336 -336
  85. data/public/stylesheets/instiki.css +222 -222
  86. data/script/breakpointer +4 -4
  87. data/script/server +93 -93
  88. metadata +4 -3
@@ -1,68 +1,68 @@
1
- # The methods added to this helper will be available to all templates in the application.
2
- module ApplicationHelper
3
-
4
- # Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container
5
- # where the elements respond to first and last (such as a two-element array), the "lasts" serve as option values and
6
- # the "firsts" as option text. Hashes are turned into this form automatically, so the keys become "firsts" and values
7
- # become lasts. If +selected+ is specified, the matching "last" or element will get the selected option-tag.
8
- #
9
- # Examples (call, result):
10
- # html_options([["Dollar", "$"], ["Kroner", "DKK"]])
11
- # <option value="$">Dollar</option>\n<option value="DKK">Kroner</option>
12
- #
13
- # html_options([ "VISA", "Mastercard" ], "Mastercard")
14
- # <option>VISA</option>\n<option selected>Mastercard</option>
15
- #
16
- # html_options({ "Basic" => "$20", "Plus" => "$40" }, "$40")
17
- # <option value="$20">Basic</option>\n<option value="$40" selected>Plus</option>
18
- def html_options(container, selected = nil)
19
- container = container.to_a if Hash === container
20
-
21
- html_options = container.inject([]) do |options, element|
22
- if element.respond_to?(:first) && element.respond_to?(:last)
23
- if element.last != selected
24
- options << "<option value=\"#{element.last}\">#{element.first}</option>"
25
- else
26
- options << "<option value=\"#{element.last}\" selected>#{element.first}</option>"
27
- end
28
- else
29
- options << ((element != selected) ? "<option>#{element}</option>" : "<option selected>#{element}</option>")
30
- end
31
- end
32
-
33
- html_options.join("\n")
34
- end
35
-
36
- # Creates a hyperlink to a Wiki page, without checking if the page exists or not
37
- def link_to_existing_page(page, text = nil, html_options = {})
38
- link_to(
39
- text || page.name,
40
- {:web => @web.address, :action => 'show', :id => page.name, :only_path => true},
41
- html_options)
42
- end
43
-
44
-
45
- # Creates a hyperlink to a Wiki page, or to a "new page" form if the page doesn't exist yet
46
- def link_to_page(page_name, web = @web, text = nil, options = {})
47
- raise 'Web not defined' if web.nil?
48
- home_page_url = url_for :web => web.address, :action => 'show', :id => 'HomePage', :only_path => true
49
- base_url = home_page_url.sub(%r-/show/HomePage/?$-, '')
50
- web.make_link(page_name, text, options.merge(:base_url => base_url))
51
- end
52
-
53
- # Creates a menu of categories
54
- def categories_menu
55
- if @categories.empty?
56
- ''
57
- else
58
- "<div id=\"categories\">\n" +
59
- '<strong>Categories</strong>:' +
60
- '[' + link_to_unless_current('Any', :web => @web.address, :action => @action_name) + "]\n" +
61
- @categories.map { |c|
62
- link_to_unless_current(c, :web => @web.address, :action => @action_name, :category => c)
63
- }.join(', ') + "\n" +
64
- '</div>'
65
- end
66
- end
67
-
68
- end
1
+ # The methods added to this helper will be available to all templates in the application.
2
+ module ApplicationHelper
3
+
4
+ # Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container
5
+ # where the elements respond to first and last (such as a two-element array), the "lasts" serve as option values and
6
+ # the "firsts" as option text. Hashes are turned into this form automatically, so the keys become "firsts" and values
7
+ # become lasts. If +selected+ is specified, the matching "last" or element will get the selected option-tag.
8
+ #
9
+ # Examples (call, result):
10
+ # html_options([["Dollar", "$"], ["Kroner", "DKK"]])
11
+ # <option value="$">Dollar</option>\n<option value="DKK">Kroner</option>
12
+ #
13
+ # html_options([ "VISA", "Mastercard" ], "Mastercard")
14
+ # <option>VISA</option>\n<option selected>Mastercard</option>
15
+ #
16
+ # html_options({ "Basic" => "$20", "Plus" => "$40" }, "$40")
17
+ # <option value="$20">Basic</option>\n<option value="$40" selected>Plus</option>
18
+ def html_options(container, selected = nil)
19
+ container = container.to_a if Hash === container
20
+
21
+ html_options = container.inject([]) do |options, element|
22
+ if element.respond_to?(:first) && element.respond_to?(:last)
23
+ if element.last != selected
24
+ options << "<option value=\"#{element.last}\">#{element.first}</option>"
25
+ else
26
+ options << "<option value=\"#{element.last}\" selected>#{element.first}</option>"
27
+ end
28
+ else
29
+ options << ((element != selected) ? "<option>#{element}</option>" : "<option selected>#{element}</option>")
30
+ end
31
+ end
32
+
33
+ html_options.join("\n")
34
+ end
35
+
36
+ # Creates a hyperlink to a Wiki page, without checking if the page exists or not
37
+ def link_to_existing_page(page, text = nil, html_options = {})
38
+ link_to(
39
+ text || page.name,
40
+ {:web => @web.address, :action => 'show', :id => page.name, :only_path => true},
41
+ html_options)
42
+ end
43
+
44
+
45
+ # Creates a hyperlink to a Wiki page, or to a "new page" form if the page doesn't exist yet
46
+ def link_to_page(page_name, web = @web, text = nil, options = {})
47
+ raise 'Web not defined' if web.nil?
48
+ home_page_url = url_for :web => web.address, :action => 'show', :id => 'HomePage', :only_path => true
49
+ base_url = home_page_url.sub(%r-/show/HomePage/?$-, '')
50
+ web.make_link(page_name, text, options.merge(:base_url => base_url))
51
+ end
52
+
53
+ # Creates a menu of categories
54
+ def categories_menu
55
+ if @categories.empty?
56
+ ''
57
+ else
58
+ "<div id=\"categories\">\n" +
59
+ '<strong>Categories</strong>:' +
60
+ '[' + link_to_unless_current('Any', :web => @web.address, :action => @action_name) + "]\n" +
61
+ @categories.map { |c|
62
+ link_to_unless_current(c, :web => @web.address, :action => @action_name, :category => c)
63
+ }.join(', ') + "\n" +
64
+ '</div>'
65
+ end
66
+ end
67
+
68
+ end
data/app/models/author.rb CHANGED
@@ -1,4 +1,4 @@
1
- class Author < String
2
- attr_accessor :ip
3
- def initialize(name, ip) @ip = ip; super(name) end
1
+ class Author < String
2
+ attr_accessor :ip
3
+ def initialize(name, ip) @ip = ip; super(name) end
4
4
  end
@@ -1,33 +1,33 @@
1
- require 'chunks/chunk'
2
-
3
- # The category chunk looks for "category: news" on a line by
4
- # itself and parses the terms after the ':' as categories.
5
- # Other classes can search for Category chunks within
6
- # rendered content to find out what categories this page
7
- # should be in.
8
- #
9
- # Category lines can be hidden using ':category: news', for example
10
- class Category < Chunk::Abstract
11
- CATEGORY_PATTERN = /^(:)?category\s*:(.*)$/i
12
- def self.pattern() CATEGORY_PATTERN end
13
-
14
- attr_reader :hidden, :list
15
-
16
- def initialize(match_data, content)
17
- super(match_data, content)
18
- @hidden = match_data[1]
19
- @list = match_data[2].split(',').map { |c| c.strip }
20
- @unmask_text = ''
21
- if @hidden
22
- @unmask_text = ''
23
- else
24
- category_urls = @list.map { |category| url(category) }.join(', ')
25
- @unmask_text = '<div class="property"> category: ' + category_urls + '</div>'
26
- end
27
- end
28
-
29
- # TODO move presentation of page metadata to controller/view
30
- def url(category)
31
- %{<a class="category_link" href="../list/?category=#{category}">#{category}</a>}
32
- end
33
- end
1
+ require 'chunks/chunk'
2
+
3
+ # The category chunk looks for "category: news" on a line by
4
+ # itself and parses the terms after the ':' as categories.
5
+ # Other classes can search for Category chunks within
6
+ # rendered content to find out what categories this page
7
+ # should be in.
8
+ #
9
+ # Category lines can be hidden using ':category: news', for example
10
+ class Category < Chunk::Abstract
11
+ CATEGORY_PATTERN = /^(:)?category\s*:(.*)$/i
12
+ def self.pattern() CATEGORY_PATTERN end
13
+
14
+ attr_reader :hidden, :list
15
+
16
+ def initialize(match_data, content)
17
+ super(match_data, content)
18
+ @hidden = match_data[1]
19
+ @list = match_data[2].split(',').map { |c| c.strip }
20
+ @unmask_text = ''
21
+ if @hidden
22
+ @unmask_text = ''
23
+ else
24
+ category_urls = @list.map { |category| url(category) }.join(', ')
25
+ @unmask_text = '<div class="property"> category: ' + category_urls + '</div>'
26
+ end
27
+ end
28
+
29
+ # TODO move presentation of page metadata to controller/view
30
+ def url(category)
31
+ %{<a class="category_link" href="../list/?category=#{category}">#{category}</a>}
32
+ end
33
+ end
@@ -1,86 +1,86 @@
1
- require 'uri/common'
2
-
3
- # A chunk is a pattern of text that can be protected
4
- # and interrogated by a renderer. Each Chunk class has a
5
- # +pattern+ that states what sort of text it matches.
6
- # Chunks are initalized by passing in the result of a
7
- # match by its pattern.
8
-
9
- module Chunk
10
- class Abstract
11
-
12
- # automatically construct the array of derivatives of Chunk::Abstract
13
- @derivatives = []
14
-
15
- class << self
16
- attr_reader :derivatives
17
- end
18
-
19
- def self::inherited( klass )
20
- Abstract::derivatives << klass
21
- end
22
-
23
- # the class name part of the mask strings
24
- def self.mask_string
25
- self.to_s.delete(':').downcase
26
- end
27
-
28
- # a regexp that matches all chunk_types masks
29
- def Abstract::mask_re(chunk_types)
30
- tmp = chunk_types.map{|klass| klass.mask_string}.join("|")
31
- Regexp.new("chunk([0-9a-f]+n\\d+)(#{tmp})chunk")
32
- end
33
-
34
- attr_reader :text, :unmask_text, :unmask_mode
35
-
36
- def initialize(match_data, content)
37
- @text = match_data[0]
38
- @content = content
39
- @unmask_mode = :normal
40
- end
41
-
42
- # Find all the chunks of the given type in content
43
- # Each time the pattern is matched, create a new
44
- # chunk for it, and replace the occurance of the chunk
45
- # in this content with its mask.
46
- def self.apply_to(content)
47
- content.gsub!( self.pattern ) do |match|
48
- new_chunk = self.new($~, content)
49
- content.add_chunk(new_chunk)
50
- new_chunk.mask
51
- end
52
- end
53
-
54
- # should contain only [a-z0-9]
55
- def mask
56
- @mask ||="chunk#{@id}#{self.class.mask_string}chunk"
57
- end
58
-
59
- # We should not use object_id because object_id is not guarantied
60
- # to be unique when we restart the wiki (new object ids can equal old ones
61
- # that were restored form madeleine storage)
62
- def id
63
- @id ||= "#{@content.page_id}n#{@content.chunk_id}"
64
- end
65
-
66
- def unmask
67
- @content.sub!(mask, @unmask_text)
68
- end
69
-
70
- def rendered?
71
- @unmask_mode == :normal
72
- end
73
-
74
- def escaped?
75
- @unmask_mode == :escape
76
- end
77
-
78
- def revert
79
- @content.sub!(mask, @text)
80
- # unregister
81
- @content.delete_chunk(self)
82
- end
83
-
84
- end
85
-
86
- end
1
+ require 'uri/common'
2
+
3
+ # A chunk is a pattern of text that can be protected
4
+ # and interrogated by a renderer. Each Chunk class has a
5
+ # +pattern+ that states what sort of text it matches.
6
+ # Chunks are initalized by passing in the result of a
7
+ # match by its pattern.
8
+
9
+ module Chunk
10
+ class Abstract
11
+
12
+ # automatically construct the array of derivatives of Chunk::Abstract
13
+ @derivatives = []
14
+
15
+ class << self
16
+ attr_reader :derivatives
17
+ end
18
+
19
+ def self::inherited( klass )
20
+ Abstract::derivatives << klass
21
+ end
22
+
23
+ # the class name part of the mask strings
24
+ def self.mask_string
25
+ self.to_s.delete(':').downcase
26
+ end
27
+
28
+ # a regexp that matches all chunk_types masks
29
+ def Abstract::mask_re(chunk_types)
30
+ tmp = chunk_types.map{|klass| klass.mask_string}.join("|")
31
+ Regexp.new("chunk([0-9a-f]+n\\d+)(#{tmp})chunk")
32
+ end
33
+
34
+ attr_reader :text, :unmask_text, :unmask_mode
35
+
36
+ def initialize(match_data, content)
37
+ @text = match_data[0]
38
+ @content = content
39
+ @unmask_mode = :normal
40
+ end
41
+
42
+ # Find all the chunks of the given type in content
43
+ # Each time the pattern is matched, create a new
44
+ # chunk for it, and replace the occurance of the chunk
45
+ # in this content with its mask.
46
+ def self.apply_to(content)
47
+ content.gsub!( self.pattern ) do |match|
48
+ new_chunk = self.new($~, content)
49
+ content.add_chunk(new_chunk)
50
+ new_chunk.mask
51
+ end
52
+ end
53
+
54
+ # should contain only [a-z0-9]
55
+ def mask
56
+ @mask ||="chunk#{@id}#{self.class.mask_string}chunk"
57
+ end
58
+
59
+ # We should not use object_id because object_id is not guarantied
60
+ # to be unique when we restart the wiki (new object ids can equal old ones
61
+ # that were restored form madeleine storage)
62
+ def id
63
+ @id ||= "#{@content.page_id}n#{@content.chunk_id}"
64
+ end
65
+
66
+ def unmask
67
+ @content.sub!(mask, @unmask_text)
68
+ end
69
+
70
+ def rendered?
71
+ @unmask_mode == :normal
72
+ end
73
+
74
+ def escaped?
75
+ @unmask_mode == :escape
76
+ end
77
+
78
+ def revert
79
+ @content.sub!(mask, @text)
80
+ # unregister
81
+ @content.delete_chunk(self)
82
+ end
83
+
84
+ end
85
+
86
+ end
@@ -1,54 +1,61 @@
1
- $: << File.dirname(__FILE__) + "../../lib"
2
-
3
- require 'redcloth'
4
- require 'rdocsupport'
5
- require 'chunks/chunk'
6
-
7
- # The markup engines are Chunks that call the one of RedCloth
8
- # or RDoc to convert text. This markup occurs when the chunk is required
9
- # to mask itself.
10
- module Engines
11
- class AbstractEngine < Chunk::Abstract
12
-
13
- # Create a new chunk for the whole content and replace it with its mask.
14
- def self.apply_to(content)
15
- new_chunk = self.new(content)
16
- content.replace(new_chunk.mask)
17
- end
18
-
19
- private
20
-
21
- # Never create engines by constructor - use apply_to instead
22
- def initialize(content)
23
- @content = content
24
- end
25
-
26
- end
27
-
28
- class Textile < AbstractEngine
29
- def mask
30
- RedCloth.new(@content, @content.options[:engine_opts]).to_html(:textile)
31
- end
32
- end
33
-
34
- class Markdown < AbstractEngine
35
- def mask
36
- RedCloth.new(@content, @content.options[:engine_opts]).to_html(:markdown)
37
- end
38
- end
39
-
40
- class Mixed < AbstractEngine
41
- def mask
42
- RedCloth.new(@content, @content.options[:engine_opts]).to_html
43
- end
44
- end
45
-
46
- class RDoc < AbstractEngine
47
- def mask
48
- RDocSupport::RDocFormatter.new(@content).to_html
49
- end
50
- end
51
-
52
- MAP = { :textile => Textile, :markdown => Markdown, :mixed => Mixed, :rdoc => RDoc, }
53
- MAP.default = Textile
54
- end
1
+ $: << File.dirname(__FILE__) + "../../lib"
2
+
3
+ require 'redcloth'
4
+ require 'bluecloth_tweaked'
5
+ require 'rdocsupport'
6
+ require 'chunks/chunk'
7
+
8
+ # The markup engines are Chunks that call the one of RedCloth
9
+ # or RDoc to convert text. This markup occurs when the chunk is required
10
+ # to mask itself.
11
+ module Engines
12
+ class AbstractEngine < Chunk::Abstract
13
+
14
+ # Create a new chunk for the whole content and replace it with its mask.
15
+ def self.apply_to(content)
16
+ new_chunk = self.new(content)
17
+ content.replace(new_chunk.mask)
18
+ end
19
+
20
+ private
21
+
22
+ # Never create engines by constructor - use apply_to instead
23
+ def initialize(content)
24
+ @content = content
25
+ end
26
+
27
+ end
28
+
29
+ class Textile < AbstractEngine
30
+ def mask
31
+ redcloth = RedCloth.new(@content, [:hard_breaks] + @content.options[:engine_opts])
32
+ redcloth.filter_html = false
33
+ redcloth.no_span_caps = false
34
+ redcloth.to_html(:textile)
35
+ end
36
+ end
37
+
38
+ class Markdown < AbstractEngine
39
+ def mask
40
+ BlueCloth.new(@content, @content.options[:engine_opts]).to_html
41
+ end
42
+ end
43
+
44
+ class Mixed < AbstractEngine
45
+ def mask
46
+ redcloth = RedCloth.new(@content, @content.options[:engine_opts])
47
+ redcloth.filter_html = false
48
+ redcloth.no_span_caps = false
49
+ redcloth.to_html
50
+ end
51
+ end
52
+
53
+ class RDoc < AbstractEngine
54
+ def mask
55
+ RDocSupport::RDocFormatter.new(@content).to_html
56
+ end
57
+ end
58
+
59
+ MAP = { :textile => Textile, :markdown => Markdown, :mixed => Mixed, :rdoc => RDoc }
60
+ MAP.default = Textile
61
+ end