gv-RedCloth 4.2.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/.gemtest +0 -0
  2. data/.rspec +1 -0
  3. data/CHANGELOG +261 -0
  4. data/COPYING +18 -0
  5. data/Gemfile +7 -0
  6. data/README.rdoc +198 -0
  7. data/Rakefile +18 -0
  8. data/bin/redcloth +28 -0
  9. data/doc/textile_reference.html +631 -0
  10. data/ext/redcloth_scan/extconf.rb +6 -0
  11. data/ext/redcloth_scan/redcloth.h +220 -0
  12. data/ext/redcloth_scan/redcloth_attributes.c +650 -0
  13. data/ext/redcloth_scan/redcloth_inline.c +7952 -0
  14. data/ext/redcloth_scan/redcloth_scan.c +24407 -0
  15. data/lib/case_sensitive_require/RedCloth.rb +6 -0
  16. data/lib/redcloth.rb +45 -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 +345 -0
  20. data/lib/redcloth/formatters/latex.rb +322 -0
  21. data/lib/redcloth/formatters/latex_entities.yml +2414 -0
  22. data/lib/redcloth/textile_doc.rb +103 -0
  23. data/lib/redcloth/version.rb +34 -0
  24. data/lib/tasks/pureruby.rake +17 -0
  25. data/redcloth.gemspec +52 -0
  26. data/spec/benchmark_spec.rb +15 -0
  27. data/spec/custom_tags_spec.rb +50 -0
  28. data/spec/erb_spec.rb +10 -0
  29. data/spec/extension_spec.rb +26 -0
  30. data/spec/fixtures/basic.yml +1028 -0
  31. data/spec/fixtures/code.yml +257 -0
  32. data/spec/fixtures/definitions.yml +82 -0
  33. data/spec/fixtures/extra_whitespace.yml +64 -0
  34. data/spec/fixtures/filter_html.yml +177 -0
  35. data/spec/fixtures/filter_pba.yml +20 -0
  36. data/spec/fixtures/html.yml +348 -0
  37. data/spec/fixtures/images.yml +279 -0
  38. data/spec/fixtures/instiki.yml +38 -0
  39. data/spec/fixtures/links.yml +291 -0
  40. data/spec/fixtures/lists.yml +462 -0
  41. data/spec/fixtures/poignant.yml +89 -0
  42. data/spec/fixtures/sanitize_html.yml +42 -0
  43. data/spec/fixtures/table.yml +434 -0
  44. data/spec/fixtures/textism.yml +509 -0
  45. data/spec/fixtures/threshold.yml +762 -0
  46. data/spec/formatters/class_filtered_html_spec.rb +7 -0
  47. data/spec/formatters/filtered_html_spec.rb +7 -0
  48. data/spec/formatters/html_no_breaks_spec.rb +9 -0
  49. data/spec/formatters/html_spec.rb +13 -0
  50. data/spec/formatters/id_filtered_html_spec.rb +7 -0
  51. data/spec/formatters/latex_spec.rb +13 -0
  52. data/spec/formatters/lite_mode_html_spec.rb +7 -0
  53. data/spec/formatters/no_span_caps_html_spec.rb +7 -0
  54. data/spec/formatters/sanitized_html_spec.rb +7 -0
  55. data/spec/formatters/style_filtered_html_spec.rb +7 -0
  56. data/spec/parser_spec.rb +102 -0
  57. data/spec/spec_helper.rb +36 -0
  58. data/tasks/compile.rake +47 -0
  59. data/tasks/gems.rake +37 -0
  60. data/tasks/ragel_extension_task.rb +127 -0
  61. data/tasks/release.rake +15 -0
  62. data/tasks/rspec.rake +13 -0
  63. data/tasks/rvm.rake +79 -0
  64. metadata +227 -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')
