ruwiki 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. data/Readme.rubygems +86 -0
  2. data/Readme.tarfile +65 -0
  3. data/bin/ruwiki +58 -0
  4. data/bin/ruwiki.cgi +87 -0
  5. data/bin/ruwiki_convert +56 -0
  6. data/bin/ruwiki_service.rb +82 -0
  7. data/bin/ruwiki_servlet +53 -0
  8. data/contrib/enscript-token.rb +55 -0
  9. data/contrib/rublog_integrator.rb +68 -0
  10. data/data/Default/ProjectIndex.ruwiki +49 -0
  11. data/data/Ruwiki/Antispam.ruwiki +65 -0
  12. data/data/Ruwiki/BugTracking.ruwiki +33 -0
  13. data/data/Ruwiki/ChangeLog.ruwiki +102 -0
  14. data/data/Ruwiki/Configuring_Ruwiki.ruwiki +151 -0
  15. data/data/Ruwiki/Extending_Ruwiki.ruwiki +317 -0
  16. data/data/Ruwiki/LicenseAndAuthorInfo.ruwiki +30 -0
  17. data/data/Ruwiki/ProjectIndex.ruwiki +84 -0
  18. data/data/Ruwiki/Roadmap.ruwiki +225 -0
  19. data/data/Ruwiki/RuwikiTemplatingLibrary.ruwiki +156 -0
  20. data/data/Ruwiki/RuwikiUtilities.ruwiki +157 -0
  21. data/data/Ruwiki/SandBox.ruwiki +9 -0
  22. data/data/Ruwiki/To_Do.ruwiki +51 -0
  23. data/data/Ruwiki/TroubleShooting.ruwiki +33 -0
  24. data/data/Ruwiki/WikiFeatures.ruwiki +17 -0
  25. data/data/Ruwiki/WikiMarkup.ruwiki +261 -0
  26. data/data/Tutorial/AddingPages.ruwiki +16 -0
  27. data/data/Tutorial/AddingProjects.ruwiki +16 -0
  28. data/data/Tutorial/ProjectIndex.ruwiki +11 -0
  29. data/data/Tutorial/SandBox.ruwiki +9 -0
  30. data/data/agents.banned +60 -0
  31. data/data/agents.readonly +321 -0
  32. data/data/hostip.banned +30 -0
  33. data/data/hostip.readonly +28 -0
  34. data/lib/ruwiki.rb +622 -0
  35. data/lib/ruwiki/auth.rb +56 -0
  36. data/lib/ruwiki/auth/gforge.rb +73 -0
  37. data/lib/ruwiki/backend.rb +318 -0
  38. data/lib/ruwiki/backend/flatfiles.rb +217 -0
  39. data/lib/ruwiki/config.rb +244 -0
  40. data/lib/ruwiki/exportable.rb +192 -0
  41. data/lib/ruwiki/handler.rb +342 -0
  42. data/lib/ruwiki/lang/de.rb +339 -0
  43. data/lib/ruwiki/lang/en.rb +334 -0
  44. data/lib/ruwiki/lang/es.rb +339 -0
  45. data/lib/ruwiki/page.rb +262 -0
  46. data/lib/ruwiki/servlet.rb +38 -0
  47. data/lib/ruwiki/template.rb +553 -0
  48. data/lib/ruwiki/utils.rb +24 -0
  49. data/lib/ruwiki/utils/command.rb +102 -0
  50. data/lib/ruwiki/utils/converter.rb +297 -0
  51. data/lib/ruwiki/utils/manager.rb +639 -0
  52. data/lib/ruwiki/utils/servletrunner.rb +295 -0
  53. data/lib/ruwiki/wiki.rb +147 -0
  54. data/lib/ruwiki/wiki/tokens.rb +136 -0
  55. data/lib/ruwiki/wiki/tokens/00default.rb +211 -0
  56. data/lib/ruwiki/wiki/tokens/01wikilinks.rb +166 -0
  57. data/lib/ruwiki/wiki/tokens/02actions.rb +63 -0
  58. data/lib/ruwiki/wiki/tokens/abbreviations.rb +40 -0
  59. data/lib/ruwiki/wiki/tokens/calendar.rb +147 -0
  60. data/lib/ruwiki/wiki/tokens/headings.rb +43 -0
  61. data/lib/ruwiki/wiki/tokens/lists.rb +112 -0
  62. data/lib/ruwiki/wiki/tokens/rubylists.rb +48 -0
  63. data/ruwiki.conf +22 -0
  64. data/ruwiki.pkg +0 -0
  65. data/templates/default/body.tmpl +19 -0
  66. data/templates/default/content.tmpl +7 -0
  67. data/templates/default/controls.tmpl +23 -0
  68. data/templates/default/edit.tmpl +27 -0
  69. data/templates/default/error.tmpl +14 -0
  70. data/templates/default/footer.tmpl +23 -0
  71. data/templates/default/ruwiki.css +297 -0
  72. data/templates/default/save.tmpl +8 -0
  73. data/templates/sidebar/body.tmpl +19 -0
  74. data/templates/sidebar/content.tmpl +8 -0
  75. data/templates/sidebar/controls.tmpl +8 -0
  76. data/templates/sidebar/edit.tmpl +27 -0
  77. data/templates/sidebar/error.tmpl +13 -0
  78. data/templates/sidebar/footer.tmpl +22 -0
  79. data/templates/sidebar/ruwiki.css +347 -0
  80. data/templates/sidebar/save.tmpl +10 -0
  81. data/templates/simple/body.tmpl +13 -0
  82. data/templates/simple/content.tmpl +7 -0
  83. data/templates/simple/controls.tmpl +8 -0
  84. data/templates/simple/edit.tmpl +25 -0
  85. data/templates/simple/error.tmpl +10 -0
  86. data/templates/simple/footer.tmpl +10 -0
  87. data/templates/simple/ruwiki.css +192 -0
  88. data/templates/simple/save.tmpl +8 -0
  89. data/tests/harness.rb +52 -0
  90. data/tests/tc_backend_flatfile.rb +103 -0
  91. data/tests/tc_bugs.rb +74 -0
  92. data/tests/tc_exportable.rb +64 -0
  93. data/tests/tc_template.rb +145 -0
  94. data/tests/tc_tokens.rb +335 -0
  95. data/tests/testall.rb +20 -0
  96. metadata +182 -0
