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,331 @@
1
+ require 'yaml'
2
+
3
+ module RedCloth::Formatters::LATEX
4
+ include RedCloth::Formatters::Base
5
+
6
+ def self.entities
7
+ @entities ||= YAML.load(File.read(File.dirname(__FILE__)+'/latex_entities.yml'))
8
+ end
9
+
10
+ module Settings
11
+ # Maps CSS style names to latex formatting options
12
+ def latex_image_styles
13
+ @latex_image_class_styles ||= {}
14
+ end
15
+ end
16
+
17
+ RedCloth::TextileDoc.send(:include, Settings)
18
+
19
+ # headers
20
+ { :h1 => 'section',
21
+ :h2 => 'subsection',
22
+ :h3 => 'subsubsection',
23
+ :h4 => 'paragraph',
24
+ :h5 => 'subparagraph',
25
+ :h6 => 'textbf',
26
+ }.each do |m,tag|
27
+ define_method(m) do |opts|
28
+ case opts[:align]
29
+ when 'left' then
30
+ "\\begin{flushleft}\\#{tag}{#{opts[:text]}}\\end{flushleft}\n\n"
31
+ when 'right' then
32
+ "\\begin{flushright}\\#{tag}{#{opts[:text]}}\\end{flushright}\n\n"
33
+ when 'center' then
34
+ "\\begin{center}\\#{tag}{#{opts[:text]}}\\end{center}\n\n"
35
+ else
36
+ "\\#{tag}{#{opts[:text]}}\n\n"
37
+ end
38
+ end
39
+ end
40
+
41
+ # commands
42
+ { :strong => 'textbf',
43
+ :em => 'emph',
44
+ :i => 'textit',
45
+ :b => 'textbf',
46
+ :ins => 'underline',
47
+ :del => 'sout',
48
+ }.each do |m,tag|
49
+ define_method(m) do |opts|
50
+ "\\#{tag}{#{opts[:text]}}"
51
+ end
52
+ end
53
+
54
+ # inline code
55
+ def code(opts)
56
+ opts[:block] ? opts[:text] : "\\verb@#{opts[:text]}@"
57
+ end
58
+
59
+ # acronyms
60
+ def acronym(opts)
61
+ "#{opts[:title]} (#{opts[:text]})"
62
+ end
63
+
64
+ # sub/superscripts
65
+ { :sup => '\textsuperscript{#1}',
66
+ :sub => '\textsubscript{#1}',
67
+ }.each do |m, expr|
68
+ define_method(m) do |opts|
69
+ expr.sub('#1', opts[:text])
70
+ end
71
+ end
72
+
73
+ # environments
74
+ { :pre => 'verbatim',
75
+ :cite => 'quote',
76
+ }.each do |m, env|
77
+ define_method(m) do |opts|
78
+ begin_chunk(env) + opts[:text] + end_chunk(env)
79
+ end
80
+ end
81
+
82
+ # ignore (or find a good solution later)
83
+ [ :span,
84
+ :div,
85
+ :caps
86
+ ].each do |m|
87
+ define_method(m) do |opts|
88
+ opts[:text].to_s
89
+ end
90
+ end
91
+
92
+ # lists
93
+ { :ol => 'enumerate',
94
+ :ul => 'itemize',
95
+ }.each do |m, env|
96
+ define_method("#{m}_open") do |opts|
97
+ opts[:block] = true
98
+ "\\begin{#{env}}\n"
99
+ end
100
+ define_method("#{m}_close") do |opts|
101
+ "\\end{#{env}}\n\n"
102
+ end
103
+ end
104
+
105
+ def li_open(opts)
106
+ " \\item #{opts[:text]}"
107
+ end
108
+
109
+ def li_close(opts=nil)
110
+ "\n"
111
+ end
112
+
113
+ # paragraphs
114
+ def p(opts)
115
+ case opts[:align]
116
+ when 'left' then
117
+ "\\begin{flushleft}#{opts[:text]}\\end{flushleft}\n\n"
118
+ when 'right' then
119
+ "\\begin{flushright}#{opts[:text]}\\end{flushright}\n\n"
120
+ when 'center' then
121
+ "\\begin{center}#{opts[:text]}\\end{center}\n\n"
122
+ else
123
+ "#{opts[:text]}\n\n"
124
+ end
125
+ end
126
+
127
+ # tables
128
+ def td(opts)
129
+ column = @table_row.size
130
+ if opts[:colspan]
131
+ opts[:text] = "\\multicolumn{#{opts[:colspan]}}{ #{"l " * opts[:colspan].to_i}}{#{opts[:text]}}"
132
+ end
133
+ if opts[:rowspan]
134
+ @table_multirow_next[column] = opts[:rowspan].to_i - 1
135
+ opts[:text] = "\\multirow{#{opts[:rowspan]}}{*}{#{opts[:text]}}"
136
+ end
137
+ @table_row.push(opts[:text])
138
+ return ""
139
+ end
140
+
141
+ def tr_open(opts)
142
+ @table_row = []
143
+ return ""
144
+ end
145
+
146
+ def tr_close(opts)
147
+ multirow_columns = @table_multirow.find_all {|c,n| n > 0}
148
+ multirow_columns.each do |c,n|
149
+ @table_row.insert(c,"")
150
+ @table_multirow[c] -= 1
151
+ end
152
+ @table_multirow.merge!(@table_multirow_next)
153
+ @table_multirow_next = {}
154
+ @table.push(@table_row)
155
+ return ""
156
+ end
157
+
158
+ # We need to know the column count before opening tabular context.
159
+ def table_open(opts)
160
+ @table = []
161
+ @table_multirow = {}
162
+ @table_multirow_next = {}
163
+ return ""
164
+ end
165
+
166
+ # FIXME: need caption and label elements similar to image -> figure
167
+ def table_close(opts)
168
+ output = "\\begin{table}\n"
169
+ output << " \\centering\n"
170
+ output << " \\begin{tabular}{ #{"l " * @table[0].size }}\n"
171
+ @table.each do |row|
172
+ output << " #{row.join(" & ")} \\\\\n"
173
+ end
174
+ output << " \\end{tabular}\n"
175
+ output << "\\end{table}\n"
176
+ output
177
+ end
178
+
179
+ # code blocks
180
+ def bc_open(opts)
181
+ opts[:block] = true
182
+ begin_chunk("verbatim") + "\n"
183
+ end
184
+
185
+ def bc_close(opts)
186
+ end_chunk("verbatim") + "\n"
187
+ end
188
+
189
+ # block quotations
190
+ def bq_open(opts)
191
+ opts[:block] = true
192
+ "\\begin{quotation}\n"
193
+ end
194
+
195
+ def bq_close(opts)
196
+ "\\end{quotation}\n\n"
197
+ end
198
+
199
+ # links
200
+ def link(opts)
201
+ "\\href{#{opts[:href]}}{#{opts[:name]}}"
202
+ end
203
+
204
+ def auto_link(opts)
205
+ return opts[:href] unless auto_link_urls
206
+ href_with_proto = opts[:href]
207
+ href_with_proto = 'http://' + href_with_proto unless href_with_proto.index('http') == 0
208
+ "\\href{#{href_with_proto}}{#{opts[:href]}}"
209
+ end
210
+
211
+ # FIXME: use includegraphics with security verification
212
+ #
213
+ # Remember to use '\RequirePackage{graphicx}' in your LaTeX header
214
+ #
215
+ # FIXME: Look at dealing with width / height gracefully as this should be
216
+ # specified in a unit like cm rather than px.
217
+ def image(opts)
218
+ # Don't know how to use remote links, plus can we trust them?
219
+ return "" if opts[:src] =~ /^\w+\:\/\//
220
+ # Resolve CSS styles if any have been set
221
+ styling = opts[:class].to_s.split(/\s+/).collect { |style| latex_image_styles[style] }.compact.join ','
222
+ # Build latex code
223
+ [ "\\begin{figure}",
224
+ " \\centering",
225
+ " \\includegraphics[#{styling}]{#{opts[:src]}}",
226
+ (" \\caption{#{escape opts[:title]}}" if opts[:title]),
227
+ (" \\label{#{escape opts[:alt]}}" if opts[:alt]),
228
+ "\\end{figure}",
229
+ ].compact.join "\n"
230
+ end
231
+
232
+ # footnotes
233
+ def footno(opts)
234
+ # TODO: insert a placeholder until we know the footnote content.
235
+ # For this to work, we need some kind of post-processing...
236
+ "\\footnotemark[#{opts[:text]}]"
237
+ end
238
+
239
+ def fn(opts)
240
+ "\\footnotetext[#{opts[:id]}]{#{opts[:text]}}"
241
+ end
242
+
243
+ # inline verbatim
244
+ def snip(opts)
245
+ "\\verb`#{opts[:text]}`"
246
+ end
247
+
248
+ def quote1(opts)
249
+ "`#{opts[:text]}'"
250
+ end
251
+
252
+ def quote2(opts)
253
+ "``#{opts[:text]}''"
254
+ end
255
+
256
+ def ellipsis(opts)
257
+ "#{opts[:text]}\\ldots{}"
258
+ end
259
+
260
+ def emdash(opts)
261
+ "---"
262
+ end
263
+
264
+ def endash(opts)
265
+ " -- "
266
+ end
267
+
268
+ def arrow(opts)
269
+ "\\rightarrow{}"
270
+ end
271
+
272
+ def trademark(opts)
273
+ "\\texttrademark{}"
274
+ end
275
+
276
+ def registered(opts)
277
+ "\\textregistered{}"
278
+ end
279
+
280
+ def copyright(opts)
281
+ "\\copyright{}"
282
+ end
283
+
284
+ # TODO: what do we do with (unknown) unicode entities ?
285
+ #
286
+ def entity(opts)
287
+ text = opts[:text][0..0] == '#' ? opts[:text][1..-1] : opts[:text]
288
+ RedCloth::Formatters::LATEX.entities[text]
289
+ end
290
+
291
+ def dim(opts)
292
+ opts[:text].gsub!('x', '\times')
293
+ opts[:text].gsub!('"', "''")
294
+ period = opts[:text].slice!(/\.$/)
295
+ "$#{opts[:text]}$#{period}"
296
+ end
297
+
298
+ # TODO: what do we do with HTML?
299
+ def inline_html(opts)
300
+ opts[:text] || ""
301
+ end
302
+
303
+ private
304
+
305
+ def escape(text)
306
+ latex_esc(text)
307
+ end
308
+
309
+ def escape_pre(text)
310
+ text
311
+ end
312
+
313
+ # Use this for block level commands that use \begin
314
+ def begin_chunk(type)
315
+ chunk_counter[type] += 1
316
+ return "\\begin{#{type}}" if 1 == chunk_counter[type]
317
+ ''
318
+ end
319
+
320
+ # Use this for block level commands that use \end
321
+ def end_chunk(type)
322
+ chunk_counter[type] -= 1
323
+ raise RuntimeError, "Bad latex #{type} nesting detected" if chunk_counter[type] < 0 # This should never need to happen
324
+ return "\\end{#{type}}" if 0 == chunk_counter[type]
325
+ ''
326
+ end
327
+
328
+ def chunk_counter
329
+ @chunk_counter ||= Hash.new 0
330
+ end
331
+ end