Pimki 1.3.092 → 1.4.092
Sign up to get free protection for your applications and to get access to all the features.
- data/README +145 -131
- data/README-PIMKI +15 -5
- data/app/controllers/wiki.rb +167 -54
- data/app/models/author.rb +3 -3
- data/app/models/chunks/chunk.rb +3 -3
- data/app/models/chunks/engines.rb +18 -21
- data/app/models/chunks/include.rb +29 -29
- data/app/models/chunks/literal.rb +20 -20
- data/app/models/chunks/match.rb +19 -19
- data/app/models/chunks/nowiki.rb +31 -31
- data/app/models/chunks/nowiki_test.rb +14 -14
- data/app/models/chunks/test.rb +18 -18
- data/app/models/chunks/todo.rb +44 -23
- data/app/models/chunks/uri.rb +97 -97
- data/app/models/chunks/uri_test.rb +92 -92
- data/app/models/chunks/wiki.rb +4 -4
- data/app/models/chunks/wiki_symbols.rb +22 -22
- data/app/models/chunks/wiki_test.rb +36 -36
- data/app/models/page.rb +39 -7
- data/app/models/page_lock.rb +23 -23
- data/app/models/page_set.rb +72 -72
- data/app/models/page_test.rb +75 -75
- data/app/models/revision.rb +1 -1
- data/app/models/revision_test.rb +251 -251
- data/app/models/web.rb +19 -6
- data/app/models/web_test.rb +52 -52
- data/app/models/wiki_content.rb +131 -119
- data/app/models/wiki_service.rb +31 -16
- data/app/models/wiki_service_test.rb +15 -15
- data/app/models/wiki_words.rb +1 -1
- data/app/models/wiki_words_test.rb +12 -12
- data/app/views/bottom.rhtml +3 -3
- data/app/views/markdown_help.rhtml +15 -15
- data/app/views/menu.rhtml +20 -20
- data/app/views/navigation.rhtml +26 -26
- data/app/views/rdoc_help.rhtml +15 -15
- data/app/views/static_style_sheet.rhtml +237 -237
- data/app/views/style.rhtml +178 -178
- data/app/views/textile_help.rhtml +27 -27
- data/app/views/top.rhtml +7 -2
- data/app/views/wiki/authors.rhtml +15 -15
- data/app/views/wiki/bliki.rhtml +101 -101
- data/app/views/wiki/bliki_edit.rhtml +3 -0
- data/app/views/wiki/bliki_new.rhtml +3 -0
- data/app/views/wiki/bliki_revision.rhtml +90 -90
- data/app/views/wiki/edit.rhtml +12 -3
- data/app/views/wiki/edit_menu.rhtml +64 -47
- data/app/views/wiki/edit_web.rhtml +65 -18
- data/app/views/wiki/export.rhtml +14 -14
- data/app/views/wiki/feeds.rhtml +10 -10
- data/app/views/wiki/list.rhtml +17 -15
- data/app/views/wiki/locked.rhtml +13 -13
- data/app/views/wiki/login.rhtml +10 -10
- data/app/views/wiki/mind.rhtml +0 -1
- data/app/views/wiki/new.rhtml +8 -3
- data/app/views/wiki/new_system.rhtml +77 -77
- data/app/views/wiki/new_web.rhtml +63 -63
- data/app/views/wiki/page.rhtml +88 -82
- data/app/views/wiki/print.rhtml +15 -15
- data/app/views/wiki/published.rhtml +2 -1
- data/app/views/wiki/recently_revised.rhtml +31 -31
- data/app/views/wiki/revision.rhtml +1 -7
- data/app/views/wiki/rollback.rhtml +31 -0
- data/app/views/wiki/rss_feed.rhtml +21 -21
- data/app/views/wiki/search.rhtml +48 -48
- data/app/views/wiki/tex.rhtml +22 -22
- data/app/views/wiki/tex_web.rhtml +34 -34
- data/app/views/wiki/todo.rhtml +90 -67
- data/app/views/wiki/web_list.rhtml +12 -12
- data/app/views/wiki_words_help.rhtml +1 -1
- data/favicon.png +0 -0
- data/libraries/action_controller_servlet.rb +17 -2
- data/libraries/bluecloth.rb +1127 -1127
- data/libraries/diff/diff.rb +474 -474
- data/libraries/diff/diff_test.rb +79 -79
- data/libraries/erb.rb +490 -490
- data/libraries/madeleine/automatic.rb +418 -357
- data/libraries/madeleine/clock.rb +94 -94
- data/libraries/madeleine/files.rb +19 -0
- data/libraries/madeleine/zmarshal.rb +60 -0
- data/libraries/madeleine_service.rb +14 -15
- data/libraries/rdocsupport.rb +155 -155
- data/libraries/redcloth_for_tex.rb +869 -869
- data/libraries/redcloth_for_tex_test.rb +40 -40
- data/libraries/view_helper.rb +32 -32
- data/libraries/web_controller_server.rb +96 -94
- data/pimki.rb +47 -6
- 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 =
|
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
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
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
|
|
data/libraries/rdocsupport.rb
CHANGED
@@ -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 "<br/>" 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 "<br/>" 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
|