@@ -0,0 +1,295 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Ruwiki
4
+ # Copyright � 2002 - 2004, Digikata and HaloStatue
5
+ # Alan Chen (alan@digikata.com)
6
+ # Austin Ziegler (ruwiki@halostatue.ca)
7
+ #
8
+ # Licensed under the same terms as Ruby.
9
+ #
10
+ # This file may be renamed to change the URI for the wiki.
11
+ #
12
+ # $Id: servletrunner.rb,v 1.8 2004/11/26 12:18:47 austin Exp $
13
+ #++
14
+
15
+ # Customize this if you put the RuWiki files in a different location.
16
+ require 'webrick'
17
+
18
+ require 'ruwiki/utils'
19
+ require 'ruwiki/exportable'
20
+ require 'ruwiki/servlet'
21
+ require 'ruwiki/lang/en'
22
+ require 'ruwiki/lang/de'
23
+ require 'ruwiki/lang/es'
24
+
25
+ require 'optparse'
26
+ require 'ostruct'
27
+
28
+ module Ruwiki::Utils::ServletRunner
29
+ COPYRIGHT = <<-"COPYRIGHT"
30
+ Ruwiki #{Ruwiki::VERSION}
31
+ Copyright � 2002 - 2004, Digikata and HaloStatue
32
+
33
+ http://rubyforge.org/projects/ruwiki/
34
+
35
+ Alan Chen (alan@digikata.com)
36
+ Austin Ziegler (ruwiki@halostatue.ca)
37
+
38
+ Licensed under the same terms as Ruby.
39
+
40
+ $Id: servletrunner.rb,v 1.8 2004/11/26 12:18:47 austin Exp $
41
+ COPYRIGHT
42
+
43
+ class WEBrickConfig
44
+ include Ruwiki::Exportable
45
+
46
+ exportable_group 'webrick-config'
47
+ attr_accessor :port
48
+ exportable :port
49
+ attr_accessor :addresses
50
+ exportable :addresses
51
+ attr_accessor :mount
52
+ exportable :mount
53
+ attr_accessor :do_log
54
+ exportable :do_log
55
+ attr_accessor :log_dest
56
+ exportable :log_dest
57
+ attr_accessor :threads
58
+ exportable :threads
59
+
60
+ def export
61
+ hash = super
62
+ sc = hash['webrick-config']
63
+ sc['addresses'] = sc['addresses'].join(";")
64
+ sc['do-log'] = (sc['do-log'] ? 'true' : 'false')
65
+ hash
66
+ end
67
+
68
+ # Because the servlet can be started from the command-line, provide
69
+ # defaults for all possible configuration options.
70
+ def initialize(exported = {})
71
+ sc = exported['webrick-config'] || {}
72
+ @port = sc['port'] || 8808
73
+ @mount = sc['mount'] || '/'
74
+ @addresses = sc['addresses']
75
+ @do_log = ((sc['do-log'] == 'false') ? false : true)
76
+ @log_dest = sc['log-dest']
77
+ @threads = sc['threads'] || 1
78
+
79
+ if @addresses.nil? or @addresses.empty?
80
+ @addresses = []
81
+ else
82
+ @addresses = @addresses.split(/;/)
83
+ end
84
+
85
+ if @log_dest.nil? or @log_dest.empty?
86
+ @log_dest = "<STDERR>"
87
+ end
88
+ end
89
+ end
90
+
91
+ def self.message=(lang)
92
+ if lang.kind_of?(Hash)
93
+ @message = lang
94
+ elsif "constant" == defined?(lang::Message)
95
+ @message = lang::Message
96
+ else
97
+ raise ArgumentError
98
+ end
99
+ end
100
+ def self.message(id)
101
+ @message[id]
102
+ end
103
+
104
+ class << self
105
+ # This is for the WEBrick version of Ruwiki. This has been abstracted to
106
+ # accept a Config global variable to reconfigure Ruwiki after initial
107
+ # creation.
108
+ def read_config(filename)
109
+ ch = {}
110
+ if File.exists?(filename)
111
+ File.open(filename, 'rb') { |ff| ch = Ruwiki::Exportable.load(ff.read) }
112
+ end
113
+
114
+ @sc = WEBrickConfig.new(ch)
115
+ @rc = Ruwiki::Config.new(ch)
116
+
117
+ if @rc.webmaster.nil? or @rc.webmaster.empty?
118
+ @rc.webmaster = "webmaster@domain.tld"
119
+ end
120
+ end
121
+
122
+ def run(argv, input = $stdin, output = $stdout, error = $stderr)
123
+ read_config(Ruwiki::Config::CONFIG_NAME)
124
+
125
+ save_config = nil
126
+
127
+ language = 'en'
128
+ find_lang = argv.grep(%r{^--language})
129
+ find_lang.each do |ee|
130
+ if ee =~ %r{^--language=}
131
+ language = ee.sub(%r{^--language=}, '')
132
+ else
133
+ language = argv[argv.index(ee).succ]
134
+ end
135
+ end
136
+
137
+ require "ruwiki/lang/#{language.downcase}"
138
+ @rc.language = Ruwiki::Lang.const_get(language.upcase)
139
+ self.message = @rc.language
140
+
141
+ argv.options do |oo|
142
+ oo.banner = self.message(:runner_usage) % [ File.basename($0) ]
143
+ oo.separator self.message(:runner_general_options)
144
+ oo.on('--save-config [FILENAME]', *([ self.message(:runner_saveconfig_desc), Ruwiki::Config::CONFIG_NAME ].flatten)) { |fname|
145
+ save_config = fname || Ruwiki::Config::CONFIG_NAME
146
+ }
147
+ oo.on('--config FILENAME', *self.message(:runner_config_desc)) { |fn|
148
+ read_config(fn)
149
+ }
150
+ oo.separator ""
151
+ oo.separator self.message(:runner_webrick_options)
152
+ oo.on('-P', '--port PORT', Numeric, *self.message(:runner_port_desc)) { |port|
153
+ @sc.port = port
154
+ }
155
+ oo.on('-A', '--accept ADDRESS,ADDRESS,ADDRESS', Array, *self.message(:runner_address_desc)) { |address|
156
+ @sc.addresses += address
157
+ }
158
+ oo.on('-L', '--local', *self.message(:runner_local_desc)) {
159
+ @sc.addresses = ["127.0.0.1"]
160
+ }
161
+ oo.on('-M', '--mount MOUNT-POINT', *self.message(:runner_mountpoint_desc)) { |mp|
162
+ @sc.mount = mp
163
+ }
164
+ oo.on('--[no-]log', *self.message(:runner_log_desc)) { |log|
165
+ @sc.do_log = log
166
+ }
167
+ oo.on('--logfile LOGFILE', *self.message(:runner_logfile_desc)) { |lf|
168
+ @sc.log_dest = lf
169
+ }
170
+ oo.on('-T', '--threads THREADS', Integer, *self.message(:runner_threads_desc)) { |tc|
171
+ @sc.threads = tc
172
+ }
173
+ oo.separator ""
174
+ oo.separator self.message(:runner_ruwiki_options)
175
+ oo.on('--language=LANGUAGE', *self.message(:runner_language_desc)) { |lang|
176
+ nil
177
+ }
178
+ oo.on('--webmaster WEBMASTER', *self.message(:runner_webmaster_desc)) { |wm|
179
+ @rc.webmaster = wm
180
+ }
181
+ oo.on('--[no-]debug', *self.message(:runner_debug_desc)) { |dd|
182
+ @rc.debug = dd
183
+ }
184
+ oo.on('--title TITLE', *self.message(:runner_title_desc)) { |tt|
185
+ @rc.title = tt
186
+ }
187
+ oo.on('--default-page PAGENAME', *self.message(:runner_defaultpage_desc)) { |dp|
188
+ @rc.default_page = dp
189
+ }
190
+ oo.on('--default-project PAGENAME', *self.message(:runner_defaultproject_desc)) { |dp|
191
+ @rc.default_project = dp
192
+ }
193
+ oo.on('--template-path TEMPLATE_PATH', *self.message(:runner_templatepath_desc)) { |tp|
194
+ @rc.template_path = tp
195
+ }
196
+ oo.on('--templates TEMPLATES', *self.message(:runner_templatename_desc)) { |tp|
197
+ @rc.template_set = tp
198
+ }
199
+ oo.on('--css CSS_NAME', *self.message(:runner_cssname_desc)) { |css|
200
+ @rc.css = css
201
+ }
202
+ oo.on('--storage-type TYPE', Ruwiki::KNOWN_BACKENDS, *([self.message(:runner_storage_desc), Ruwiki::KNOWN_BACKENDS.join(", ")].flatten)) { |st|
203
+ @rc.storage_type = st
204
+ @rc.storage_options[@rc.storage_type]['data-path'] ||= "./data/"
205
+ @rc.storage_options[@rc.storage_type]['extension'] ||= "ruwiki"
206
+ }
207
+ oo.on('--data-path PATH', *self.message(:runner_datapath_desc)) { |fdp|
208
+ @rc.storage_options['flatfiles']['data-path'] = fdp
209
+ }
210
+ oo.on('--extension EXT', *self.message(:runner_extension_desc)) { |ext|
211
+ @rc.storage_options['flatfiles']['data-path'] = fdp
212
+ }
213
+ if defined?(Gem::Cache)
214
+ oo.separator ""
215
+ oo.on('--central', *self.message(:runner_central_desc)) {
216
+ gempath = Gem::Cache.from_installed_gems.search("ruwiki", "=#{Ruwiki::VERSION}").last.full_gem_path
217
+ @rc.storage_type = 'flatfiles'
218
+ @rc.storage_options['flatfiles']['data-path'] = "#{gempath}/data"
219
+ @rc.storage_options['flatfiles']['extension'] = "ruwiki"
220
+ @rc.storage_options['flatfiles']['format'] = "exportable"
221
+ @rc.template_path = "#{gempath}/templates"
222
+ @rc.template_set = "sidebar"
223
+ }
224
+ end
225
+
226
+ # TODO: Add options for time, date, and datetime formats.
227
+ oo.separator ""
228
+ oo.separator self.message(:runner_general_info)
229
+ oo.on_tail('--help', *self.message(:runner_help_desc)) {
230
+ error << oo << "\n"
231
+ return 0
232
+ }
233
+ oo.on_tail('--version', *self.message(:runner_version_desc)) {
234
+ error << COPYRIGHT << "\n"
235
+ return 0
236
+ }
237
+ oo.parse!
238
+ end
239
+
240
+ if save_config
241
+ sc = @sc.export
242
+ rc = @rc.export
243
+ cf = sc.merge(rc)
244
+
245
+ File.open(save_config, 'wb') { |ff| ff.puts Ruwiki::Exportable.dump(cf) }
246
+ return 0
247
+ end
248
+
249
+ # If the list of accepted addresses is not empty, provide IP-based
250
+ # restrictions.
251
+ if not @sc.addresses.empty?
252
+ localonly = lambda do |sock|
253
+ if not @sc.addresses.include?(sock.peeraddr[3])
254
+ raise WEBrick::ServerError, self.message(:runner_rejected_address) % [ sock.peeraddr[3], @sc.addresses.join(", ") ]
255
+ end
256
+ end
257
+ else
258
+ localonly = nil
259
+ end
260
+
261
+ if @sc.do_log
262
+ if "<STDERR>" == @sc.log_dest
263
+ dest = $stderr
264
+ else
265
+ dest = File.open(@sc.log_dest, "wb+")
266
+ end
267
+ logger = WEBrick::Log.new(dest, WEBrick::Log::DEBUG)
268
+ else
269
+ logger = nil
270
+ end
271
+
272
+ banner = self.message(:runner_banner) %
273
+ [ Ruwiki::Utils::ServletRunner::COPYRIGHT, @sc.port,
274
+ @sc.addresses.join(", "), @sc.mount, @sc.do_log, @sc.log_dest,
275
+ @sc.threads, @rc.webmaster, @rc.debug, @rc.title,
276
+ @rc.default_project, @rc.default_page, @rc.template_path,
277
+ @rc.template_set, @rc.css, @rc.storage_type,
278
+ @rc.storage_options[@rc.storage_type]['data-path'],
279
+ @rc.storage_options[@rc.storage_type]['extension'] ]
280
+
281
+ banner.each { |bb| logger.info(bb) } unless logger.nil?
282
+
283
+ server = WEBrick::HTTPServer.new(:Port => @sc.port.to_i,
284
+ :StartThreads => @sc.threads.to_i,
285
+ :AcceptCallback => localonly,
286
+ :Logger => logger)
287
+ @rc.logger = logger
288
+ Ruwiki::Servlet.config = @rc
289
+
290
+ server.mount(@sc.mount, Ruwiki::Servlet)
291
+ trap("INT") { server.shutdown; return }
292
+ server.start
293
+ end
294
+ end
295
+ end
@@ -0,0 +1,147 @@
1
+ #--
2
+ # Ruwiki
3
+ # Copyright � 2002 - 2004, Digikata and HaloStatue
4
+ # Alan Chen (alan@digikata.com)
5
+ # Austin Ziegler (ruwiki@halostatue.ca)
6
+ #
7
+ # Licensed under the same terms as Ruby.
8
+ #
9
+ # $Id: wiki.rb,v 1.14 2004/11/28 05:27:32 austin Exp $
10
+ #++
11
+ # Ruwiki's Wiki markup class. This will convert the Wiki markup known by
12
+ # Ruwiki (defined by Token classes). The algorithm is as follows:
13
+ #
14
+ # 1. For each known Token class, match each instance of it in the content
15
+ # stream. Replace each instance in the content stream with a Token
16
+ # marker: TOKEN_x or \TOKEN_x, where x is a digit representing the Token.
17
+ # (\TOKEN_x is a special case of token matching. See
18
+ # Ruwiki::Markup::Token for more information.) Store the Token for later
19
+ # processing.
20
+ # 2. Go back through the content, replacing each instance of \TOKEN_x with
21
+ # the Token's defined restore value (which should be the same value as was
22
+ # originally matched).
23
+ # 3. Go through the content, replacing each instance of TOKEN_x with the
24
+ # Token's defined replacement value.
25
+ # 4. Go through the tokens, in reverse, and execute the post replacement
26
+ # routine defined by the Token. (This may be necessary to collapse
27
+ # consecutive HTML structures.)
28
+ # 5. Return the parsed content and the collected metadata.
29
+ #
30
+ # == Tokens
31
+ # Look at Ruwiki::Markup::Token describes how to create Token objects.
32
+ class Ruwiki::Wiki
33
+ def parse(content, project)
34
+ content = clean(content)
35
+ tokens = []
36
+ project ||= @default_project
37
+
38
+ Token.tokenlist.each do |token|
39
+ content.gsub!(token.regexp) do |mm|
40
+ match = Regexp.last_match
41
+ tc = token.new(match, project, @backend, @script, @message, @title)
42
+ tokens << tc
43
+ if mm[0, 1] == '\\'
44
+ "\\TOKEN_#{tokens.size - 1}"
45
+ else
46
+ "TOKEN_#{tokens.size - 1}"
47
+ end
48
+ end
49
+ end
50
+
51
+ replaced = []
52
+ ss = true
53
+ loop do
54
+ break if replaced.size >= tokens.size
55
+ break if ss.nil?
56
+ ss = content.gsub!(/\\TOKEN_(\d+)/) { |mm|
57
+ match = Regexp.last_match
58
+ itoken = match[1].to_i
59
+ replaced << itoken
60
+ tokens[itoken].restore
61
+ }
62
+
63
+ ss = content.gsub!(/TOKEN_(\d+)/) { |mm|
64
+ match = Regexp.last_match
65
+ itoken = match[1].to_i
66
+ replaced << itoken
67
+ tokens[itoken].replace
68
+ }
69
+ end
70
+
71
+ token_classes = tokens.map { |token| token.class }.sort_by { |token| token.rank }
72
+ token_classes.uniq.each { |tc| tc.post_replace(content) }
73
+
74
+ content
75
+ end
76
+
77
+ attr_accessor :default_project
78
+ attr_accessor :script
79
+ attr_accessor :backend
80
+ attr_accessor :message
81
+
82
+ # Creates the markup class.
83
+ def initialize(default_project, script, title)
84
+ @default_project = default_project
85
+ @script = script
86
+ @title = title
87
+ end
88
+
89
+ private
90
+ # Find HTML tags
91
+ SIMPLE_TAG_RE = %r{<[^<>]+?>} # Ensure that only the tag is grabbed.
92
+ HTML_TAG_RE = %r{\A< # Tag must be at start of match.
93
+ (/)? # Closing tag?
94
+ ([\w:]+) # Tag name
95
+ (?:\s+ # Space
96
+ ([^>]+) # Attributes
97
+ (/)? # Singleton tag?
98
+ )? # The above three are optional
99
+ >}x
100
+ ATTRIBUTES_RE = %r{([\w:]+)(=(?:\w+|"[^"]+?"|'[^']+?'))?}x
101
+ STYLE_NOVD_RE = %r{(?:\s?(visibility|display):[^'";]+;?)}x
102
+ ALLOWED_ATTR = %w(style title type lang dir class id cite datetime abbr) +
103
+ %w(colspan rowspan compact start media)
104
+ ALLOWED_HTML = %w(abbr acronym address b big blockquote br caption cite) +
105
+ %w(code col colgroup dd del dfn dir div dl dt em h1 h2 h3) +
106
+ %w(h4 h5 h6 hr i ins kbd li menu ol p pre q s samp small) +
107
+ %w(span strike strong style sub sup table tbody td tfoot) +
108
+ %w(th thead tr tt u ul var)
109
+
110
+ # Clean the content of unsupported HTML and attributes. This includes
111
+ # XML namespaced HTML. Sorry, but there's too much possibility for
112
+ # abuse.
113
+ def clean(content)
114
+ content = content.gsub(SIMPLE_TAG_RE) do |tag|
115
+ tagset = HTML_TAG_RE.match(tag)
116
+
117
+ if tagset.nil?
118
+ tag = Ruwiki.clean_entities(tag)
119
+ else
120
+ closer, name, attributes, single = tagset.captures
121
+
122
+ if ALLOWED_HTML.include?(name.downcase)
123
+ unless closer or attributes.nil?
124
+ attributes = attributes.scan(ATTRIBUTES_RE).map do |set|
125
+ if ALLOWED_ATTR.include?(set[0].downcase)
126
+ if set[0] == 'style'
127
+ set[1].gsub!(STYLE_NOVD_RE, '')
128
+ end
129
+ set.join
130
+ else
131
+ nil
132
+ end
133
+ end.compact.join(" ")
134
+ tag = "<#{closer}#{name} #{attributes}#{single}>"
135
+ else
136
+ tag = "<#{closer}#{name}>"
137
+ end
138
+ else
139
+ tag = Ruwiki.clean_entities(tag)
140
+ end
141
+ end
142
+ tag.gsub(%r{((?:href|src)=["'])(#{Ruwiki::Wiki::RE_URI_SCHEME})}) { "#{$1}\\#{$2}" }
143
+ end
144
+ end
145
+ end
146
+
147
+ require 'ruwiki/wiki/tokens'
@@ -0,0 +1,136 @@
1
+ #--
2
+ # Ruwiki
3
+ # Copyright � 2002 - 2004, Digikata and HaloStatue
4
+ # Alan Chen (alan@digikata.com)
5
+ # Austin Ziegler (ruwiki@halostatue.ca)
6
+ #
7
+ # Licensed under the same terms as Ruby.
8
+ #
9
+ # $Id: tokens.rb,v 1.8 2004/11/26 12:18:47 austin Exp $
10
+ #++
11
+ class Ruwiki
12
+ class Wiki
13
+ # The base Token class. All Token classes must inherit from Token and
14
+ # *must* implement the following methods:
15
+ #
16
+ # [self.regexp] The regular expression that the Token will be
17
+ # replacing.
18
+ # [replace] The mechanism for replacing the Token with the desired
19
+ # results.
20
+ #
21
+ # Token classes <i>should</i> implement the following method:
22
+ # [self.rank] Default: <tt>5000</tt>. Affects the sort order.
23
+ # Must return an integer.
24
+ #
25
+ # Token classes <i>may</i> implement the following methods:
26
+ # [restore] Restores the token without replacement.
27
+ # Implements the results of the escape character.
28
+ # NOTE: each Token class is responsible for its own
29
+ # restore. Tokens that are anchored to the
30
+ # beginning of a line are the most likely to need
31
+ # to reimplement this.
32
+ # [self.post_replace] Performs any necessary massaging of the data. See
33
+ # the implementation of Ruwiki::Wiki::Lists for
34
+ # more information.
35
+ class Token
36
+ @@tokenlist = []
37
+ @@sorted = false
38
+
39
+ class << self
40
+ # Tokens should define rank if they must be first or last in
41
+ # processing. Otherwise, they are sorted in the order defined.
42
+ def rank
43
+ 5000
44
+ end
45
+
46
+ # The Wiki parsing routine uses Token.tokenlist to determine the
47
+ # tokens that are processed, and the order in which they are
48
+ # processed. See Token.rank for more information.
49
+ def tokenlist
50
+ unless @@sorted
51
+ head = @@tokenlist.shift
52
+ @@tokenlist.sort! { |aa, bb| aa.rank <=> bb.rank }
53
+ @@tokenlist.unshift(head)
54
+ sorted = true
55
+ end
56
+ @@tokenlist
57
+ end
58
+
59
+ def inherited(child_class) #:nodoc:
60
+ @@tokenlist << Token if @@tokenlist.empty?
61
+
62
+ # Make the child class post_replace a blank function because we
63
+ # don't want to propogate the currently defined post_replace.
64
+ # The current post_replace is specific to Token_Base only.
65
+ class << child_class
66
+ def self.post_replace(content)
67
+ content
68
+ end
69
+ end
70
+
71
+ @@tokenlist << child_class
72
+ @@sorted = false
73
+ end
74
+
75
+ # The replacement regular expression.
76
+ def regexp
77
+ /TOKEN_(\d*)/
78
+ end
79
+ end
80
+
81
+ # All Token classes must match this header signature if they define
82
+ # #initialize.
83
+ #
84
+ # [match] The MatchData object for this Token.
85
+ # [project] The project being processed.
86
+ # [backend] The backend for the wiki. This is used to determine if
87
+ # the page or project exists. The object passed must
88
+ # respond to #project_exists?(project) and
89
+ # #page_exists?(page, project).
90
+ # [script] The URI to the script.
91
+ # [message] The message hash for localized messages.
92
+ # [title] The title of the Wiki.
93
+ def initialize(match, project, backend, script, message, title)
94
+ @match = match
95
+ @project = project
96
+ @backend = backend
97
+ @script = script
98
+ @message = message
99
+ @title = title
100
+ end
101
+
102
+ # The replacement method. Uses @match to replace the token with the
103
+ # appropriate values.
104
+ def replace
105
+ "TOKEN_#{@match[1]}"
106
+ end
107
+
108
+ # Restores the token without replacement. By default, replaces
109
+ # "dangerous" HTML characters.
110
+ def restore
111
+ Ruwiki.clean_entities(@match[0])
112
+ end
113
+
114
+ # The content may need massaging after processing.
115
+ def self.post_replace(content)
116
+ content
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ # Load the tokens from the ruwiki/wiki/tokens directory.
123
+ tokens_dir = 'ruwiki/wiki/tokens'
124
+
125
+ $LOAD_PATH.each do |path|
126
+ target = "#{path}/#{tokens_dir}"
127
+ if File.exists?(target) and File.directory?(target)
128
+ Dir::glob("#{target}/*.rb") do |token|
129
+ begin
130
+ require token
131
+ rescue LoadError
132
+ nil
133
+ end
134
+ end
135
+ end
136
+ end