Pimki 1.0.092

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/README +158 -0
  2. data/README-PIMKI +87 -0
  3. data/app/controllers/wiki.rb +563 -0
  4. data/app/models/author.rb +4 -0
  5. data/app/models/chunks/category.rb +31 -0
  6. data/app/models/chunks/category_test.rb +21 -0
  7. data/app/models/chunks/chunk.rb +20 -0
  8. data/app/models/chunks/engines.rb +34 -0
  9. data/app/models/chunks/include.rb +29 -0
  10. data/app/models/chunks/literal.rb +19 -0
  11. data/app/models/chunks/match.rb +19 -0
  12. data/app/models/chunks/nowiki.rb +31 -0
  13. data/app/models/chunks/nowiki_test.rb +14 -0
  14. data/app/models/chunks/test.rb +18 -0
  15. data/app/models/chunks/todo.rb +22 -0
  16. data/app/models/chunks/uri.rb +97 -0
  17. data/app/models/chunks/uri_test.rb +92 -0
  18. data/app/models/chunks/wiki.rb +82 -0
  19. data/app/models/chunks/wiki_test.rb +36 -0
  20. data/app/models/page.rb +91 -0
  21. data/app/models/page_lock.rb +24 -0
  22. data/app/models/page_set.rb +73 -0
  23. data/app/models/page_test.rb +76 -0
  24. data/app/models/revision.rb +91 -0
  25. data/app/models/revision_test.rb +252 -0
  26. data/app/models/web.rb +277 -0
  27. data/app/models/web_test.rb +53 -0
  28. data/app/models/wiki_content.rb +113 -0
  29. data/app/models/wiki_service.rb +137 -0
  30. data/app/models/wiki_service_test.rb +15 -0
  31. data/app/models/wiki_words.rb +26 -0
  32. data/app/models/wiki_words_test.rb +12 -0
  33. data/app/views/bottom.rhtml +4 -0
  34. data/app/views/markdown_help.rhtml +16 -0
  35. data/app/views/menu.rhtml +20 -0
  36. data/app/views/navigation.rhtml +26 -0
  37. data/app/views/rdoc_help.rhtml +16 -0
  38. data/app/views/static_style_sheet.rhtml +231 -0
  39. data/app/views/style.rhtml +179 -0
  40. data/app/views/textile_help.rhtml +28 -0
  41. data/app/views/top.rhtml +52 -0
  42. data/app/views/wiki/authors.rhtml +15 -0
  43. data/app/views/wiki/bliki.rhtml +101 -0
  44. data/app/views/wiki/bliki_edit.rhtml +33 -0
  45. data/app/views/wiki/bliki_new.rhtml +61 -0
  46. data/app/views/wiki/bliki_revision.rhtml +51 -0
  47. data/app/views/wiki/edit.rhtml +34 -0
  48. data/app/views/wiki/edit_menu.rhtml +27 -0
  49. data/app/views/wiki/edit_web.rhtml +139 -0
  50. data/app/views/wiki/export.rhtml +14 -0
  51. data/app/views/wiki/feeds.rhtml +10 -0
  52. data/app/views/wiki/list.rhtml +164 -0
  53. data/app/views/wiki/locked.rhtml +14 -0
  54. data/app/views/wiki/login.rhtml +11 -0
  55. data/app/views/wiki/mind.rhtml +39 -0
  56. data/app/views/wiki/new.rhtml +27 -0
  57. data/app/views/wiki/new_system.rhtml +78 -0
  58. data/app/views/wiki/new_web.rhtml +64 -0
  59. data/app/views/wiki/page.rhtml +84 -0
  60. data/app/views/wiki/print.rhtml +16 -0
  61. data/app/views/wiki/published.rhtml +10 -0
  62. data/app/views/wiki/recently_revised.rhtml +31 -0
  63. data/app/views/wiki/revision.rhtml +87 -0
  64. data/app/views/wiki/rss_feed.rhtml +22 -0
  65. data/app/views/wiki/search.rhtml +26 -0
  66. data/app/views/wiki/tex.rhtml +23 -0
  67. data/app/views/wiki/tex_web.rhtml +35 -0
  68. data/app/views/wiki/todo.rhtml +39 -0
  69. data/app/views/wiki/web_list.rhtml +13 -0
  70. data/app/views/wiki_words_help.rhtml +8 -0
  71. data/libraries/action_controller_servlet.rb +177 -0
  72. data/libraries/bluecloth.rb +1127 -0
  73. data/libraries/diff/diff.rb +475 -0
  74. data/libraries/diff/diff_test.rb +80 -0
  75. data/libraries/erb.rb +490 -0
  76. data/libraries/madeleine/automatic.rb +357 -0
  77. data/libraries/madeleine/clock.rb +94 -0
  78. data/libraries/madeleine_service.rb +69 -0
  79. data/libraries/rdocsupport.rb +156 -0
  80. data/libraries/redcloth_for_tex.rb +869 -0
  81. data/libraries/redcloth_for_tex_test.rb +41 -0
  82. data/libraries/view_helper.rb +33 -0
  83. data/libraries/web_controller_server.rb +95 -0
  84. data/pimki.rb +97 -0
  85. metadata +169 -0
