instiki 0.9.2 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. data/CHANGELOG +165 -0
  2. data/README +68 -172
  3. data/app/controllers/admin_controller.rb +94 -0
  4. data/app/controllers/application.rb +131 -0
  5. data/app/controllers/file_controller.rb +129 -0
  6. data/app/controllers/wiki_controller.rb +354 -0
  7. data/{libraries/view_helper.rb → app/helpers/application_helper.rb} +68 -33
  8. data/app/models/author.rb +3 -3
  9. data/app/models/chunks/category.rb +33 -31
  10. data/app/models/chunks/chunk.rb +86 -20
  11. data/app/models/chunks/engines.rb +54 -38
  12. data/app/models/chunks/include.rb +41 -29
  13. data/app/models/chunks/literal.rb +31 -19
  14. data/app/models/chunks/nowiki.rb +28 -31
  15. data/app/models/chunks/test.rb +18 -18
  16. data/app/models/chunks/uri.rb +182 -97
  17. data/app/models/chunks/wiki.rb +141 -82
  18. data/app/models/file_yard.rb +58 -0
  19. data/app/models/page.rb +112 -86
  20. data/app/models/page_lock.rb +22 -23
  21. data/app/models/page_set.rb +89 -64
  22. data/app/models/revision.rb +123 -90
  23. data/app/models/web.rb +176 -89
  24. data/app/models/wiki_content.rb +207 -105
  25. data/app/models/wiki_service.rb +233 -83
  26. data/app/models/wiki_words.rb +23 -25
  27. data/app/views/{wiki/new_system.rhtml → admin/create_system.rhtml} +83 -78
  28. data/app/views/{wiki/new_web.rhtml → admin/create_web.rhtml} +69 -64
  29. data/app/views/admin/edit_web.rhtml +136 -0
  30. data/app/views/file/file.rhtml +19 -0
  31. data/app/views/file/import.rhtml +23 -0
  32. data/app/views/layouts/default.rhtml +85 -0
  33. data/app/views/markdown_help.rhtml +12 -16
  34. data/app/views/mixed_help.rhtml +7 -0
  35. data/app/views/navigation.rhtml +30 -19
  36. data/app/views/rdoc_help.rhtml +12 -16
  37. data/app/views/textile_help.rhtml +24 -28
  38. data/app/views/wiki/authors.rhtml +11 -13
  39. data/app/views/wiki/edit.rhtml +39 -31
  40. data/app/views/wiki/export.rhtml +12 -14
  41. data/app/views/wiki/feeds.rhtml +14 -10
  42. data/app/views/wiki/list.rhtml +64 -57
  43. data/app/views/wiki/locked.rhtml +23 -14
  44. data/app/views/wiki/login.rhtml +14 -11
  45. data/app/views/wiki/new.rhtml +31 -27
  46. data/app/views/wiki/page.rhtml +115 -81
  47. data/app/views/wiki/print.rhtml +14 -16
  48. data/app/views/wiki/published.rhtml +9 -10
  49. data/app/views/wiki/recently_revised.rhtml +27 -30
  50. data/app/views/wiki/revision.rhtml +103 -81
  51. data/app/views/wiki/rollback.rhtml +14 -9
  52. data/app/views/wiki/rss_feed.rhtml +22 -22
  53. data/app/views/wiki/search.rhtml +38 -15
  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 -13
  57. data/app/views/wiki_words_help.rhtml +9 -8
  58. data/config/environment.rb +82 -0
  59. data/config/environments/development.rb +5 -0
  60. data/config/environments/production.rb +4 -0
  61. data/config/environments/test.rb +17 -0
  62. data/config/routes.rb +18 -0
  63. data/instiki +6 -67
  64. data/instiki.rb +3 -0
  65. data/lib/active_record_stub.rb +31 -0
  66. data/{libraries/diff → lib}/diff.rb +444 -475
  67. data/lib/instiki_errors.rb +15 -0
  68. data/{libraries → lib}/rdocsupport.rb +151 -155
  69. data/lib/redcloth_for_tex.rb +736 -0
  70. data/natives/osx/desktop_launcher/AppDelegate.h +18 -0
  71. data/natives/osx/desktop_launcher/AppDelegate.mm +109 -0
  72. data/natives/osx/desktop_launcher/Credits.html +16 -0
  73. data/natives/osx/desktop_launcher/English.lproj/InfoPlist.strings +0 -0
  74. data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/classes.nib +13 -0
  75. data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/info.nib +24 -0
  76. data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/objects.nib +0 -0
  77. data/natives/osx/desktop_launcher/Info.plist +13 -0
  78. data/natives/osx/desktop_launcher/Instiki.xcode/project.pbxproj +592 -0
  79. data/natives/osx/desktop_launcher/Instiki_Prefix.pch +7 -0
  80. data/natives/osx/desktop_launcher/MakeDMG.sh +9 -0
  81. data/natives/osx/desktop_launcher/main.mm +14 -0
  82. data/natives/osx/desktop_launcher/version.plist +16 -0
  83. data/public/404.html +6 -0
  84. data/public/500.html +6 -0
  85. data/public/dispatch.rb +10 -0
  86. data/public/favicon.ico +0 -0
  87. data/public/javascripts/edit_web.js +52 -0
  88. data/public/javascripts/prototype.js +336 -0
  89. data/{app/views/static_style_sheet.rhtml → public/stylesheets/instiki.css} +221 -198
  90. data/script/breakpointer +4 -0
  91. data/script/server +93 -0
  92. metadata +59 -32
  93. data/app/controllers/wiki.rb +0 -389
  94. data/app/models/chunks/match.rb +0 -19
  95. data/app/views/bottom.rhtml +0 -4
  96. data/app/views/top.rhtml +0 -49
  97. data/app/views/wiki/edit_web.rhtml +0 -138
  98. data/libraries/action_controller_servlet.rb +0 -177
  99. data/libraries/erb.rb +0 -490
  100. data/libraries/madeleine_service.rb +0 -68
  101. data/libraries/redcloth_for_tex.rb +0 -869
  102. data/libraries/web_controller_server.rb +0 -81
