parity-RedCloth 4.2.9

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 (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