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.
- checksums.yaml +7 -0
- data/.gemtest +0 -0
- data/.rspec +1 -0
- data/CHANGELOG +265 -0
- data/COPYING +18 -0
- data/Gemfile +7 -0
- data/README.rdoc +215 -0
- data/Rakefile +18 -0
- data/bin/redcloth +28 -0
- data/doc/textile_reference.html +631 -0
- data/ext/redcloth_scan/extconf.rb +6 -0
- data/ext/redcloth_scan/redcloth.h +220 -0
- data/ext/redcloth_scan/redcloth_attributes.c +650 -0
- data/ext/redcloth_scan/redcloth_inline.c +8153 -0
- data/ext/redcloth_scan/redcloth_scan.c +24407 -0
- data/lib/case_sensitive_require/RedCloth.rb +6 -0
- data/lib/redcloth/erb_extension.rb +27 -0
- data/lib/redcloth/formatters/base.rb +63 -0
- data/lib/redcloth/formatters/html.rb +352 -0
- data/lib/redcloth/formatters/latex.rb +331 -0
- data/lib/redcloth/formatters/latex_entities.yml +2414 -0
- data/lib/redcloth/textile_doc.rb +113 -0
- data/lib/redcloth/version.rb +34 -0
- data/lib/redcloth.rb +45 -0
- data/lib/tasks/pureruby.rake +17 -0
- data/redcloth.gemspec +54 -0
- data/spec/benchmark_spec.rb +15 -0
- data/spec/custom_tags_spec.rb +50 -0
- data/spec/erb_spec.rb +10 -0
- data/spec/extension_spec.rb +26 -0
- data/spec/fixtures/basic.yml +1028 -0
- data/spec/fixtures/code.yml +257 -0
- data/spec/fixtures/definitions.yml +82 -0
- data/spec/fixtures/extra_whitespace.yml +64 -0
- data/spec/fixtures/filter_html.yml +177 -0
- data/spec/fixtures/filter_pba.yml +20 -0
- data/spec/fixtures/html.yml +348 -0
- data/spec/fixtures/images.yml +279 -0
- data/spec/fixtures/instiki.yml +38 -0
- data/spec/fixtures/links.yml +291 -0
- data/spec/fixtures/lists.yml +462 -0
- data/spec/fixtures/poignant.yml +89 -0
- data/spec/fixtures/sanitize_html.yml +42 -0
- data/spec/fixtures/table.yml +434 -0
- data/spec/fixtures/textism.yml +509 -0
- data/spec/fixtures/threshold.yml +762 -0
- data/spec/formatters/class_filtered_html_spec.rb +7 -0
- data/spec/formatters/filtered_html_spec.rb +7 -0
- data/spec/formatters/html_no_breaks_spec.rb +9 -0
- data/spec/formatters/html_spec.rb +13 -0
- data/spec/formatters/id_filtered_html_spec.rb +7 -0
- data/spec/formatters/latex_spec.rb +13 -0
- data/spec/formatters/lite_mode_html_spec.rb +7 -0
- data/spec/formatters/no_span_caps_html_spec.rb +7 -0
- data/spec/formatters/sanitized_html_spec.rb +7 -0
- data/spec/formatters/style_filtered_html_spec.rb +7 -0
- data/spec/parser_spec.rb +102 -0
- data/spec/spec_helper.rb +36 -0
- data/tasks/compile.rake +47 -0
- data/tasks/gems.rake +37 -0
- data/tasks/ragel_extension_task.rb +127 -0
- data/tasks/release.rake +15 -0
- data/tasks/rspec.rake +13 -0
- data/tasks/rvm.rake +79 -0
- 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
|