@@ -1,31 +1,28 @@
1
- require 'chunks/chunk'
2
-
3
- # This chunks allows certain parts of a wiki page to be hidden from the
4
- # rest of the rendering pipeline. It should be run at the beginning
5
- # of the pipeline in `wiki_content.rb`.
6
- #
7
- # An example use of this chunk is to markup double brackets or
8
- # auto URI links:
9
- # <nowiki>Here are [[double brackets]] and a URI: www.uri.org</nowiki>
10
- #
11
- # The contents of the chunks will not be processed by any other chunk
12
- # so the `www.uri.org` and the double brackets will appear verbatim.
13
- #
14
- # Author: Mark Reid <mark at threewordslong dot com>
15
- # Created: 8th June 2004
16
- class NoWiki < Chunk::Abstract
17
-
18
- def self.pattern() Regexp.new('<nowiki>(.*?)</nowiki>') end
19
-
20
- attr_reader :plain_text
21
-
22
- def initialize(match_data)
23
- super(match_data)
24
- @plain_text = match_data[1]
25
- end
26
-
27
- # The nowiki content is not unmasked. This means the chunk will be reverted
28
- # using the plain text.
29
- def unmask(content) nil end
30
- def revert(content) content.sub!( Regexp.new(mask(content)), plain_text ) end
31
- end
1
+ require 'chunks/chunk'
2
+
3
+ # This chunks allows certain parts of a wiki page to be hidden from the
4
+ # rest of the rendering pipeline. It should be run at the beginning
5
+ # of the pipeline in `wiki_content.rb`.
6
+ #
7
+ # An example use of this chunk is to markup double brackets or
8
+ # auto URI links:
9
+ # <nowiki>Here are [[double brackets]] and a URI: www.uri.org</nowiki>
10
+ #
11
+ # The contents of the chunks will not be processed by any other chunk
12
+ # so the `www.uri.org` and the double brackets will appear verbatim.
13
+ #
14
+ # Author: Mark Reid <mark at threewordslong dot com>
15
+ # Created: 8th June 2004
16
+ class NoWiki < Chunk::Abstract
17
+
18
+ NOWIKI_PATTERN = Regexp.new('<nowiki>(.*?)</nowiki>')
19
+ def self.pattern() NOWIKI_PATTERN end
20
+
21
+ attr_reader :plain_text
22
+
23
+ def initialize(match_data, content)
24
+ super
25
+ @plain_text = @unmask_text = match_data[1]
26
+ end
27
+
28
+ end
@@ -1,18 +1,18 @@
1
- require 'test/unit'
2
-
3
- class ChunkTest < Test::Unit::TestCase
4
-
5
- # Asserts a number of tests for the given type and text.
6
- def match(type, test_text, expected)
7
- pattern = type.pattern
8
- assert_match(pattern, test_text)
9
- pattern =~ test_text # Previous assertion guarantees match
10
- chunk = type.new($~)
11
-
12
- # Test if requested parts are correct.
13
- for method_sym, value in expected do
14
- assert_respond_to(chunk, method_sym)
15
- assert_equal(value, chunk.method(method_sym).call, "Checking value of '#{method_sym}'")
16
- end
17
- end
18
- end
1
+ require 'test/unit'
2
+
3
+ class ChunkTest < Test::Unit::TestCase
4
+
5
+ # Asserts a number of tests for the given type and text.
6
+ def match(type, test_text, expected)
7
+ pattern = type.pattern
8
+ assert_match(pattern, test_text)
9
+ pattern =~ test_text # Previous assertion guarantees match
10
+ chunk = type.new($~)
11
+
12
+ # Test if requested parts are correct.
13
+ for method_sym, value in expected do
14
+ assert_respond_to(chunk, method_sym)
15
+ assert_equal(value, chunk.method(method_sym).call, "Checking value of '#{method_sym}'")
16
+ end
17
+ end
18
+ end
@@ -1,97 +1,182 @@
1
- require 'chunks/chunk'
2
-
3
- # This wiki chunk matches arbitrary URIs, using patterns from the Ruby URI modules.
4
- # It parses out a variety of fields that could be used by renderers to format
5
- # the links in various ways (shortening domain names, hiding email addresses)
6
- # It matches email addresses and host.com.au domains without schemes (http://)
7
- # but adds these on as required.
8
- #
9
- # The heuristic used to match a URI is designed to err on the side of caution.
10
- # That is, it is more likely to not autolink a URI than it is to accidently
11
- # autolink something that is not a URI. The reason behind this is it is easier
12
- # to force a URI link by prefixing 'http://' to it than it is to escape and
13
- # incorrectly marked up non-URI.
14
- #
15
- # I'm using a part of the [ISO 3166-1 Standard][iso3166] for country name suffixes.
16
- # The generic names are from www.bnoack.com/data/countrycode2.html)
17
- # [iso3166]: http://geotags.com/iso3166/
18
- class URIChunk < Chunk::Abstract
19
- include URI::REGEXP::PATTERN
20
-
21
- GENERIC = '(?:aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org)'
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
-
24
- # These are needed otherwise HOST will match almost anything
25
- TLDS = "\\.(?:#{GENERIC}|#{COUNTRY})"
26
-
27
- # Redefine USERINFO so that it must have non-zero length
28
- USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})+"
29
-
30
- # Pattern of legal URI endings to stop interference with some Textile
31
- # markup. (Images: !URI!) and other punctuation eg, (http://wiki.com/)
32
- URI_ENDING = '[)!]'
33
-
34
- # The basic URI expression as a string
35
- URI_PATTERN =
36
- "(?:(#{SCHEME})://)?" + # Optional scheme:// (\1|\8)
37
- "(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2|\9)
38
- "(#{HOSTNAME}#{TLDS})" + # Mandatory host eg, HOST.com.au (\3|\10)
39
- "(?::(#{PORT}))?" + # Optional :port (\4|\11)
40
- "(#{ABS_PATH})?" + # Optional absolute path (\5|\12)
41
- "(?:\\?(#{QUERY}))?" + # Optional ?query (\6|\13)
42
- "(?:\\#(#{FRAGMENT}))?" # Optional #fragment (\7|\14)
43
-
44
- def self.pattern()
45
- # This pattern first tries to match the URI_PATTERN that ends with
46
- # punctuation that is a valid URI character (eg, ')', '!'). If
47
- # such a match occurs, there should be no backtracking (hence the ?> ).
48
- # If the string cannot match a URI ending with URI_ENDING, then a second
49
- # attempt is tried.
50
- Regexp.new("(?>#{URI_PATTERN}(?=#{URI_ENDING}))|#{URI_PATTERN}", Regexp::EXTENDED, 'N')
51
- end
52
-
53
- attr_reader :uri, :scheme, :user, :host, :port, :path, :query, :fragment, :link_text
54
-
55
- def initialize(match_data)
56
- super(match_data)
57
- # Since the URI_PATTERN is tried twice, there are two sets of
58
- # groups, one from \1 to \7 and the second from \8 to \14.
59
- # The fields are set by which ever group matches.
60
- @scheme = match_data[1] || match_data[8]
61
- @user = match_data[2] || match_data[9]
62
- @host = match_data[3] || match_data[10]
63
- @port = match_data[4] || match_data[11]
64
- @path = match_data[5] || match_data[12]
65
- @query = match_data[6] || match_data[13]
66
- @fragment = match_data[7] || match_data[14]
67
-
68
- # If there is no scheme, add an appropriate one, otherwise
69
- # set the URI to the matched text.
70
- @text_scheme = scheme
71
- @uri = (scheme ? match_data[0] : nil )
72
- @scheme = scheme || ( user ? 'mailto' : 'http' )
73
- @delimiter = ( scheme == 'mailto' ? ':' : '://' )
74
- @uri ||= scheme + @delimiter + match_data[0]
75
-
76
- # Build up the link text. Schemes are omitted unless explicitly given.
77
- @link_text = ''
78
- @link_text << "#{@scheme}#{@delimiter}" if @text_scheme
79
- @link_text << "#{@user}@" if @user
80
- @link_text << "#{@host}" if @host
81
- @link_text << ":#{@port}" if @port
82
- @link_text << "#{@path}" if @path
83
- @link_text << "?#{@query}" if @query
84
- end
85
-
86
- # If the text should be escaped then don't keep this chunk.
87
- # Otherwise only keep this chunk if it was substituted back into the
88
- # content.
89
- def unmask(content)
90
- return nil if escaped_text
91
- return self if content.sub!( Regexp.new(mask(content)), "<a href=\"#{uri}\">#{link_text}</a>" )
92
- end
93
-
94
- # If there is no hostname in the URI, do not render it
95
- # It's probably only contains the scheme, eg 'something:'
96
- def escaped_text() ( host.nil? ? @uri : nil ) end
97
- end
1
+ require 'chunks/chunk'
2
+
3
+ # This wiki chunk matches arbitrary URIs, using patterns from the Ruby URI modules.
4
+ # It parses out a variety of fields that could be used by renderers to format
5
+ # the links in various ways (shortening domain names, hiding email addresses)
6
+ # It matches email addresses and host.com.au domains without schemes (http://)
7
+ # but adds these on as required.
8
+ #
9
+ # The heuristic used to match a URI is designed to err on the side of caution.
10
+ # That is, it is more likely to not autolink a URI than it is to accidently
11
+ # autolink something that is not a URI. The reason behind this is it is easier
12
+ # to force a URI link by prefixing 'http://' to it than it is to escape and
13
+ # incorrectly marked up non-URI.
14
+ #
15
+ # I'm using a part of the [ISO 3166-1 Standard][iso3166] for country name suffixes.
16
+ # The generic names are from www.bnoack.com/data/countrycode2.html)
17
+ # [iso3166]: http://geotags.com/iso3166/
18
+
19
+ class URIChunk < Chunk::Abstract
20
+ include URI::REGEXP::PATTERN
21
+
22
+ # this condition is to get rid of pesky warnings in tests
23
+ unless defined? URIChunk::INTERNET_URI_REGEXP
24
+
25
+ GENERIC = 'aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org'
26
+
27
+ COUNTRY = 'ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|' +
28
+ 'bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cf|cd|cg|ch|ci|ck|cl|' +
29
+ 'cm|cn|co|cr|cs|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|fi|' +
30
+ 'fj|fk|fm|fo|fr|fx|ga|gb|gd|ge|gf|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|' +
31
+ 'hk|hm|hn|hr|ht|hu|id|ie|il|in|io|iq|ir|is|it|jm|jo|jp|ke|kg|kh|ki|km|kn|' +
32
+ 'kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|' +
33
+ 'mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nt|' +
34
+ 'nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|' +
35
+ 'sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|' +
36
+ 'tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|' +
37
+ 'ws|ye|yt|yu|za|zm|zr|zw'
38
+ # These are needed otherwise HOST will match almost anything
39
+ TLDS = "(?:#{GENERIC}|#{COUNTRY})"
40
+
41
+ # Redefine USERINFO so that it must have non-zero length
42
+ USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})+"
43
+
44
+ # unreserved_no_ending = alphanum | mark, but URI_ENDING [)!] excluded
45
+ UNRESERVED_NO_ENDING = "-_.~*'(#{ALNUM}"
46
+
47
+ # this ensures that query or fragment do not end with URI_ENDING
48
+ # and enable us to use a much simpler self.pattern Regexp
49
+
50
+ # uric_no_ending = reserved | unreserved_no_ending | escaped
51
+ URIC_NO_ENDING = "(?:[#{UNRESERVED_NO_ENDING}#{RESERVED}]|#{ESCAPED})"
52
+ # query = *uric
53
+ QUERY = "#{URIC_NO_ENDING}*"
54
+ # fragment = *uric
55
+ FRAGMENT = "#{URIC_NO_ENDING}*"
56
+
57
+ # DOMLABEL is defined in the ruby uri library, TLDS is defined above
58
+ INTERNET_HOSTNAME = "(?:#{DOMLABEL}\\.)+#{TLDS}"
59
+
60
+ # Correct a typo bug in ruby 1.8.x lib/uri/common.rb
61
+ PORT = '\\d*'
62
+
63
+ INTERNET_URI =
64
+ "(?:(#{SCHEME}):/{0,2})?" + # Optional scheme: (\1)
65
+ "(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2)
66
+ "(#{INTERNET_HOSTNAME})" + # Mandatory hostname (\3)
67
+ "(?::(#{PORT}))?" + # Optional :port (\4)
68
+ "(#{ABS_PATH})?" + # Optional absolute path (\5)
69
+ "(?:\\?(#{QUERY}))?" + # Optional ?query (\6)
70
+ "(?:\\#(#{FRAGMENT}))?" + # Optional #fragment (\7)
71
+ '(?=\.?(?:\s|\)|\z))' # ends only with optional dot + space or ")"
72
+ # or end of the string
73
+
74
+ SUSPICIOUS_PRECEDING_CHARACTER = '(!|\"\:|\"|\\\')?' # any of !, ":, ", '
75
+
76
+ INTERNET_URI_REGEXP =
77
+ Regexp.new(SUSPICIOUS_PRECEDING_CHARACTER + INTERNET_URI, Regexp::EXTENDED, 'N')
78
+
79
+ end
80
+
81
+ def URIChunk.pattern
82
+ INTERNET_URI_REGEXP
83
+ end
84
+
85
+ attr_reader :user, :host, :port, :path, :query, :fragment, :link_text
86
+
87
+ def self.apply_to(content)
88
+ content.gsub!( self.pattern ) do |matched_text|
89
+ chunk = self.new($~, content)
90
+ if chunk.avoid_autolinking?
91
+ # do not substitute nor register the chunk
92
+ matched_text
93
+ else
94
+ content.add_chunk(chunk)
95
+ chunk.mask
96
+ end
97
+ end
98
+ end
99
+
100
+ def initialize(match_data, content)
101
+ super
102
+ @link_text = match_data[0]
103
+ @suspicious_preceding_character = match_data[1]
104
+ @original_scheme, @user, @host, @port, @path, @query, @fragment = match_data[2..-1]
105
+ treat_trailing_character
106
+ @unmask_text = "<a href=\"#{uri}\">#{link_text}</a>"
107
+ end
108
+
109
+ def avoid_autolinking?
110
+ not @suspicious_preceding_character.nil?
111
+ end
112
+
113
+ def treat_trailing_character
114
+ # If the last character matched by URI pattern is in ! or ), this may be part of the markup,
115
+ # not a URL. We should handle it as such. It is possible to do it by a regexp, but
116
+ # much easier to do programmatically
117
+ last_char = @link_text[-1..-1]
118
+ if last_char == ')' or last_char == '!'
119
+ @trailing_punctuation = last_char
120
+ @link_text.chop!
121
+ [@original_scheme, @user, @host, @port, @path, @query, @fragment].compact.last.chop!
122
+ else
123
+ @trailing_punctuation = nil
124
+ end
125
+ end
126
+
127
+ def scheme
128
+ @original_scheme or (@user ? 'mailto' : 'http')
129
+ end
130
+
131
+ def scheme_delimiter
132
+ scheme == 'mailto' ? ':' : '://'
133
+ end
134
+
135
+ def user_delimiter
136
+ '@' unless @user.nil?
137
+ end
138
+
139
+ def port_delimiter
140
+ ':' unless @port.nil?
141
+ end
142
+
143
+ def query_delimiter
144
+ '?' unless @query.nil?
145
+ end
146
+
147
+ def uri
148
+ [scheme, scheme_delimiter, user, user_delimiter, host, port_delimiter, port, path,
149
+ query_delimiter, query].compact.join
150
+ end
151
+
152
+ end
153
+
154
+ # uri with mandatory scheme but less restrictive hostname, like
155
+ # http://localhost:2500/blah.html
156
+ class LocalURIChunk < URIChunk
157
+
158
+ unless defined? LocalURIChunk::LOCAL_URI_REGEXP
159
+ # hostname can be just a simple word like 'localhost'
160
+ ANY_HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?"
161
+
162
+ # The basic URI expression as a string
163
+ # Scheme and hostname are mandatory
164
+ LOCAL_URI =
165
+ "(?:(#{SCHEME})://)+" + # Mandatory scheme:// (\1)
166
+ "(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2)
167
+ "(#{ANY_HOSTNAME})" + # Mandatory hostname (\3)
168
+ "(?::(#{PORT}))?" + # Optional :port (\4)
169
+ "(#{ABS_PATH})?" + # Optional absolute path (\5)
170
+ "(?:\\?(#{QUERY}))?" + # Optional ?query (\6)
171
+ "(?:\\#(#{FRAGMENT}))?" + # Optional #fragment (\7)
172
+ '(?=\.?(?:\s|\)|\z))' # ends only with optional dot + space or ")"
173
+ # or end of the string
174
+
175
+ LOCAL_URI_REGEXP = Regexp.new(SUSPICIOUS_PRECEDING_CHARACTER + LOCAL_URI, Regexp::EXTENDED, 'N')
176
+ end
177
+
178
+ def LocalURIChunk.pattern
179
+ LOCAL_URI_REGEXP
180
+ end
181
+
182
+ end
@@ -1,82 +1,141 @@
1
- require 'wiki_words'
2
- require 'chunks/chunk'
3
- require 'cgi'
4
-
5
- # Contains all the methods for finding and replacing wiki related
6
- # links.
7
- module WikiChunk
8
- include Chunk
9
-
10
- # A wiki link is the top-level class for anything that refers to
11
- # another wiki page.
12
- class WikiLink < Chunk::Abstract
13
- # By default, no escaped text
14
- def escaped_text() nil end
15
-
16
- # Delimit the link text with markers to replace later unless
17
- # the word is escaped. In that case, just return the link text
18
- def mask(content) escaped_text || pre_mask + link_text + post_mask end
19
-
20
- def regexp() Regexp.new(pre_mask + '(.*)?' + post_mask) end
21
-
22
- def revert(content) content.sub!(regexp, text) end
23
-
24
- # Do not keep this chunk if it is escaped.
25
- # Otherwise, pass the link procedure a page_name and link_text and
26
- # get back a string of HTML to replace the mask with.
27
- def unmask(content)
28
- return nil if escaped_text
29
- return self if content.sub!(regexp) { |match| content.page_link(page_name, $1) }
30
- end
31
- end
32
-
33
- # This chunk matches a WikiWord. WikiWords can be escaped
34
- # by prepending a '\'. When this is the case, the +escaped_text+
35
- # method will return the WikiWord instead of the usual +nil+.
36
- # The +page_name+ method returns the matched WikiWord.
37
- class Word < WikiLink
38
- def self.pattern
39
- Regexp.new('(\\\\)?(' + WikiWords::WIKI_WORD_PATTERN + ')\b', 0, "utf-8")
40
- end
41
-
42
- attr_reader :page_name
43
-
44
- def initialize(match_data)
45
- super(match_data)
46
- @escape = match_data[1]
47
- @page_name = match_data[2]
48
- end
49
-
50
- def escaped_text() (@escape.nil? ? nil : page_name) end
51
- def link_text() WikiWords.separate(page_name) end
52
- end
53
-
54
- # This chunk handles [[bracketted wiki words]] and
55
- # [[AliasedWords|aliased wiki words]]. The first part of an
56
- # aliased wiki word must be a WikiWord. If the WikiWord
57
- # is aliased, the +link_text+ field will contain the
58
- # alias, otherwise +link_text+ will contain the entire
59
- # contents within the double brackets.
60
- #
61
- # NOTE: This chunk must be tested before WikiWord since
62
- # a WikiWords can be a substring of a WikiLink.
63
- class Link < WikiLink
64
- def self.pattern() /\[\[([^\]]+)\]\]/ end
65
- ALIASED_LINK_PATTERN= Regexp.new('^(.*)?\|(.*)$', 0, "utf-8")
66
-
67
- attr_reader :page_name, :link_text
68
-
69
- def initialize(match_data)
70
- super(match_data)
71
-
72
- # If the like is aliased, set the page name to the first bit
73
- # and the link text to the second, otherwise set both to the
74
- # contents of the double brackets.
75
- if match_data[1] =~ ALIASED_LINK_PATTERN
76
- @page_name, @link_text = $1, $2
77
- else
78
- @page_name, @link_text = match_data[1], match_data[1]
79
- end
80
- end
81
- end
82
- end
1
+ require 'wiki_words'
2
+ require 'chunks/chunk'
3
+ require 'chunks/wiki'
4
+ require 'cgi'
5
+
6
+ # Contains all the methods for finding and replacing wiki related links.
7
+ module WikiChunk
8
+ include Chunk
9
+
10
+ # A wiki reference is the top-level class for anything that refers to
11
+ # another wiki page.
12
+ class WikiReference < Chunk::Abstract
13
+
14
+ # Name of the referenced page
15
+ attr_reader :page_name
16
+
17
+ # the referenced page
18
+ def refpage
19
+ @content.web.pages[@page_name]
20
+ end
21
+
22
+ end
23
+
24
+ # A wiki link is the top-level class for links that refers to
25
+ # another wiki page.
26
+ class WikiLink < WikiReference
27
+
28
+ attr_reader :link_text, :link_type
29
+
30
+ def initialize(match_data, content)
31
+ super
32
+ @link_type = :show
33
+ end
34
+
35
+ def self.apply_to(content)
36
+ content.gsub!( self.pattern ) do |matched_text|
37
+ chunk = self.new($~, content)
38
+ if chunk.textile_url?
39
+ # do not substitute
40
+ matched_text
41
+ else
42
+ content.add_chunk(chunk)
43
+ chunk.mask
44
+ end
45
+ end
46
+ end
47
+
48
+ # the referenced page
49
+ def refpage
50
+ @content.web.pages[@page_name]
51
+ end
52
+
53
+ def textile_url?
54
+ not @textile_link_suffix.nil?
55
+ end
56
+
57
+ end
58
+
59
+ # This chunk matches a WikiWord. WikiWords can be escaped
60
+ # by prepending a '\'. When this is the case, the +escaped_text+
61
+ # method will return the WikiWord instead of the usual +nil+.
62
+ # The +page_name+ method returns the matched WikiWord.
63
+ class Word < WikiLink
64
+
65
+ attr_reader :escaped_text
66
+
67
+ unless defined? WIKI_WORD
68
+ WIKI_WORD = Regexp.new('(":)?(\\\\)?(' + WikiWords::WIKI_WORD_PATTERN + ')\b', 0, "utf-8")
69
+ end
70
+
71
+ def self.pattern
72
+ WIKI_WORD
73
+ end
74
+
75
+ def initialize(match_data, content)
76
+ super
77
+ @textile_link_suffix, @escape, @page_name = match_data[1..3]
78
+ if @escape
79
+ @unmask_mode = :escape
80
+ @escaped_text = @page_name
81
+ else
82
+ @escaped_text = nil
83
+ end
84
+ @link_text = WikiWords.separate(@page_name)
85
+ @unmask_text = (@escaped_text || @content.page_link(@page_name, @link_text, @link_type))
86
+ end
87
+
88
+ end
89
+
90
+ # This chunk handles [[bracketted wiki words]] and
91
+ # [[AliasedWords|aliased wiki words]]. The first part of an
92
+ # aliased wiki word must be a WikiWord. If the WikiWord
93
+ # is aliased, the +link_text+ field will contain the
94
+ # alias, otherwise +link_text+ will contain the entire
95
+ # contents within the double brackets.
96
+ #
97
+ # NOTE: This chunk must be tested before WikiWord since
98
+ # a WikiWords can be a substring of a WikiLink.
99
+ class Link < WikiLink
100
+
101
+ unless defined? WIKI_LINK
102
+ WIKI_LINK = /(":)?\[\[([^\]]+)\]\]/
103
+ LINK_TYPE_SEPARATION = Regexp.new('^(.+):((file)|(pic))$', 0, 'utf-8')
104
+ ALIAS_SEPARATION = Regexp.new('^(.+)\|(.+)$', 0, 'utf-8')
105
+ end
106
+
107
+ def self.pattern() WIKI_LINK end
108
+
109
+ def initialize(match_data, content)
110
+ super
111
+ @textile_link_suffix, @page_name = match_data[1..2]
112
+ @link_text = @page_name
113
+ separate_link_type
114
+ separate_alias
115
+ @unmask_text = @content.page_link(@page_name, @link_text, @link_type)
116
+ end
117
+
118
+ private
119
+
120
+ # if link wihin the brackets has a form of [[filename:file]] or [[filename:pic]],
121
+ # this means a link to a picture or a file
122
+ def separate_link_type
123
+ link_type_match = LINK_TYPE_SEPARATION.match(@page_name)
124
+ if link_type_match
125
+ @link_text = @page_name = link_type_match[1]
126
+ @link_type = link_type_match[2..3].compact[0].to_sym
127
+ end
128
+ end
129
+
130
+ # link text may be different from page name. this will look like [[actual page|link text]]
131
+ def separate_alias
132
+ alias_match = ALIAS_SEPARATION.match(@page_name)
133
+ if alias_match
134
+ @page_name, @link_text = alias_match[1..2]
135
+ end
136
+ # note that [[filename|link text:file]] is also supported
137
+ end
138
+
139
+ end
140
+
141
+ end