Changesets can be listed by changeset number.
The Git repository is here.
- Revision:
- 2
- Log:
Initial import of Instiki 0.11.0 sources from a downloaded Tarball.
Instiki is a Ruby On Rails based Wiki clone.
- Author:
- adh
- Date:
- Sat Jul 22 14:54:51 +0100 2006
- Size:
- 6880 Bytes
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 | |
19 | class URIChunk < Chunk::Abstract |
20 | include URI::REGEXP::PATTERN |
21 | |
22 | # this condition is to get rid of pesky warnings in tests |
23 | unless defined? URIChunk::INTERNET_URI_REGEXP |
24 | |
25 | GENERIC = 'aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org' |
26 | |
27 | COUNTRY = 'ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|' + |
28 | 'bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cf|cd|cg|ch|ci|ck|cl|' + |
29 | 'cm|cn|co|cr|cs|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|fi|' + |
30 | 'fj|fk|fm|fo|fr|fx|ga|gb|gd|ge|gf|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|' + |
31 | 'hk|hm|hn|hr|ht|hu|id|ie|il|in|io|iq|ir|is|it|jm|jo|jp|ke|kg|kh|ki|km|kn|' + |
32 | 'kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|' + |
33 | 'mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nt|' + |
34 | 'nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|' + |
35 | 'sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|' + |
36 | 'tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|' + |
37 | 'ws|ye|yt|yu|za|zm|zr|zw' |
38 | # These are needed otherwise HOST will match almost anything |
39 | TLDS = "(?:#{GENERIC}|#{COUNTRY})" |
40 | |
41 | # Redefine USERINFO so that it must have non-zero length |
42 | USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})+" |
43 | |
44 | # unreserved_no_ending = alphanum | mark, but URI_ENDING [)!] excluded |
45 | UNRESERVED_NO_ENDING = "-_.~*'(#{ALNUM}" |
46 | |
47 | # this ensures that query or fragment do not end with URI_ENDING |
48 | # and enable us to use a much simpler self.pattern Regexp |
49 | |
50 | # uric_no_ending = reserved | unreserved_no_ending | escaped |
51 | URIC_NO_ENDING = "(?:[#{UNRESERVED_NO_ENDING}#{RESERVED}]|#{ESCAPED})" |
52 | # query = *uric |
53 | QUERY = "#{URIC_NO_ENDING}*" |
54 | # fragment = *uric |
55 | FRAGMENT = "#{URIC_NO_ENDING}*" |
56 | |
57 | # DOMLABEL is defined in the ruby uri library, TLDS is defined above |
58 | INTERNET_HOSTNAME = "(?:#{DOMLABEL}\\.)+#{TLDS}" |
59 | |
60 | # Correct a typo bug in ruby 1.8.x lib/uri/common.rb |
61 | PORT = '\\d*' |
62 | |
63 | INTERNET_URI = |
64 | "(?:(#{SCHEME}):/{0,2})?" + # Optional scheme: (\1) |
65 | "(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2) |
66 | "(#{INTERNET_HOSTNAME})" + # Mandatory hostname (\3) |
67 | "(?::(#{PORT}))?" + # Optional :port (\4) |
68 | "(#{ABS_PATH})?" + # Optional absolute path (\5) |
69 | "(?:\\?(#{QUERY}))?" + # Optional ?query (\6) |
70 | "(?:\\#(#{FRAGMENT}))?" + # Optional #fragment (\7) |
71 | '(?=\.?(?:\s|\)|\z))' # ends only with optional dot + space or ")" |
72 | # or end of the string |
73 | |
74 | SUSPICIOUS_PRECEDING_CHARACTER = '(!|\"\:|\"|\\\'|\]\()?' # any of !, ":, ", ', ]( |
75 | |
76 | INTERNET_URI_REGEXP = |
77 | Regexp.new(SUSPICIOUS_PRECEDING_CHARACTER + INTERNET_URI, Regexp::EXTENDED, 'N') |
78 | |
79 | end |
80 | |
81 | def URIChunk.pattern |
82 | INTERNET_URI_REGEXP |
83 | end |
84 | |
85 | attr_reader :user, :host, :port, :path, :query, :fragment, :link_text |
86 | |
87 | def self.apply_to(content) |
88 | content.gsub!( self.pattern ) do |matched_text| |
89 | chunk = self.new($~, content) |
90 | if chunk.avoid_autolinking? |
91 | # do not substitute nor register the chunk |
92 | matched_text |
93 | else |
94 | content.add_chunk(chunk) |
95 | chunk.mask |
96 | end |
97 | end |
98 | end |
99 | |
100 | def initialize(match_data, content) |
101 | super |
102 | @link_text = match_data[0] |
103 | @suspicious_preceding_character = match_data[1] |
104 | @original_scheme, @user, @host, @port, @path, @query, @fragment = match_data[2..-1] |
105 | treat_trailing_character |
106 | @unmask_text = "<a href=\"#{uri}\">#{link_text}</a>" |
107 | end |
108 | |
109 | def avoid_autolinking? |
110 | not @suspicious_preceding_character.nil? |
111 | end |
112 | |
113 | def treat_trailing_character |
114 | # If the last character matched by URI pattern is in ! or ), this may be part of the markup, |
115 | # not a URL. We should handle it as such. It is possible to do it by a regexp, but |
116 | # much easier to do programmatically |
117 | last_char = @link_text[-1..-1] |
118 | if last_char == ')' or last_char == '!' |
119 | @trailing_punctuation = last_char |
120 | @link_text.chop! |
121 | [@original_scheme, @user, @host, @port, @path, @query, @fragment].compact.last.chop! |
122 | else |
123 | @trailing_punctuation = nil |
124 | end |
125 | end |
126 | |
127 | def scheme |
128 | @original_scheme or (@user ? 'mailto' : 'http') |
129 | end |
130 | |
131 | def scheme_delimiter |
132 | scheme == 'mailto' ? ':' : '://' |
133 | end |
134 | |
135 | def user_delimiter |
136 | '@' unless @user.nil? |
137 | end |
138 | |
139 | def port_delimiter |
140 | ':' unless @port.nil? |
141 | end |
142 | |
143 | def query_delimiter |
144 | '?' unless @query.nil? |
145 | end |
146 | |
147 | def uri |
148 | [scheme, scheme_delimiter, user, user_delimiter, host, port_delimiter, port, path, |
149 | query_delimiter, query].compact.join |
150 | end |
151 | |
152 | end |
153 | |
154 | # uri with mandatory scheme but less restrictive hostname, like |
155 | # http://localhost:2500/blah.html |
156 | class LocalURIChunk < URIChunk |
157 | |
158 | unless defined? LocalURIChunk::LOCAL_URI_REGEXP |
159 | # hostname can be just a simple word like 'localhost' |
160 | ANY_HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?" |
161 | |
162 | # The basic URI expression as a string |
163 | # Scheme and hostname are mandatory |
164 | LOCAL_URI = |
165 | "(?:(#{SCHEME})://)+" + # Mandatory scheme:// (\1) |
166 | "(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2) |
167 | "(#{ANY_HOSTNAME})" + # Mandatory hostname (\3) |
168 | "(?::(#{PORT}))?" + # Optional :port (\4) |
169 | "(#{ABS_PATH})?" + # Optional absolute path (\5) |
170 | "(?:\\?(#{QUERY}))?" + # Optional ?query (\6) |
171 | "(?:\\#(#{FRAGMENT}))?" + # Optional #fragment (\7) |
172 | '(?=\.?(?:\s|\)|\z))' # ends only with optional dot + space or ")" |
173 | # or end of the string |
174 | |
175 | LOCAL_URI_REGEXP = Regexp.new(SUSPICIOUS_PRECEDING_CHARACTER + LOCAL_URI, Regexp::EXTENDED, 'N') |
176 | end |
177 | |
178 | def LocalURIChunk.pattern |
179 | LOCAL_URI_REGEXP |
180 | end |
181 | |
182 | end |