parity-RedCloth 4.2.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/.rspec +1 -0
  4. data/CHANGELOG +265 -0
  5. data/COPYING +18 -0
  6. data/Gemfile +7 -0
  7. data/README.rdoc +215 -0
  8. data/Rakefile +18 -0
  9. data/bin/redcloth +28 -0
  10. data/doc/textile_reference.html +631 -0
  11. data/ext/redcloth_scan/extconf.rb +6 -0
  12. data/ext/redcloth_scan/redcloth.h +220 -0
  13. data/ext/redcloth_scan/redcloth_attributes.c +650 -0
  14. data/ext/redcloth_scan/redcloth_inline.c +8153 -0
  15. data/ext/redcloth_scan/redcloth_scan.c +24407 -0
  16. data/lib/case_sensitive_require/RedCloth.rb +6 -0
  17. data/lib/redcloth/erb_extension.rb +27 -0
  18. data/lib/redcloth/formatters/base.rb +63 -0
  19. data/lib/redcloth/formatters/html.rb +352 -0
  20. data/lib/redcloth/formatters/latex.rb +331 -0
  21. data/lib/redcloth/formatters/latex_entities.yml +2414 -0
  22. data/lib/redcloth/textile_doc.rb +113 -0
  23. data/lib/redcloth/version.rb +34 -0
  24. data/lib/redcloth.rb +45 -0
  25. data/lib/tasks/pureruby.rake +17 -0
  26. data/redcloth.gemspec +54 -0
  27. data/spec/benchmark_spec.rb +15 -0
  28. data/spec/custom_tags_spec.rb +50 -0
  29. data/spec/erb_spec.rb +10 -0
  30. data/spec/extension_spec.rb +26 -0
  31. data/spec/fixtures/basic.yml +1028 -0
  32. data/spec/fixtures/code.yml +257 -0
  33. data/spec/fixtures/definitions.yml +82 -0
  34. data/spec/fixtures/extra_whitespace.yml +64 -0
  35. data/spec/fixtures/filter_html.yml +177 -0
  36. data/spec/fixtures/filter_pba.yml +20 -0
  37. data/spec/fixtures/html.yml +348 -0
  38. data/spec/fixtures/images.yml +279 -0
  39. data/spec/fixtures/instiki.yml +38 -0
  40. data/spec/fixtures/links.yml +291 -0
  41. data/spec/fixtures/lists.yml +462 -0
  42. data/spec/fixtures/poignant.yml +89 -0
  43. data/spec/fixtures/sanitize_html.yml +42 -0
  44. data/spec/fixtures/table.yml +434 -0
  45. data/spec/fixtures/textism.yml +509 -0
  46. data/spec/fixtures/threshold.yml +762 -0
  47. data/spec/formatters/class_filtered_html_spec.rb +7 -0
  48. data/spec/formatters/filtered_html_spec.rb +7 -0
  49. data/spec/formatters/html_no_breaks_spec.rb +9 -0
  50. data/spec/formatters/html_spec.rb +13 -0
  51. data/spec/formatters/id_filtered_html_spec.rb +7 -0
  52. data/spec/formatters/latex_spec.rb +13 -0
  53. data/spec/formatters/lite_mode_html_spec.rb +7 -0
  54. data/spec/formatters/no_span_caps_html_spec.rb +7 -0
  55. data/spec/formatters/sanitized_html_spec.rb +7 -0
  56. data/spec/formatters/style_filtered_html_spec.rb +7 -0
  57. data/spec/parser_spec.rb +102 -0
  58. data/spec/spec_helper.rb +36 -0
  59. data/tasks/compile.rake +47 -0
  60. data/tasks/gems.rake +37 -0
  61. data/tasks/ragel_extension_task.rb +127 -0
  62. data/tasks/release.rake +15 -0
  63. data/tasks/rspec.rake +13 -0
  64. data/tasks/rvm.rake +79 -0
  65. metadata +239 -0
