Pimki 1.3.092 → 1.4.092

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/README +145 -131
  2. data/README-PIMKI +15 -5
  3. data/app/controllers/wiki.rb +167 -54
  4. data/app/models/author.rb +3 -3
  5. data/app/models/chunks/chunk.rb +3 -3
  6. data/app/models/chunks/engines.rb +18 -21
  7. data/app/models/chunks/include.rb +29 -29
  8. data/app/models/chunks/literal.rb +20 -20
  9. data/app/models/chunks/match.rb +19 -19
  10. data/app/models/chunks/nowiki.rb +31 -31
  11. data/app/models/chunks/nowiki_test.rb +14 -14
  12. data/app/models/chunks/test.rb +18 -18
  13. data/app/models/chunks/todo.rb +44 -23
  14. data/app/models/chunks/uri.rb +97 -97
  15. data/app/models/chunks/uri_test.rb +92 -92
  16. data/app/models/chunks/wiki.rb +4 -4
  17. data/app/models/chunks/wiki_symbols.rb +22 -22
  18. data/app/models/chunks/wiki_test.rb +36 -36
  19. data/app/models/page.rb +39 -7
  20. data/app/models/page_lock.rb +23 -23
  21. data/app/models/page_set.rb +72 -72
  22. data/app/models/page_test.rb +75 -75
  23. data/app/models/revision.rb +1 -1
  24. data/app/models/revision_test.rb +251 -251
  25. data/app/models/web.rb +19 -6
  26. data/app/models/web_test.rb +52 -52
  27. data/app/models/wiki_content.rb +131 -119
  28. data/app/models/wiki_service.rb +31 -16
  29. data/app/models/wiki_service_test.rb +15 -15
  30. data/app/models/wiki_words.rb +1 -1
  31. data/app/models/wiki_words_test.rb +12 -12
  32. data/app/views/bottom.rhtml +3 -3
  33. data/app/views/markdown_help.rhtml +15 -15
  34. data/app/views/menu.rhtml +20 -20
  35. data/app/views/navigation.rhtml +26 -26
  36. data/app/views/rdoc_help.rhtml +15 -15
  37. data/app/views/static_style_sheet.rhtml +237 -237
  38. data/app/views/style.rhtml +178 -178
  39. data/app/views/textile_help.rhtml +27 -27
  40. data/app/views/top.rhtml +7 -2
  41. data/app/views/wiki/authors.rhtml +15 -15
  42. data/app/views/wiki/bliki.rhtml +101 -101
  43. data/app/views/wiki/bliki_edit.rhtml +3 -0
  44. data/app/views/wiki/bliki_new.rhtml +3 -0
  45. data/app/views/wiki/bliki_revision.rhtml +90 -90
  46. data/app/views/wiki/edit.rhtml +12 -3
  47. data/app/views/wiki/edit_menu.rhtml +64 -47
  48. data/app/views/wiki/edit_web.rhtml +65 -18
  49. data/app/views/wiki/export.rhtml +14 -14
  50. data/app/views/wiki/feeds.rhtml +10 -10
  51. data/app/views/wiki/list.rhtml +17 -15
  52. data/app/views/wiki/locked.rhtml +13 -13
  53. data/app/views/wiki/login.rhtml +10 -10
  54. data/app/views/wiki/mind.rhtml +0 -1
  55. data/app/views/wiki/new.rhtml +8 -3
  56. data/app/views/wiki/new_system.rhtml +77 -77
  57. data/app/views/wiki/new_web.rhtml +63 -63
  58. data/app/views/wiki/page.rhtml +88 -82
  59. data/app/views/wiki/print.rhtml +15 -15
  60. data/app/views/wiki/published.rhtml +2 -1
  61. data/app/views/wiki/recently_revised.rhtml +31 -31
  62. data/app/views/wiki/revision.rhtml +1 -7
  63. data/app/views/wiki/rollback.rhtml +31 -0
  64. data/app/views/wiki/rss_feed.rhtml +21 -21
  65. data/app/views/wiki/search.rhtml +48 -48
  66. data/app/views/wiki/tex.rhtml +22 -22
  67. data/app/views/wiki/tex_web.rhtml +34 -34
  68. data/app/views/wiki/todo.rhtml +90 -67
  69. data/app/views/wiki/web_list.rhtml +12 -12
  70. data/app/views/wiki_words_help.rhtml +1 -1
  71. data/favicon.png +0 -0
  72. data/libraries/action_controller_servlet.rb +17 -2
  73. data/libraries/bluecloth.rb +1127 -1127
  74. data/libraries/diff/diff.rb +474 -474
  75. data/libraries/diff/diff_test.rb +79 -79
  76. data/libraries/erb.rb +490 -490
  77. data/libraries/madeleine/automatic.rb +418 -357
  78. data/libraries/madeleine/clock.rb +94 -94
  79. data/libraries/madeleine/files.rb +19 -0
  80. data/libraries/madeleine/zmarshal.rb +60 -0
  81. data/libraries/madeleine_service.rb +14 -15
  82. data/libraries/rdocsupport.rb +155 -155
  83. data/libraries/redcloth_for_tex.rb +869 -869
  84. data/libraries/redcloth_for_tex_test.rb +40 -40
  85. data/libraries/view_helper.rb +32 -32
  86. data/libraries/web_controller_server.rb +96 -94
  87. data/pimki.rb +47 -6
  88. metadata +18 -4
