RedCloth 4.1.9 → 4.2.0

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 (70) hide show
  1. data/CHANGELOG +55 -0
  2. data/Manifest +34 -38
  3. data/README +17 -5
  4. data/Rakefile +79 -30
  5. data/RedCloth.gemspec +5 -6
  6. data/ext/redcloth_scan/redcloth.h +38 -13
  7. data/ext/redcloth_scan/redcloth_attributes.c +349 -383
  8. data/ext/redcloth_scan/redcloth_inline.c +4769 -16591
  9. data/ext/redcloth_scan/redcloth_scan.c +21592 -9540
  10. data/lib/redcloth.rb +9 -3
  11. data/lib/redcloth/formatters/html.rb +2 -2
  12. data/lib/redcloth/formatters/latex.rb +99 -54
  13. data/lib/redcloth/formatters/latex_entities.yml +2 -2
  14. data/lib/redcloth/version.rb +9 -4
  15. data/lib/tasks/pureruby.rake +12 -0
  16. data/spec/custom_tags_spec.rb +50 -0
  17. data/spec/differs/inline.rb +48 -0
  18. data/{test/test_erb.rb → spec/erb_spec.rb} +6 -9
  19. data/spec/extension_spec.rb +26 -0
  20. data/{test → spec/fixtures}/basic.yml +90 -4
  21. data/{test → spec/fixtures}/code.yml +29 -0
  22. data/{test → spec/fixtures}/definitions.yml +0 -0
  23. data/{test → spec/fixtures}/extra_whitespace.yml +0 -0
  24. data/{test → spec/fixtures}/filter_html.yml +0 -0
  25. data/{test → spec/fixtures}/filter_pba.yml +0 -0
  26. data/{test → spec/fixtures}/html.yml +15 -0
  27. data/{test → spec/fixtures}/images.yml +16 -6
  28. data/{test → spec/fixtures}/instiki.yml +0 -0
  29. data/{test → spec/fixtures}/links.yml +7 -1
  30. data/{test → spec/fixtures}/lists.yml +162 -1
  31. data/{test → spec/fixtures}/poignant.yml +0 -0
  32. data/{test → spec/fixtures}/sanitize_html.yml +0 -0
  33. data/{test → spec/fixtures}/table.yml +121 -23
  34. data/{test → spec/fixtures}/textism.yml +44 -15
  35. data/{test → spec/fixtures}/threshold.yml +6 -14
  36. data/spec/formatters/class_filtered_html_spec.rb +7 -0
  37. data/spec/formatters/filtered_html_spec.rb +7 -0
  38. data/spec/formatters/html_no_breaks_spec.rb +9 -0
  39. data/spec/formatters/html_spec.rb +13 -0
  40. data/spec/formatters/id_filtered_html_spec.rb +7 -0
  41. data/spec/formatters/latex_spec.rb +13 -0
  42. data/spec/formatters/lite_mode_html_spec.rb +7 -0
  43. data/spec/formatters/no_span_caps_html_spec.rb +7 -0
  44. data/spec/formatters/sanitized_html_spec.rb +7 -0
  45. data/spec/formatters/style_filtered_html_spec.rb +7 -0
  46. data/spec/parser_spec.rb +95 -0
  47. data/spec/spec.opts +3 -0
  48. data/spec/spec_helper.rb +42 -0
  49. metadata +40 -49
  50. data/ext/mingw-rbconfig.rb +0 -176
  51. data/ext/redcloth_scan/redcloth_attributes.c.rl +0 -55
  52. data/ext/redcloth_scan/redcloth_attributes.java.rl +0 -95
  53. data/ext/redcloth_scan/redcloth_attributes.rl +0 -33
  54. data/ext/redcloth_scan/redcloth_common.c.rl +0 -18
  55. data/ext/redcloth_scan/redcloth_common.java.rl +0 -18
  56. data/ext/redcloth_scan/redcloth_common.rl +0 -115
  57. data/ext/redcloth_scan/redcloth_inline.c.rl +0 -193
  58. data/ext/redcloth_scan/redcloth_inline.java.rl +0 -140
  59. data/ext/redcloth_scan/redcloth_inline.rl +0 -156
  60. data/ext/redcloth_scan/redcloth_scan.c.rl +0 -228
  61. data/ext/redcloth_scan/redcloth_scan.java.rl +0 -577
  62. data/ext/redcloth_scan/redcloth_scan.rl +0 -320
  63. data/extras/ragel_profiler.rb +0 -73
  64. data/test/helper.rb +0 -108
  65. data/test/test_custom_tags.rb +0 -58
  66. data/test/test_extensions.rb +0 -31
  67. data/test/test_formatters.rb +0 -24
  68. data/test/test_parser.rb +0 -73
  69. data/test/test_restrictions.rb +0 -41
  70. data/test/validate_fixtures.rb +0 -74
