Soks 0.0.2

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.
Files changed (46) hide show
  1. data/LICENSE.txt +60 -0
  2. data/README.txt +65 -0
  3. data/bin/soks-create-wiki.rb +41 -0
  4. data/contrib/diff/lcs.rb +1105 -0
  5. data/contrib/diff/lcs/array.rb +21 -0
  6. data/contrib/diff/lcs/block.rb +51 -0
  7. data/contrib/diff/lcs/callbacks.rb +322 -0
  8. data/contrib/diff/lcs/change.rb +169 -0
  9. data/contrib/diff/lcs/hunk.rb +257 -0
  10. data/contrib/diff/lcs/ldiff.rb +226 -0
  11. data/contrib/diff/lcs/string.rb +19 -0
  12. data/contrib/diff_licence.txt +76 -0
  13. data/contrib/redcloth-2.0.11.rb +894 -0
  14. data/contrib/redcloth-3.0.1.rb +1019 -0
  15. data/contrib/redcloth_license.txt +27 -0
  16. data/lib/authenticators.rb +79 -0
  17. data/lib/soks-helpers.rb +321 -0
  18. data/lib/soks-model.rb +208 -0
  19. data/lib/soks-servlet.rb +125 -0
  20. data/lib/soks-utils.rb +80 -0
  21. data/lib/soks-view.rb +424 -0
  22. data/lib/soks.rb +19 -0
  23. data/template/attachment/logo.png +0 -0
  24. data/template/attachment/stylesheet.css +63 -0
  25. data/template/content/How%20to%20export%20a%20site%20from%20this%20wiki.textile +5 -0
  26. data/template/content/How%20to%20hack%20soks.textile +60 -0
  27. data/template/content/How%20to%20import%20a%20site%20from%20instiki.textile +13 -0
  28. data/template/content/Improving%20the%20style%20of%20this%20wiki.textile +30 -0
  29. data/template/content/Picture%20of%20a%20pair%20of%20soks.textile +1 -0
  30. data/template/content/Pointers%20on%20adjusting%20the%20settings.textile +39 -0
  31. data/template/content/Pointers%20on%20how%20to%20use%20this%20wiki.textile +21 -0
  32. data/template/content/Recent%20Changes%20to%20This%20Site.textile +203 -0
  33. data/template/content/Soks%20Licence.textile +64 -0
  34. data/template/content/home%20page.textile +18 -0
  35. data/template/start.rb +74 -0
  36. data/template/views/AttachmentPage_edit.rhtml +36 -0
  37. data/template/views/ImagePage_edit.rhtml +36 -0
  38. data/template/views/Page_content.rhtml +1 -0
  39. data/template/views/Page_edit.rhtml +34 -0
  40. data/template/views/Page_print.rhtml +5 -0
  41. data/template/views/Page_revisions.rhtml +18 -0
  42. data/template/views/Page_rss.rhtml +34 -0
  43. data/template/views/Page_search_results.rhtml +19 -0
  44. data/template/views/Page_view.rhtml +3 -0
  45. data/template/views/frame.rhtml +34 -0
  46. metadata +88 -0
