RedCloth 3.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of RedCloth might be problematic. Click here for more details.

@@ -1,3 +1,3 @@
1
- #!/usr/local/bin/ruby18
1
+ #!/usr/local/bin/ruby
2
2
  require 'redcloth'
3
3
  puts RedCloth.new( ARGF.read ).to_html
@@ -166,7 +166,7 @@
166
166
 
167
167
  class RedCloth < String
168
168
 
169
- VERSION = '3.0.1'
169
+ VERSION = '3.0.2'
170
170
  DEFAULT_RULES = [:textile, :markdown]
171
171
 
172
172
  #
@@ -271,16 +271,19 @@ class RedCloth < String
271
271
  no_textile text
272
272
 
273
273
  # start processor
274
- pre_list = rip_offtags text
274
+ @pre_list = []
275
+ rip_offtags text
276
+ hard_break text
275
277
  refs text
276
278
  blocks text
277
279
  inline text
278
- smooth_offtags text, pre_list
280
+ smooth_offtags text
279
281
 
280
282
  retrieve text
281
283
 
282
284
  text.gsub!( /<\/?notextile>/, '' )
283
285
  text.gsub!( /x%x%/, '&#38;' )
286
+ clean_html text if filter_html
284
287
  text.strip!
285
288
  text
286
289
 
@@ -364,36 +367,39 @@ class RedCloth < String
364
367
  '~' => 'bottom'
365
368
  }
366
369
 