@@ -1,5 +1,3 @@
1
- $:.unshift(File.dirname(__FILE__))
2
-
3
1
  # If this is a frozen gem in Rails 2.1 and RedCloth 3.x was already
4
2
  # loaded by Rails' ActionView::Helpers::TextHelper, the user will get
5
3
  # "redcloth_scan.bundle: Class is not a module (TypeError)"
@@ -7,7 +5,15 @@ $:.unshift(File.dirname(__FILE__))
7
5
  # appears to be fixed in Edge Rails [51e4106].
8
6
  Object.send(:remove_const, :RedCloth) if Object.const_defined?(:RedCloth) && RedCloth.is_a?(Class)
9
7
 
10
- require 'redcloth_scan'
8
+ module RedCloth
9
+ class NotCompiledError < LoadError; end
10
+ end
11
+
12
+ begin
13
+ require 'redcloth_scan'
14
+ rescue LoadError
15
+ raise RedCloth::NotCompiledError, "RedCloth uses native extensions. It's extremely fast but must be compiled. Installing the RedCloth gem is the easiest method."
16
+ end
11
17
  require 'redcloth/version'
12
18
  require 'redcloth/textile_doc'
13
19
  require 'redcloth/formatters/base'
@@ -43,12 +43,12 @@ module RedCloth::Formatters::HTML
43
43
  "#{"\n" if opts[:nest] > 1}#{"\t" * (opts[:nest] - 1)}<#{m}#{pba(opts)}>\n"
44
44
  end
45
45
  define_method("#{m}_close") do |opts|
46
- "#{li_close}#{"\t" * (opts[:nest] - 1)}</#{m}>#{"\n" if opts[:nest] <= 1}"
46
+ "#{"\t" * (opts[:nest] - 1)}</#{m}>#{"\n" if opts[:nest] <= 1}"
47
47
  end
48
48
  end
49
49
 
50
50
  def li_open(opts)
51
- "#{li_close unless opts.delete(:first)}#{"\t" * opts[:nest]}<li#{pba(opts)}>#{opts[:text]}"
51
+ "#{"\t" * opts[:nest]}<li#{pba(opts)}>#{opts[:text]}"
52
52
  end
53
53
 
54
54
  def li_close(opts=nil)
@@ -2,8 +2,8 @@ require 'yaml'
2
2
 
3
3
  module RedCloth::Formatters::LATEX
4
4
  include RedCloth::Formatters::Base
5
-
6
- ENTITIES = YAML::load(File.read(File.dirname(__FILE__)+'/latex_entities.yml'))
5
+
6
+ ENTITIES = YAML::load(File.read(File.dirname(__FILE__)+'/latex_entities.yml'))
7
7
 
8
8
  module Settings
9
9
  # Maps CSS style names to latex formatting options
@@ -13,20 +13,29 @@ module RedCloth::Formatters::LATEX
13
13
  end
14
14
 
15
15
  RedCloth::TextileDoc.send(:include, Settings)
16
-
16
+
17
17
  # headers