@@ -1,94 +1,94 @@
1
- #
2
- # Copyright(c) Anders Bengtsson 2003
3
- #
4
-
5
- require 'madeleine'
6
-
7
- module Madeleine
8
- module Clock
9
-
10
- # Deprecated. Use SnapshotMadeleine instead.
11
- class ClockedSnapshotMadeleine < ::Madeleine::SnapshotMadeleine
12
- end
13
-
14
- # Let your system extend this module if you need to access the
15
- # machine time. Used together with a TimeActor that keeps
16
- # the clock current.
17
- module ClockedSystem
18
-
19
- # Returns this system's Clock.
20
- def clock
21
- unless defined? @clock
22
- @clock = Clock.new
23
- end
24
- @clock
25
- end
26
- end
27
-
28
- # Sends clock ticks to update a ClockedSystem, so that time can be
29
- # dealt with in a deterministic way.
30
- class TimeActor
31
-
32
- # Create and launch a new TimeActor
33
- #
34
- # * <tt>madeleine</tt> - The SnapshotMadeleine instance to work on.
35
- # * <tt>delay</tt> - Delay between ticks in seconds (Optional).
36
- def self.launch(madeleine, delay=0.1)
37
- result = new(madeleine, delay)
38
- result
39
- end
40
-
41
- # Stops the TimeActor.
42
- def destroy
43
- @is_destroyed = true
44
- @thread.wakeup
45
- @thread.join
46
- end
47
-
48
- private_class_method :new
49
-
50
- private
51
-
52
- def initialize(madeleine, delay) #:nodoc:
53
- @madeleine = madeleine
54
- @is_destroyed = false
55
- send_tick
56
- @thread = Thread.new {
57
- until @is_destroyed
58
- sleep(delay)
59
- send_tick
60
- end
61
- }
62
- end
63
-
64
- def send_tick
65
- @madeleine.execute_command(Tick.new(Time.now))
66
- end
67
- end
68
-
69
- # Keeps track of time in a ClockedSystem.
70
- class Clock
71
- # Returns the system's time as a Ruby <tt>Time</tt>.
72
- attr_reader :time
73
-
74
- def initialize
75
- @time = Time.at(0)
76
- end
77
-
78
- def forward_to(newTime)
79
- @time = newTime
80
- end
81
- end
82
-
83
- #
84
- # Internal classes below
85
- #
86
-
87
- # Deprecated. Merged into default implementation.
88
- class TimeOptimizingLogger < ::Madeleine::Logger
89
- end
90
-
91
- end
92
- end
93
-
94
- ClockedSnapshotMadeleine = Madeleine::Clock::ClockedSnapshotMadeleine
1
+ #
2
+ # Copyright(c) Anders Bengtsson 2003
3
+ #
4
+
5
+ require 'madeleine'
6
+
7
+ module Madeleine
8
+ module Clock
9
+
10
+ # Deprecated. Use SnapshotMadeleine instead.
11
+ class ClockedSnapshotMadeleine < ::Madeleine::SnapshotMadeleine # :nodoc:
12
+ end
13
+
14
+ # Let your system extend this module if you need to access the
15
+ # machine time. Used together with a TimeActor that keeps
16
+ # the clock current.
17
+ module ClockedSystem
18
+
19
+ # Returns this system's Clock.
20
+ def clock
21
+ unless defined? @clock
22
+ @clock = Clock.new
23
+ end
24
+ @clock
25
+ end
26
+ end
27
+
28
+ # Sends clock ticks to update a ClockedSystem, so that time can be
29
+ # dealt with in a deterministic way.
30
+ class TimeActor
31
+
32
+ # Create and launch a new TimeActor
33
+ #
34
+ # * <tt>madeleine</tt> - The SnapshotMadeleine instance to work on.
35
+ # * <tt>delay</tt> - Delay between ticks in seconds (Optional).
36
+ def self.launch(madeleine, delay=0.1)
37
+ result = new(madeleine, delay)
38
+ result
39
+ end
40
+
41
+ # Stops the TimeActor.
42
+ def destroy
43
+ @is_destroyed = true
44
+ @thread.wakeup
45
+ @thread.join
46
+ end
47
+
48
+ private_class_method :new
49
+
50
+ private
51
+
52
+ def initialize(madeleine, delay) #:nodoc:
53
+ @madeleine = madeleine
54
+ @is_destroyed = false
55
+ send_tick
56
+ @thread = Thread.new {
57
+ until @is_destroyed
58
+ sleep(delay)
59
+ send_tick
60
+ end
61
+ }
62
+ end
63
+
64
+ def send_tick
65
+ @madeleine.execute_command(Tick.new(Time.now))
66
+ end
67
+ end
68
+
69
+ # Keeps track of time in a ClockedSystem.
70
+ class Clock
71
+ # Returns the system's time as a Ruby <tt>Time</tt>.
72
+ attr_reader :time
73
+
74
+ def initialize
75
+ @time = Time.at(0)
76
+ end
77
+
78
+ def forward_to(newTime)
79
+ @time = newTime
80
+ end
81
+ end
82
+
83
+ #
84
+ # Internal classes below
85
+ #
86
+
87
+ # Deprecated. Merged into default implementation.
88
+ class TimeOptimizingLogger < ::Madeleine::Logger # :nodoc:
89
+ end
90
+
91
+ end
92
+ end
93
+
94
+ ClockedSnapshotMadeleine = Madeleine::Clock::ClockedSnapshotMadeleine
@@ -0,0 +1,19 @@
1
+ #
2
+ # Wrapper for Ruby's file services, replaced during testing
3
+ # so we can run tests without touching a real filesystem.
4
+ #
5
+
6
+ class FileService
7
+
8
+ def open(*args)
9
+ super(*args)
10
+ end
11
+
12
+ def exist?(name)
13
+ File.exist?(name)
14
+ end
15
+
16
+ def dir_entries(name)
17
+ Dir.entries(name)
18
+ end
19
+ end
@@ -0,0 +1,60 @@
1
+ #
2
+ # Author:: Anders Bengtsson <ndrsbngtssn@yahoo.se>
3
+ # Copyright:: Copyright (c) 2004
4
+ #
5
+
6
+ require 'zlib'
7
+
8
+ module Madeleine
9
+ #
10
+ # Snapshot marshaller for compressed snapshots.
11
+ #
12
+ # Compresses the snapshots created by another marshaller. Uses either
13
+ # Marshal (the default) or another supplied marshaller.
14
+ #
15
+ # Uses <tt>zlib</tt> to do on-the-fly compression/decompression.
16
+ #
17
+ # ZMarshal works with Ruby's own Marshal and YAML, but not with SOAP
18
+ # marshalling.
19
+ #
20
+ # Usage:
21
+ #
22
+ # require 'madeleine'
23
+ # require 'madeleine/zmarshal'
24
+ #
25
+ # marshaller = Madeleine::ZMarshal.new(YAML)
26
+ # madeleine = SnapshotMadeleine.new("my_example_storage", marshaller) {
27
+ # SomeExampleApplication.new()
28
+ # }
29
+ #
30
+ class ZMarshal
31
+
32
+ def initialize(marshaller=Marshal)
33
+ @marshaller = marshaller
34
+ end
35
+
36
+ def load(stream)
37
+ zstream = Zlib::GzipReader.new(stream)
38
+ begin
39
+ # Buffer into a string first, since GzipReader can't handle
40
+ # Marshal's 0-sized reads and SOAP can't handle streams at all.
41
+ # In a bright future we can revert to reading directly from the
42
+ # stream again.
43
+ buffer = zstream.read
44
+ return @marshaller.load(buffer)
45
+ ensure
46
+ zstream.finish
47
+ end
48
+ end
49
+
50
+ def dump(system, stream)
51
+ zstream = Zlib::GzipWriter.new(stream)
52
+ begin
53
+ @marshaller.dump(system, zstream)
54
+ ensure
55
+ zstream.finish
56
+ end
57
+ nil
58
+ end
59
+ end
60
+ end
@@ -1,5 +1,6 @@
1
- require 'madeleine/automatic'
2
1
  require 'madeleine'
