Autolink URLs like http://localhost:8000 (anything that has a schema like http:// and looks like a URL), in addition to internet URLs.
This commit is contained in:
parent
b74244ee3f
commit
dce2af06aa
|
@ -19,8 +19,7 @@ class URIChunk < Chunk::Abstract
|
|||
include URI::REGEXP::PATTERN
|
||||
|
||||
# this condition is to get rid of pesky warnings in tests
|
||||
unless defined? URI_CHUNK_CONSTANTS_DEFINED
|
||||
URI_CHUNK_CONSTANTS_DEFINED = true
|
||||
unless defined? URIChunk::INTERNET_URI_REGEXP
|
||||
|
||||
GENERIC = '(?:aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org)'
|
||||
COUNTRY = '(?:au|at|be|ca|ch|de|dk|fr|hk|in|ir|it|jp|nl|no|pt|ru|se|sw|tv|tw|uk|us)'
|
||||
|
@ -45,27 +44,28 @@ class URIChunk < Chunk::Abstract
|
|||
FRAGMENT = "#{URIC_NO_ENDING}*"
|
||||
|
||||
# DOMLABEL is defined in the ruby uri library, TLDS is defined above
|
||||
FULL_HOSTNAME = "(?:#{DOMLABEL}\\.)+#{TLDS}"
|
||||
INTERNET_HOSTNAME = "(?:#{DOMLABEL}\\.)+#{TLDS}"
|
||||
|
||||
# Correct a typo bug in ruby 1.8.x lib/uri/common.rb
|
||||
PORT = '\\d*'
|
||||
|
||||
URI_PATTERN =
|
||||
INTERNET_URI =
|
||||
"(?:(#{SCHEME}):/{0,2})?" + # Optional scheme: (\1)
|
||||
"(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2)
|
||||
"(#{FULL_HOSTNAME})" + # Mandatory hostname (\3)
|
||||
"(#{INTERNET_HOSTNAME})" + # Mandatory hostname (\3)
|
||||
"(?::(#{PORT}))?" + # Optional :port (\4)
|
||||
"(#{ABS_PATH})?" + # Optional absolute path (\5)
|
||||
"(?:\\?(#{QUERY}))?" + # Optional ?query (\6)
|
||||
"(?:\\#(#{FRAGMENT}))?" # Optional #fragment (\7)
|
||||
|
||||
TEXTILE_SYNTAX_PREFIX = '(!)?'
|
||||
|
||||
INTERNET_URI_REGEXP = Regexp.new(TEXTILE_SYNTAX_PREFIX + INTERNET_URI, Regexp::EXTENDED, 'N')
|
||||
|
||||
end
|
||||
|
||||
TEXTILE_SYNTAX_PREFIX = '(!)?'
|
||||
|
||||
URI_PATTERN_REGEXP = Regexp.new(TEXTILE_SYNTAX_PREFIX + URI_PATTERN, Regexp::EXTENDED, 'N')
|
||||
|
||||
def self.pattern
|
||||
URI_PATTERN_REGEXP
|
||||
INTERNET_URI_REGEXP
|
||||
end
|
||||
|
||||
attr_reader :uri, :scheme, :user, :host, :port, :path, :query, :fragment, :link_text
|
||||
|
@ -149,3 +149,31 @@ class URIChunk < Chunk::Abstract
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
# uri with mandatory scheme but less restrictive hostname, like
|
||||
# http://localhost:2500/blah.html
|
||||
class LocalURIChunk < URIChunk
|
||||
|
||||
unless defined? LocalURIChunk::LOCAL_URI_REGEXP
|
||||
# hostname can be just a simple word like 'localhost'
|
||||
ANY_HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?"
|
||||
|
||||
# The basic URI expression as a string
|
||||
# Scheme and hostname are mandatory
|
||||
LOCAL_URI =
|
||||
"(?:(#{SCHEME})://)+" + # Mandatory scheme:// (\1)
|
||||
"(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2)
|
||||
"(#{ANY_HOSTNAME})" + # Mandatory hostname (\3)
|
||||
"(?::(#{PORT}))?" + # Optional :port (\4)
|
||||
"(#{ABS_PATH})?" + # Optional absolute path (\5)
|
||||
"(?:\\?(#{QUERY}))?" + # Optional ?query (\6)
|
||||
"(?:\\#(#{FRAGMENT}))?" # Optional #fragment (\7)
|
||||
|
||||
LOCAL_URI_REGEXP = Regexp.new(TEXTILE_SYNTAX_PREFIX + LOCAL_URI, Regexp::EXTENDED, 'N')
|
||||
end
|
||||
|
||||
def self.pattern
|
||||
LOCAL_URI_REGEXP
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -39,7 +39,9 @@ require 'chunks/nowiki'
|
|||
# UPDATED: 22nd May 2004
|
||||
class WikiContent < String
|
||||
|
||||
PRE_ENGINE_ACTIONS = [ NoWiki, Category, Include, URIChunk, WikiChunk::Link, WikiChunk::Word ]
|
||||
PRE_ENGINE_ACTIONS = [ NoWiki, Category, Include,
|
||||
URIChunk, LocalURIChunk,
|
||||
WikiChunk::Link, WikiChunk::Word ]
|
||||
POST_ENGINE_ACTIONS = [ Literal::Pre, Literal::Tags ]
|
||||
DEFAULT_OPTS = {
|
||||
:pre_engine_actions => PRE_ENGINE_ACTIONS,
|
||||
|
|
|
@ -36,37 +36,32 @@ end
|
|||
# This module is to be included in unit tests that involve matching chunks.
|
||||
# It provides a easy way to test whether a chunk matches a particular string
|
||||
# and any the values of any fields that should be set after a match.
|
||||
class ContentStub < String
|
||||
attr_reader :chunks, :content
|
||||
def initialize(str)
|
||||
super
|
||||
@chunks = []
|
||||
end
|
||||
end
|
||||
|
||||
module ChunkMatch
|
||||
|
||||
# Asserts a number of tests for the given type and text.
|
||||
def match(type, test_text, expected)
|
||||
pattern = type.pattern
|
||||
assert_match(pattern, test_text)
|
||||
pattern =~ test_text # Previous assertion guarantees match
|
||||
chunk = type.new($~)
|
||||
def match(chunk_type, test_text, expected_chunk_state)
|
||||
if chunk_type.respond_to? :pattern
|
||||
assert_match(chunk_type.pattern, test_text)
|
||||
end
|
||||
|
||||
content = ContentStub.new(test_text)
|
||||
chunk_type.apply_to(content)
|
||||
|
||||
# Test if requested parts are correct.
|
||||
for method_sym, value in expected do
|
||||
assert_respond_to(chunk, method_sym)
|
||||
assert_equal(value, chunk.method(method_sym).call, "Checking value of '#{method_sym}'")
|
||||
expected_chunk_state.each_pair do |a_method, expected_value|
|
||||
assert content.chunks.last.kind_of?(chunk_type)
|
||||
assert_respond_to(content.chunks.last, a_method)
|
||||
assert_equal(expected_value, content.chunks.last.send(a_method.to_sym),
|
||||
"Wrong #{a_method} value")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ActionController
|
||||
class TestResponse
|
||||
def binary_content
|
||||
sio = StringIO.new
|
||||
begin
|
||||
$stdout = sio
|
||||
body.call
|
||||
ensure
|
||||
$stdout = STDOUT
|
||||
end
|
||||
|
||||
sio.rewind
|
||||
sio.read
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,8 +7,9 @@ class URITest < Test::Unit::TestCase
|
|||
include ChunkMatch
|
||||
|
||||
def test_non_matches
|
||||
assert_no_match(URIChunk.pattern, 'There is no URI here')
|
||||
assert_no_match(URIChunk.pattern, 'One gemstone is the garnet:reddish in colour, like ruby')
|
||||
assert_conversion_does_not_apply(URIChunk, 'There is no URI here')
|
||||
assert_conversion_does_not_apply(URIChunk,
|
||||
'One gemstone is the garnet:reddish in colour, like ruby')
|
||||
end
|
||||
|
||||
def test_simple_uri
|
||||
|
@ -110,9 +111,9 @@ class URITest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_non_uri
|
||||
assert_no_match(URIChunk.pattern, 'httpd.conf')
|
||||
assert_no_match(URIChunk.pattern, 'libproxy.so')
|
||||
assert_no_match(URIChunk.pattern, 'ld.so.conf')
|
||||
assert_conversion_does_not_apply URIChunk, 'httpd.conf'
|
||||
assert_conversion_does_not_apply URIChunk, 'libproxy.so'
|
||||
assert_conversion_does_not_apply URIChunk, 'ld.so.conf'
|
||||
end
|
||||
|
||||
def test_uri_in_text
|
||||
|
@ -152,4 +153,27 @@ class URITest < Test::Unit::TestCase
|
|||
:query => 'arg=val,')
|
||||
end
|
||||
|
||||
def test_local_urls
|
||||
# normal
|
||||
match(LocalURIChunk, 'http://perforce:8001/toto.html',
|
||||
:scheme => 'http', :host => 'perforce',
|
||||
:port => '8001', :link_text => 'http://perforce:8001/toto.html')
|
||||
|
||||
# in parentheses
|
||||
match(LocalURIChunk, 'URI (http://localhost:2500) in brackets',
|
||||
:host => 'localhost', :port => '2500')
|
||||
match(LocalURIChunk, 'because (as shown at http://perforce:8001) the results',
|
||||
:host => 'perforce', :port => '8001')
|
||||
match(LocalURIChunk,
|
||||
'A wiki (http://localhost:2500/wiki.cgi?WhatIsWiki) page',
|
||||
:scheme => 'http', :host => 'localhost', :path => '/wiki.cgi',
|
||||
:port => '2500', :query => 'WhatIsWiki')
|
||||
end
|
||||
|
||||
def assert_conversion_does_not_apply(chunk_type, str)
|
||||
processed_str = str.dup
|
||||
URIChunk.apply_to(processed_str)
|
||||
assert_equal(str, processed_str)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue