Changesets can be listed by changeset number.
The Git repository is here.
- Revision:
- 344
- Log:
Massive changeset which brings the old, ROOL customised Instiki
version up to date, but without any ROOL customisations in this
latest checked-in version (which is 0.19.1). This is deliberate,
so that it's easy to see the changes made for the ROOL version
in a subsequent changeset. The 'app/views/shared' directory is not
part of Instiki but is kept to maintain the change history with
updated ROOL customisations, some of which involve the same files
in that same directory.
- Author:
- rool
- Date:
- Sat Mar 19 19:52:13 +0000 2011
- Size:
- 7062 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 | Regexp.new(SUSPICIOUS_PRECEDING_CHARACTER + INTERNET_URI, Regexp::EXTENDED) |
79 | |
80 | end |
81 | |
82 | def URIChunk.pattern |
83 | INTERNET_URI_REGEXP |
84 | end |
85 | |
86 | attr_reader :user, :host, :port, :path, :query, :fragment, :link_text |
87 | |
88 | def self.apply_to(content) |
89 | content.gsub!( self.pattern ) do |matched_text| |
90 | chunk = self.new($~, content) |
91 | if chunk.avoid_autolinking? |
92 | # do not substitute nor register the chunk |
93 | matched_text |
94 | else |
95 | content.add_chunk(chunk) |
96 | chunk.mask |
97 | end |
98 | end |
99 | end |
100 | |
101 | def initialize(match_data, content) |
102 | super |
103 | @link_text = match_data[0] |
104 | @suspicious_preceding_character = match_data[1] |
105 | @original_scheme, @user, @host, @port, @path, @query, @fragment = match_data[2..-1] |
106 | treat_trailing_character |
107 | @unmask_text = "<a href=\"#{uri}\">#{link_text}</a>" |
108 | end |
109 | |
110 | def avoid_autolinking? |
111 | not @suspicious_preceding_character.nil? |
112 | end |
113 | |
114 | def treat_trailing_character |
115 | # If the last character matched by URI pattern is in ! or ), this may be part of the markup, |
116 | # not a URL. We should handle it as such. It is possible to do it by a regexp, but |
117 | # much easier to do programmatically |
118 | last_char = @link_text[-1..-1] |
119 | if last_char == ')' or last_char == '!' |
120 | @trailing_punctuation = last_char |
121 | @link_text.chop! |
122 | [@original_scheme, @user, @host, @port, @path, @query, @fragment].compact.last.chop! |
123 | else |
124 | @trailing_punctuation = nil |
125 | end |
126 | end |
127 | |
128 | def scheme |
129 | @original_scheme or (@user ? 'mailto' : 'http') |
130 | end |
131 | |
132 | def scheme_delimiter |
133 | scheme == 'mailto' ? ':' : '://' |
134 | end |
135 | |
136 | def user_delimiter |
137 | '@' unless @user.nil? |
138 | end |
139 | |
140 | def port_delimiter |
141 | ':' unless @port.nil? |
142 | end |
143 | |
144 | def query_delimiter |
145 | '?' unless @query.nil? |
146 | end |
147 | |
148 | def uri |
149 | [scheme, scheme_delimiter, user, user_delimiter, host, port_delimiter, port, path, |
150 | query_delimiter, query].compact.join |
151 | end |
152 | |
153 | end |
154 | |
155 | # uri with mandatory scheme but less restrictive hostname, like |
156 | # http://localhost:2500/blah.html |
157 | class LocalURIChunk < URIChunk |
158 | |
159 | unless defined? LocalURIChunk::LOCAL_URI_REGEXP |
160 | # hostname can be just a simple word like 'localhost' |
161 | ANY_HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?" |
162 | |
163 | # The basic URI expression as a string |
164 | # Scheme and hostname are mandatory |
165 | LOCAL_URI = |
166 | "(?:(#{SCHEME})://)+" + # Mandatory scheme:// (\1) |
167 | "(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2) |
168 | "(#{ANY_HOSTNAME})" + # Mandatory hostname (\3) |
169 | "(?::(#{PORT}))?" + # Optional :port (\4) |
170 | "(#{ABS_PATH})?" + # Optional absolute path (\5) |
171 | "(?:\\?(#{QUERY}))?" + # Optional ?query (\6) |
172 | "(?:\\#(#{FRAGMENT}))?" + # Optional #fragment (\7) |
173 | '(?=\.?(?:\s|\)|\z))' # ends only with optional dot + space or ")" |
174 | # or end of the string |
175 | |
176 | # LOCAL_URI_REGEXP = Regexp.new(SUSPICIOUS_PRECEDING_CHARACTER + LOCAL_URI, Regexp::EXTENDED, 'N') |
177 | LOCAL_URI_REGEXP = Regexp.new(SUSPICIOUS_PRECEDING_CHARACTER + LOCAL_URI, Regexp::EXTENDED) |
178 | end |
179 | |
180 | def LocalURIChunk.pattern |
181 | LOCAL_URI_REGEXP |
182 | end |
183 | |
184 | end |