@@ -0,0 +1,19 @@
1
+ #! /usr/env/bin ruby
2
+ #--
3
+ # Copyright 2004 Austin Ziegler <diff-lcs@halostatue.ca>
4
+ # adapted from:
5
+ # Algorithm::Diff (Perl) by Ned Konz <perl@bike-nomad.com>
6
+ # Smalltalk by Mario I. Wolczko <mario@wolczko.com>
7
+ # implements McIlroy-Hunt diff algorithm
8
+ #
9
+ # This program is free software. It may be redistributed and/or modified under
10
+ # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
11
+ # Ruby licence.
12
+ #
13
+ # $Id: string.rb,v 1.2 2004/12/15 22:07:19 tamc Exp $
14
+ #++
15
+ # Includes Diff::LCS into String.
16
+
17
+ class String
18
+ include Diff::LCS
19
+ end
@@ -0,0 +1,76 @@
1
+ Diff::LCS README
2
+ ================
3
+ Diff::LCS is a port of Algorithm::Diff[1] that uses the McIlroy-Hunt
4
+ longest common subsequence (LCS) algorithm to compute intelligent
5
+ differences between two sequenced enumerable containers[2]. The
6
+ implementation is based on Mario I. Wolczko's[3] Smalltalk version (1.2,
7
+ 1993)[4] and Ned Konz's[5] Perl version (Algorithm::Diff)[6].
8
+
9
+ This release is version 1.1.2, fixing an htmldiff bug in 1.1.1. Version 1.1.0
10
+ added new features, including the ability to #patch and #unpatch changes as
11
+ well as a new contextual diff callback, Diff::LCS::ContextDiffCallbacks, that
12
+ should improve the context sensitivity of patching.
13
+
14
+ Using this module is quite simple. By default, Diff::LCS does not extend
15
+ objects with the Diff::LCS interface, but will be called as if it were a
16
+ function:
17
+
18
+ require 'diff/lcs'
19
+
20
+ seq1 = %w(a b c e h j l m n p)
21
+ seq2 = %w(b c d e f j k l m r s t)
22
+
23
+ lcs = Diff::LCS.LCS(seq1, seq2)
24
+ diffs = Diff::LCS.diff(seq1, seq2)
25
+ sdiff = Diff::LCS.sdiff(seq1, seq2)
26
+ seq = Diff::LCS.traverse_sequences(seq1, seq2, callback_obj)
27
+ bal = Diff::LCS.traverse_balanced(seq1, seq2, callback_obj)
28
+ seq2 == Diff::LCS.patch!(seq1, diffs)
29
+ seq1 == Diff::LCS.unpatch!(seq2, diffs)
30
+ seq2 == Diff::LCS.patch!(seq1, sdiff)
31
+ seq1 == Diff::LCS.unpatch!(seq2, sdiff)
32
+
33
+ Objects can be extended with Diff::LCS:
34
+
35
+ seq1.extend(Diff::LCS)
36
+ lcs = seq1.lcs(seq2)
37
+ diffs = seq1.diff(seq2)
38
+ sdiff = seq1.sdiff(seq2)
39
+ seq = seq1.traverse_sequences(seq2, callback_obj)
40
+ bal = seq1.traverse_balanced(seq2, callback_obj)
41
+ seq2 == seq1.patch!(diffs)
42
+ seq1 == seq2.unpatch!(diffs)
43
+ seq2 == seq1.patch!(sdiff)
44
+ seq1 == seq2.unpatch!(sdiff)
45
+
46
+ By requiring 'diff/lcs/array' or 'diff/lcs/string', Array or String will
47
+ be extended for use this way.
48
+
49
+ Copyright
50
+ =========
51
+ # Copyright 2004 Austin Ziegler <diff-lcs@halostatue.ca>
52
+ # adapted from:
53
+ # Algorithm::Diff (Perl) by Ned Konz <perl@bike-nomad.com>
54
+ # Smalltalk by Mario I. Wolczko <mario@wolczko.com>
55
+ # implements McIlroy-Hunt diff algorithm
56
+ #
57
+ # This program is free software. It may be redistributed and/or modified
58
+ # under the terms of the GPL version 2 (or later), the Perl Artistic
59
+ # licence, or the Ruby licence.
60
+ #
61
+ # $Id: diff_licence.txt,v 1.1.1.1 2004/12/15 17:50:25 tamc Exp $
62
+
63
+ Footnotes
64
+ =========
65
+ [1] This library is called Diff::LCS because there are multiple
66
+ Ruby libraries called Algorithm::Diff maintained by other authors.
67
+ [2] By sequenced enumerable, I mean that the order of enumeration is
68
+ predictable and consistent for the same set of data. While it is
69
+ theoretically possible to generate a diff for unordereded hash, it
70
+ will only be meaningful if the enumeration of the hashes is
71
+ consistent. In general, this will mean that containers that behave
72
+ like String or Array will perform best.
73
+ [3] mario@wolczko.com
74
+ [4] ftp://st.cs.uiuc.edu/pub/Smalltalk/MANCHESTER/manchester/4.0/diff.st
75
+ [5] perl@bike-nomad.com
76
+ [6] http://search.cpan.org/~nedkonz/Algorithm-Diff-1.15/
@@ -0,0 +1,894 @@
1
+ # vim:ts=4:sw=4:
2
+ # = RedCloth - Textile for Ruby
3
+ #
4
+ # Homepage:: http://whytheluckystiff.net/ruby/redcloth/
5
+ # Author:: why the lucky stiff (http://whytheluckystiff.net/)
6
+ # Copyright:: (c) 2004 why the lucky stiff (and his puppet organizations.)
7
+ # License:: BSD
8
+ #
9
+ # (see http://hobix.com/textile/ for a Textile Reference.)
10
+ #
11
+ # Based on (and also inspired by) both:
12
+ #
13
+ # PyTextile: http://diveintomark.org/projects/textile/textile.py.txt
14
+ # Textism for PHP: http://www.textism.com/tools/textile/
15
+ #
16
+ #
17
+
18
+ class String
19
+ #
20
+ # Flexible HTML escaping
21
+ #
22
+ def htmlesc!( mode )
23
+ gsub!( '&', '&amp;' )
24
+ gsub!( '"', '&quot;' ) if mode != :NoQuotes
25
+ gsub!( "'", '&#039;' ) if mode == :Quotes
26
+ gsub!('<', '&lt;')
27
+ gsub!('>', '&gt;')
28
+ end
29
+ end
30
+
31
+ # = RedCloth
32
+ #
33
+ # RedCloth is a Ruby library for converting Textile
34
+ # into HTML.
35
+ #
36
+ # == What is Textile?
37
+ #
38
+ # Textile is a simple formatting style for text
39
+ # documents, loosely based on some HTML conventions.
40
+ #
41
+ # == Sample Textile Text
42
+ #
43
+ # h2. This is a title
44
+ #
45
+ # h3. This is a subhead
46
+ #
47
+ # This is a bit of paragraph.
48
+ #
49
+ # bq. This is a blockquote.
50
+ #
51
+ # = Writing Textile
52
+ #
53
+ # A Textile document consists of paragraphs. Paragraphs
54
+ # can be specially formatted by adding a small instruction
55
+ # to the beginning of the paragraph.
56
+ #
57
+ # h[n]. Header of size [n].
58
+ # bq. Blockquote.
59
+ # # Numeric list.
60
+ # * Bulleted list.
61
+ #
62
+ # == Quick Phrase Modifiers
63
+ #
64
+ # Quick phrase modifiers are also included, to allow formatting
65
+ # of small portions of text within a paragraph.
66
+ #
67
+ # \_emphasis\_
68
+ # \_\_italicized\_\_
69
+ # \*strong\*
70
+ # \*\*bold\*\*
71
+ # ??citation??
72
+ # -deleted text-
73
+ # +inserted text+
74
+ # ^superscript^
75
+ # ~subscript~
76
+ # @code@
77
+ # %(classname)span%
78
+ #
79
+ # ==notextile== (leave text alone)
80
+ #
81
+ # == Links
82
+ #
83
+ # To make a hypertext link, put the link text in "quotation
84
+ # marks" followed immediately by a colon and the URL of the link.
85
+ #
86
+ # Optional: text in (parentheses) following the link text,
87
+ # but before the closing quotation mark, will become a Title
88
+ # attribute for the link, visible as a tool tip when a cursor is above it.
89
+ #
90
+ # Example:
91
+ #
92
+ # "This is a link (This is a title) ":http://www.textism.com
93
+ #
94
+ # Will become:
95
+ #
96
+ # <a href="http://www.textism.com" title="This is a title">This is a link</a>
97
+ #
98
+ # == Images
99
+ #
100
+ # To insert an image, put the URL for the image inside exclamation marks.
101
+ #
102
+ # Optional: text that immediately follows the URL in (parentheses) will
103
+ # be used as the Alt text for the image. Images on the web should always
104
+ # have descriptive Alt text for the benefit of readers using non-graphical
105
+ # browsers.
106
+ #
107
+ # Optional: place a colon followed by a URL immediately after the
108
+ # closing ! to make the image into a link.
109
+ #
110
+ # Example:
111
+ #
112
+ # !http://www.textism.com/common/textist.gif(Textist)!
113
+ #
114
+ # Will become:
115
+ #
116
+ # <img src="http://www.textism.com/common/textist.gif" alt="Textist" />
117
+ #
118
+ # With a link:
119
+ #
120
+ # !/common/textist.gif(Textist)!:http://textism.com
121
+ #
122
+ # Will become:
123
+ #
124
+ # <a href="http://textism.com"><img src="/common/textist.gif" alt="Textist" /></a>
125
+ #
126
+ # == Defining Acronyms
127
+ #
128
+ # HTML allows authors to define acronyms via the tag. The definition appears as a
129
+ # tool tip when a cursor hovers over the acronym. A crucial aid to clear writing,
130
+ # this should be used at least once for each acronym in documents where they appear.
131
+ #
132
+ # To quickly define an acronym in Textile, place the full text in (parentheses)
133
+ # immediately following the acronym.
134
+ #
135
+ # Example:
136
+ #
137
+ # ACLU(American Civil Liberties Union)
138
+ #
139
+ # Will become:
140
+ #
141
+ # <acronym title="American Civil Liberties Union">ACLU</acronym>
142
+ #
143
+ # == Adding Tables
144
+ #
145
+ # In Textile, simple tables can be added by seperating each column by
146
+ # a pipe.
147
+ #
148
+ # |a|simple|table|row|
149
+ # |And|Another|table|row|
150
+ #
151
+ # Attributes are defined by style definitions in parentheses.
152
+ #
153
+ # table(border:1px solid black).
154
+ # (background:#ddd;color:red). |{}| | | |
155
+ #
156
+ # == Using RedCloth
157
+ #
158
+ # RedCloth is simply an extension of the String class, which can handle
159
+ # Textile formatting. Use it like a String and output HTML with its
160
+ # RedCloth#to_html method.
161
+ #
162
+ # doc = RedCloth.new "
163
+ #
164
+ # h2. Test document
165
+ #
166
+ # Just a simple test."
167
+ #
168
+ # puts doc.to_html
169
+
170
+ class RedCloth < String
171
+
172
+ VERSION = '2.0.11'
173
+
174
+ #
175
+ # Two accessor for setting security restrictions.
176
+ #
177
+ # This is a nice thing if you're using RedCloth for
178
+ # formatting in public places (e.g. Wikis) where you
179
+ # don't want users to abuse HTML for bad things.
180
+ #
181
+ # If +:filter_html+ is set, HTML which wasn't
182
+ # created by the Textile processor will be escaped.
183
+ #
184
+ # If +:filter_styles+ is set, it will also disable
185
+ # the style markup specifier. ('{color: red}')
186
+ #
187
+ attr_accessor :filter_html, :filter_styles
188
+
189
+ #
190
+ # Accessor for toggling line folding.
191
+ #
192
+ # If +:fold_lines+ is set, single newlines will
193
+ # not be converted to break tags.
194
+ #
195
+ attr_accessor :fold_lines
196
+
197
+ #
198
+ # Returns a new RedCloth object, based on _string_ and
199
+ # enforcing all the included _restrictions_.
200
+ #
201
+ # r = RedCloth.new( "h1. A <b>bold</b> man", [:filter_html] )
202
+ # r.to_html
203
+ # #=>"<h1>A &lt;b&gt;bold&lt;/b&gt; man</h1>"
204
+ #
205
+ def initialize( string, restrictions = [] )
206
+ @lite = false
207
+ restrictions.each { |r| method( "#{ r }=" ).call( true ) }
208
+ super( string )
209
+ end
210
+
211
+ #
212
+ # Generates HTML from the Textile contents. The _lite_ flag
213
+ # may be used to honor only inline markup, ignoring lists, tables,
214
+ # and block formatting.
215
+ #
216
+ # r = RedCloth.new( "And then? She *fell*!" )
217
+ # r.to_html( true )
218
+ # #=>"And then? She <strong>fell</strong>!"
219
+ #
220
+ def to_html( lite = nil )
221
+
222
+ @lite = lite unless lite.nil?
223
+
224
+ # make our working copy
225
+ text = self.dup
226
+
227
+ @urlrefs = {}
228
+ @shelf = []
229
+
230
+ incoming_entities text
231
+ ## encode_entities text
232
+ ## fix_entities text
233
+ clean_white_space text
234
+
235
+ get_refs text
236
+
237
+ no_textile text
238
+
239
+ inline text
240
+
241
+ unless @lite
242
+ fold text
243
+ block text
244
+ end
245
+
246
+ retrieve text
247
+
248
+ text.gsub!( /<\/?notextile>/, '' )
249
+ text.gsub!( /x%x%/, '&#38;' )
250
+ text.gsub!( /<br \/>/, "<br />\n" )
251
+ text.strip!
252
+ text
253
+
254
+ end
255
+
256
+ #######
257
+ private
258
+ #######
259
+ #
260
+ # Mapping of 8-bit ASCII codes to HTML numerical entity equivalents.
261
+ # (from PyTextile)
262
+ #
263
+ TEXTILE_TAGS =
264
+
265
+ [[128, 8364], [129, 0], [130, 8218], [131, 402], [132, 8222], [133, 8230],
266
+ [134, 8224], [135, 8225], [136, 710], [137, 8240], [138, 352], [139, 8249],
267
+ [140, 338], [141, 0], [142, 0], [143, 0], [144, 0], [145, 8216], [146, 8217],
268
+ [147, 8220], [148, 8221], [149, 8226], [150, 8211], [151, 8212], [152, 732],
269
+ [153, 8482], [154, 353], [155, 8250], [156, 339], [157, 0], [158, 0], [159, 376]].
270
+
271
+ collect! do |a, b|
272
+ [a.chr, ( b.zero? and "" or "&#{ b };" )]
273
+ end
274
+
275
+ #
276
+ # Regular expressions to convert to HTML.
277
+ #
278
+ A_HLGN = /(?:(?:<>|<|>|\=|[()]+)+)/
279
+ A_VLGN = /[\-^~]/
280
+ C_CLAS = '(?:\([^)]+\))'
281
+ C_LNGE = '(?:\[[^\]]+\])'
282
+ C_STYL = '(?:\{[^}]+\})'
283
+ S_CSPN = '(?:\\\\\d+)'
284
+ S_RSPN = '(?:/\d+)'
285
+ A = "(?:#{A_HLGN}?#{A_VLGN}?|#{A_VLGN}?#{A_HLGN}?)"
286
+ S = "(?:#{S_CSPN}?#{S_RSPN}|#{S_RSPN}?#{S_CSPN}?)"
287
+ C = "(?:#{C_CLAS}?#{C_STYL}?#{C_LNGE}?|#{C_STYL}?#{C_LNGE}?#{C_CLAS}?|#{C_LNGE}?#{C_STYL}?#{C_CLAS}?)"
288
+ # PUNCT = Regexp::quote( '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' )
289
+ PUNCT = Regexp::quote( '!"#$%&\'*+,-./:;=?@\\^_`|~' )
290
+ HYPERLINK = '(\S+?)([^\w\s/;=\?]*?)(\s|$)'
291
+
292
+ GLYPHS = [
293
+ # [ /([^\s\[{(>])?\'([dmst]\b|ll\b|ve\b|\s|:|$)/, '\1&#8217;\2' ], # single closing
294
+ [ /([^\s\[{(>])\'/, '\1&#8217;' ], # single closing
295
+ [ /\'(?=\s|s\b|[#{PUNCT}])/, '&#8217;' ], # single closing
296
+ [ /\'/, '&#8216;' ], # single opening
297
+ # [ /([^\s\[{(])?"(\s|:|$)/, '\1&#8221;\2' ], # double closing
298
+ [ /([^\s\[{(>])"/, '\1&#8221;' ], # double closing
299
+ [ /"(?=\s|[#{PUNCT}])/, '&#8221;' ], # double closing
300
+ [ /"/, '&#8220;' ], # double opening
301
+ [ /\b( )?\.{3}/, '\1&#8230;' ], # ellipsis
302
+ [ /\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/, '<acronym title="\2">\1</acronym>' ], # 3+ uppercase acronym
303
+ [ /(^|[^"][>\s])([A-Z][A-Z0-9 ]{2,})([^<a-z0-9]|$)/, '\1<span class="caps">\2</span>\3' ], # 3+ uppercase caps
304
+ [ /(\.\s)?\s?--\s?/, '\1&#8212;' ], # em dash
305
+ [ /\s->\s/, ' &rarr; ' ], # en dash
306
+ [ /\s-\s/, ' &#8211; ' ], # en dash
307
+ [ /(\d+) ?x ?(\d+)/, '\1&#215;\2' ], # dimension sign
308
+ [ /\b ?[(\[]TM[\])]/i, '&#8482;' ], # trademark
309
+ [ /\b ?[(\[]R[\])]/i, '&#174;' ], # registered
310
+ [ /\b ?[(\[]C[\])]/i, '&#169;' ] # copyright
311
+ ]
312
+
313
+ I_ALGN_VALS = {
314
+ '<' => 'left',
315
+ '=' => 'center',
316
+ '>' => 'right'
317
+ }
318
+
319
+ H_ALGN_VALS = {
320
+ '<' => 'left',
321
+ '=' => 'center',
322
+ '>' => 'right',
323
+ '<>' => 'justify'
324
+ }
325
+
326
+ V_ALGN_VALS = {
327
+ '^' => 'top',
328
+ '-' => 'middle',
329
+ '~' => 'bottom'
330
+ }
331
+
332
+ QTAGS = [
333
+ ['**', 'b'],
334
+ ['*', 'strong'],
335
+ ['??', 'cite'],
336
+ ['-', 'del'],
337
+ ['__', 'i'],
338
+ ['_', 'em'],
339
+ ['%', 'span'],
340
+ ['+', 'ins'],
341
+ ['^', 'sup'],
342
+ ['~', 'sub']
343
+ ].collect do |rc, ht|
344
+ ttr = Regexp.quote(rc)
345
+ punct = PUNCT.sub( Regexp::quote(rc), '' )
346
+ re = /(^|[\s\>#{punct}{(\[])
347
+ #{ttr}
348
+ (#{C})
349
+ (?::(\S+?))?
350
+ ([^\s#{ttr}]+?(?:[^\n]|\n(?!\n))*?)
351
+ ([#{punct}]*?)
352
+ #{ttr}
353
+ (?=[\s\])}<#{punct}]|$)/xm
354
+ [re, ht]
355
+ end
356
+
357
+ def pgl( text )
358
+ GLYPHS.each do |re, resub|
359
+ text.gsub! re, resub
360
+ end
361
+ end
362
+
363
+ def pba( text_in, element = "" )
364
+
365
+ return '' unless text_in
366
+
367
+ style = []
368
+ text = text_in.dup
369
+ if element == 'td'
370
+ colspan = $1 if text =~ /\\(\d+)/
371
+ rowspan = $1 if text =~ /\/(\d+)/
372
+ style << "vertical-align:#{ v_align( $& ) };" if text =~ A_VLGN
373
+ end
374
+
375
+ style << "#{ $1 };" if not @filter_styles and
376
+ text.sub!( /\{([^}]*)\}/, '' )
377
+
378
+ lang = $1 if
379
+ text.sub!( /\[([^)]+?)\]/, '' )
380
+
381
+ cls = $1 if
382
+ text.sub!( /\(([^()]+?)\)/, '' )
383
+
384
+ style << "padding-left:#{ $1.length }em;" if
385
+ text.sub!( /([(]+)/, '' )
386
+
387
+ style << "padding-right:#{ $1.length }em;" if text.sub!( /([)]+)/, '' )
388
+
389
+ style << "text-align:#{ h_align( $& ) };" if text =~ A_HLGN
390
+
391
+ cls, id = $1, $2 if cls =~ /^(.*?)#(.*)$/
392
+
393
+ atts = ''
394
+ atts << " style=\"#{ style.join }\"" unless style.empty?
395
+ atts << " class=\"#{ cls }\"" unless cls.to_s.empty?
396
+ atts << " lang=\"#{ lang }\"" if lang
397
+ atts << " id=\"#{ id }\"" if id
398
+ atts << " colspan=\"#{ colspan }\"" if colspan
399
+ atts << " rowspan=\"#{ rowspan }\"" if rowspan
400
+
401
+ atts
402
+ end
403
+
404
+ TABLE_RE = /^(?:table(_?#{S}#{A}#{C})\. ?\n)?^(#{A}#{C}\.? ?\|.*?\|)(\n\n|\Z)/m
405
+
406
+ def table( text )
407
+ text.gsub!( TABLE_RE ) do |matches|
408
+
409
+ tatts, fullrow = $~[1..2]
410
+ tatts = pba( tatts, 'table' )
411
+ rows = []
412
+
413
+ fullrow.
414
+ split( /\|$/m ).
415
+ delete_if { |x| x.empty? }.
416
+ each do |row|
417
+
418
+ ratts, row = pba( $1, 'tr' ), $2 if row =~ /^(#{A}#{C}\. )(.*)/m
419
+
420
+ cells = []
421
+ row.split( '|' ).each do |cell|
422
+ ctyp = 'd'
423
+ ctyp = 'h' if cell =~ /^_/
424
+
425
+ catts = ''
426
+ catts, cell = pba( $1, 'td' ), $2 if cell =~ /^(_?#{S}#{A}#{C}\. )(.*)/
427
+
428
+ unless cell.strip.empty?
429
+ cells << "\t\t\t<t#{ ctyp }#{ catts }>#{ cell }</t#{ ctyp }>"
430
+ end
431
+ end
432
+ rows << "\t\t<tr#{ ratts }>\n#{ cells.join( "\n" ) }\n\t\t</tr>"
433
+ end
434
+ "\t<table#{ tatts }>\n#{ rows.join( "\n" ) }\n\t</table>\n\n"
435
+ end
436
+ end
437
+
438
+ LISTS_RE = /^([#*]+?#{C} .*?)$(?![^#*])/m
439
+ LISTS_CONTENT_RE = /^([#*]+)(#{A}#{C}) (.*)$/m
440
+
441
+ def lists( text )
442
+ text.gsub!( LISTS_RE ) do |match|
443
+ lines = match.split( /\n/ )
444
+ last_line = -1
445
+ depth = []
446
+ lines.each_with_index do |line, line_id|
447
+ if line =~ LISTS_CONTENT_RE
448
+ tl,atts,content = $~[1..3]
449
+ if depth.last
450
+ if depth.last.length > tl.length
451
+ (depth.length - 1).downto(0) do |i|
452
+ break if depth[i].length == tl.length
453
+ lines[line_id - 1] << "</li>\n\t</#{ lT( depth[i] ) }l>\n\t"
454
+ depth.pop
455
+ end
456
+ end
457
+ if depth.last.length == tl.length
458
+ lines[line_id - 1] << '</li>'
459
+ end
460
+ end
461
+ unless depth.last == tl
462
+ depth << tl
463
+ atts = pba( atts )
464
+ lines[line_id] = "\t<#{ lT(tl) }l#{ atts }>\n\t<li>#{ content }"
465
+ else
466
+ lines[line_id] = "\t\t<li>#{ content }"
467
+ end
468
+ last_line = line_id
469
+
470
+ elsif line =~ /^\s+\S/
471
+ last_line = line_id
472
+ elsif line_id - last_line < 2 and line =~ /^\S/
473
+ last_line = line_id
474
+ end
475
+ if line_id - last_line > 1 or line_id == lines.length - 1
476
+ depth.delete_if do |v|
477
+ lines[last_line] << "</li>\n\t</#{ lT( v ) }l>"
478
+ end
479
+ end
480
+ end
481
+ lines.join( "\n" )
482
+ end
483
+ end
484
+
485
+ def lT( text )
486
+ text =~ /\#$/ ? 'o' : 'u'
487
+ end
488
+
489
+ def fold( text )
490
+ text.gsub!( /(.+)\n(?![#*\s|])/, "\\1#{ @fold_lines ? ' ' : '<br />' }" )
491
+ end
492
+
493
+ BLOCK_RE = ['bq','h[1-6]','fn\d+','p'].collect!{|stag|
494
+ [stag,
495
+ /^(#{ stag })(#{A}#{C})\.(?::(\S+))? (.*)$/]
496
+ }
497
+
498
+ def block( text )
499
+ pre = false
500
+ find = ['bq','h[1-6]','fn\d+','p']
501
+
502
+ lines = text.split( /\n/ ) + [' ']
503
+ new_text =
504
+ lines.collect do |line|
505
+ pre = true if line =~ /<(pre|notextile)[^>]*>/i
506
+ BLOCK_RE.each do |stag, ctag|
507
+ line.gsub!( ctag ) do |m|
508
+ tag,atts,cite,content = $~[1..4]
509
+
510
+ atts = pba( atts )
511
+
512
+ if tag =~ /fn(\d+)/
513
+ tag = 'p';
514
+ atts << " id=\"fn#{ $1 }\""
515
+ content = "<sup>#{ $1 }</sup> #{ content }"
516
+ end
517
+
518
+ start = "\t<#{ tag }"
519
+ tend = "</#{ tag }>"
520
+
521
+ if tag == "bq"
522
+ cite = check_refs( cite )
523
+ cite = " cite=\"#{ cite }\"" if cite
524
+ start = "\t<blockquote#{ cite }>\n\t\t<p";
525
+ tend = "</p>\n\t</blockquote>";
526
+ end
527
+
528
+ "#{ start }#{ atts }>#{ content }#{ tend }"
529
+ end unless pre
530
+ end
531
+
532
+ line.gsub!( /^(?!\t|<\/?div|<\/?pre|<\/?notextile|<\/?code|$| )(.*)/, "\t<p>\\1</p>" ) unless pre
533
+
534
+ line.gsub!( "<br />", "\n" ) if pre
535
+ pre = false if line =~ /<\/(pre|notextile)>/i
536
+
537
+ line
538
+ end.join( "\n" )
539
+ text.replace( new_text )
540
+ end
541
+
542
+ def span( text )
543
+ QTAGS.each do |ttr, ht|
544
+ text.gsub!(ttr) do |m|
545
+
546
+ start,atts,cite,content,tend = $~[1..5]
547
+ atts = pba( atts )
548
+ atts << " cite=\"#{ cite }\"" if cite
549
+
550
+ "#{ start }<#{ ht }#{ atts }>#{ content }#{ tend }</#{ ht }>"
551
+
552
+ end
553
+ end
554
+ end
555
+
556
+ LINK_RE = /
557
+ ([\s\[{(]|[#{PUNCT}])? # $pre
558
+ " # start
559
+ (#{C}) # $atts
560
+ ([^"]+?) # $text
561
+ \s?
562
+ (?:\(([^)]+?)\)(?="))? # $title
563
+ ":
564
+ (\S+?) # $url
565
+ (\/)? # $slash
566
+ ([^\w\/;]*?) # $post
567
+ (?=<|\s|$)
568
+ /x
569
+
570
+ def links( text )
571
+ text.gsub!( LINK_RE ) do |m|
572
+ pre,atts,text,title,url,slash,post = $~[1..7]
573
+
574
+ url = check_refs( url )
575
+
576
+ atts = pba( atts )
577
+ atts << " title=\"#{ title }\"" if title
578
+ atts = shelve( atts ) if atts
579
+
580
+ "#{ pre }<a href=\"#{ url }#{ slash }\"#{ atts }>#{ text }</a>#{ post }"
581
+ end
582
+ end
583
+
584
+ REFS_RE = /(^|\s)\[(.+?)\]((?:http:\/\/|javascript:|ftp:\/\/|\/)\S+?)(?=\s|$)/
585
+
586
+ def get_refs( text )
587
+ text.gsub!( REFS_RE ) do |m|
588
+ flag, url = $~[2..3]
589
+ @urlrefs[flag] = url
590
+ nil
591
+ end
592
+ end
593
+
594
+ def check_refs( text )
595
+ @urlrefs[text] || text
596
+ end
597
+
598
+ IMAGE_RE = /
599
+ \! # opening
600
+ (\<|\=|\>)? # optional alignment atts
601
+ (#{C}) # optional style,class atts
602
+ (?:\. )? # optional dot-space
603
+ ([^\s(!]+?) # presume this is the src
604
+ \s? # optional space
605
+ (?:\(((?:[^\(\)]|\([^\)]+\))+?)\))? # optional title
606
+ \! # closing
607
+ (?::#{ HYPERLINK })? # optional href
608
+ /x
609
+
610
+ def image( text )
611
+ text.gsub!( IMAGE_RE ) do |m|
612
+ algn,atts,url,title,href,href_a1,href_a2 = $~[1..7]
613
+ atts = pba( atts )
614
+ atts << " align=\"#{ i_align( algn ) }\"" if algn
615
+ atts << " title=\"#{ title }\"" if title
616
+ atts << " alt=\"#{ title }\""
617
+ # size = @getimagesize($url);
618
+ # if($size) $atts.= " $size[3]";
619
+
620
+ href = check_refs( href ) if href
621
+ url = check_refs( url )
622
+ atts << " border=\"0\"" if href
623
+
624
+ out = ''
625
+ out << "<a href=\"#{ href }\">" if href
626
+ out << "<img src=\"#{ url }\"#{ atts } />"
627
+ out << "</a>#{ href_a1 }#{ href_a2 }" if href
628
+
629
+ out
630
+ end
631
+ end
632
+
633
+ CODE_RE = /
634
+ (^|[\s>#{PUNCT}{(\[]) # 1 open bracket?
635
+ @ # opening
636
+ (?:\|(\w+?)\|)? # 2 language
637
+ (\S(?:[^\n]|\n(?!\n))*?) # 3 code
638
+ @ # closing
639
+ (?=[\s\]}\)<#{PUNCT}]|$) # 4 closing bracket?
640
+ /x
641
+
642
+ def code( text )
643
+ text.gsub!( CODE_RE ) do |m|
644
+ before,lang,code,after = $~[1..4]
645
+ lang = " language=\"#{ lang }\"" if lang
646
+ "#{ before }<code#{ lang }>#{ code }</code>#{ after }"
647
+ end
648
+ end
649
+
650
+ def shelve( val )
651
+ @shelf << val
652
+ " <#{ @shelf.length }>"
653
+ end
654
+
655
+ def retrieve( text )
656
+ @shelf.each_with_index do |r, i|
657
+ text.gsub!( " <#{ i + 1 }>", r )
658
+ end
659
+ end
660
+
661
+ def incoming_entities( text )
662
+ ## turn any incoming ampersands into a dummy character for now.
663
+ ## This uses a negative lookahead for alphanumerics followed by a semicolon,
664
+ ## implying an incoming html entity, to be skipped
665
+
666
+ text.gsub!( /&(?![#a-z0-9]+;)/i, "x%x%" )
667
+ end
668
+
669
+ def encode_entities( text )
670
+ ## Convert high and low ascii to entities.
671
+ # if $-K == "UTF-8"
672
+ # encode_high( text )
673
+ # else
674
+ text.htmlesc!( :NoQuotes )
675
+ # end
676
+ end
677
+
678
+ def fix_entities( text )
679
+ ## de-entify any remaining angle brackets or ampersands
680
+ text.gsub!( "&gt;", ">" )
681
+ text.gsub!( "&lt;", "<" )
682
+ text.gsub!( "&amp;", "&" )
683
+ end
684
+
685
+ def clean_white_space( text )
686
+ text.gsub!( /\r\n/, "\n" )
687
+ text.gsub!( /\t/, '' )
688
+ text.gsub!( /\n{3,}/, "\n\n" )
689
+ text.gsub!( /\n *\n/, "\n\n" )
690
+ text.gsub!( /"$/, "\" " )
691
+ end
692
+
693
+ def no_textile( text )
694
+ text.gsub!( /(^|\s)==(.*?)==(\s|$)?/,
695
+ '\1<notextile>\2</notextile>\3' )
696
+ end
697
+
698
+ def footnote_ref( text )
699
+ text.gsub!( /\b\[([0-9]+?)\](\s)?/,
700
+ '<sup><a href="#fn\1">\1</a></sup>\2' )
701
+ end
702
+
703
+ OFFTAGS = /(code|pre|kbd|notextile)/
704
+ OFFTAG_MATCH = /(?:(<\/#{ OFFTAGS }>)|(<#{ OFFTAGS }[^>]*>))(.*?)(?=<\/?#{ OFFTAGS }>|\Z)/mi
705
+ OFFTAG_OPEN = /<#{ OFFTAGS }/
706
+ OFFTAG_CLOSE = /<\/?#{ OFFTAGS }/
707
+ HASTAG_MATCH = /(<\/?\w[^\n]*?>)/m
708
+ ALLTAG_MATCH = /(<\/?\w[^\n]*?>)|.*?(?=<\/?\w[^\n]*?>|$)/m
709
+
710
+ def glyphs( text, level = 0 )
711
+ if text !~ HASTAG_MATCH
712
+ pgl text
713
+ footnote_ref text
714
+ else
715
+ codepre = 0
716
+ text.gsub!( ALLTAG_MATCH ) do |line|
717
+ ## matches are off if we're between <code>, <pre> etc.
718
+ if $1
719
+ if @filter_html
720
+ line.htmlesc!( :NoQuotes )
721
+ elsif line =~ OFFTAG_OPEN
722
+ codepre += 1
723
+ elsif line =~ OFFTAG_CLOSE
724
+ codepre -= 1
725
+ codepre = 0 if codepre < 0
726
+ end
727
+ ## do htmlspecial if between <code>
728
+ elsif codepre.zero?
729
+ glyphs( line, level + 1 )
730
+ else
731
+ line.htmlesc!( :NoQuotes )
732
+ end
733
+ ## p [level, codepre, orig_line, line]
734
+
735
+ line
736
+ end
737
+ end
738
+ end
739
+
740
+ def rip_offtags( text )
741
+ pre_list = []
742
+ if text =~ /<.*>/
743
+ ## strip and encode <pre> content
744
+ codepre, used_offtags = 0, {}
745
+ text.gsub!( OFFTAG_MATCH ) do |line|
746
+ if $3
747
+ offtag, aftertag = $4, $5
748
+ codepre += 1
749
+ used_offtags[offtag] = true
750
+ if codepre - used_offtags.length > 0
751
+ line.htmlesc!( :NoQuotes )
752
+ pre_list.last << line
753
+ line = ""
754
+ else
755
+ aftertag.htmlesc!( :NoQuotes ) if aftertag
756
+ line = "<redpre##{ pre_list.length }>"
757
+ pre_list << "#{ $3 }#{ aftertag }"
758
+ end
759
+ elsif $1 and codepre > 0
760
+ if codepre - used_offtags.length > 0
761
+ line.htmlesc!( :NoQuotes )
762
+ pre_list.last << line
763
+ line = ""
764
+ end
765
+ codepre -= 1 unless codepre.zero?
766
+ used_offtags = {} if codepre.zero?
767
+ end
768
+ line
769
+ end
770
+ end
771
+ pre_list
772
+ end
773
+
774
+ def smooth_offtags( text, pre_list )
775
+ unless pre_list.empty?
776
+ ## replace <pre> content
777
+ text.gsub!( /<redpre#(\d+)>/ ) { pre_list[$1.to_i] }
778
+ end
779
+ end
780
+
781
+ def inline( text )
782
+ text.gsub!( /"\z/, "\" " )
783
+ pre_list = rip_offtags text
784
+
785
+ ## apply inline markup
786
+ unless @lite
787
+ lists text
788
+ table text
789
+ end
790
+
791
+ image text
792
+ links text
793
+ code text
794
+ span text
795
+
796
+ ## replace entities
797
+ glyphs text
798
+ smooth_offtags text, pre_list
799
+ end
800
+
801
+ def i_align( text )
802
+ I_ALGN_VALS[text]
803
+ end
804
+
805
+ def h_align( text )
806
+ H_ALGN_VALS[text]
807
+ end
808
+
809
+ def v_align( text )
810
+ V_ALGN_VALS[text]
811
+ end
812
+
813
+ def encode_high( text )
814
+ ## mb_encode_numericentity($text, $cmap, $charset);
815
+ end
816
+
817
+ def decode_high( text )
818
+ ## mb_decode_numericentity($text, $cmap, $charset);
819
+ end
820
+
821
+ def textile_popup_help( name, helpvar, windowW, windowH )
822
+ ' <a target="_blank" href="http://www.textpattern.com/help/?item=' + helpvar + '" onclick="window.open(this.href, \'popupwindow\', \'width=' + windowW + ',height=' + windowH + ',scrollbars,resizable\'); return false;">' + name + '</a><br />'
823
+ end
824
+
825
+ CMAP = [
826
+ 160, 255, 0, 0xffff,
827
+ 402, 402, 0, 0xffff,
828
+ 913, 929, 0, 0xffff,
829
+ 931, 937, 0, 0xffff,
830
+ 945, 969, 0, 0xffff,
831
+ 977, 978, 0, 0xffff,
832
+ 982, 982, 0, 0xffff,
833
+ 8226, 8226, 0, 0xffff,
834
+ 8230, 8230, 0, 0xffff,
835
+ 8242, 8243, 0, 0xffff,
836
+ 8254, 8254, 0, 0xffff,
837
+ 8260, 8260, 0, 0xffff,
838
+ 8465, 8465, 0, 0xffff,
839
+ 8472, 8472, 0, 0xffff,
840
+ 8476, 8476, 0, 0xffff,
841
+ 8482, 8482, 0, 0xffff,
842
+ 8501, 8501, 0, 0xffff,
843
+ 8592, 8596, 0, 0xffff,
844
+ 8629, 8629, 0, 0xffff,
845
+ 8656, 8660, 0, 0xffff,
846
+ 8704, 8704, 0, 0xffff,
847
+ 8706, 8707, 0, 0xffff,
848
+ 8709, 8709, 0, 0xffff,
849
+ 8711, 8713, 0, 0xffff,
850
+ 8715, 8715, 0, 0xffff,
851
+ 8719, 8719, 0, 0xffff,
852
+ 8721, 8722, 0, 0xffff,
853
+ 8727, 8727, 0, 0xffff,
854
+ 8730, 8730, 0, 0xffff,
855
+ 8733, 8734, 0, 0xffff,
856
+ 8736, 8736, 0, 0xffff,
857
+ 8743, 8747, 0, 0xffff,
858
+ 8756, 8756, 0, 0xffff,
859
+ 8764, 8764, 0, 0xffff,
860
+ 8773, 8773, 0, 0xffff,
861
+ 8776, 8776, 0, 0xffff,
862
+ 8800, 8801, 0, 0xffff,
863
+ 8804, 8805, 0, 0xffff,
864
+ 8834, 8836, 0, 0xffff,
865
+ 8838, 8839, 0, 0xffff,
866
+ 8853, 8853, 0, 0xffff,
867
+ 8855, 8855, 0, 0xffff,
868
+ 8869, 8869, 0, 0xffff,
869
+ 8901, 8901, 0, 0xffff,
870
+ 8968, 8971, 0, 0xffff,
871
+ 9001, 9002, 0, 0xffff,
872
+ 9674, 9674, 0, 0xffff,
873
+ 9824, 9824, 0, 0xffff,
874
+ 9827, 9827, 0, 0xffff,
875
+ 9829, 9830, 0, 0xffff,
876
+ 338, 339, 0, 0xffff,
877
+ 352, 353, 0, 0xffff,
878
+ 376, 376, 0, 0xffff,
879
+ 710, 710, 0, 0xffff,
880
+ 732, 732, 0, 0xffff,
881
+ 8194, 8195, 0, 0xffff,
882
+ 8201, 8201, 0, 0xffff,
883
+ 8204, 8207, 0, 0xffff,
884
+ 8211, 8212, 0, 0xffff,
885
+ 8216, 8218, 0, 0xffff,
886
+ 8218, 8218, 0, 0xffff,
887
+ 8220, 8222, 0, 0xffff,
888
+ 8224, 8225, 0, 0xffff,
889
+ 8240, 8240, 0, 0xffff,
890
+ 8249, 8250, 0, 0xffff,
891
+ 8364, 8364, 0, 0xffff
892
+ ]
893
+ end
894
+