Pimki 1.3.092 → 1.4.092
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|