2
+ require 'madeleine/automatic'
3
+ require 'madeleine/zmarshal'
3
4
  require 'singleton'
4
5
  require 'yaml'
5
6
 
@@ -17,40 +18,38 @@ class MadeleineService
17
18
  @@storage_path = storage_path
18
19
  end
19
20
 
20
- def clean_storage
21
- MadeleineServer.clean_storage(self)
22
- end
23
-
24
21
  def instance
25
22
  @system = MadeleineServer.new(self).system if @system.nil?
26
23
  @system
27
24
  end
28
25
 
29
26
  def restart
30
- clean_storage
27
+ MadeleineServer.clean_storage(self)
31
28
  @system = MadeleineServer.new(self).system
32
29
  end
33
30
  end
34
31
  end
35
32
 
36
33
  class MadeleineServer
37
- SNAPSHOT_INTERVAL = 60 * 60 * 24 # seconds * minutes * hours => Each day
34
+ SNAPSHOT_INTERVAL = 30 * 60 * 24 # Each day
38
35
  AUTOMATIC_SNAPSHOTS = true
39
36
 
40
37
  # Clears all the command_log and snapshot files located in the storage directory, so the
41
- # database is essentially dropped and recreated as blank
38
+ # database is essentially dropped and recreated as blank. Used in tests.
42
39
  def self.clean_storage(service)