@@ -0,0 +1,6 @@
1
+ # A workaround to make Rails 2.1 gem dependency easier on case-sensitive filesystems.
2
+ # Since the gem name is RedCloth and the file is redcloth.rb, config.gem 'RedCloth' doesn't
3
+ # work. You'd have to use config.gem 'RedCloth', :lib => 'redcloth', and that's not
4
+ # immediately obvious. This file remedies that.
5
+ #
6
+ require File.join(File.dirname(__FILE__), '..', 'redcloth')
@@ -0,0 +1,27 @@
1
+ class ERB
2
+ module Util
3
+
4
+ #
5
+ # A utility method for transforming Textile in _s_ to HTML.
6
+ #
7
+ # require "erb"
8
+ # include ERB::Util
9
+ #
10
+ # puts textilize("Isn't ERB *great*?")
11
+ #
12
+ # _Generates_
13
+ #
14
+ # <p>Isn&#8217;t <span class="caps">ERB</span> <strong>great</strong>?</p>
15
+ #
16
+ def textilize( s )
17
+ if s && s.respond_to?(:to_s)
18
+ RedCloth.new( s.to_s ).to_html
19
+ end
20
+ end
21
+
22
+ alias t textilize
23
+ module_function :t
24
+ module_function :textilize
25
+
26
+ end
27
+ end
@@ -0,0 +1,63 @@
1
+ module RedCloth::Formatters
2
+ module Base
3
+
4
+ def ignore(opts)
5
+ opts[:text]
6
+ end
7
+ alias_method :notextile, :ignore
8
+
9
+ def redcloth_version(opts)
10
+ p(:text => "#{opts[:prefix]}#{RedCloth::VERSION}")
11
+ end
12
+
13
+ def inline_redcloth_version(opts)
14
+ RedCloth::VERSION::STRING
15
+ end
16
+
17
+ [:del_phrase, :sup_phrase, :sub_phrase, :span_phrase].each do |phrase_method|
18
+ method = phrase_method.to_s.split('_')[0]
19
+ define_method(phrase_method) do |opts|
20
+ "#{opts[:beginning_space]}#{self.send(method, opts)}"
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def pba(opts)
27
+ opts.delete(:style) if filter_styles
28
+ opts.delete(:class) if filter_classes
29
+ opts.delete(:id) if filter_ids
30
+
31
+ atts = ''
32
+ opts[:"text-align"] = opts.delete(:align)
33
+ opts[:style] += ';' if opts[:style] && (opts[:style][-1..-1] != ';')
34
+ [:float, :"text-align", :"vertical-align"].each do |a|
35
+ opts[:style] = "#{a}:#{opts[a]};#{opts[:style]}" if opts[a]
36
+ end
37
+ [:"padding-right", :"padding-left"].each do |a|
38
+ opts[:style] = "#{a}:#{opts[a]}em;#{opts[:style]}" if opts[a]
39
+ end
40
+ [:style, :class, :lang, :id, :colspan, :rowspan, :title, :start, :align].each do |a|
41
+ atts << " #{a}=\"#{ html_esc(opts[a].to_s, :html_escape_attributes) }\"" if opts[a]
42
+ end
43
+ atts
44
+ end
45
+
46
+ def method_missing(method, opts)
47
+ opts[:text] || ""
48
+ end
49
+
50
+ def before_transform(text)
51
+
52
+ end
53
+
54
+ def after_transform(text)
55
+
56
+ end
57
+
58
+ def formatter_methods
59
+ singleton_methods.map! {|method| method.to_sym }
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,352 @@
1
+ module RedCloth::Formatters::HTML
2
+ include RedCloth::Formatters::Base
3
+
4
+ [:h1, :h2, :h3, :h4, :h5, :h6, :p, :pre, :div].each do |m|
5
+ define_method(m) do |opts|
6
+ "<#{m}#{pba(opts)}>#{opts[:text]}</#{m}>\n"
7
+ end
8
+ end
9
+
10
+ [:strong, :code, :em, :i, :b, :ins, :sup, :sub, :span, :cite].each do |m|
11
+ define_method(m) do |opts|
12
+ opts[:block] = true
13
+ "<#{m}#{pba(opts)}>#{opts[:text]}</#{m}>"
14
+ end
15
+ end
16
+
17
+ def hr(opts)
18
+ "<hr#{pba(opts)} />\n"
19
+ end
20
+
21
+ def acronym(opts)
22
+ opts[:block] = true
23
+ "<acronym#{pba(opts)}>#{caps(:text => opts[:text])}</acronym>"
24
+ end
25
+
26
+ def caps(opts)
27
+ if no_span_caps
28
+ opts[:text]
29
+ else
30
+ opts[:class] = 'caps'
31
+ span(opts)
32
+ end
33
+ end
34
+
35
+ def del(opts)
36
+ opts[:block] = true
37
+ "<del#{pba(opts)}>#{opts[:text]}</del>"
38
+ end
39
+
40
+ [:ol, :ul].each do |m|
41
+ define_method("#{m}_open") do |opts|
42
+ opts[:block] = true
43
+ "#{"\n" if opts[:nest] > 1}#{"\t" * (opts[:nest] - 1)}<#{m}#{pba(opts)}>\n"
44
+ end
45
+ define_method("#{m}_close") do |opts|
46
+ "#{"\t" * (opts[:nest] - 1)}</#{m}>#{"\n" if opts[:nest] <= 1}"
47
+ end
48
+ end
49
+
50
+ def li_open(opts)
51
+ "#{"\t" * opts[:nest]}<li#{pba(opts)}>#{opts[:text]}"
52
+ end
53
+
54
+ def li_close(opts=nil)
55
+ "</li>\n"
56
+ end
57
+
58
+ def dl_open(opts)
59
+ opts[:block] = true
60
+ "<dl#{pba(opts)}>\n"
61
+ end
62
+
63
+ def dl_close(opts=nil)
64
+ "</dl>\n"
65
+ end
66
+
67
+ [:dt, :dd].each do |m|
68
+ define_method(m) do |opts|
69
+ "\t<#{m}#{pba(opts)}>#{opts[:text]}</#{m}>\n"
70
+ end
71
+ end
72
+
73
+ def td(opts)
74
+ tdtype = opts[:th] ? 'th' : 'td'
75
+ "\t\t<#{tdtype}#{pba(opts)}>#{opts[:text]}</#{tdtype}>\n"
76
+ end
77
+
78
+ def tr_open(opts)
79
+ "\t<tr#{pba(opts)}>\n"
80
+ end
81
+
82
+ def tr_close(opts)
83
+ "\t</tr>\n"
84
+ end
85
+
86
+ def table_open(opts)
87
+ "<table#{pba(opts)}>\n"
88
+ end
89
+
90
+ def table_close(opts)
91
+ "</table>\n"
92
+ end
93
+
94
+ def bc_open(opts)
95
+ opts[:block] = true
96
+ "<pre#{pba(opts)}>"
97
+ end
98
+
99
+ def bc_close(opts)
100
+ "</pre>\n"
101
+ end
102
+
103
+ def bq_open(opts)
104
+ opts[:block] = true
105
+ cite = opts[:cite] ? " cite=\"#{ escape_attribute opts[:cite] }\"" : ''
106
+ "<blockquote#{cite}#{pba(opts)}>\n"
107
+ end
108
+
109
+ def bq_close(opts)
110
+ "</blockquote>\n"
111
+ end
112
+
113
+ def link(opts)
114
+ "<a href=\"#{escape_attribute opts[:href]}\"#{pba(opts)}>#{opts[:name]}</a>"
115
+ end
116
+
117
+ def auto_link(opts)
118
+ return opts[:href] unless auto_link_urls
119
+ href_with_proto = opts[:href]
120
+ href_with_proto = 'http://' + href_with_proto unless href_with_proto.index('http') == 0
121
+ "<a href=\"#{escape_attribute href_with_proto}\">#{escape_attribute opts[:href]}</a>"
122
+ end
123
+
124
+ def image(opts)
125
+ opts.delete(:align)
126
+ opts[:alt] = opts[:title]
127
+ img = "<img src=\"#{escape_attribute opts[:src]}\"#{pba(opts)} alt=\"#{escape_attribute opts[:alt].to_s}\" />"
128
+ img = "<a href=\"#{escape_attribute opts[:href]}\">#{img}</a>" if opts[:href]
129
+ img
130
+ end
131
+
132
+ def footno(opts)
133
+ opts[:id] ||= opts[:text]
134
+ %Q{<sup class="footnote" id=\"fnr#{opts[:id]}\"><a href=\"#fn#{opts[:id]}\">#{opts[:text]}</a></sup>}
135
+ end
136
+
137
+ def fn(opts)
138
+ no = opts[:id]
139
+ opts[:id] = "fn#{no}"
140
+ opts[:class] = ["footnote", opts[:class]].compact.join(" ")
141
+ "<p#{pba(opts)}><a href=\"#fnr#{no}\"><sup>#{no}</sup></a> #{opts[:text]}</p>\n"
142
+ end
143
+
144
+ def snip(opts)
145
+ "<pre#{pba(opts)}><code>#{opts[:text]}</code></pre>\n"
146
+ end
147
+
148
+ def quote1(opts)
149
+ "&#8216;#{opts[:text]}&#8217;"
150
+ end
151
+
152
+ def quote2(opts)
153
+ "&#8220;#{opts[:text]}&#8221;"
154
+ end
155
+
156
+ def multi_paragraph_quote(opts)
157
+ "&#8220;#{opts[:text]}"
158
+ end
159
+
160
+ def ellipsis(opts)
161
+ "#{opts[:text]}&#8230;"
162
+ end
163
+
164
+ def emdash(opts)
165
+ "&#8212;"
166
+ end
167
+
168
+ def endash(opts)
169
+ " &#8211; "
170
+ end
171
+
172
+ def arrow(opts)
173
+ "&#8594;"
174
+ end
175
+
176
+ def dim(opts)
177
+ opts[:text].gsub!('x', '&#215;')
178
+ opts[:text].gsub!("'", '&#8242;')
179
+ opts[:text].gsub!('"', '&#8243;')
180
+ opts[:text]
181
+ end
182
+
183
+ def trademark(opts)
184
+ "&#8482;"
185
+ end
186
+
187
+ def registered(opts)
188
+ "&#174;"
189
+ end
190
+
191
+ def copyright(opts)
192
+ "&#169;"
193
+ end
194
+
195
+ def entity(opts)
196
+ "&#{opts[:text]};"
197
+ end
198
+
199
+ def amp(opts)
200
+ "&amp;"
201
+ end
202
+
203
+ def gt(opts)
204
+ "&gt;"
205
+ end
206
+
207
+ def lt(opts)
208
+ "&lt;"
209
+ end
210
+
211
+ def br(opts)
212
+ if hard_breaks == false
213
+ "\n"
214
+ else
215
+ "<br#{pba(opts)} />\n"
216
+ end
217
+ end
218
+
219
+ def quot(opts)
220
+ "&quot;"
221
+ end
222
+
223
+ def squot(opts)
224
+ "&#8217;"
225
+ end
226
+
227
+ def apos(opts)
228
+ "&#39;"
229
+ end
230
+
231
+ def html(opts)
232
+ "#{opts[:text]}\n"
233
+ end
234
+
235
+ def html_block(opts)
236
+ inline_html(:text => "#{opts[:indent_before_start]}#{opts[:start_tag]}#{opts[:indent_after_start]}") +
237
+ "#{opts[:text]}" +
238
+ inline_html(:text => "#{opts[:indent_before_end]}#{opts[:end_tag]}#{opts[:indent_after_end]}")
239
+ end
240
+
241
+ def notextile(opts)
242
+ if filter_html
243
+ html_esc(opts[:text], :html_escape_preformatted)
244
+ else
245
+ opts[:text]
246
+ end
247
+ end
248
+
249
+ def inline_html(opts)
250
+ if filter_html
251
+ html_esc(opts[:text], :html_escape_preformatted)
252
+ else
253
+ "#{opts[:text]}" # nil-safe
254
+ end
255
+ end
256
+
257
+ def ignored_line(opts)
258
+ opts[:text] + "\n"
259
+ end
260
+
261
+ private
262
+
263
+ # escapement for regular HTML (not in PRE tag)
264
+ def escape(text)
265
+ html_esc(text)
266
+ end
267
+
268
+ # escapement for HTML in a PRE tag
269
+ def escape_pre(text)
270
+ html_esc(text, :html_escape_preformatted)
271
+ end
272
+
273
+ # escaping for HTML attributes
274
+ def escape_attribute(text)
275
+ html_esc(text, :html_escape_attributes)
276
+ end
277
+
278
+ def after_transform(text)
279
+ text.chomp!
280
+ end
281
+
282
+
283
+ def before_transform(text)
284
+ clean_html(text) if sanitize_html
285
+ end
286
+
287
+ # HTML cleansing stuff
288
+ BASIC_TAGS = {
289
+ 'a' => ['href', 'title'],
290
+ 'img' => ['src', 'alt', 'title'],
291
+ 'br' => [],
292
+ 'i' => nil,
293
+ 'u' => nil,
294
+ 'b' => nil,
295
+ 'pre' => nil,
296
+ 'kbd' => nil,
297
+ 'code' => ['lang'],
298
+ 'cite' => nil,
299
+ 'strong' => nil,
300
+ 'em' => nil,
301
+ 'ins' => nil,
302
+ 'sup' => nil,
303
+ 'sub' => nil,
304
+ 'del' => nil,
305
+ 'table' => nil,
306
+ 'tr' => nil,
307
+ 'td' => ['colspan', 'rowspan'],
308
+ 'th' => nil,
309
+ 'ol' => ['start'],
310
+ 'ul' => nil,
311
+ 'li' => nil,
312
+ 'p' => nil,
313
+ 'h1' => nil,
314
+ 'h2' => nil,
315
+ 'h3' => nil,
316
+ 'h4' => nil,
317
+ 'h5' => nil,
318
+ 'h6' => nil,
319
+ 'blockquote' => ['cite'],
320
+ 'notextile' => nil
321
+ }
322
+
323
+ # Clean unauthorized tags.
324
+ def clean_html( text, allowed_tags = BASIC_TAGS )
325
+ text.gsub!( /<!\[CDATA\[/, '' )
326
+ text.gsub!( /<(\/*)([A-Za-z]\w*)([^>]*?)(\s?\/?)>/ ) do |m|
327
+ raw = $~
328
+ tag = raw[2].downcase
329
+ if allowed_tags.has_key? tag
330
+ pcs = [tag]
331
+ allowed_tags[tag].each do |prop|
332
+ ['"', "'", ''].each do |q|
333
+ q2 = ( q != '' ? q : '\s' )
334
+ if raw[3] =~ /#{prop}\s*=\s*#{q}([^#{q2}]+)#{q}/i
335
+ attrv = $1
336
+ next if (prop == 'src' or prop == 'href') and not attrv =~ %r{^(http|https|ftp):}
337
+ pcs << "#{prop}=\"#{attrv.gsub('"', '\\"')}\""
338
+ break
339
+ end
340
+ end
341
+ end if allowed_tags[tag]
342
+ "<#{raw[1]}#{pcs.join " "}#{raw[4]}>"
343
+ else # Unauthorized tag
344
+ if block_given?
345
+ yield m
346
+ else
347
+ ''
348
+ end
349
+ end
350
+ end
351
+ end
352
+ end