RedCloth 4.0.0-x86-mswin32-60

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.

Files changed (49) hide show
  1. data/CHANGELOG +17 -0
  2. data/COPYING +18 -0
  3. data/README +156 -0
  4. data/Rakefile +240 -0
  5. data/bin/redcloth +28 -0
  6. data/ext/redcloth_scan/extconf.rb +9 -0
  7. data/ext/redcloth_scan/redcloth.h +149 -0
  8. data/ext/redcloth_scan/redcloth_attributes.c +650 -0
  9. data/ext/redcloth_scan/redcloth_attributes.rl +78 -0
  10. data/ext/redcloth_scan/redcloth_common.rl +113 -0
  11. data/ext/redcloth_scan/redcloth_inline.c +5102 -0
  12. data/ext/redcloth_scan/redcloth_inline.rl +282 -0
  13. data/ext/redcloth_scan/redcloth_scan.c +9300 -0
  14. data/ext/redcloth_scan/redcloth_scan.rl +523 -0
  15. data/extras/mingw-rbconfig.rb +176 -0
  16. data/extras/ragel_profiler.rb +73 -0
  17. data/lib/redcloth.rb +24 -0
  18. data/lib/redcloth/formatters/base.rb +50 -0
  19. data/lib/redcloth/formatters/html.rb +342 -0
  20. data/lib/redcloth/formatters/latex.rb +227 -0
  21. data/lib/redcloth/formatters/latex_entities.yml +2414 -0
  22. data/lib/redcloth/textile_doc.rb +105 -0
  23. data/lib/redcloth/version.rb +18 -0
  24. data/lib/redcloth_scan.bundle +0 -0
  25. data/lib/redcloth_scan.so +0 -0
  26. data/test/basic.yml +794 -0
  27. data/test/code.yml +195 -0
  28. data/test/definitions.yml +71 -0
  29. data/test/extra_whitespace.yml +64 -0
  30. data/test/filter_html.yml +177 -0
  31. data/test/filter_pba.yml +12 -0
  32. data/test/helper.rb +108 -0
  33. data/test/html.yml +271 -0
  34. data/test/images.yml +202 -0
  35. data/test/instiki.yml +38 -0
  36. data/test/links.yml +214 -0
  37. data/test/lists.yml +283 -0
  38. data/test/poignant.yml +89 -0
  39. data/test/sanitize_html.yml +42 -0
  40. data/test/table.yml +267 -0
  41. data/test/test_custom_tags.rb +46 -0
  42. data/test/test_extensions.rb +31 -0
  43. data/test/test_formatters.rb +15 -0
  44. data/test/test_parser.rb +68 -0
  45. data/test/test_restrictions.rb +41 -0
  46. data/test/textism.yml +480 -0
  47. data/test/threshold.yml +772 -0
  48. data/test/validate_fixtures.rb +73 -0
  49. metadata +104 -0