43
- begin
44
- Dir.foreach(service.storage_path) do |file|
45
- File.delete(service.storage_path + File::SEPARATOR + file) if file =~ /(command_log|snapshot)$/
46
- end
47
- rescue
48
- Dir.mkdir(service.storage_path)
40
+ require 'fileutils'
41
+ if (File.directory?(service.storage_path))
42
+ FileUtils.rm_rf(Dir[service.storage_path + '/*.command_log'])
43
+ FileUtils.rm_rf(Dir[service.storage_path + '/*.snapshot'])
44
+ else
45
+ FileUtils.mkdir_p(service.storage_path)
49
46
  end
50
47
  end
51
48
 
52
49
  def initialize(service)
53
- @server = Madeleine::Automatic::AutomaticSnapshotMadeleine.new(service.storage_path) { service.new }
50
+ marshaller = Madeleine::ZMarshal.new()
51
+ @server = Madeleine::Automatic::AutomaticSnapshotMadeleine.new(service.storage_path,
52
+ marshaller) { service.new }
54
53
  start_snapshot_thread if AUTOMATIC_SNAPSHOTS
55
54
  end
56
55
 
@@ -1,156 +1,156 @@
1
- begin
2
- require "rdoc/markup/simple_markup"
3
- require 'rdoc/markup/simple_markup/to_html'
4
- rescue LoadError
5
- # use old version if available
6
- require 'markup/simple_markup'
7
- require 'markup/simple_markup/to_html'
8
- end
9
-
10
- module RDocSupport
11
-
12
- # A simple +rdoc+ markup class which recognizes some additional
13
- # formatting commands suitable for Wiki use.
14
- class RDocMarkup < SM::SimpleMarkup
15
- def initialize
16
- super()
17
-
18
- pre = '(?:\\s|^|\\\\)'
19
-
20
- # links of the form
21
- # [[<url> description with spaces]]
22
- add_special(/((\\)?\[\[\S+?\s+.+?\]\])/,:TIDYLINK)
23
-
24
- # and external references
25
- add_special(/((\\)?(link:|anchor:|http:|mailto:|ftp:|img:|www\.)\S+\w\/?)/,
26
- :HYPERLINK)
27
-
28
- # <br/>
29
- add_special(%r{(#{pre}<br/>)}, :BR)
30
-
31
- # and <center> ... </center>
32
- add_html("center", :CENTER)
33
- end
34
-
35
- def convert(text, handler)
36
- #$stderr.puts text.inspect
37
- res = super
38
- res.sub!(/^<p>\n/, '')
39
- res.sub!(/<\/p>$/, '')
40
- res
41
- end
42
- end
43
-
44
- # Handle special hyperlinking requirments for RDoc formatted
45
- # entries. Requires RDoc
46
-
47
- class HyperLinkHtml < SM::ToHtml
48
-
49
- # Initialize the HyperLinkHtml object.
50
- # [path] location of the node
51
- # [site] object representing the whole site (typically of class
52
- # +Site+)
53
- def initialize
54
- super()
55
- add_tag(:CENTER, "<center>", "</center>")
56
- end
57
-
58
- # handle <br/>
59
- def handle_special_BR(special)
60
- return "&lt;br/&gt" if special.text[0,1] == '\\'
61
- special.text
62
- end
63
-
64
- # We're invoked with a potential external hyperlink.
65
- # [mailto:] just gets inserted.
66
- # [http:] links are checked to see if they
67
- # reference an image. If so, that image gets inserted
68
- # using an <img> tag. Otherwise a conventional <a href>
69
- # is used.
70
- # [img:] insert a <tt><img></tt> tag
71
- # [link:] used to insert arbitrary <tt><a></tt> references
72
- # [anchor:] used to create an anchor
73
- def handle_special_HYPERLINK(special)
74
- text = special.text.strip
75
- return text[1..-1] if text[0,1] == '\\'
76
- url = special.text.strip
77
- if url =~ /([A-Za-z]+):(.*)/
78
- type = $1
79
- path = $2
80
- else
81
- type = "http"
82
- path = url
83
- url = "http://#{url}"
84
- end
85
-
86
- case type
87
- when "http"
88
- if url =~ /\.(gif|png|jpg|jpeg|bmp)$/
89
- "<img src=\"#{url}\"/>"
90
- else
91
- "<a href=\"#{url}\">#{url.sub(%r{^\w+:/*}, '')}</a>"
92
- end
93
- when "img"
94
- "<img src=\"#{path}\"/>"
95
- when "link"
96
- "<a href=\"#{path}\">#{path}</a>"
97
- when "anchor"
98
- "<a name=\"#{path}\"></a>"
99
- else
100
- "<a href=\"#{url}\">#{url.sub(%r{^\w+:/*}, '')}</a>"
101
- end
102
- end
103
-
104
- # Here's a hyperlink where the label is different to the URL
105
- # [[url label that may contain spaces]]
106
- #
107
-
108
- def handle_special_TIDYLINK(special)
109
- text = special.text.strip
110
- return text[1..-1] if text[0,1] == '\\'
111
- unless text =~ /\[\[(\S+?)\s+(.+?)\]\]/
112
- return text
113
- end
114
- url = $1
115
- label = $2
116
- label = RDocFormatter.new(label).to_html
117
- label = label.split.select{|x| x =~ /\S/}.
118
- map{|x| x.chomp}.join(' ')
119
-
120
- case url
121
- when /link:(\S+)/
122
- return %{<a href="#{$1}">#{label}</a>}
123
- when /img:(\S+)/
124
- return %{<img src="http://#{$1}" alt="#{label}" />}
125
- when /rubytalk:(\S+)/
126
- return %{<a href="http://ruby-talk.org/blade/#{$1}">#{label}</a>}
127
- when /rubygarden:(\S+)/
128
- return %{<a href="http://www.rubygarden.org/ruby?#{$1}">#{label}</a>}
129
- when /c2:(\S+)/
130
- return %{<a href="http://c2.com/cgi/wiki?#{$1}">#{label}</a>}
131
- when /isbn:(\S+)/
132
- return %{<a href="http://search.barnesandnoble.com/bookSearch/} +
133
- %{isbnInquiry.asp?isbn=#{$1}">#{label}</a>}
134
- end
135
-
136
- unless url =~ /\w+?:/
137
- url = "http://#{url}"
138
- end
139
-
140
- "<a href=\"#{url}\">#{label}</a>"
141
- end
142
- end
143
-
144
- class RDocFormatter
145
- def initialize(text)
146
- @text = text
147
- end
148
-
149
- def to_html
150
- markup = RDocMarkup.new
151
- h = HyperLinkHtml.new
152
- markup.convert(@text, h)
153
- end
154
- end
155
-
1
+ begin
2
+ require "rdoc/markup/simple_markup"
3
+ require 'rdoc/markup/simple_markup/to_html'
4
+ rescue LoadError
5
+ # use old version if available
6
+ require 'markup/simple_markup'
7
+ require 'markup/simple_markup/to_html'
8
+ end
9
+
10
+ module RDocSupport
11
+
12
+ # A simple +rdoc+ markup class which recognizes some additional
13
+ # formatting commands suitable for Wiki use.
14
+ class RDocMarkup < SM::SimpleMarkup
15
+ def initialize
16
+ super()
17
+
18
+ pre = '(?:\\s|^|\\\\)'
19
+
20
+ # links of the form
21
+ # [[<url> description with spaces]]
22
+ add_special(/((\\)?\[\[\S+?\s+.+?\]\])/,:TIDYLINK)
23
+
24
+ # and external references
25
+ add_special(/((\\)?(link:|anchor:|http:|mailto:|ftp:|img:|www\.)\S+\w\/?)/,
26
+ :HYPERLINK)
27
+
28
+ # <br/>
29
+ add_special(%r{(#{pre}<br/>)}, :BR)
30
+
31
+ # and <center> ... </center>
32
+ add_html("center", :CENTER)
33
+ end
34
+
35
+ def convert(text, handler)
36
+ #$stderr.puts text.inspect
37
+ res = super
38
+ res.sub!(/^<p>\n/, '')
39
+ res.sub!(/<\/p>$/, '')
40
+ res
41
+ end
42
+ end
43
+
44
+ # Handle special hyperlinking requirments for RDoc formatted
45
+ # entries. Requires RDoc
46
+
47
+ class HyperLinkHtml < SM::ToHtml
48
+
49
+ # Initialize the HyperLinkHtml object.
50
+ # [path] location of the node
51
+ # [site] object representing the whole site (typically of class
52
+ # +Site+)
53
+ def initialize
54
+ super()
55
+ add_tag(:CENTER, "<center>", "</center>")
56
+ end
57
+
58
+ # handle <br/>
59
+ def handle_special_BR(special)
60
+ return "&lt;br/&gt" if special.text[0,1] == '\\'
61
+ special.text
62
+ end
63
+
64
+ # We're invoked with a potential external hyperlink.
65
+ # [mailto:] just gets inserted.
66
+ # [http:] links are checked to see if they
67
+ # reference an image. If so, that image gets inserted
68
+ # using an <img> tag. Otherwise a conventional <a href>
69
+ # is used.
70
+ # [img:] insert a <tt><img></tt> tag
71
+ # [link:] used to insert arbitrary <tt><a></tt> references
72
+ # [anchor:] used to create an anchor
73
+ def handle_special_HYPERLINK(special)
74
+ text = special.text.strip
75
+ return text[1..-1] if text[0,1] == '\\'
76
+ url = special.text.strip
77
+ if url =~ /([A-Za-z]+):(.*)/
78
+ type = $1
79
+ path = $2
80
+ else
81
+ type = "http"
82
+ path = url
83
+ url = "http://#{url}"
84
+ end
85
+
86
+ case type
87
+ when "http"
88
+ if url =~ /\.(gif|png|jpg|jpeg|bmp)$/
89
+ "<img src=\"#{url}\"/>"
90
+ else
91
+ "<a href=\"#{url}\">#{url.sub(%r{^\w+:/*}, '')}</a>"
92
+ end
93
+ when "img"
94
+ "<img src=\"#{path}\"/>"
95
+ when "link"
96
+ "<a href=\"#{path}\">#{path}</a>"
97
+ when "anchor"
98
+ "<a name=\"#{path}\"></a>"
99
+ else
100
+ "<a href=\"#{url}\">#{url.sub(%r{^\w+:/*}, '')}</a>"
101
+ end
102
+ end
103
+
104
+ # Here's a hyperlink where the label is different to the URL
105
+ # [[url label that may contain spaces]]
106
+ #
107
+
108
+ def handle_special_TIDYLINK(special)
109
+ text = special.text.strip
110
+ return text[1..-1] if text[0,1] == '\\'
111
+ unless text =~ /\[\[(\S+?)\s+(.+?)\]\]/
112
+ return text
113
+ end
114
+ url = $1
115
+ label = $2
116
+ label = RDocFormatter.new(label).to_html
117
+ label = label.split.select{|x| x =~ /\S/}.
118
+ map{|x| x.chomp}.join(' ')
119
+
120
+ case url
121
+ when /link:(\S+)/
122
+ return %{<a href="#{$1}">#{label}</a>}
123
+ when /img:(\S+)/
124
+ return %{<img src="http://#{$1}" alt="#{label}" />}
125
+ when /rubytalk:(\S+)/
126
+ return %{<a href="http://ruby-talk.org/blade/#{$1}">#{label}</a>}
127
+ when /rubygarden:(\S+)/
128
+ return %{<a href="http://www.rubygarden.org/ruby?#{$1}">#{label}</a>}
129
+ when /c2:(\S+)/
130
+ return %{<a href="http://c2.com/cgi/wiki?#{$1}">#{label}</a>}
131
+ when /isbn:(\S+)/
132
+ return %{<a href="http://search.barnesandnoble.com/bookSearch/} +
133
+ %{isbnInquiry.asp?isbn=#{$1}">#{label}</a>}
134
+ end
135
+
136
+ unless url =~ /\w+?:/
137
+ url = "http://#{url}"
138
+ end
139
+
140
+ "<a href=\"#{url}\">#{label}</a>"
141
+ end
142
+ end
143
+
144
+ class RDocFormatter
145
+ def initialize(text)
146
+ @text = text
147
+ end
148
+
149
+ def to_html
150
+ markup = RDocMarkup.new
151
+ h = HyperLinkHtml.new
152
+ markup.convert(@text, h)
153
+ end
154
+ end
155
+
156
156
  end