18
- { :h1 => 'section*',
19
- :h2 => 'subsection*',
20
- :h3 => 'subsubsection*',
21
- :h4 => 'textbf',
22
- :h5 => 'textbf',
18
+ { :h1 => 'section',
19
+ :h2 => 'subsection',
20
+ :h3 => 'subsubsection',
21
+ :h4 => 'paragraph',
22
+ :h5 => 'subparagraph',
23
23
  :h6 => 'textbf',
24
24
  }.each do |m,tag|
25
25
  define_method(m) do |opts|
26
- "\\#{tag}{#{opts[:text]}}\n\n"
26
+ case opts[:align]
27
+ when 'left' then
28
+ "\\begin{flushleft}\\#{tag}{#{opts[:text]}}\\end{flushleft}\n\n"
29
+ when 'right' then
30
+ "\\begin{flushright}\\#{tag}{#{opts[:text]}}\\end{flushright}\n\n"
31
+ when 'center' then
32
+ "\\begin{center}\\#{tag}{#{opts[:text]}}\\end{center}\n\n"
33
+ else
34
+ "\\#{tag}{#{opts[:text]}}\n\n"
35
+ end
27
36
  end
28
37
  end
29
-
38
+
30
39
  # commands
31
40
  { :strong => 'textbf',
32
41
  :em => 'emph',
@@ -34,41 +43,51 @@ module RedCloth::Formatters::LATEX
34
43
  :b => 'textbf',
35
44
  :ins => 'underline',
36
45
  :del => 'sout',
37
- :acronym => 'MakeUppercase',
38
- :caps => 'MakeUppercase',
39
46
  }.each do |m,tag|
40
47
  define_method(m) do |opts|
41
48
  "\\#{tag}{#{opts[:text]}}"
42
49
  end
43
50
  end
44
-
45
- { :sup => '\ensuremath{^\textrm{#1}}',
46
- :sub => '\ensuremath{_\textrm{#1}}',
51
+
52
+ # inline code
53
+ def code(opts)
54
+ opts[:block] ? opts[:text] : "\\verb@#{opts[:text]}@"
55
+ end
56
+
57
+ # acronyms
58
+ def acronym(opts)
59
+ "#{opts[:title]} (#{opts[:text]})"
60
+ end
61
+
62
+ # sub/superscripts
63
+ { :sup => '\textsuperscript{#1}',
64
+ :sub => '\textsubscript{#1}',
47
65
  }.each do |m, expr|
48
66
  define_method(m) do |opts|
49
67
  expr.sub('#1', opts[:text])
50
68
  end
51
69
  end
52
-
70
+
53
71
  # environments
54
72
  { :pre => 'verbatim',
55
- :code => 'verbatim',
56
73
  :cite => 'quote',
57
74
  }.each do |m, env|
58
75
  define_method(m) do |opts|
59
76
  begin_chunk(env) + opts[:text] + end_chunk(env)
60
77
  end
61
78
  end
62
-
79
+
63
80
  # ignore (or find a good solution later)
64
81
  [ :span,
65
82
  :div,
83
+ :caps
66
84
  ].each do |m|
67
85
  define_method(m) do |opts|
68
86
  opts[:text].to_s
69
87
  end
70
88
  end
71
-
89
+
90
+ # lists
72
91
  { :ol => 'enumerate',
73
92
  :ul => 'itemize',
74
93
  }.each do |m, env|
@@ -77,22 +96,33 @@ module RedCloth::Formatters::LATEX
77
96
  "\\begin{#{env}}\n"
78
97
  end
79
98
  define_method("#{m}_close") do |opts|
80
- "#{li_close}\\end{#{env}}\n\n"
99
+ "\\end{#{env}}\n\n"
81
100
  end
82
101
  end
83
-
102
+
84
103
  def li_open(opts)
85
- "#{li_close unless opts.delete(:first)}\t\\item #{opts[:text]}"
104
+ " \\item #{opts[:text]}"
86
105
  end
87
-
106
+
88
107
  def li_close(opts=nil)
89
108
  "\n"
90
109
  end
91
-
110
+
111
+ # paragraphs
92
112
  def p(opts)
93
- opts[:text] + "\n\n"
113
+ case opts[:align]
114
+ when 'left' then
115
+ "\\begin{flushleft}#{opts[:text]}\\end{flushleft}\n\n"
116
+ when 'right' then
117
+ "\\begin{flushright}#{opts[:text]}\\end{flushright}\n\n"
118
+ when 'center' then
119
+ "\\begin{center}#{opts[:text]}\\end{center}\n\n"
120
+ else
121
+ "#{opts[:text]}\n\n"
122
+ end
94
123
  end
95
-
124
+
125
+ # tables
96
126
  def td(opts)
97
127
  column = @table_row.size
98
128
  if opts[:colspan]
@@ -105,12 +135,12 @@ module RedCloth::Formatters::LATEX
105
135
  @table_row.push(opts[:text])
106
136
  return ""
107
137
  end
108
-
138
+
109
139
  def tr_open(opts)
110
140
  @table_row = []
111
141
  return ""
112
142
  end
113
-
143
+
114
144
  def tr_close(opts)
115
145
  multirow_columns = @table_multirow.find_all {|c,n| n > 0}
116
146
  multirow_columns.each do |c,n|
@@ -122,7 +152,7 @@ module RedCloth::Formatters::LATEX
122
152
  @table.push(@table_row)
123
153
  return ""
124
154
  end
125
-
155
+
126
156
  # We need to know the column count before opening tabular context.
127
157
  def table_open(opts)
128
158
  @table = []
@@ -130,16 +160,21 @@ module RedCloth::Formatters::LATEX
130
160
  @table_multirow_next = {}
131
161
  return ""
132
162
  end
133
-
163
+
164
+ # FIXME: need caption and label elements similar to image -> figure
134
165
  def table_close(opts)
135
- output = "\\begin{tabular}{ #{"l " * @table[0].size }}\n"
166
+ output = "\\begin{table}\n"
167
+ output << " \\centering\n"
168
+ output << " \\begin{tabular}{ #{"l " * @table[0].size }}\n"
136
169
  @table.each do |row|
137
- output << " #{row.join(" & ")} \\\\\n"
170
+ output << " #{row.join(" & ")} \\\\\n"
138
171
  end
139
- output << "\\end{tabular}\n"
172
+ output << " \\end{tabular}\n"
173
+ output << "\\end{table}\n"
140
174
  output
141
175
  end
142
176
 
177
+ # code blocks
143
178
  def bc_open(opts)
144
179
  opts[:block] = true
145
180
  begin_chunk("verbatim") + "\n"
@@ -149,6 +184,7 @@ module RedCloth::Formatters::LATEX
149
184
  end_chunk("verbatim") + "\n"
150
185
  end
151
186
 
187
+ # block quotations
152
188
  def bq_open(opts)
153
189
  opts[:block] = true
154
190
  "\\begin{quotation}\n"
@@ -157,7 +193,8 @@ module RedCloth::Formatters::LATEX
157
193
  def bq_close(opts)
158
194
  "\\end{quotation}\n\n"
159
195
  end
160
-
196
+
197
+ # links
161
198
  def link(opts)
162
199
  "\\href{#{opts[:href]}}{#{opts[:name]}}"
163
200
  end
@@ -174,71 +211,74 @@ module RedCloth::Formatters::LATEX
174
211
  # Resolve CSS styles if any have been set
175
212
  styling = opts[:class].to_s.split(/\s+/).collect { |style| latex_image_styles[style] }.compact.join ','
176
213
  # Build latex code
177
- [ "\\begin{figure}[htp]",
214
+ [ "\\begin{figure}",
215
+ " \\centering",
178
216
  " \\includegraphics[#{styling}]{#{opts[:src]}}",
179
217
  (" \\caption{#{escape opts[:title]}}" if opts[:title]),
180
218
  (" \\label{#{escape opts[:alt]}}" if opts[:alt]),
181
219
  "\\end{figure}",
182
220
  ].compact.join "\n"
183
221
  end
184
-
222
+
223
+ # footnotes
185
224
  def footno(opts)
186
225
  # TODO: insert a placeholder until we know the footnote content.
187
226
  # For this to work, we need some kind of post-processing...
188
227
  "\\footnotemark[#{opts[:text]}]"
189
228
  end
190
-
229
+
191
230
  def fn(opts)
192
231
  "\\footnotetext[#{opts[:id]}]{#{opts[:text]}}"
193
232
  end
194
-
233
+
234
+ # inline verbatim
195
235
  def snip(opts)
196
- "\\begin{verbatim}#{opts[:text]}\\end{verbatim}"
236
+ "\\verb`#{opts[:text]}`"
197
237
  end
198
-
238
+
199
239
  def quote1(opts)
200
240
  "`#{opts[:text]}'"
201
241
  end
202
-
242
+
203
243
  def quote2(opts)
204
244
  "``#{opts[:text]}\""
205
245
  end
206
-
246
+
207
247
  def ellipsis(opts)
208
248
  "#{opts[:text]}\\ldots{}"
209
249
  end
210
-
250
+
211
251
  def emdash(opts)
212
252
  "---"
213
253
  end
214
-
254
+
215
255
  def endash(opts)
216
256
  "--"
217
257
  end
218
-
258
+
219
259
  def arrow(opts)
220
260
  "\\rightarrow{}"
221
261
  end
222
-
262
+
223
263
  def trademark(opts)
224
264
  "\\texttrademark{}"
225
265
  end
226
-
266
+
227
267
  def registered(opts)
228
268
  "\\textregistered{}"
229
269
  end
230
-
270
+
231
271
  def copyright(opts)
232
272
  "\\copyright{}"
233
273
  end
234
-
274
+
235
275
  # TODO: what do we do with (unknown) unicode entities ?
236
276
  #
237
277
  def entity(opts)
238
278
  text = opts[:text][0..0] == '#' ? opts[:text][1..-1] : opts[:text]
239
279
  ENTITIES[text]
240
280
  end
241
-
281
+
242
282
  def dim(opts)
243
283
  opts[:text].gsub!('x', '\times')
244
284
  opts[:text].gsub!('"', "''")
@@ -246,8 +286,13 @@ module RedCloth::Formatters::LATEX
246
286
  "$#{opts[:text]}$#{period}"
247
287
  end
248
288
 
249
- private
289
+ # TODO: what do we do with HTML?
290
+ def inline_html(opts)
291
+ opts[:text] || ""
292
+ end
250
293
 
294
+ private
295
+
251
296
  def escape(text)
252
297
  latex_esc(text)
253
298
  end
@@ -255,14 +300,14 @@ module RedCloth::Formatters::LATEX
255
300
  def escape_pre(text)
256
301
  text
257
302
  end
258
-
303
+
259
304
  # Use this for block level commands that use \begin
260
305
  def begin_chunk(type)
261
306
  chunk_counter[type] += 1
262
307
  return "\\begin{#{type}}" if 1 == chunk_counter[type]
263
308
  ''
264
309
  end
265
-
310
+
266
311
  # Use this for block level commands that use \end
267
312
  def end_chunk(type)
268
313
  chunk_counter[type] -= 1
@@ -270,7 +315,7 @@ module RedCloth::Formatters::LATEX
270
315
  return "\\end{#{type}}" if 0 == chunk_counter[type]
271
316
  ''
272
317
  end
273
-
318
+
274
319
  def chunk_counter
275
320
  @chunk_counter ||= Hash.new 0
276
321
  end
@@ -2354,7 +2354,7 @@ tilde: \~{}
2354
2354
  #HORIZONTAL TABULATION
2355
2355
  "9": \>,\=
2356
2356
  #LINE FEED
2357
- "10": \\
2357
+ "10": "\n"
2358
2358
  #SINGLE LEFT-POINTING ANGLE QUOTATION MARK
2359
2359
  #requires fontenc:T1
2360
2360
  lsaquo: \guilsinglleft{}
@@ -2411,4 +2411,4 @@ euro: \texteuro{}
2411
2411
  "865": \t{}
2412
2412
  #REFERENCE MARK
2413
2413
  #requires textcomp
2414
- "8251": \textreferencemark{}
2414
+ "8251": \textreferencemark{}
@@ -1,8 +1,8 @@
1
1
  module RedCloth
2
2
  module VERSION
3
3
  MAJOR = 4
4
- MINOR = 1
5
- TINY = 9
4
+ MINOR = 2
5
+ TINY = 0
6
6
  RELEASE_CANDIDATE = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY].join('.')
@@ -23,6 +23,11 @@ module RedCloth
23
23
  NAME = "RedCloth"
24
24
  GEM_NAME = NAME
25
25
  URL = "http://redcloth.org/"
26
+ description = "Textile parser for Ruby."
26
27
 
27
- DESCRIPTION = "#{NAME}-#{VERSION::FULL_VERSION} - Textile parser for Ruby.\n#{URL}"
28
- end
28
+ if RedCloth.const_defined?(:EXTENSION_LANGUAGE)
29
+ DESCRIPTION = "#{NAME}-#{VERSION::FULL_VERSION}-#{EXTENSION_LANGUAGE} - #{description}\n#{URL}"
30
+ else
31
+ DESCRIPTION = "#{NAME}-#{VERSION::FULL_VERSION} - #{description}\n#{URL}"
32
+ end
33
+ end
@@ -0,0 +1,12 @@
1
+ Gem::Specification::PLATFORM_CROSS_TARGETS << "pureruby"
2
+
3
+ task 'pureruby' do
4
+ reset_target 'pureruby'
5
+ end
6
+
7
+ if target = ARGV.detect do |arg|
8
+ # Hack to get the platform set before the Rakefile evaluates
9
+ Gem::Specification::PLATFORM_CROSS_TARGETS.include? arg
10
+ end
11
+ reset_target target
12
+ end
@@ -0,0 +1,50 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ module FigureTag
4
+ def fig( opts )
5
+ label, img = opts[:text].split('|').map! {|str| str.strip}
6
+
7
+ html = %Q{<div class="img" id="figure-#{label.tr('.', '-')}">\n}
8
+ html << %Q{ <a class="fig" href="/images/#{img}">\n}
9
+ html << %Q{ <img src="/images/thumbs/#{img}" alt="Figure #{label}" />\n}
10
+ html << %Q{ </a>\n}
11
+ html << %Q{ <p>Figure #{label}</p>\n}
12
+ html << %Q{<div>\n}
13
+ end
14
+ end
15
+
16
+ describe "custom tags" do
17
+ it "should recognize the custom tag" do
18
+ input = %Q{The first line of text.\n\n}
19
+ input << %Q{fig. 1.1 | img.jpg\n\n}
20
+ input << %Q{The last line of text.\n}
21
+ r = RedCloth.new input
22
+ r.extend FigureTag
23
+
24
+ html = %Q{<p>The first line of text.</p>\n}
25
+ html << %Q{<div class="img" id="figure-1-1">\n}
26
+ html << %Q{ <a class="fig" href="/images/img.jpg">\n}
27
+ html << %Q{ <img src="/images/thumbs/img.jpg" alt="Figure 1.1" />\n}
28
+ html << %Q{ </a>\n}
29
+ html << %Q{ <p>Figure 1.1</p>\n}
30
+ html << %Q{<div>\n}
31
+ html << %Q{<p>The last line of text.</p>}
32
+
33
+ r.to_html.should == html
34
+ end
35
+
36
+ it "should fall back if custom tag isn't defined" do
37
+ r = RedCloth.new %Q/fig()>[no]{color:red}. 1.1 | img.jpg/
38
+
39
+ r.to_html.should == "<p>fig()>[no]{color:red}. 1.1 | img.jpg</p>"
40
+ end
41
+
42
+ it "should not call just regular string methods" do
43
+ r = RedCloth.new "next. "
44
+ r.extend FigureTag
45
+
46
+ html = "<p>next. </p>"
47
+
48
+ r.to_html.should == html
49
+ end
50
+ end