@@ -0,0 +1,176 @@
1
+
2
+ # This rbconfig.rb corresponds to a Ruby installation for win32 cross-compiled
3
+ # with mingw under i686-linux. It can be used to cross-compile extensions for
4
+ # win32 using said toolchain.
5
+ #
6
+ # This file assumes that a cross-compiled mingw32 build (compatible with the
7
+ # mswin32 builds) is installed under $HOME/ruby-mingw32.
8
+
9
+ module Config
10
+ #RUBY_VERSION == "1.8.5" or
11
+ # raise "ruby lib version (1.8.5) doesn't match executable version (#{RUBY_VERSION})"
12
+
13
+ mingw32 = ENV['MINGW32_RUBY'] || "#{ENV["HOME"]}/ruby-mingw32"
14
+ mingwpre = ENV['MINGW32_PREFIX']
15
+ TOPDIR = File.dirname(__FILE__).chomp!("/lib/ruby/1.8/i386-mingw32")
16
+ DESTDIR = '' unless defined? DESTDIR
17
+ CONFIG = {}
18
+ CONFIG["DESTDIR"] = DESTDIR
19
+ CONFIG["INSTALL"] = "/usr/bin/install -c"
20
+ CONFIG["prefix"] = (TOPDIR || DESTDIR + mingw32)
21
+ CONFIG["EXEEXT"] = ".exe"
22
+ CONFIG["ruby_install_name"] = "ruby"
23
+ CONFIG["RUBY_INSTALL_NAME"] = "ruby"
24
+ CONFIG["RUBY_SO_NAME"] = "msvcrt-ruby18"
25
+ CONFIG["SHELL"] = "/bin/sh"
26
+ CONFIG["PATH_SEPARATOR"] = ":"
27
+ CONFIG["PACKAGE_NAME"] = ""
28
+ CONFIG["PACKAGE_TARNAME"] = ""
29
+ CONFIG["PACKAGE_VERSION"] = ""
30
+ CONFIG["PACKAGE_STRING"] = ""
31
+ CONFIG["PACKAGE_BUGREPORT"] = ""
32
+ CONFIG["exec_prefix"] = "$(prefix)"
33
+ CONFIG["bindir"] = "$(exec_prefix)/bin"
34
+ CONFIG["sbindir"] = "$(exec_prefix)/sbin"
35
+ CONFIG["libexecdir"] = "$(exec_prefix)/libexec"
36
+ CONFIG["datadir"] = "$(prefix)/share"
37
+ CONFIG["sysconfdir"] = "$(prefix)/etc"
38
+ CONFIG["sharedstatedir"] = "$(prefix)/com"
39
+ CONFIG["localstatedir"] = "$(prefix)/var"
40
+ CONFIG["libdir"] = "$(exec_prefix)/lib"
41
+ CONFIG["includedir"] = "$(prefix)/include"
42
+ CONFIG["oldincludedir"] = "/usr/include"
43
+ CONFIG["infodir"] = "$(prefix)/info"
44
+ CONFIG["mandir"] = "$(prefix)/man"
45
+ CONFIG["build_alias"] = "i686-linux"
46
+ CONFIG["host_alias"] = "#{mingwpre}"
47
+ CONFIG["target_alias"] = "i386-mingw32"
48
+ CONFIG["ECHO_C"] = ""
49
+ CONFIG["ECHO_N"] = "-n"
50
+ CONFIG["ECHO_T"] = ""
51
+ CONFIG["LIBS"] = "-lwsock32 "
52
+ CONFIG["MAJOR"] = "1"
53
+ CONFIG["MINOR"] = "8"
54
+ CONFIG["TEENY"] = "4"
55
+ CONFIG["build"] = "i686-pc-linux"
56
+ CONFIG["build_cpu"] = "i686"
57
+ CONFIG["build_vendor"] = "pc"
58
+ CONFIG["build_os"] = "linux"
59
+ CONFIG["host"] = "i586-pc-mingw32msvc"
60
+ CONFIG["host_cpu"] = "i586"
61
+ CONFIG["host_vendor"] = "pc"
62
+ CONFIG["host_os"] = "mingw32msvc"
63
+ CONFIG["target"] = "i386-pc-mingw32"
64
+ CONFIG["target_cpu"] = "i386"
65
+ CONFIG["target_vendor"] = "pc"
66
+ CONFIG["target_os"] = "mingw32"
67
+ CONFIG["CC"] = "#{mingwpre}-gcc"
68
+ CONFIG["CFLAGS"] = "-g "
69
+ CONFIG["LDFLAGS"] = ""
70
+ CONFIG["CPPFLAGS"] = ""
71
+ CONFIG["OBJEXT"] = "o"
72
+ CONFIG["CPP"] = "#{mingwpre}-gcc -E"
73
+ CONFIG["EGREP"] = "grep -E"
74
+ CONFIG["GNU_LD"] = "yes"
75
+ CONFIG["CPPOUTFILE"] = "-o conftest.i"
76
+ CONFIG["OUTFLAG"] = "-o "
77
+ CONFIG["YACC"] = "bison -y"
78
+ CONFIG["RANLIB"] = "#{mingwpre}-ranlib"
79
+ CONFIG["AR"] = "#{mingwpre}-ar"
80
+ CONFIG["NM"] = "#{mingwpre}-nm"
81
+ CONFIG["WINDRES"] = "#{mingwpre}-windres"
82
+ CONFIG["DLLWRAP"] = "#{mingwpre}-dllwrap"
83
+ CONFIG["OBJDUMP"] = "#{mingwpre}-objdump"
84
+ CONFIG["LN_S"] = "ln -s"
85
+ CONFIG["SET_MAKE"] = ""
86
+ CONFIG["INSTALL_PROGRAM"] = "$(INSTALL)"
87
+ CONFIG["INSTALL_SCRIPT"] = "$(INSTALL)"
88
+ CONFIG["INSTALL_DATA"] = "$(INSTALL) -m 644"
89
+ CONFIG["RM"] = "rm -f"
90
+ CONFIG["CP"] = "cp"
91
+ CONFIG["MAKEDIRS"] = "mkdir -p"
92
+ CONFIG["LIBOBJS"] = " fileblocks$(U).o crypt$(U).o flock$(U).o acosh$(U).o win32$(U).o"
93
+ CONFIG["ALLOCA"] = ""
94
+ CONFIG["DLDFLAGS"] = " -Wl,--enable-auto-import,--export-all"
95
+ CONFIG["ARCH_FLAG"] = ""
96
+ CONFIG["STATIC"] = ""
97
+ CONFIG["CCDLFLAGS"] = ""
98
+ CONFIG["LDSHARED"] = "#{mingwpre}-gcc -shared -s"
99
+ CONFIG["DLEXT"] = "so"
100
+ CONFIG["DLEXT2"] = "dll"
101
+ CONFIG["LIBEXT"] = "a"
102
+ CONFIG["LINK_SO"] = ""
103
+ CONFIG["LIBPATHFLAG"] = " -L\"%s\""
104
+ CONFIG["RPATHFLAG"] = ""
105
+ CONFIG["LIBPATHENV"] = ""
106
+ CONFIG["TRY_LINK"] = ""
107
+ CONFIG["STRIP"] = "strip"
108
+ CONFIG["EXTSTATIC"] = ""
109
+ CONFIG["setup"] = "Setup"
110
+ CONFIG["MINIRUBY"] = "ruby -rfake"
111
+ CONFIG["PREP"] = "fake.rb"
112
+ CONFIG["RUNRUBY"] = "$(MINIRUBY) -I`cd $(srcdir)/lib; pwd`"
113
+ CONFIG["EXTOUT"] = ".ext"
114
+ CONFIG["ARCHFILE"] = ""
115
+ CONFIG["RDOCTARGET"] = ""
116
+ CONFIG["XCFLAGS"] = " -DRUBY_EXPORT"
117
+ CONFIG["XLDFLAGS"] = " -Wl,--stack,0x02000000 -L."
118
+ CONFIG["LIBRUBY_LDSHARED"] = "#{mingwpre}-gcc -shared -s"
119
+ CONFIG["LIBRUBY_DLDFLAGS"] = " -Wl,--enable-auto-import,--export-all -Wl,--out-implib=$(LIBRUBY)"
120
+ CONFIG["rubyw_install_name"] = "rubyw"
121
+ CONFIG["RUBYW_INSTALL_NAME"] = "rubyw"
122
+ CONFIG["LIBRUBY_A"] = "lib$(RUBY_SO_NAME)-static.a"
123
+ CONFIG["LIBRUBY_SO"] = "$(RUBY_SO_NAME).dll"
124
+ CONFIG["LIBRUBY_ALIASES"] = ""
125
+ CONFIG["LIBRUBY"] = "lib$(LIBRUBY_SO).a"
126
+ CONFIG["LIBRUBYARG"] = "$(LIBRUBYARG_SHARED)"
127
+ CONFIG["LIBRUBYARG_STATIC"] = "-l$(RUBY_SO_NAME)-static"
128
+ CONFIG["LIBRUBYARG_SHARED"] = "-l$(RUBY_SO_NAME)"
129
+ CONFIG["SOLIBS"] = "$(LIBS)"
130
+ CONFIG["DLDLIBS"] = ""
131
+ CONFIG["ENABLE_SHARED"] = "yes"
132
+ CONFIG["MAINLIBS"] = ""
133
+ CONFIG["COMMON_LIBS"] = "m"
134
+ CONFIG["COMMON_MACROS"] = ""
135
+ CONFIG["COMMON_HEADERS"] = "windows.h winsock.h"
136
+ CONFIG["EXPORT_PREFIX"] = ""
137
+ CONFIG["MINIOBJS"] = "dmydln.o"
138
+ CONFIG["MAKEFILES"] = "Makefile GNUmakefile"
139
+ CONFIG["arch"] = "i386-mingw32"
140
+ CONFIG["sitearch"] = "i386-msvcrt"
141
+ CONFIG["sitedir"] = "$(prefix)/lib/ruby/site_ruby"
142
+ CONFIG["configure_args"] = "'--host=#{mingwpre}' '--target=i386-mingw32' '--build=i686-linux' '--prefix=#{mingw32}' 'build_alias=i686-linux' 'host_alias=#{mingwpre}' 'target_alias=i386-mingw32'"
143
+ CONFIG["NROFF"] = "/usr/bin/nroff"
144
+ CONFIG["MANTYPE"] = "doc"
145
+ CONFIG["LTLIBOBJS"] = " fileblocks$(U).lo crypt$(U).lo flock$(U).lo acosh$(U).lo win32$(U).lo"
146
+ CONFIG["ruby_version"] = "$(MAJOR).$(MINOR)"
147
+ CONFIG["rubylibdir"] = "$(libdir)/ruby/$(ruby_version)"
148
+ CONFIG["archdir"] = "$(rubylibdir)/$(arch)"
149
+ CONFIG["sitelibdir"] = "$(sitedir)/$(ruby_version)"
150
+ CONFIG["sitearchdir"] = "$(sitelibdir)/$(sitearch)"
151
+ CONFIG["topdir"] = File.dirname(__FILE__)
152
+ MAKEFILE_CONFIG = {}
153
+ CONFIG.each{|k,v| MAKEFILE_CONFIG[k] = v.dup}
154
+ def Config::expand(val, config = CONFIG)
155
+ val.gsub!(/\$\$|\$\(([^()]+)\)|\$\{([^{}]+)\}/) do |var|
156
+ if !(v = $1 || $2)
157
+ '$'
158
+ elsif key = config[v = v[/\A[^:]+(?=(?::(.*?)=(.*))?\z)/]]
159
+ pat, sub = $1, $2
160
+ config[v] = false
161
+ Config::expand(key, config)
162
+ config[v] = key
163
+ key = key.gsub(/#{Regexp.quote(pat)}(?=\s|\z)/n) {sub} if pat
164
+ key
165
+ else
166
+ var
167
+ end
168
+ end
169
+ val
170
+ end
171
+ CONFIG.each_value do |val|
172
+ Config::expand(val)
173
+ end
174
+ end
175
+ RbConfig = Config # compatibility for ruby-1.9
176
+ CROSS_COMPILING = nil unless defined? CROSS_COMPILING
@@ -0,0 +1,73 @@
1
+ class RagelProfiler
2
+ MEM_CONVERSION = 1024
3
+
4
+ COMMANDS = { :compile => %w(ragel rlgen-cd gcc-4.0 gnumake cc1),
5
+ :test => %w(ruby) }
6
+
7
+ FIELDS = %w(compile_time compile_max_rss test_time test_max_rss ext_so_size)
8
+
9
+ @@results = {}
10
+
11
+ def initialize(name)
12
+ @name = name
13
+ @@results[name] = []
14
+ end
15
+
16
+ def measure(type)
17
+ raise "not a valid type" unless COMMANDS.keys.include?(type)
18
+ regex = COMMANDS[type].map {|c| Regexp.escape(c) }.join("|")
19
+ t = Thread.new do
20
+ Thread.current[:max] = 0
21
+ loop do
22
+ Thread.current[:max] = [run(regex), Thread.current[:max]].max
23
+ sleep 0.5
24
+ end
25
+ end
26
+ begin_time = Time.now
27
+ yield
28
+ total_time = Time.now - begin_time
29
+
30
+ t.kill
31
+ store_result(type, "time", total_time)
32
+ store_result(type, "max_rss", t[:max])
33
+ end
34
+
35
+ def ext_size(ext_so)
36
+ store_result(:ext_so, "size", File.size(ext_so) / MEM_CONVERSION)
37
+ end
38
+
39
+ def self.results
40
+ out = []
41
+ out << "name\t" + FIELDS.join("\t")
42
+ @@results.each do |name, results|
43
+ out << [name, results ].flatten.join("\t")
44
+ end
45
+ out.join("\n")
46
+ end
47
+
48
+ private
49
+
50
+ def store_result(type, metric, value)
51
+ index = FIELDS.index("#{type.to_s}_#{metric}")
52
+ @@results[@name][index] = "%.2f" % value
53
+ end
54
+
55
+ def run(ps_regex)
56
+ ps_command = "ps axucww"
57
+ ps_output = `#{ps_command}`
58
+ fields = ps_output.to_a.first.downcase.split
59
+ memory_index = fields.index("rss")
60
+ pid_index = fields.index("pid")
61
+ ppid_index = fields.index("ppid")
62
+ total = ps_output.grep(/(#{ps_regex})\s+$/i).map do |com|
63
+ Float(com.split[memory_index]).abs
64
+ end.inject(0) { |s,v| s += v }
65
+ if total
66
+ return total/MEM_CONVERSION
67
+ else
68
+ STDERR.puts "Command not found. No processes found matching #{ps_regex}."
69
+ end
70
+
71
+ end
72
+
73
+ end
data/lib/redcloth.rb ADDED
@@ -0,0 +1,24 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+
3
+ require 'redcloth_scan'
4
+ require 'redcloth/version'
5
+ require 'redcloth/textile_doc'
6
+ require 'redcloth/formatters/base'
7
+ require 'redcloth/formatters/html'
8
+ require 'redcloth/formatters/latex'
9
+
10
+ module RedCloth
11
+
12
+ # A convenience method for creating a new TextileDoc. See
13
+ # RedCloth::TextileDoc.
14
+ def self.new( *args, &block )
15
+ RedCloth::TextileDoc.new( *args, &block )
16
+ end
17
+
18
+ # Include extension modules (if any) in TextileDoc.
19
+ def self.include(*args)
20
+ RedCloth::TextileDoc.send(:include, *args)
21
+ end
22
+
23
+ end
24
+
@@ -0,0 +1,50 @@
1
+ module RedCloth::Formatters
2
+ module Base
3
+
4
+ def pba(opts)
5
+ opts.delete(:style) if filter_styles
6
+ opts.delete(:class) if filter_classes
7
+ opts.delete(:id) if filter_ids
8
+
9
+ atts = ''
10
+ opts[:"text-align"] = opts.delete(:align)
11
+ opts[:style] += ';' if opts[:style] && (opts[:style][-1..-1] != ';')
12
+ [:float, :"text-align", :"vertical-align"].each do |a|
13
+ opts[:style] = "#{a}:#{opts[a]};#{opts[:style]}" if opts[a]
14
+ end
15
+ [:"padding-right", :"padding-left"].each do |a|
16
+ opts[:style] = "#{a}:#{opts[a]}em;#{opts[:style]}" if opts[a]
17
+ end
18
+ [:style, :class, :lang, :id, :colspan, :rowspan, :title, :start, :align].each do |a|
19
+ atts << " #{a}=\"#{ opts[a] }\"" if opts[a]
20
+ end
21
+ atts
22
+ end
23
+
24
+ def ignore(opts)
25
+ opts[:text]
26
+ end
27
+ alias_method :notextile, :ignore
28
+
29
+ def redcloth_version(opts)
30
+ p(:text => "#{opts[:prefix]}#{RedCloth::VERSION::STRING}")
31
+ end
32
+
33
+ def inline_redcloth_version(opts)
34
+ RedCloth::VERSION::STRING
35
+ end
36
+
37
+ def method_missing(method, opts)
38
+ opts[:text] || ""
39
+ end
40
+
41
+ def before_transform(text)
42
+
43
+ end
44
+
45
+ def after_transform(text)
46
+
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,342 @@
1
+ module RedCloth::Formatters::HTML
2
+ include RedCloth::Formatters::Base
3
+
4
+ # escapement for regular HTML (not in PRE tag)
5
+ def escape(text)
6
+ html_esc(text)
7
+ end
8
+
9
+ # escapement for HTML in a PRE tag
10
+ def escape_pre(text)
11
+ html_esc(text, :html_escape_preformatted)
12
+ end
13
+
14
+ def after_transform(text)
15
+ text.chomp!
16
+ end
17
+
18
+ [:h1, :h2, :h3, :h4, :h5, :h6, :p, :pre, :div].each do |m|
19
+ define_method(m) do |opts|
20
+ "<#{m}#{pba(opts)}>#{opts[:text]}</#{m}>\n"
21
+ end
22
+ end
23
+
24
+ [:strong, :code, :em, :i, :b, :ins, :sup, :sub, :span, :cite].each do |m|
25
+ define_method(m) do |opts|
26
+ opts[:block] = true
27
+ "<#{m}#{pba(opts)}>#{opts[:text]}</#{m}>"
28
+ end
29
+ end
30
+
31
+ def acronym(opts)
32
+ opts[:block] = true
33
+ "<acronym#{pba(opts)}>#{caps(:text => opts[:text])}</acronym>"
34
+ end
35
+
36
+ def caps(opts)
37
+ if no_span_caps
38
+ opts[:text]
39
+ else
40
+ opts[:class] = 'caps'
41
+ span(opts)
42
+ end
43
+ end
44
+
45
+ def del(opts)
46
+ opts[:block] = true
47
+ "<del#{pba(opts)}>#{opts[:text]}</del>"
48
+ end
49
+
50
+ def del_phrase(opts)
51
+ " #{del(opts)}"
52
+ end
53
+
54
+ [:ol, :ul].each do |m|
55
+ define_method("#{m}_open") do |opts|
56
+ opts[:block] = true
57
+ "#{"\n" if opts[:nest] > 1}#{"\t" * (opts[:nest] - 1)}<#{m}#{pba(opts)}>\n"
58
+ end
59
+ define_method("#{m}_close") do |opts|
60
+ "#{li_close}#{"\t" * (opts[:nest] - 1)}</#{m}>#{"\n" if opts[:nest] <= 1}"
61
+ end
62
+ end
63
+
64
+ def li_open(opts)
65
+ "#{li_close unless opts.delete(:first)}#{"\t" * opts[:nest]}<li#{pba(opts)}>#{opts[:text]}"
66
+ end
67
+
68
+ def li_close(opts=nil)
69
+ "</li>\n"
70
+ end
71
+
72
+ def dl_open(opts)
73
+ opts[:block] = true
74
+ "<dl#{pba(opts)}>\n"
75
+ end
76
+
77
+ def dl_close(opts=nil)
78
+ "</dl>\n"
79
+ end
80
+
81
+ [:dt, :dd].each do |m|
82
+ define_method(m) do |opts|
83
+ "\t<#{m}#{pba(opts)}>#{opts[:text]}</#{m}>\n"
84
+ end
85
+ end
86
+
87
+ def td(opts)
88
+ tdtype = opts[:th] ? 'th' : 'td'
89
+ "\t\t<#{tdtype}#{pba(opts)}>#{opts[:text]}</#{tdtype}>\n"
90
+ end
91
+
92
+ def tr_open(opts)
93
+ "\t<tr#{pba(opts)}>\n"
94
+ end
95
+
96
+ def tr_close(opts)
97
+ "\t</tr>\n"
98
+ end
99
+
100
+ def table_open(opts)
101
+ "<table#{pba(opts)}>\n"
102
+ end
103
+
104
+ def table_close(opts)
105
+ "</table>\n"
106
+ end
107
+
108
+ def bc_open(opts)
109
+ opts[:block] = true
110
+ "<pre#{pba(opts)}>"
111
+ end
112
+
113
+ def bc_close(opts)
114
+ "</pre>\n"
115
+ end
116
+
117
+ def bq_open(opts)
118
+ opts[:block] = true
119
+ cite = opts[:cite] ? " cite=\"#{ opts[:cite] }\"" : ''
120
+ "<blockquote#{cite}#{pba(opts)}>\n"
121
+ end
122
+
123
+ def bq_close(opts)
124
+ "</blockquote>\n"
125
+ end
126
+
127
+ LINK_TEXT_WITH_TITLE_RE = /
128
+ ([^"]+?) # $text
129
+ \s?
130
+ \(([^)]+?)\) # $title
131
+ $
132
+ /x
133
+ def link(opts)
134
+ if opts[:name] =~ LINK_TEXT_WITH_TITLE_RE
135
+ md = LINK_TEXT_WITH_TITLE_RE.match(opts[:name])
136
+ opts[:name] = md[1]
137
+ opts[:title] = md[2]
138
+ end
139
+ "<a href=\"#{opts[:href].gsub(/&/, '&#38;')}\"#{pba(opts)}>#{opts[:name]}</a>"
140
+ end
141
+
142
+ def image(opts)
143
+ opts.delete(:align)
144
+ opts[:alt] = opts[:title]
145
+ img = "<img src=\"#{urlesc opts[:src]}\"#{pba(opts)} alt=\"#{opts[:alt]}\" />"
146
+ img = "<a href=\"#{urlesc opts[:href]}\">#{img}</a>" if opts[:href]
147
+ img
148
+ end
149
+
150
+ def footno(opts)
151
+ opts[:id] ||= opts[:text]
152
+ %Q{<sup class="footnote"><a href=\"#fn#{opts[:id]}\">#{opts[:text]}</a></sup>}
153
+ end
154
+
155
+ def fn(opts)
156
+ no = opts[:id]
157
+ opts[:id] = "fn#{no}"
158
+ opts[:class] = ["footnote", opts[:class]].compact.join(" ")
159
+ "<p#{pba(opts)}><sup>#{no}</sup> #{opts[:text]}</p>\n"
160
+ end
161
+
162
+ def snip(opts)
163
+ "<pre#{pba(opts)}><code>#{opts[:text]}</code></pre>\n"
164
+ end
165
+
166
+ def quote1(opts)
167
+ "&#8216;#{opts[:text]}&#8217;"
168
+ end
169
+
170
+ def quote2(opts)
171
+ "&#8220;#{opts[:text]}&#8221;"
172
+ end
173
+
174
+ def ellipsis(opts)
175
+ "#{opts[:text]}&#8230;"
176
+ end
177
+
178
+ def emdash(opts)
179
+ "&#8212;"
180
+ end
181
+
182
+ def endash(opts)
183
+ " &#8211; "
184
+ end
185
+
186
+ def arrow(opts)
187
+ "&#8594;"
188
+ end
189
+
190
+ def dim(opts)
191
+ space = opts[:space] ? " " : ''
192
+ "#{opts[:text]}#{space}&#215;#{space}"
193
+ end
194
+
195
+ def trademark(opts)
196
+ "&#8482;"
197
+ end
198
+
199
+ def registered(opts)
200
+ "&#174;"
201
+ end
202
+
203
+ def copyright(opts)
204
+ "&#169;"
205
+ end
206
+
207
+ def entity(opts)
208
+ "&#{opts[:text]};"
209
+ end
210
+
211
+ def urlesc(txt)
212
+ txt.gsub(/&/, '&amp;')
213
+ end
214
+
215
+ def amp(opts)
216
+ "&amp;"
217
+ end
218
+
219
+ def gt(opts)
220
+ "&gt;"
221
+ end
222
+
223
+ def lt(opts)
224
+ "&lt;"
225
+ end
226
+
227
+ def br(opts)
228
+ if hard_breaks == false
229
+ "\n"
230
+ else
231
+ "<br />\n"
232
+ end
233
+ end
234
+
235
+ def quot(opts)
236
+ "&quot;"
237
+ end
238
+
239
+ def squot(opts)
240
+ "&#8217;"
241
+ end
242
+
243
+ def html(opts)
244
+ "#{opts[:text]}\n"
245
+ end
246
+
247
+ def html_block(opts)
248
+ inline_html(:text => "#{opts[:indent_before_start]}#{opts[:start_tag]}#{opts[:indent_after_start]}") +
249
+ "#{opts[:text]}" +
250
+ inline_html(:text => "#{opts[:indent_before_end]}#{opts[:end_tag]}#{opts[:indent_after_end]}")
251
+ end
252
+
253
+ def notextile(opts)
254
+ if filter_html
255
+ html_esc(opts[:text], :html_escape_preformatted)
256
+ else
257
+ opts[:text]
258
+ end
259
+ end
260
+
261
+ def inline_html(opts)
262
+ if filter_html
263
+ html_esc(opts[:text], :html_escape_preformatted)
264
+ else
265
+ "#{opts[:text]}" # nil-safe
266
+ end
267
+ end
268
+
269
+ def ignored_line(opts)
270
+ opts[:text] + "\n"
271
+ end
272
+
273
+ def before_transform(text)
274
+ clean_html(text) if sanitize_html
275
+ end
276
+
277
+ # HTML cleansing stuff
278
+ BASIC_TAGS = {
279
+ 'a' => ['href', 'title'],
280
+ 'img' => ['src', 'alt', 'title'],
281
+ 'br' => [],
282
+ 'i' => nil,
283
+ 'u' => nil,
284
+ 'b' => nil,
285
+ 'pre' => nil,
286
+ 'kbd' => nil,
287
+ 'code' => ['lang'],
288
+ 'cite' => nil,
289
+ 'strong' => nil,
290
+ 'em' => nil,
291
+ 'ins' => nil,
292
+ 'sup' => nil,
293
+ 'sub' => nil,
294
+ 'del' => nil,
295
+ 'table' => nil,
296
+ 'tr' => nil,
297
+ 'td' => ['colspan', 'rowspan'],
298
+ 'th' => nil,
299
+ 'ol' => ['start'],
300
+ 'ul' => nil,
301
+ 'li' => nil,
302
+ 'p' => nil,
303
+ 'h1' => nil,
304
+ 'h2' => nil,
305
+ 'h3' => nil,
306
+ 'h4' => nil,
307
+ 'h5' => nil,
308
+ 'h6' => nil,
309
+ 'blockquote' => ['cite'],
310
+ 'notextile' => nil
311
+ }
312
+
313
+ # Clean unauthorized tags.
314
+ def clean_html( text, allowed_tags = BASIC_TAGS )
315
+ text.gsub!( /<!\[CDATA\[/, '' )
316
+ text.gsub!( /<(\/*)([A-Za-z]\w*)([^>]*?)(\s?\/?)>/ ) do |m|
317
+ raw = $~
318
+ tag = raw[2].downcase
319
+ if allowed_tags.has_key? tag
320
+ pcs = [tag]
321
+ allowed_tags[tag].each do |prop|
322
+ ['"', "'", ''].each do |q|
323
+ q2 = ( q != '' ? q : '\s' )
324
+ if raw[3] =~ /#{prop}\s*=\s*#{q}([^#{q2}]+)#{q}/i
325
+ attrv = $1
326
+ next if (prop == 'src' or prop == 'href') and not attrv =~ %r{^(http|https|ftp):}
327
+ pcs << "#{prop}=\"#{attrv.gsub('"', '\\"')}\""
328
+ break
329
+ end
330
+ end
331
+ end if allowed_tags[tag]
332
+ "<#{raw[1]}#{pcs.join " "}#{raw[4]}>"
333
+ else # Unauthorized tag
334
+ if block_given?
335
+ yield m
336
+ else
337
+ ''
338
+ end
339
+ end
340
+ end
341
+ end
342
+ end