@@ -0,0 +1,4 @@
1
+ class Author < String
2
+ attr_accessor :ip
3
+ def initialize(name, ip) @ip = ip; super(name) end
4
+ end
@@ -0,0 +1,31 @@
1
+ require 'chunks/chunk'
2
+
3
+ # The category chunk looks for "category: news" on a line by
4
+ # itself and parses the terms after the ':' as categories.
5
+ # Other classes can search for Category chunks within
6
+ # rendered content to find out what categories this page
7
+ # should be in.
8
+ #
9
+ # Category lines can be hidden using ':category: news', for example
10
+ class Category < Chunk::Abstract
11
+ def self.pattern() return /^(:)?category\s*:(.*)$/i end
12
+
13
+ attr_reader :hidden, :list
14
+
15
+ def initialize(match_data)
16
+ super(match_data)
17
+ @hidden = match_data[1]
18
+ @list = match_data[2].split(',').map { |c| c.strip }
19
+ end
20
+
21
+ # Mark this chunk's start and end points but allow the terms
22
+ # after the ':' to be marked up.
23
+ def mask(content) pre_mask + list.join(', ') + post_mask end
24
+
25
+ # If the chunk is hidden, erase the mask and return this chunk
26
+ # otherwise, surround it with a 'div' block.
27
+ def unmask(content)
28
+ replacement = ( hidden ? '' : '<div class="property">category:\1</div>' )
29
+ self if content.sub!( Regexp.new( pre_mask+'(.*)?'+post_mask ), replacement )
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ require 'chunks/category'
2
+ require 'chunks/match'
3
+ require 'test/unit'
4
+
5
+ class CategoryTest < Test::Unit::TestCase
6
+ include ChunkMatch
7
+
8
+ def test_single_category
9
+ match(Category, 'category: test', :list => ['test'], :hidden => nil)
10
+ match(Category, 'category : chunk test ', :list => ['chunk test'], :hidden => nil)
11
+ match(Category, ':category: test', :list => ['test'], :hidden => ':')
12
+ end
13
+
14
+ def test_multiple_categories
15
+ match(Category, 'category: test, multiple', :list => ['test', 'multiple'], :hidden => nil)
16
+ match(Category, 'category : chunk test , multi category,regression test case ',
17
+ :list => ['chunk test','multi category','regression test case'], :hidden => nil
18
+ )
19
+ end
20
+
21
+ end
@@ -0,0 +1,20 @@
1
+ require 'digest/md5'
2
+ require 'uri/common'
3
+
4
+ # A chunk is a pattern of text that can be protected
5
+ # and interrogated by a renderer. Each Chunk class has a
6
+ # +pattern+ that states what sort of text it matches.
7
+ # Chunks are initalized by passing in the result of a
8
+ # match by its pattern.
9
+ module Chunk
10
+ class Abstract
11
+ attr_reader :text
12
+
13
+ def initialize(match_data) @text = match_data[0] end
14
+ def pre_mask() "chunk#{self.id}start " end
15
+ def post_mask() " chunk#{self.id}end" end
16
+ def mask(content) "chunk#{self.id}chunk" end
17
+ def revert(content) content.sub!( Regexp.new(mask(content)), text ) end
18
+ def unmask(content) self if revert(content) end
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ require 'rdocsupport'
2
+ require 'chunks/chunk'
3
+
4
+ # The markup engines are Chunks that call the one of RedCloth, BlueCloth
5
+ # or RDoc to convert text. This markup occurs when the chunk is required
6
+ # to mask itself.
7
+ module Engines
8
+ class Textile < Chunk::Abstract
9
+ def self.pattern() /^(.*)$/m end
10
+ def mask(content)
11
+ RedCloth.new(text,content.options[:engine_opts]).to_html
12
+ end
13
+ def unmask(content) self end
14
+ end
15
+
16
+ class Markdown < Chunk::Abstract
17
+ def self.pattern() /^(.*)$/m end
18
+ def mask(content)
19
+ BlueCloth.new(text,content.options[:engine_opts]).to_html
20
+ end
21
+ def unmask(content) self end
22
+ end
23
+
24
+ class RDoc < Chunk::Abstract
25
+ def self.pattern() /^(.*)$/m end
26
+ def mask(content)
27
+ RDocSupport::RDocFormatter.new(text).to_html
28
+ end
29
+ def unmask(content) self end
30
+ end
31
+
32
+ MAP = { :textile => Textile, :markdown => Markdown, :rdoc => RDoc }
33
+ end
34
+
@@ -0,0 +1,29 @@
1
+ require 'chunks/wiki'
2
+
3
+ # Includes the contents of another page for rendering.
4
+ # The include command looks like this: "[[!include PageName]]".
5
+ # It is a WikiLink since it refers to another page (PageName)
6
+ # and the wiki content using this command must be notified
7
+ # of changes to that page.
8
+ # If the included page could not be found, a warning is displayed.
9
+ class Include < WikiChunk::WikiLink
10
+ def self.pattern() /^\[\[!include(.*)\]\]\s*$/i end
11
+
12
+ attr_reader :page_name
13
+
14
+ def initialize(match_data)
15
+ super(match_data)
16
+ @page_name = match_data[1].strip
17
+ end
18
+
19
+ # This replaces the [[!include PageName]] text with
20
+ # the contents of PageName if it exists. Otherwise
21
+ # a warning is displayed.
22
+ def mask(content)
23
+ page = content.web.pages[page_name]
24
+ (page ? page.content : "<em>Could not include #{page_name}</em>")
25
+ end
26
+
27
+ # Keep this chunk regardless of what happens.
28
+ def unmask(content) self end
29
+ end
@@ -0,0 +1,19 @@
1
+ require 'chunks/chunk'
2
+
3
+ # These are basic chunks that have a pattern and can be protected.
4
+ # They are used by rendering process to prevent wiki rendering
5
+ # occuring within literal areas such as <code> and <pre> blocks
6
+ # and within HTML tags.
7
+ module Literal
8
+ # A literal chunk that protects 'code' and 'pre' tags from wiki rendering.
9
+ class Pre < Chunk::Abstract
10
+ PRE_BLOCKS = "a|pre|code"
11
+ def self.pattern() Regexp.new('<('+PRE_BLOCKS+')\b[^>]*?>.*?</\1>', Regexp::MULTILINE) end
12
+ end
13
+
14
+ # A literal chunk that protects HTML tags from wiki rendering.
15
+ class Tags < Chunk::Abstract
16
+ TAGS = "a|img|em|strong|div|span|table|td|th|ul|ol|li|dl|dt|dd"
17
+ def self.pattern() Regexp.new('<(?:'+TAGS+')[^>]*?>', Regexp::MULTILINE) end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # This module is to be included in unit tests that involve matching chunks.
2
+ # It provides a easy way to test whether a chunk matches a particular string
3
+ # and any the values of any fields that should be set after a match.
4
+ module ChunkMatch
5
+
6
+ # Asserts a number of tests for the given type and text.
7
+ def match(type, test_text, expected)
8
+ pattern = type.pattern
9
+ assert_match(pattern, test_text)
10
+ pattern =~ test_text # Previous assertion guarantees match
11
+ chunk = type.new($~)
12
+
13
+ # Test if requested parts are correct.
14
+ for method_sym, value in expected do
15
+ assert_respond_to(chunk, method_sym)
16
+ assert_equal(value, chunk.method(method_sym).call, "Checking value of '#{method_sym}'")
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
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
+ def self.pattern() Regexp.new('<nowiki>(.*?)</nowiki>') end
19
+
20
+ attr_reader :plain_text
21
+
22
+ def initialize(match_data)
23
+ super(match_data)
24
+ @plain_text = match_data[1]
25
+ end
26
+
27
+ # The nowiki content is not unmasked. This means the chunk will be reverted
28
+ # using the plain text.
29
+ def unmask(content) nil end
30
+ def revert(content) content.sub!( Regexp.new(mask(content)), plain_text ) end
31
+ end
@@ -0,0 +1,14 @@
1
+ require 'chunks/nowiki'
2
+ require 'chunks/match'
3
+ require 'test/unit'
4
+
5
+ class NoWikiTest < Test::Unit::TestCase
6
+ include ChunkMatch
7
+
8
+ def test_simple_nowiki
9
+ match(NoWiki, 'This sentence contains <nowiki>[[raw text]]</nowiki>. Do not touch!',
10
+ :plain_text => '[[raw text]]'
11
+ )
12
+ end
13
+
14
+ end
@@ -0,0 +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
@@ -0,0 +1,22 @@
1
+ require 'chunks/wiki'
2
+ require 'date'
3
+ require 'parsedate'
4
+
5
+ # ToDo items.
6
+ class Todo < Chunk::Abstract
7
+ def self.pattern() /todo: ([^\n]+)/i end
8
+
9
+ def initialize(match_data)
10
+ super(match_data)
11
+ end
12
+
13
+ def escaped_text() nil end
14
+
15
+ def unmask(content)
16
+ return self if content.gsub!( Regexp.new(mask(content)),
17
+ # the style 'todo' is bright-red to be eye catching. It is not expected that
18
+ # there will be too many items on one page, but each is supposed to stand out.
19
+ # The ToDo special page differentiates between the 'todo' and 'todoFuture' styles.
20
+ "<span class=\"todo\"><strong>TODO:</strong> #{@text.gsub(/todo:\s*/, '')}</span>" )
21
+ end
22
+ end
@@ -0,0 +1,97 @@
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
+ class URIChunk < Chunk::Abstract
19
+ include URI::REGEXP::PATTERN
20
+
21
+ GENERIC = '(?:aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org)'
22
+ COUNTRY = '(?:au|at|be|ca|ch|de|dk|fr|hk|in|ir|it|jp|nl|no|pt|ru|se|sw|tv|tw|uk|us)'
23
+
24
+ # These are needed otherwise HOST will match almost anything
25
+ TLDS = "\\.(?:#{GENERIC}|#{COUNTRY})"
26
+
27
+ # Redefine USERINFO so that it must have non-zero length
28
+ USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})+"
29
+
30
+ # Pattern of legal URI endings to stop interference with some Textile
31
+ # markup. (Images: !URI!) and other punctuation eg, (http://wiki.com/)
32
+ URI_ENDING = '[)!]'
33
+
34
+ # The basic URI expression as a string
35
+ URI_PATTERN =
36
+ "(?:(#{SCHEME})://)?" + # Optional scheme:// (\1|\8)
37
+ "(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2|\9)
38
+ "(#{HOSTNAME}#{TLDS})" + # Mandatory host eg, HOST.com.au (\3|\10)
39
+ "(?::(#{PORT}))?" + # Optional :port (\4|\11)
40
+ "(#{ABS_PATH})?" + # Optional absolute path (\5|\12)
41
+ "(?:\\?(#{QUERY}))?" + # Optional ?query (\6|\13)
42
+ "(?:\\#(#{FRAGMENT}))?" # Optional #fragment (\7|\14)
43
+
44
+ def self.pattern()
45
+ # This pattern first tries to match the URI_PATTERN that ends with
46
+ # punctuation that is a valid URI character (eg, ')', '!'). If
47
+ # such a match occurs, there should be no backtracking (hence the ?> ).
48
+ # If the string cannot match a URI ending with URI_ENDING, then a second
49
+ # attempt is tried.
50
+ Regexp.new("(?>#{URI_PATTERN}(?=#{URI_ENDING}))|#{URI_PATTERN}", Regexp::EXTENDED, 'N')
51
+ end
52
+
53
+ attr_reader :uri, :scheme, :user, :host, :port, :path, :query, :fragment, :link_text
54
+
55
+ def initialize(match_data)
56
+ super(match_data)
57
+ # Since the URI_PATTERN is tried twice, there are two sets of
58
+ # groups, one from \1 to \7 and the second from \8 to \14.
59
+ # The fields are set by which ever group matches.
60
+ @scheme = match_data[1] || match_data[8]
61
+ @user = match_data[2] || match_data[9]
62
+ @host = match_data[3] || match_data[10]
63
+ @port = match_data[4] || match_data[11]
64
+ @path = match_data[5] || match_data[12]
65
+ @query = match_data[6] || match_data[13]
66
+ @fragment = match_data[7] || match_data[14]
67
+
68
+ # If there is no scheme, add an appropriate one, otherwise
69
+ # set the URI to the matched text.
70
+ @text_scheme = scheme
71
+ @uri = (scheme ? match_data[0] : nil )
72
+ @scheme = scheme || ( user ? 'mailto' : 'http' )
73
+ @delimiter = ( scheme == 'mailto' ? ':' : '://' )
74
+ @uri ||= scheme + @delimiter + match_data[0]
75
+
76
+ # Build up the link text. Schemes are omitted unless explicitly given.
77
+ @link_text = ''
78
+ @link_text << "#{@scheme}#{@delimiter}" if @text_scheme
79
+ @link_text << "#{@user}@" if @user
80
+ @link_text << "#{@host}" if @host
81
+ @link_text << ":#{@port}" if @port
82
+ @link_text << "#{@path}" if @path
83
+ @link_text << "?#{@query}" if @query
84
+ end
85
+
86
+ # If the text should be escaped then don't keep this chunk.
87
+ # Otherwise only keep this chunk if it was substituted back into the
88
+ # content.
89
+ def unmask(content)
90
+ return nil if escaped_text
91
+ return self if content.sub!( Regexp.new(mask(content)), "<a href=\"#{uri}\">#{link_text}</a>" )
92
+ end
93
+
94
+ # If there is no hostname in the URI, do not render it
95
+ # It's probably only contains the scheme, eg 'something:'
96
+ def escaped_text() ( host.nil? ? @uri : nil ) end
97
+ end
@@ -0,0 +1,92 @@
1
+ require 'chunks/uri'
2
+ require 'chunks/match'
3
+ require 'test/unit'
4
+
5
+ class URITest < Test::Unit::TestCase
6
+ include ChunkMatch
7
+
8
+ def test_non_matches
9
+ assert_no_match(URIChunk.pattern, 'There is no URI here')
10
+ assert_no_match(URIChunk.pattern, 'One gemstone is the garnet:reddish in colour, like ruby')
11
+ end
12
+
13
+ def test_simple_uri
14
+ match(URIChunk, 'http://www.example.com',
15
+ :scheme =>'http', :host =>'www.example.com', :path => nil,
16
+ :link_text => 'http://www.example.com'
17
+ )
18
+ match(URIChunk, 'http://www.example.com/',
19
+ :scheme =>'http', :host =>'www.example.com', :path => '/',
20
+ :link_text => 'http://www.example.com/'
21
+ )
22
+ match(URIChunk, 'www.example.com',
23
+ :scheme =>'http', :host =>'www.example.com', :link_text => 'www.example.com'
24
+ )
25
+ match(URIChunk, 'example.com',
26
+ :scheme =>'http',:host =>'example.com', :link_text => 'example.com'
27
+ )
28
+ match(URIChunk, 'http://example.com.au/',
29
+ :scheme =>'http', :host =>'example.com.au', :link_text => 'http://example.com.au/'
30
+ )
31
+ match(URIChunk, 'example.com.au',
32
+ :scheme =>'http', :host =>'example.com.au', :link_text => 'example.com.au'
33
+ )
34
+ match(URIChunk, 'http://www.example.co.uk/',
35
+ :scheme =>'http', :host =>'www.example.co.uk',
36
+ :link_text => 'http://www.example.co.uk/'
37
+ )
38
+ match(URIChunk, 'example.co.uk',
39
+ :scheme =>'http', :host =>'example.co.uk', :link_text => 'example.co.uk'
40
+ )
41
+ match(URIChunk, 'http://moinmoin.wikiwikiweb.de/HelpOnNavigation',
42
+ :scheme => 'http', :host => 'moinmoin.wikiwikiweb.de', :path => '/HelpOnNavigation',
43
+ :link_text => 'http://moinmoin.wikiwikiweb.de/HelpOnNavigation'
44
+ )
45
+ match(URIChunk, 'moinmoin.wikiwikiweb.de/HelpOnNavigation',
46
+ :scheme => 'http', :host => 'moinmoin.wikiwikiweb.de', :path => '/HelpOnNavigation',
47
+ :link_text => 'moinmoin.wikiwikiweb.de/HelpOnNavigation'
48
+ )
49
+ end
50
+
51
+ def test_email_uri
52
+ match(URIChunk, 'mail@example.com',
53
+ :user => 'mail', :host => 'example.com', :link_text => 'mail@example.com'
54
+ )
55
+ end
56
+
57
+ def test_non_email
58
+ # The @ is part of the normal text, but 'example.com' is marked up.
59
+ match(URIChunk, 'Not an email: @example.com', :user => nil, :uri => 'http://example.com')
60
+ end
61
+
62
+ def test_non_uri
63
+ assert_no_match(URIChunk.pattern, 'httpd.conf')
64
+ assert_no_match(URIChunk.pattern, 'libproxy.so')
65
+ end
66
+
67
+ def test_uri_in_text
68
+ match(URIChunk, 'Go to: http://www.example.com/', :host => 'www.example.com', :path =>'/')
69
+ match(URIChunk, 'http://www.example.com/ is a link.', :host => 'www.example.com')
70
+ match(URIChunk,
71
+ 'Email david@loudthinking.com',
72
+ :scheme =>'mailto', :user =>'david', :host =>'loudthinking.com'
73
+ )
74
+ end
75
+
76
+ def test_uri_in_parentheses
77
+ match(URIChunk, 'URI (http://brackets.com.de) in brackets', :host => 'brackets.com.de')
78
+ match(URIChunk, 'because (as shown at research.net) the results', :host => 'research.net')
79
+ match(URIChunk,
80
+ 'A wiki (http://wiki.org/wiki.cgi?WhatIsWiki) page',
81
+ :scheme => 'http', :host => 'wiki.org', :path => '/wiki.cgi', :query => 'WhatIsWiki'
82
+ )
83
+ end
84
+
85
+ def test_uri_list_item
86
+ match(
87
+ URIChunk,
88
+ '* http://www.btinternet.com/~mail2minh/SonyEricssonP80xPlatform.sis',
89
+ :path => '/~mail2minh/SonyEricssonP80xPlatform.sis'
90
+ )
91
+ end
92
+ end