data/lib/redcloth.rb ADDED
@@ -0,0 +1,45 @@
1
+ # If this is a frozen gem in Rails 2.1 and RedCloth 3.x was already
2
+ # loaded by Rails' ActionView::Helpers::TextHelper, the user will get
3
+ # "redcloth_scan.bundle: Class is not a module (TypeError)"
4
+ # This hack is to work around that Rails loading problem. The problem
5
+ # appears to be fixed in Edge Rails [51e4106].
6
+ Object.send(:remove_const, :RedCloth) if Object.const_defined?(:RedCloth) && RedCloth.is_a?(Class)
7
+
8
+ require 'rbconfig'
9
+ begin
10
+ conf = Object.const_get(defined?(RbConfig) ? :RbConfig : :Config)::CONFIG
11
+ prefix = conf['arch'] =~ /mswin|mingw/ ? "#{conf['MAJOR']}.#{conf['MINOR']}/" : ''
12
+ lib = "#{prefix}redcloth_scan"
13
+ require lib
14
+ rescue LoadError => e
15
+ e.message << %{\nCouldn't load #{lib}\nThe $LOAD_PATH was:\n#{$LOAD_PATH.join("\n")}}
16
+ raise e
17
+ end
18
+
19
+ require 'redcloth/version'
20
+ require 'redcloth/textile_doc'
21
+ require 'redcloth/formatters/base'
22
+ require 'redcloth/formatters/html'
23
+ require 'redcloth/formatters/latex'
24
+
25
+ module RedCloth
26
+
27
+ # A convenience method for creating a new TextileDoc. See
28
+ # RedCloth::TextileDoc.
29
+ def self.new( *args, &block )
30
+ RedCloth::TextileDoc.new( *args, &block )
31
+ end
32
+
33
+ # Include extension modules (if any) in TextileDoc.
34
+ def self.include(*args)
35
+ RedCloth::TextileDoc.send(:include, *args)
36
+ end
37
+
38
+ end
39
+
40
+ begin
41
+ require 'erb'
42
+ require 'redcloth/erb_extension'
43
+ include ERB::Util
44
+ rescue LoadError
45
+ end
@@ -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,345 @@
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 image(opts)
118
+ opts.delete(:align)
119
+ opts[:alt] = opts[:title]
120
+ img = "<img src=\"#{escape_attribute opts[:src]}\"#{pba(opts)} alt=\"#{escape_attribute opts[:alt].to_s}\" />"
121
+ img = "<a href=\"#{escape_attribute opts[:href]}\">#{img}</a>" if opts[:href]
122
+ img
123
+ end
124
+
125
+ def footno(opts)
126
+ opts[:id] ||= opts[:text]
127
+ %Q{<sup class="footnote" id=\"fnr#{opts[:id]}\"><a href=\"#fn#{opts[:id]}\">#{opts[:text]}</a></sup>}
128
+ end
129
+
130
+ def fn(opts)
131
+ no = opts[:id]
132
+ opts[:id] = "fn#{no}"
133
+ opts[:class] = ["footnote", opts[:class]].compact.join(" ")
134
+ "<p#{pba(opts)}><a href=\"#fnr#{no}\"><sup>#{no}</sup></a> #{opts[:text]}</p>\n"
135
+ end
136
+
137
+ def snip(opts)
138
+ "<pre#{pba(opts)}><code>#{opts[:text]}</code></pre>\n"
139
+ end
140
+
141
+ def quote1(opts)
142
+ "&#8216;#{opts[:text]}&#8217;"
143
+ end
144
+
145
+ def quote2(opts)
146
+ "&#8220;#{opts[:text]}&#8221;"
147
+ end
148
+
149
+ def multi_paragraph_quote(opts)
150
+ "&#8220;#{opts[:text]}"
151
+ end
152
+
153
+ def ellipsis(opts)
154
+ "#{opts[:text]}&#8230;"
155
+ end
156
+
157
+ def emdash(opts)
158
+ "&#8212;"
159
+ end
160
+
161
+ def endash(opts)
162
+ " &#8211; "
163
+ end
164
+
165
+ def arrow(opts)
166
+ "&#8594;"
167
+ end
168
+
169
+ def dim(opts)
170
+ opts[:text].gsub!('x', '&#215;')
171
+ opts[:text].gsub!("'", '&#8242;')
172
+ opts[:text].gsub!('"', '&#8243;')
173
+ opts[:text]
174
+ end
175
+
176
+ def trademark(opts)
177
+ "&#8482;"
178
+ end
179
+
180
+ def registered(opts)
181
+ "&#174;"
182
+ end
183
+
184
+ def copyright(opts)
185
+ "&#169;"
186
+ end
187
+
188
+ def entity(opts)
189
+ "&#{opts[:text]};"
190
+ end
191
+
192
+ def amp(opts)
193
+ "&amp;"
194
+ end
195
+
196
+ def gt(opts)
197
+ "&gt;"
198
+ end
199
+
200
+ def lt(opts)
201
+ "&lt;"
202
+ end
203
+
204
+ def br(opts)
205
+ if hard_breaks == false
206
+ "\n"
207
+ else
208
+ "<br#{pba(opts)} />\n"
209
+ end
210
+ end
211
+
212
+ def quot(opts)
213
+ "&quot;"
214
+ end
215
+
216
+ def squot(opts)
217
+ "&#8217;"
218
+ end
219
+
220
+ def apos(opts)
221
+ "&#39;"
222
+ end
223
+
224
+ def html(opts)
225
+ "#{opts[:text]}\n"
226
+ end
227
+
228
+ def html_block(opts)
229
+ inline_html(:text => "#{opts[:indent_before_start]}#{opts[:start_tag]}#{opts[:indent_after_start]}") +
230
+ "#{opts[:text]}" +
231
+ inline_html(:text => "#{opts[:indent_before_end]}#{opts[:end_tag]}#{opts[:indent_after_end]}")
232
+ end
233
+
234
+ def notextile(opts)
235
+ if filter_html
236
+ html_esc(opts[:text], :html_escape_preformatted)
237
+ else
238
+ opts[:text]
239
+ end
240
+ end
241
+
242
+ def inline_html(opts)
243
+ if filter_html
244
+ html_esc(opts[:text], :html_escape_preformatted)
245
+ else
246
+ "#{opts[:text]}" # nil-safe
247
+ end
248
+ end
249
+
250
+ def ignored_line(opts)
251
+ opts[:text] + "\n"
252
+ end
253
+
254
+ private
255
+
256
+ # escapement for regular HTML (not in PRE tag)
257
+ def escape(text)
258
+ html_esc(text)
259
+ end
260
+
261
+ # escapement for HTML in a PRE tag
262
+ def escape_pre(text)
263
+ html_esc(text, :html_escape_preformatted)
264
+ end
265
+
266
+ # escaping for HTML attributes
267
+ def escape_attribute(text)
268
+ html_esc(text, :html_escape_attributes)
269
+ end
270
+
271
+ def after_transform(text)
272
+ text.chomp!
273
+ end
274
+
275
+
276
+ def before_transform(text)
277
+ clean_html(text) if sanitize_html
278
+ end
279
+
280
+ # HTML cleansing stuff
281
+ BASIC_TAGS = {
282
+ 'a' => ['href', 'title'],
283
+ 'img' => ['src', 'alt', 'title'],
284
+ 'br' => [],
285
+ 'i' => nil,
286
+ 'u' => nil,
287
+ 'b' => nil,
288
+ 'pre' => nil,
289
+ 'kbd' => nil,
290
+ 'code' => ['lang'],
291
+ 'cite' => nil,
292
+ 'strong' => nil,
293
+ 'em' => nil,
294
+ 'ins' => nil,
295
+ 'sup' => nil,
296
+ 'sub' => nil,
297
+ 'del' => nil,
298
+ 'table' => nil,
299
+ 'tr' => nil,
300
+ 'td' => ['colspan', 'rowspan'],
301
+ 'th' => nil,
302
+ 'ol' => ['start'],
303
+ 'ul' => nil,
304
+ 'li' => nil,
305
+ 'p' => nil,
306
+ 'h1' => nil,
307
+ 'h2' => nil,
308
+ 'h3' => nil,
309
+ 'h4' => nil,
310
+ 'h5' => nil,
311
+ 'h6' => nil,
312
+ 'blockquote' => ['cite'],
313
+ 'notextile' => nil
314
+ }
315
+
316
+ # Clean unauthorized tags.
317
+ def clean_html( text, allowed_tags = BASIC_TAGS )
318
+ text.gsub!( /<!\[CDATA\[/, '' )
319
+ text.gsub!( /<(\/*)([A-Za-z]\w*)([^>]*?)(\s?\/?)>/ ) do |m|
320
+ raw = $~
321
+ tag = raw[2].downcase
322
+ if allowed_tags.has_key? tag
323
+ pcs = [tag]
324
+ allowed_tags[tag].each do |prop|
325
+ ['"', "'", ''].each do |q|
326
+ q2 = ( q != '' ? q : '\s' )
327
+ if raw[3] =~ /#{prop}\s*=\s*#{q}([^#{q2}]+)#{q}/i
328
+ attrv = $1
329
+ next if (prop == 'src' or prop == 'href') and not attrv =~ %r{^(http|https|ftp):}
330
+ pcs << "#{prop}=\"#{attrv.gsub('"', '\\"')}\""
331
+ break
332
+ end
333
+ end
334
+ end if allowed_tags[tag]
335
+ "<#{raw[1]}#{pcs.join " "}#{raw[4]}>"
336
+ else # Unauthorized tag
337
+ if block_given?
338
+ yield m
339
+ else
340
+ ''
341
+ end
342
+ end
343
+ end
344
+ end
345
+ end