instiki 0.9.2 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +165 -0
- data/README +68 -172
- data/app/controllers/admin_controller.rb +94 -0
- data/app/controllers/application.rb +131 -0
- data/app/controllers/file_controller.rb +129 -0
- data/app/controllers/wiki_controller.rb +354 -0
- data/{libraries/view_helper.rb → app/helpers/application_helper.rb} +68 -33
- data/app/models/author.rb +3 -3
- data/app/models/chunks/category.rb +33 -31
- data/app/models/chunks/chunk.rb +86 -20
- data/app/models/chunks/engines.rb +54 -38
- data/app/models/chunks/include.rb +41 -29
- data/app/models/chunks/literal.rb +31 -19
- data/app/models/chunks/nowiki.rb +28 -31
- data/app/models/chunks/test.rb +18 -18
- data/app/models/chunks/uri.rb +182 -97
- data/app/models/chunks/wiki.rb +141 -82
- data/app/models/file_yard.rb +58 -0
- data/app/models/page.rb +112 -86
- data/app/models/page_lock.rb +22 -23
- data/app/models/page_set.rb +89 -64
- data/app/models/revision.rb +123 -90
- data/app/models/web.rb +176 -89
- data/app/models/wiki_content.rb +207 -105
- data/app/models/wiki_service.rb +233 -83
- data/app/models/wiki_words.rb +23 -25
- data/app/views/{wiki/new_system.rhtml → admin/create_system.rhtml} +83 -78
- data/app/views/{wiki/new_web.rhtml → admin/create_web.rhtml} +69 -64
- data/app/views/admin/edit_web.rhtml +136 -0
- data/app/views/file/file.rhtml +19 -0
- data/app/views/file/import.rhtml +23 -0
- data/app/views/layouts/default.rhtml +85 -0
- data/app/views/markdown_help.rhtml +12 -16
- data/app/views/mixed_help.rhtml +7 -0
- data/app/views/navigation.rhtml +30 -19
- data/app/views/rdoc_help.rhtml +12 -16
- data/app/views/textile_help.rhtml +24 -28
- data/app/views/wiki/authors.rhtml +11 -13
- data/app/views/wiki/edit.rhtml +39 -31
- data/app/views/wiki/export.rhtml +12 -14
- data/app/views/wiki/feeds.rhtml +14 -10
- data/app/views/wiki/list.rhtml +64 -57
- data/app/views/wiki/locked.rhtml +23 -14
- data/app/views/wiki/login.rhtml +14 -11
- data/app/views/wiki/new.rhtml +31 -27
- data/app/views/wiki/page.rhtml +115 -81
- data/app/views/wiki/print.rhtml +14 -16
- data/app/views/wiki/published.rhtml +9 -10
- data/app/views/wiki/recently_revised.rhtml +27 -30
- data/app/views/wiki/revision.rhtml +103 -81
- data/app/views/wiki/rollback.rhtml +14 -9
- data/app/views/wiki/rss_feed.rhtml +22 -22
- data/app/views/wiki/search.rhtml +38 -15
- data/app/views/wiki/tex.rhtml +22 -22
- data/app/views/wiki/tex_web.rhtml +34 -34
- data/app/views/wiki/web_list.rhtml +18 -13
- data/app/views/wiki_words_help.rhtml +9 -8
- data/config/environment.rb +82 -0
- data/config/environments/development.rb +5 -0
- data/config/environments/production.rb +4 -0
- data/config/environments/test.rb +17 -0
- data/config/routes.rb +18 -0
- data/instiki +6 -67
- data/instiki.rb +3 -0
- data/lib/active_record_stub.rb +31 -0
- data/{libraries/diff → lib}/diff.rb +444 -475
- data/lib/instiki_errors.rb +15 -0
- data/{libraries → lib}/rdocsupport.rb +151 -155
- data/lib/redcloth_for_tex.rb +736 -0
- data/natives/osx/desktop_launcher/AppDelegate.h +18 -0
- data/natives/osx/desktop_launcher/AppDelegate.mm +109 -0
- data/natives/osx/desktop_launcher/Credits.html +16 -0
- data/natives/osx/desktop_launcher/English.lproj/InfoPlist.strings +0 -0
- data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/classes.nib +13 -0
- data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/info.nib +24 -0
- data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/objects.nib +0 -0
- data/natives/osx/desktop_launcher/Info.plist +13 -0
- data/natives/osx/desktop_launcher/Instiki.xcode/project.pbxproj +592 -0
- data/natives/osx/desktop_launcher/Instiki_Prefix.pch +7 -0
- data/natives/osx/desktop_launcher/MakeDMG.sh +9 -0
- data/natives/osx/desktop_launcher/main.mm +14 -0
- data/natives/osx/desktop_launcher/version.plist +16 -0
- data/public/404.html +6 -0
- data/public/500.html +6 -0
- data/public/dispatch.rb +10 -0
- data/public/favicon.ico +0 -0
- data/public/javascripts/edit_web.js +52 -0
- data/public/javascripts/prototype.js +336 -0
- data/{app/views/static_style_sheet.rhtml → public/stylesheets/instiki.css} +221 -198
- data/script/breakpointer +4 -0
- data/script/server +93 -0
- metadata +59 -32
- data/app/controllers/wiki.rb +0 -389
- data/app/models/chunks/match.rb +0 -19
- data/app/views/bottom.rhtml +0 -4
- data/app/views/top.rhtml +0 -49
- data/app/views/wiki/edit_web.rhtml +0 -138
- data/libraries/action_controller_servlet.rb +0 -177
- data/libraries/erb.rb +0 -490
- data/libraries/madeleine_service.rb +0 -68
- data/libraries/redcloth_for_tex.rb +0 -869
- data/libraries/web_controller_server.rb +0 -81
data/app/models/chunks/nowiki.rb
CHANGED
@@ -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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
data/app/models/chunks/test.rb
CHANGED
@@ -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
|
data/app/models/chunks/uri.rb
CHANGED
@@ -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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
#
|
48
|
-
#
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
#
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
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
|
data/app/models/chunks/wiki.rb
CHANGED
@@ -1,82 +1,141 @@
|
|
1
|
-
require 'wiki_words'
|
2
|
-
require 'chunks/chunk'
|
3
|
-
require '
|
4
|
-
|
5
|
-
|
6
|
-
# links.
|
7
|
-
module WikiChunk
|
8
|
-
include Chunk
|
9
|
-
|
10
|
-
# A wiki
|
11
|
-
# another wiki page.
|
12
|
-
class
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
# the
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
class
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
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
|