367
- QTAGS_1 = [
370
+ QTAGS = [
368
371
  ['**', 'b'],
369
372
  ['*', 'strong'],
370
373
  ['??', 'cite'],
374
+ ['-', 'del', :limit],
371
375
  ['__', 'i'],
376
+ ['_', 'em', :limit],
377
+ ['%', 'span', :limit],
378
+ ['+', 'ins', :limit],
372
379
  ['^', 'sup'],
373
380
  ['~', 'sub']
374
381
  ]
375
- QTAGS_RE_1 = /(#{ QTAGS_1.collect { |rc, ht| Regexp::quote( rc ) }.join( '|' ) })
376
- (#{C})
377
- (?::(\S+?))?
378
- ([^\s\1]+?(?:[^\n]|\n(?!\n))*?)
379
- \1/xm
380
-
381
- QTAGS_2 = [
382
- ['-', 'del'],
383
- ['_', 'em'],
384
- ['%', 'span'],
385
- ['+', 'ins'],
386
- ['^', 'sup'],
387
- ['~', 'sub']
388
- ]
389
- QTAGS_RE_2 = /(^|[\s\>#{ PUNCT }{(\[])
390
- (#{ QTAGS_2.collect { |rc, ht| Regexp::quote( rc ) }.join( '|' ) })
391
- (#{C})
392
- (?::(\S+?))?
393
- ([^\s\2]+?(?:[^\n]|\n(?!\n))*?)
394
- \2
395
- (?=[\s\])}<#{ PUNCT }]|$)/xm
396
- QTAGS = QTAGS_1 + QTAGS_2
382
+ QTAGS.collect! do |rc, ht, rtype|
383
+ rcq = Regexp::quote rc
384
+ re =
385
+ case rtype
386
+ when :limit
387
+ /(\W)
388
+ (#{rcq})
389
+ (#{C})
390
+ (?::(\S+?))?
391
+ (.+?)
392
+ #{rcq}
393
+ (?=\W)/x
394
+ else
395
+ /(#{rcq})
396
+ (#{C})
397
+ (?::(\S+?))?
398
+ (.+?)
399
+ #{rcq}/xm
400
+ end
401
+ [rc, ht, re, rtype]
402
+ end
397
403
 
398
404
  #
399
405
  # Flexible HTML escaping
@@ -426,7 +432,7 @@ class RedCloth < String
426
432
  style << "vertical-align:#{ v_align( $& ) };" if text =~ A_VLGN
427
433
  end
428
434
 
429
- style << "#{ $1 };" if not @filter_styles and
435
+ style << "#{ $1 };" if not filter_styles and
430
436
  text.sub!( /\{([^}]*)\}/, '' )
431
437
 
432
438
  lang = $1 if
@@ -553,7 +559,7 @@ class RedCloth < String
553
559
  text.gsub!( CODE_RE ) do |m|
554
560
  before,lang,code,after = $~[1..4]
555
561
  lang = " lang=\"#{ lang }\"" if lang
556
- "#{ before }<code#{ lang }>#{ code }</code>#{ after }"
562
+ rip_offtags( "#{ before }<code#{ lang }>#{ code }</code>#{ after }" )
557
563
  end
558
564
  end
559
565
 
@@ -562,14 +568,14 @@ class RedCloth < String
562
568
  end
563
569
 
564
570
  def hard_break( text )
565
- text.gsub!( /(.)\n(?! *[#*\s|])/, "\\1<br />" ) if @hard_breaks
571
+ text.gsub!( /(.)\n(?! *[#*\s|]|$)/, "\\1<br />" ) if hard_breaks
566
572
  end
567
573
 
568
- BLOCKS_GROUP_RE = /((?:^([#*> ])(?:[^\n]|\n+(?:\2|>)|\n(?!\n|\Z))+))|((?:[^\n]+|\n+ +|\n(?![#*\n]|\Z))+)/m
574
+ BLOCKS_GROUP_RE = /\n{2,}(?! )/m
569
575
 
570
576
  def blocks( text, deep_code = false )
571
- text.gsub!( BLOCKS_GROUP_RE ) do |blk|
572
- plain = $3 ? true : false
577
+ text.replace( text.split( BLOCKS_GROUP_RE ).collect do |blk|
578
+ plain = blk !~ /\A[#*> ]/
573
579
 
574
580
  # skip blocks that are complex HTML
575
581
  if blk =~ /^<\/?(\w+).*>/ and not SIMPLE_HTML_TAGS.include? $1
@@ -592,11 +598,11 @@ class RedCloth < String
592
598
  end
593
599
  end
594
600
 
595
- block_applied = nil
601
+ block_applied = 0
596
602
  @rules.each do |rule_name|
597
- break if block_applied = ( rule_name.to_s.match /^block_/ and method( rule_name ).call( blk ) )
603
+ block_applied += 1 if ( rule_name.to_s.match /^block_/ and method( rule_name ).call( blk ) )
598
604
  end
599
- unless block_applied
605
+ if block_applied.zero?
600
606
  if deep_code
601
607
  blk = "\t<pre><code>#{ blk }</code></pre>"
602
608
  else
@@ -608,7 +614,7 @@ class RedCloth < String
608
614
  end
609
615
  end
610
616
 
611
- end
617
+ end.join( "\n\n" ) )
612
618
  end
613
619
 
614
620
  def textile_bq( tag, atts, cite, content )
@@ -708,27 +714,23 @@ class RedCloth < String
708
714
  end
709
715
 
710
716
  def inline_textile_span( text )
711
- text.gsub!( QTAGS_RE_1 ) do |m|
712
-
713
- qtag,atts,cite,content = $~[1..4]
714
- ht = QTAGS.assoc( qtag ).last
715
- atts = pba( atts )
716
- atts << " cite=\"#{ cite }\"" if cite
717
- atts = shelve( atts ) if atts
718
-
719
- "<#{ ht }#{ atts }>#{ content }</#{ ht }>"
720
-
721
- end
722
- text.gsub!( QTAGS_RE_2 ) do |m|
723
-
724
- sta,qtag,atts,cite,content = $~[1..5]
725
- ht = QTAGS.assoc( qtag ).last
726
- atts = pba( atts )
727
- atts << " cite=\"#{ cite }\"" if cite
728
- atts = shelve( atts ) if atts
717
+ QTAGS.each do |qtag_rc, ht, qtag_re, rtype|
718
+ text.gsub!( qtag_re ) do |m|
719
+
720
+ case rtype
721
+ when :limit
722
+ sta,qtag,atts,cite,content = $~[1..5]
723
+ else
724
+ qtag,atts,cite,content = $~[1..4]
725
+ sta = ''
726
+ end
727
+ atts = pba( atts )
728
+ atts << " cite=\"#{ cite }\"" if cite
729
+ atts = shelve( atts ) if atts
729
730
 
730
- "#{ sta }<#{ ht }#{ atts }>#{ content }</#{ ht }>"
731
+ "#{ sta }<#{ ht }#{ atts }>#{ content }</#{ ht }>"
731
732
 
733
+ end
732
734
  end
733
735
  end
734
736
 
@@ -980,7 +982,6 @@ class RedCloth < String
980
982
  end
981
983
 
982
984
  def rip_offtags( text )
983
- pre_list = []
984
985
  if text =~ /<.*>/
985
986
  ## strip and encode <pre> content
986
987
  codepre, used_offtags = 0, {}
@@ -991,17 +992,17 @@ class RedCloth < String
991
992
  used_offtags[offtag] = true
992
993
  if codepre - used_offtags.length > 0
993
994
  htmlesc( line, :NoQuotes ) unless used_offtags['notextile']
994
- pre_list.last << line
995
+ @pre_list.last << line
995
996
  line = ""
996
997
  else
997
998
  htmlesc( aftertag, :NoQuotes ) if aftertag and not used_offtags['notextile']
998
- line = "<redpre##{ pre_list.length }>"
999
- pre_list << "#{ $3 }#{ aftertag }"
999
+ line = "<redpre##{ @pre_list.length }>"
1000
+ @pre_list << "#{ $3 }#{ aftertag }"
1000
1001
  end
1001
1002
  elsif $1 and codepre > 0
1002
1003
  if codepre - used_offtags.length > 0
1003
1004
  htmlesc( line, :NoQuotes ) unless used_offtags['notextile']
1004
- pre_list.last << line
1005
+ @pre_list.last << line
1005
1006
  line = ""
1006
1007
  end
1007
1008
  codepre -= 1 unless codepre.zero?
@@ -1010,13 +1011,13 @@ class RedCloth < String
1010
1011
  line
1011
1012
  end
1012
1013
  end
1013
- pre_list
1014
+ text
1014
1015
  end
1015
1016
 
1016
- def smooth_offtags( text, pre_list )
1017
- unless pre_list.empty?
1017
+ def smooth_offtags( text )
1018
+ unless @pre_list.empty?
1018
1019
  ## replace <pre> content
1019
- text.gsub!( /<redpre#(\d+)>/ ) { pre_list[$1.to_i] }
1020
+ text.gsub!( /<redpre#(\d+)>/ ) { @pre_list[$1.to_i] }
1020
1021
  end
1021
1022
  end
1022
1023
 
@@ -1038,5 +1039,64 @@ class RedCloth < String
1038
1039
  ' <a target="_blank" href="http://hobix.com/textile/#' + helpvar + '" onclick="window.open(this.href, \'popupwindow\', \'width=' + windowW + ',height=' + windowH + ',scrollbars,resizable\'); return false;">' + name + '</a><br />'
1039
1040
  end
1040
1041
 
1042
+ # HTML cleansing stuff
1043
+ BASIC_TAGS = {
1044
+ 'a' => ['href', 'title'],
1045
+ 'img' => ['src', 'alt', 'title'],
1046
+ 'br' => [],
1047
+ 'i' => nil,
1048
+ 'u' => nil,
1049
+ 'b' => nil,
1050
+ 'pre' => nil,
1051
+ 'kbd' => nil,
1052
+ 'code' => ['lang'],
1053
+ 'cite' => nil,
1054
+ 'strong' => nil,
1055
+ 'em' => nil,
1056
+ 'ins' => nil,
1057
+ 'sup' => nil,
1058
+ 'sub' => nil,
1059
+ 'del' => nil,
1060
+ 'table' => nil,
1061
+ 'tr' => nil,
1062
+ 'td' => ['colspan', 'rowspan'],
1063
+ 'th' => nil,
1064
+ 'ol' => nil,
1065
+ 'ul' => nil,
1066
+ 'li' => nil,
1067
+ 'p' => nil,
1068
+ 'h1' => nil,
1069
+ 'h2' => nil,
1070
+ 'h3' => nil,
1071
+ 'h4' => nil,
1072
+ 'h5' => nil,
1073
+ 'h6' => nil,
1074
+ 'blockquote' => ['cite']
1075
+ }
1076
+
1077
+ def clean_html( text, tags = BASIC_TAGS )
1078
+ text.gsub!( /<!\[CDATA\[/, '' )
1079
+ text.gsub!( /<(\/*)(\w+)([^>]*)>/ ) do
1080
+ raw = $~
1081
+ tag = raw[2].downcase
1082
+ if tags.has_key? tag
1083
+ pcs = [tag]
1084
+ tags[tag].each do |prop|
1085
+ ['"', "'", ''].each do |q|
1086
+ q2 = ( q != '' ? q : '\s' )
1087
+ if raw[3] =~ /#{prop}\s*=\s*#{q}([^#{q2}]+)#{q}/i
1088
+ attrv = $1
1089
+ next if prop == 'src' and attrv !~ /^http/
1090
+ pcs << "#{prop}=\"#{$1.gsub('"', '\\"')}\""
1091
+ break
1092
+ end
1093
+ end
1094
+ end if tags[tag]
1095
+ "<#{raw[1]}#{pcs.join " "}>"
1096
+ else
1097
+ " "
1098
+ end
1099
+ end
1100
+ end
1041
1101
  end
1042
1102
 
@@ -12,6 +12,9 @@ Dir["tests/*.yml"].each do |testfile|
12
12
  red.to_html
13
13
  end
14
14
  puts "---"
15
+
16
+ html.gsub!( /\n+/, "\n" )
17
+ doc['out'].gsub!( /\n+/, "\n" )
15
18
  if html == doc['out']
16
19
  puts "success: true"
17
20
  else
@@ -18,6 +18,7 @@ out: '<p><span style="color:red;">nested span because of <span><span class="newW
18
18
  ---
19
19
  in: |-
20
20
  h2. Version History
21
+
21
22
  * "Version
22
23
  0.0":http://www.threewordslong.com/render-0-8-9b.patch - Early version using MD5 hashes.
23
24
  * "Version
@@ -25,6 +26,7 @@ in: |-
25
26
  * "Version 0.2":http://www.threewordslong.com/chunk-0-2.patch.gz - Fixed problem with "authors" page and some tests.
26
27
  out: |-
27
28
  <h2>Version History</h2>
29
+
28
30
  <ul>
29
31
  <li><a href="http://www.threewordslong.com/render-0-8-9b.patch">Version
30
32
  0.0</a> &#8211; Early version using <span class="caps">MD5</span> hashes.</li>
@@ -45,7 +45,6 @@ in: |-
45
45
  yeah number
46
46
  #* bullet
47
47
  *** okay
48
-
49
48
  ****# what
50
49
 
51
50
 
@@ -66,7 +65,6 @@ out: |-
66
65
  <li>bullet
67
66
  <ul>
68
67
  <li>okay
69
-
70
68
  <ol>
71
69
  <li>what</li>
72
70
  </ul></li>
@@ -0,0 +1,198 @@
1
+ in: |
2
+ {background:#ddd}. |S|Target|Complete|App|Milestone|
3
+ |!/i/g.gif!|11/18/04|11/18/04|070|XML spec complete|
4
+ |!/i/g.gif!|11/29/04|11/29/04|011|XML spec complete (KH is on schedule)|
5
+ |!/i/g.gif!|11/29/04|11/29/04|051|XML spec complete (KH is on schedule)|
6
+ |!/i/g.gif!|11/29/04|11/29/04|081|XML spec complete (KH is on schedule)|
7
+ |!/i/g.gif!|11/19/04|11/22/04|070|Preprocessor complete|
8
+ |!/i/g.gif!|11/22/04|11/22/04|070|Dialog pass 1 builds an index file|
9
+ |!/i/g.gif!|11/24/04|11/24/04|070|Dialog pass 2 98% complete|
10
+ |!/i/g.gif!|11/30/04|11/30/04|070|Feature complete. Passes end-to-end smoke test.|
11
+ |!/i/g.gif!|11/30/04|11/30/04|011|Preprocessor updates complete|
12
+ |!/i/g.gif!|11/30/04|11/30/04|051|Preprocessor updates complete|
13
+ |!/i/g.gif!|11/30/04|11/29/04|081|Preprocessor updates complete|
14
+ |!/i/w.gif!|12/02/04|.|011|Dialog pass 1 and 2 complete (98+%)|
15
+ |!/i/w.gif!|12/02/04|.|051|Dialog pass 1 and 2 complete (98+%)|
16
+ |!/i/w.gif!|12/02/04|.|081|Dialog pass 1 and 2 complete (98+%)|
17
+ |!/i/w.gif!|12/03/04|.|011|Feature complete|
18
+ |!/i/w.gif!|12/03/04|.|051|Feature complete|
19
+ |!/i/w.gif!|12/03/04|.|081|Feature complete|
20
+ |!/i/w.gif!|12/10/04|.|011|Deployed to Napa test workstation. Passes smoke test.|
21
+ |!/i/w.gif!|12/10/04|.|051|Deployed to Napa test workstation. Passes smoke test.|
22
+ |!/i/w.gif!|12/10/04|.|081|Deployed to Napa test workstation. Passes smoke test.|
23
+ |!/i/w.gif!|12/10/04|.|070|Deployed to Napa test workstation. Passes smoke test.|
24
+ |!/i/w.gif!|12/17/04|.|011|System testing complete. Begin testing with live customer data.|
25
+ |!/i/w.gif!|12/17/04|.|051|System testing complete. Begin testing with live customer data.|
26
+ |!/i/w.gif!|12/17/04|.|081|System testing complete. Begin testing with live customer data.|
27
+ |!/i/w.gif!|12/17/04|.|070|System testing complete. Begin testing with live customer data.|
28
+ out: |-
29
+ <table>
30
+ <tr style="background:#ddd;">
31
+ <td>S</td>
32
+ <td>Target</td>
33
+ <td>Complete</td>
34
+ <td>App</td>
35
+ <td>Milestone</td>
36
+ </tr>
37
+ <tr>
38
+ <td><img src="/i/g.gif" alt="" /></td>
39
+ <td>11/18/04</td>
40
+ <td>11/18/04</td>
41
+ <td>070</td>
42
+ <td>XML spec complete</td>
43
+ </tr>
44
+ <tr>
45
+ <td><img src="/i/g.gif" alt="" /></td>
46
+ <td>11/29/04</td>
47
+ <td>11/29/04</td>
48
+ <td>011</td>
49
+ <td>XML spec complete (KH is on schedule)</td>
50
+ </tr>
51
+ <tr>
52
+ <td><img src="/i/g.gif" alt="" /></td>
53
+ <td>11/29/04</td>
54
+ <td>11/29/04</td>
55
+ <td>051</td>
56
+ <td>XML spec complete (KH is on schedule)</td>
57
+ </tr>
58
+ <tr>
59
+ <td><img src="/i/g.gif" alt="" /></td>
60
+ <td>11/29/04</td>
61
+ <td>11/29/04</td>
62
+ <td>081</td>
63
+ <td>XML spec complete (KH is on schedule)</td>
64
+ </tr>
65
+ <tr>
66
+ <td><img src="/i/g.gif" alt="" /></td>
67
+ <td>11/19/04</td>
68
+ <td>11/22/04</td>
69
+ <td>070</td>
70
+ <td>Preprocessor complete</td>
71
+ </tr>
72
+ <tr>
73
+ <td><img src="/i/g.gif" alt="" /></td>
74
+ <td>11/22/04</td>
75
+ <td>11/22/04</td>
76
+ <td>070</td>
77
+ <td>Dialog pass 1 builds an index file</td>
78
+ </tr>
79
+ <tr>
80
+ <td><img src="/i/g.gif" alt="" /></td>
81
+ <td>11/24/04</td>
82
+ <td>11/24/04</td>
83
+ <td>070</td>
84
+ <td>Dialog pass 2 98% complete</td>
85
+ </tr>
86
+ <tr>
87
+ <td><img src="/i/g.gif" alt="" /></td>
88
+ <td>11/30/04</td>
89
+ <td>11/30/04</td>
90
+ <td>070</td>
91
+ <td>Feature complete. Passes end-to-end smoke test.</td>
92
+ </tr>
93
+ <tr>
94
+ <td><img src="/i/g.gif" alt="" /></td>
95
+ <td>11/30/04</td>
96
+ <td>11/30/04</td>
97
+ <td>011</td>
98
+ <td>Preprocessor updates complete</td>
99
+ </tr>
100
+ <tr>
101
+ <td><img src="/i/g.gif" alt="" /></td>
102
+ <td>11/30/04</td>
103
+ <td>11/30/04</td>
104
+ <td>051</td>
105
+ <td>Preprocessor updates complete</td>
106
+ </tr>
107
+ <tr>
108
+ <td><img src="/i/g.gif" alt="" /></td>
109
+ <td>11/30/04</td>
110
+ <td>11/29/04</td>
111
+ <td>081</td>
112
+ <td>Preprocessor updates complete</td>
113
+ </tr>
114
+ <tr>
115
+ <td><img src="/i/w.gif" alt="" /></td>
116
+ <td>12/02/04</td>
117
+ <td>011</td>
118
+ <td>Dialog pass 1 and 2 complete (98+%)</td>
119
+ </tr>
120
+ <tr>
121
+ <td><img src="/i/w.gif" alt="" /></td>
122
+ <td>12/02/04</td>
123
+ <td>051</td>
124
+ <td>Dialog pass 1 and 2 complete (98+%)</td>
125
+ </tr>
126
+ <tr>
127
+ <td><img src="/i/w.gif" alt="" /></td>
128
+ <td>12/02/04</td>
129
+ <td>081</td>
130
+ <td>Dialog pass 1 and 2 complete (98+%)</td>
131
+ </tr>
132
+ <tr>
133
+ <td><img src="/i/w.gif" alt="" /></td>
134
+ <td>12/03/04</td>
135
+ <td>011</td>
136
+ <td>Feature complete</td>
137
+ </tr>
138
+ <tr>
139
+ <td><img src="/i/w.gif" alt="" /></td>
140
+ <td>12/03/04</td>
141
+ <td>051</td>
142
+ <td>Feature complete</td>
143
+ </tr>
144
+ <tr>
145
+ <td><img src="/i/w.gif" alt="" /></td>
146
+ <td>12/03/04</td>
147
+ <td>081</td>
148
+ <td>Feature complete</td>
149
+ </tr>
150
+ <tr>
151
+ <td><img src="/i/w.gif" alt="" /></td>
152
+ <td>12/10/04</td>
153
+ <td>011</td>
154
+ <td>Deployed to Napa test workstation. Passes smoke test.</td>
155
+ </tr>
156
+ <tr>
157
+ <td><img src="/i/w.gif" alt="" /></td>
158
+ <td>12/10/04</td>
159
+ <td>051</td>
160
+ <td>Deployed to Napa test workstation. Passes smoke test.</td>
161
+ </tr>
162
+ <tr>
163
+ <td><img src="/i/w.gif" alt="" /></td>
164
+ <td>12/10/04</td>
165
+ <td>081</td>
166
+ <td>Deployed to Napa test workstation. Passes smoke test.</td>
167
+ </tr>
168
+ <tr>
169
+ <td><img src="/i/w.gif" alt="" /></td>
170
+ <td>12/10/04</td>
171
+ <td>070</td>
172
+ <td>Deployed to Napa test workstation. Passes smoke test.</td>
173
+ </tr>
174
+ <tr>
175
+ <td><img src="/i/w.gif" alt="" /></td>
176
+ <td>12/17/04</td>
177
+ <td>011</td>
178
+ <td>System testing complete. Begin testing with live customer data.</td>
179
+ </tr>
180
+ <tr>
181
+ <td><img src="/i/w.gif" alt="" /></td>
182
+ <td>12/17/04</td>
183
+ <td>051</td>
184
+ <td>System testing complete. Begin testing with live customer data.</td>
185
+ </tr>
186
+ <tr>
187
+ <td><img src="/i/w.gif" alt="" /></td>
188
+ <td>12/17/04</td>
189
+ <td>081</td>
190
+ <td>System testing complete. Begin testing with live customer data.</td>
191
+ </tr>
192
+ <tr>
193
+ <td><img src="/i/w.gif" alt="" /></td>
194
+ <td>12/17/04</td>
195
+ <td>070</td>
196
+ <td>System testing complete. Begin testing with live customer data.</td>
197
+ </tr>
198
+ </table>