kramdown 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of kramdown might be problematic. Click here for more details.

Files changed (44) hide show
  1. data/ChangeLog +276 -0
  2. data/Rakefile +2 -2
  3. data/VERSION +1 -1
  4. data/benchmark/benchmark.rb +1 -1
  5. data/benchmark/historic-jruby-1.4.0.dat +7 -7
  6. data/benchmark/historic-ruby-1.8.6.dat +7 -7
  7. data/benchmark/historic-ruby-1.8.7.dat +7 -7
  8. data/benchmark/historic-ruby-1.9.1p243.dat +7 -7
  9. data/benchmark/historic-ruby-1.9.2dev.dat +7 -7
  10. data/bin/kramdown +46 -1
  11. data/doc/index.page +2 -2
  12. data/doc/syntax.page +7 -3
  13. data/lib/kramdown/converter.rb +6 -285
  14. data/lib/kramdown/converter/base.rb +75 -0
  15. data/lib/kramdown/converter/html.rb +325 -0
  16. data/lib/kramdown/converter/latex.rb +516 -0
  17. data/lib/kramdown/document.rb +36 -66
  18. data/lib/kramdown/options.rb +262 -0
  19. data/lib/kramdown/parser/kramdown.rb +36 -17
  20. data/lib/kramdown/parser/kramdown/attribute_list.rb +1 -1
  21. data/lib/kramdown/parser/kramdown/autolink.rb +1 -1
  22. data/lib/kramdown/parser/kramdown/codespan.rb +1 -1
  23. data/lib/kramdown/parser/kramdown/emphasis.rb +2 -2
  24. data/lib/kramdown/parser/kramdown/escaped_chars.rb +2 -2
  25. data/lib/kramdown/parser/kramdown/extension.rb +46 -2
  26. data/lib/kramdown/parser/kramdown/footnote.rb +1 -1
  27. data/lib/kramdown/parser/kramdown/html.rb +2 -2
  28. data/lib/kramdown/parser/kramdown/html_entity.rb +4 -5
  29. data/lib/kramdown/parser/kramdown/line_break.rb +1 -1
  30. data/lib/kramdown/parser/kramdown/link.rb +2 -2
  31. data/lib/kramdown/parser/kramdown/smart_quotes.rb +213 -0
  32. data/lib/kramdown/parser/kramdown/typographic_symbol.rb +1 -1
  33. data/lib/kramdown/version.rb +1 -1
  34. data/test/testcases/encoding.html +46 -0
  35. data/test/testcases/encoding.text +28 -0
  36. data/test/testcases/span/01_link/inline.html +1 -1
  37. data/test/testcases/span/01_link/reference.html +2 -2
  38. data/test/testcases/span/escaped_chars/normal.html +4 -0
  39. data/test/testcases/span/escaped_chars/normal.text +4 -0
  40. data/test/testcases/span/text_substitutions/entities.html +1 -1
  41. data/test/testcases/span/text_substitutions/typography.html +12 -0
  42. data/test/testcases/span/text_substitutions/typography.text +12 -0
  43. metadata +9 -3
  44. data/lib/kramdown/extension.rb +0 -98
@@ -0,0 +1,516 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown.
7
+ #
8
+ # kramdown is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ #++
21
+ #
22
+
23
+ module Kramdown
24
+
25
+ module Converter
26
+
27
+ # Converts a Kramdown::Document to LaTeX. This converter uses ideas from other Markdown-to-LaTeX
28
+ # converters like Pandoc and Maruku.
29
+ class Latex < Base
30
+
31
+ # :stopdoc:
32
+
33
+ # Initialize the LaTeX converter with the given Kramdown document +doc+.
34
+ def initialize(doc)
35
+ super
36
+ #TODO: set the footnote counter at the beginning of the document
37
+ @doc.options[:footnote_nr]
38
+ @doc.conversion_infos[:packages] = []
39
+ end
40
+
41
+ def convert(el, opts = {})
42
+ send("convert_#{el.type}", el, opts)
43
+ end
44
+
45
+ def inner(el, opts)
46
+ result = ''
47
+ el.children.each do |inner_el|
48
+ result << send("convert_#{inner_el.type}", inner_el, opts)
49
+ end
50
+ result
51
+ end
52
+
53
+ def convert_root(el, opts)
54
+ inner(el, opts)
55
+ end
56
+
57
+ def convert_blank(el, opts)
58
+ ""
59
+ end
60
+
61
+ def convert_text(el, opts)
62
+ escape(el.value)
63
+ end
64
+
65
+ def convert_eob(el, opts)
66
+ ''
67
+ end
68
+
69
+ def convert_p(el, opts)
70
+ "#{inner(el, opts)}\n\n"
71
+ end
72
+
73
+ def convert_codeblock(el, opts)
74
+ show_whitespace = el.options[:attr] && el.options[:attr]['class'].to_s =~ /\bshow-whitespaces\b/
75
+ lang = el.options[:attr] && el.options[:attr]['lang']
76
+ if show_whitespace || lang
77
+ result = "\\lstset{showspaces=%s,showtabs=%s}\n" % (show_whitespace ? ['true', 'true'] : ['false', 'false'])
78
+ result += "\\lstset{language=#{lang}}\n" if lang
79
+ result += "\\lstset{basicstyle=\\ttfamily\\footnotesize}\\lstset{columns=fixed,frame=tlbr}\n"
80
+ "#{result}\\begin{lstlisting}\n#{el.value}\n\\end{lstlisting}"
81
+ else
82
+ "\\begin{verbatim}#{el.value}\\end{verbatim}\n"
83
+ end
84
+ end
85
+
86
+ def latex_environment(type, text)
87
+ "\\begin{#{type}}\n#{text}\n\\end{#{type}}\n"
88
+ end
89
+
90
+ def convert_blockquote(el, opts)
91
+ latex_environment('quote', inner(el, opts))
92
+ end
93
+
94
+ HEADER_TYPES = {
95
+ 1 => 'section',
96
+ 2 => 'subsection',
97
+ 3 => 'subsubsection',
98
+ 4 => 'paragraph',
99
+ 5 => 'subparagraph',
100
+ 6 => 'subparagraph'
101
+ }
102
+ def convert_header(el, opts)
103
+ type = HEADER_TYPES[el.options[:level]]
104
+ if el.options[:attr] && (id = el.options[:attr]['id'])
105
+ "\\hypertarget{#{id}}{}\\#{type}*{#{inner(el, opts)}}\\label{#{id}}\n\n"
106
+ else
107
+ "\\#{type}*{#{inner(el, opts)}}\n\n"
108
+ end
109
+ end
110
+
111
+ def convert_hr(el, opts)
112
+ "\\begin{center}\\rule{3in}{0.4pt}\\end{center}\n"
113
+ end
114
+
115
+ def convert_ul(el, opts)
116
+ latex_environment('itemize', inner(el, opts))
117
+ end
118
+
119
+ def convert_ol(el, opts)
120
+ latex_environment('enumerate', inner(el, opts))
121
+ end
122
+
123
+ def convert_dl(el, opts)
124
+ latex_environment('description', inner(el, opts))
125
+ end
126
+
127
+ def convert_li(el, opts)
128
+ "\\item #{inner(el, opts)}\n"
129
+ end
130
+
131
+ def convert_dt(el, opts)
132
+ "\\item[#{inner(el, opts)}] "
133
+ end
134
+
135
+ def convert_dd(el, opts)
136
+ "#{inner(el, opts)}\n\n"
137
+ end
138
+
139
+ def convert_html_element(el, opts)
140
+ @doc.warnings << "Can't convert HTML element"
141
+ end
142
+
143
+ def convert_html_text(el, opts)
144
+ @doc.warnings << "Can't convert HTML text"
145
+ end
146
+
147
+ def convert_xml_comment(el, opts)
148
+ ''
149
+ end
150
+ alias :convert_xml_pi :convert_xml_comment
151
+
152
+ TABLE_ALIGNMENT_CHAR = {:default => 'l', :left => 'l', :center => 'c', :right => 'r'}
153
+
154
+ def convert_table(el, opts)
155
+ align = el.options[:alignment].map {|a| TABLE_ALIGNMENT_CHAR[a]}.join('|')
156
+ "\\begin{tabular}{|#{align}|}\n\\hline\n#{inner(el, opts)}\\hline\n\\end{tabular}\n\n"
157
+ end
158
+
159
+ def convert_thead(el, opts)
160
+ "#{inner(el, opts)}\\hline\n"
161
+ end
162
+
163
+ def convert_tbody(el, opts)
164
+ inner(el, opts)
165
+ end
166
+
167
+ def convert_tfoot(el, opts)
168
+ "\\hline \\hline \n#{inner(el, opts)}"
169
+ end
170
+
171
+ def convert_tr(el, opts)
172
+ el.children.map {|c| send("convert_#{c.type}", c, opts)}.join(' & ') + "\\\\\n"
173
+ end
174
+
175
+ def convert_td(el, opts)
176
+ inner(el, opts)
177
+ end
178
+
179
+ def convert_br(el, opts)
180
+ "\\newline\n"
181
+ end
182
+
183
+ def convert_a(el, opts)
184
+ url = el.options[:attr]['href']
185
+ if url =~ /^#/
186
+ "\\hyperlink{#{url[1..-1]}}{#{inner(el, opts)}}"
187
+ else
188
+ "\\href{#{url}}{#{inner(el, opts)}}"
189
+ end
190
+ end
191
+
192
+ def convert_img(el, opts)
193
+ if el.options[:attr]['src'] =~ /^(https?|ftps?):\/\//
194
+ @doc.warnings << "Cannot include non-local image"
195
+ ''
196
+ else
197
+ @doc.conversion_infos[:packages] << 'graphicx'
198
+ "\\includegraphics{#{el.options[:attr]['src']}}"
199
+ end
200
+ end
201
+
202
+ def convert_codespan(el, opts)
203
+ "{\\tt #{escape(el.value)}}"
204
+ end
205
+
206
+ def convert_footnote(el, opts)
207
+ "\\footnote{#{inner(@doc.parse_infos[:footnotes][el.options[:name]])}}"
208
+ end
209
+
210
+ def convert_raw(el, opts)
211
+ escape(el.value)
212
+ end
213
+
214
+ def convert_em(el, opts)
215
+ "\\emph{#{inner(el, opts)}}"
216
+ end
217
+
218
+ def convert_strong(el, opts)
219
+ "\\textbf{#{inner(el, opts)}}"
220
+ end
221
+
222
+ # Inspired by Maruku: entity conversion table taken from htmltolatex
223
+ # (http://sourceforge.net/projects/htmltolatex/), with some small adjustments as noted
224
+ ENTITY_CONV_TABLE = <<'EOF'
225
+ <char num='913' name='Alpha' convertTo='$A$' />
226
+ <char num='914' name='Beta' convertTo='$B$' />
227
+ <char num='915' name='Gamma' convertTo='$\Gamma$' />
228
+ <char num='916' name='Delta' convertTo='$\Delta$' />
229
+ <char num='917' name='Epsilon' convertTo='$E$' />
230
+ <char num='918' name='Zeta' convertTo='$Z$' />
231
+ <char num='919' name='Eta' convertTo='$H$' />
232
+ <char num='920' name='Theta' convertTo='$\Theta$' />
233
+ <char num='921' name='Iota' convertTo='$I$' />
234
+ <char num='922' name='Kappa' convertTo='$K$' />
235
+ <char num='923' name='Lambda' convertTo='$\Lambda$' />
236
+ <char num='924' name='Mu' convertTo='$M$' />
237
+ <char num='925' name='Nu' convertTo='$N$' />
238
+ <char num='926' name='Xi' convertTo='$\Xi$' />
239
+ <char num='927' name='Omicron' convertTo='$O$' />
240
+ <char num='928' name='Pi' convertTo='$\Pi$' />
241
+ <char num='929' name='Rho' convertTo='$P$' />
242
+ <char num='931' name='Sigma' convertTo='$\Sigma$' />
243
+ <char num='932' name='Tau' convertTo='$T$' />
244
+ <char num='933' name='Upsilon' convertTo='$Y$' />
245
+ <char num='934' name='Phi' convertTo='$\Phi$' />
246
+ <char num='935' name='Chi' convertTo='$X$' />
247
+ <char num='936' name='Psi' convertTo='$\Psi$' />
248
+ <char num='937' name='Omega' convertTo='$\Omega$' />
249
+ <char num='945' name='alpha' convertTo='$\alpha$' />
250
+ <char num='946' name='beta' convertTo='$\beta$' />
251
+ <char num='947' name='gamma' convertTo='$\gamma$' />
252
+ <char num='948' name='delta' convertTo='$\delta$' />
253
+ <char num='949' name='epsilon' convertTo='$\epsilon$' />
254
+ <char num='950' name='zeta' convertTo='$\zeta$' />
255
+ <char num='951' name='eta' convertTo='$\eta$' />
256
+ <char num='952' name='theta' convertTo='$\theta$' />
257
+ <char num='953' name='iota' convertTo='$\iota$' />
258
+ <char num='954' name='kappa' convertTo='$\kappa$' />
259
+ <char num='955' name='lambda' convertTo='$\lambda$' />
260
+ <char num='956' name='mu' convertTo='$\mu$' />
261
+ <char num='957' name='nu' convertTo='$\nu$' />
262
+ <char num='958' name='xi' convertTo='$\xi$' />
263
+ <char num='959' name='omicron' convertTo='$o$' />
264
+ <char num='960' name='pi' convertTo='$\pi$' />
265
+ <char num='961' name='rho' convertTo='$\rho$' />
266
+ <char num='963' name='sigma' convertTo='$\sigma$' />
267
+ <char num='964' name='tau' convertTo='$\tau$' />
268
+ <char num='965' name='upsilon' convertTo='$\upsilon$' />
269
+ <char num='966' name='phi' convertTo='$\phi$' />
270
+ <char num='967' name='chi' convertTo='$\chi$' />
271
+ <char num='968' name='psi' convertTo='$\psi$' />
272
+ <char num='969' name='omega' convertTo='$\omega$' />
273
+ <char num='962' name='sigmaf' convertTo='$\varsigma$' />
274
+ <char num='977' name='thetasym' convertTo='$\vartheta$' />
275
+ <char num='982' name='piv' convertTo='$\varpi$' />
276
+ <char num='8230' name='hellip' convertTo='\ldots' />
277
+ <char num='8242' name='prime' convertTo='$\prime$' />
278
+ <char num='8254' name='oline' convertTo='-' />
279
+ <char num='8260' name='frasl' convertTo='/' />
280
+ <char num='8472' name='weierp' convertTo='$\wp$' />
281
+ <char num='8465' name='image' convertTo='$\Im$' />
282
+ <char num='8476' name='real' convertTo='$\Re$' />
283
+ <char num='8501' name='alefsym' convertTo='$\aleph$' />
284
+ <char num='8226' name='bull' convertTo='$\bullet$' />
285
+ <char num='8482' name='trade' convertTo='$^{\rm TM}$' /> <!-- \texttrademark -->
286
+ <char num='8592' name='larr' convertTo='$\leftarrow$' />
287
+ <char num='8594' name='rarr' convertTo='$\rightarrow$' />
288
+ <char num='8593' name='uarr' convertTo='$\uparrow$' />
289
+ <char num='8595' name='darr' convertTo='$\downarrow$' />
290
+ <char num='8596' name='harr' convertTo='$\leftrightarrow$' />
291
+ <char num='8629' name='crarr' convertTo='$\hookleftarrow$' />
292
+ <char num='8657' name='uArr' convertTo='$\Uparrow$' />
293
+ <char num='8659' name='dArr' convertTo='$\Downarrow$' />
294
+ <char num='8656' name='lArr' convertTo='$\Leftarrow$' />
295
+ <char num='8658' name='rArr' convertTo='$\Rightarrow$' />
296
+ <char num='8660' name='hArr' convertTo='$\Leftrightarrow$' />
297
+ <char num='8704' name='forall' convertTo='$\forall$' />
298
+ <char num='8706' name='part' convertTo='$\partial$' />
299
+ <char num='8707' name='exist' convertTo='$\exists$' />
300
+ <char num='8709' name='empty' convertTo='$\emptyset$' />
301
+ <char num='8711' name='nabla' convertTo='$\nabla$' />
302
+ <char num='8712' name='isin' convertTo='$\in$' />
303
+ <char num='8715' name='ni' convertTo='$\ni$' />
304
+ <char num='8713' name='notin' convertTo='$\notin$' />
305
+ <char num='8721' name='sum' convertTo='$\sum$' />
306
+ <char num='8719' name='prod' convertTo='$\prod$' />
307
+ <char num='8722' name='minus' convertTo='$-$' />
308
+ <char num='8727' name='lowast' convertTo='$\ast$' />
309
+ <char num='8730' name='radic' convertTo='$\surd$' />
310
+ <char num='8733' name='prop' convertTo='$\propto$' />
311
+ <char num='8734' name='infin' convertTo='$\infty$' />
312
+ <char num='8736' name='ang' convertTo='$\angle$' />
313
+ <char num='8743' name='and' convertTo='$\wedge$' />
314
+ <char num='8744' name='or' convertTo='$\vee$' />
315
+ <char num='8745' name='cup' convertTo='$\cup$' />
316
+ <char num='8746' name='cap' convertTo='$\cap$' />
317
+ <char num='8747' name='int' convertTo='$\int$' />
318
+ <char num='8756' name='there4' convertTo='$\therefore$' /> <!-- amssymb --> --CHANGED!!!
319
+ <char num='8764' name='sim' convertTo='$\sim$' />
320
+ <char num='8776' name='asymp' convertTo='$\approx$' />
321
+ <char num='8773' name='cong' convertTo='$\cong$' />
322
+ <char num='8800' name='ne' convertTo='$\neq$' />
323
+ <char num='8801' name='equiv' convertTo='$\equiv$' />
324
+ <char num='8804' name='le' convertTo='$\leq$' />
325
+ <char num='8805' name='ge' convertTo='$\geq$' />
326
+ <char num='8834' name='sub' convertTo='$\subset$' />
327
+ <char num='8835' name='sup' convertTo='$\supset$' />
328
+ <char num='8838' name='sube' convertTo='$\subseteq$' />
329
+ <char num='8839' name='supe' convertTo='$\supseteq$' />
330
+ <char num='8836' name='nsub' convertTo='$\nsubset$' /> <!-- amssymb --> --CHANGED!!!
331
+ <char num='8853' name='oplus' convertTo='$\oplus$' />
332
+ <char num='8855' name='otimes' convertTo='$\otimes$' />
333
+ <char num='8869' name='perp' convertTo='$\perp$' />
334
+ <char num='8901' name='sdot' convertTo='$\cdot$' />
335
+ <char num='8968' name='rceil' convertTo='$\rceil$' />
336
+ <char num='8969' name='lceil' convertTo='$\lceil$' />
337
+ <char num='8970' name='lfloor' convertTo='$\lfloor$' />
338
+ <char num='8971' name='rfloor' convertTo='$\rfloor$' />
339
+ <char num='9001' name='rang' convertTo='$\rangle$' />
340
+ <char num='9002' name='lang' convertTo='$\langle$' />
341
+ <char num='9674' name='loz' convertTo='$\lozenge$' /> <!-- amssymb --> --CHANGED!!!
342
+ <char num='9824' name='spades' convertTo='$\spadesuit$' />
343
+ <char num='9827' name='clubs' convertTo='$\clubsuit$' />
344
+ <char num='9829' name='hearts' convertTo='$\heartsuit$' />
345
+ <char num='9830' name='diams' convertTo='$\diamondsuit$' />
346
+ <char num='38' name='amp' convertTo='\@AMP' />
347
+ <char num='34' name='quot' convertTo='@DOUBLEQUOT' />
348
+ <char num='39' name='apos' convertTo='@QUOT' /> -- ADDED!!!
349
+ <char num='169' name='copy' convertTo='\copyright' />
350
+ <char num='60' name='lt' convertTo='\textless{}' /> -- CHANGED!!!
351
+ <char num='62' name='gt' convertTo='\textgreater{}' /> -- CHANGED!!!
352
+ <char num='338' name='OElig' convertTo='\OE' />
353
+ <char num='339' name='oelig' convertTo='\oe' />
354
+ <char num='352' name='Scaron' convertTo='\v{S}' />
355
+ <char num='353' name='scaron' convertTo='\v{s}' />
356
+ <char num='376' name='Yuml' convertTo='\"Y' />
357
+ <char num='710' name='circ' convertTo='\textasciicircum' />
358
+ <char num='732' name='tilde' convertTo='\textasciitilde' />
359
+ <char num='8211' name='ndash' convertTo='--' />
360
+ <char num='8212' name='mdash' convertTo='---' />
361
+ <char num='8216' name='lsquo' convertTo='`' />
362
+ <char num='8217' name='rsquo' convertTo='@QUOT' />
363
+ <char num='8220' name='ldquo' convertTo='``' />
364
+ <char num='8221' name='rdquo' convertTo='@QUOT@QUOT' />
365
+ <char num='8224' name='dagger' convertTo='\dag' />
366
+ <char num='8225' name='Dagger' convertTo='\ddag' />
367
+ <char num='8240' name='permil' convertTo='\permil' /> <!-- wasysym package -->
368
+ <char num='8364' name='euro' convertTo='\euro' /> <!-- eurosym package -->
369
+ <char num='8249' name='lsaquo' convertTo='\guilsinglleft' />
370
+ <char num='8250' name='rsaquo' convertTo='\guilsinglright' />
371
+ <char num='160' name='nbsp' convertTo='\nolinebreak' />
372
+ <char num='161' name='iexcl' convertTo='\textexclamdown' />
373
+ <char num='163' name='pound' convertTo='\pounds' />
374
+ <char num='164' name='curren' convertTo='\currency' /> <!-- wasysym package -->
375
+ <char num='165' name='yen' convertTo='\textyen' /> <!-- textcomp -->
376
+ <char num='166' name='brvbar' convertTo='\brokenvert' /> <!-- wasysym -->
377
+ <char num='167' name='sect' convertTo='\S' />
378
+ <char num='171' name='laquo' convertTo='\guillemotleft' />
379
+ <char num='187' name='raquo' convertTo='\guillemotright' />
380
+ <char num='174' name='reg' convertTo='\textregistered' />
381
+ <char num='170' name='ordf' convertTo='\textordfeminine' />
382
+ <char num='172' name='not' convertTo='$\neg$' />
383
+ <char num='176' name='deg' convertTo='$\degree$' /> <!-- mathabx -->
384
+ <char num='177' name='plusmn' convertTo='$\pm$' />
385
+ <char num='180' name='acute' convertTo='@QUOT' />
386
+ <char num='181' name='micro' convertTo='$\mu$' />
387
+ <char num='182' name='para' convertTo='\P' />
388
+ <char num='183' name='middot' convertTo='$\cdot$' />
389
+ <char num='186' name='ordm' convertTo='\textordmasculine' />
390
+ <char num='162' name='cent' convertTo='\cent' /> <!-- wasysym -->
391
+ <char num='185' name='sup1' convertTo='$^1$' />
392
+ <char num='178' name='sup2' convertTo='$^2$' />
393
+ <char num='179' name='sup3' convertTo='$^3$' />
394
+ <char num='189' name='frac12' convertTo='$\frac{1}{2}$' />
395
+ <char num='188' name='frac14' convertTo='$\frac{1}{4}$' />
396
+ <char num='190' name='frac34' convertTo='$\frac{3}{4}' />
397
+ <char num='192' name='Agrave' convertTo='\`A' />
398
+ <char num='193' name='Aacute' convertTo='\@QUOTA' />
399
+ <char num='194' name='Acirc' convertTo='\^A' />
400
+ <char num='195' name='Atilde' convertTo='\~A' />
401
+ <char num='196' name='Auml' convertTo='\@DOUBLEQUOTA' />
402
+ <char num='197' name='Aring' convertTo='\AA' />
403
+ <char num='198' name='AElig' convertTo='\AE' />
404
+ <char num='199' name='Ccedil' convertTo='\cC' />
405
+ <char num='200' name='Egrave' convertTo='\`E' />
406
+ <char num='201' name='Eacute' convertTo='\@QUOTE' />
407
+ <char num='202' name='Ecirc' convertTo='\^E' />
408
+ <char num='203' name='Euml' convertTo='\@DOUBLEQUOTE' />
409
+ <char num='204' name='Igrave' convertTo='\`I' />
410
+ <char num='205' name='Iacute' convertTo='\@QUOTI' />
411
+ <char num='206' name='Icirc' convertTo='\^I' />
412
+ <char num='207' name='Iuml' convertTo='\"I' />
413
+ <char num='208' name='ETH' convertTo='$\eth$' /> <!-- amssymb --> --CHANGED!!!
414
+ <char num='209' name='Ntilde' convertTo='\~N' />
415
+ <char num='210' name='Ograve' convertTo='\`O' />
416
+ <char num='211' name='Oacute' convertTo='\@QUOTO' />
417
+ <char num='212' name='Ocirc' convertTo='\^O' />
418
+ <char num='213' name='Otilde' convertTo='\~O' />
419
+ <char num='214' name='Ouml' convertTo='\@DOUBLEQUOTO' />
420
+ <char num='215' name='times' convertTo='$\times$' />
421
+ <char num='216' name='Oslash' convertTo='\O' />
422
+ <char num='217' name='Ugrave' convertTo='\`U' />
423
+ <char num='218' name='Uacute' convertTo='\@QUOTU' />
424
+ <char num='219' name='Ucirc' convertTo='\^U' />
425
+ <char num='220' name='Uuml' convertTo='\@DOUBLEQUOTU' />
426
+ <char num='221' name='Yacute' convertTo='\@QUOTY' />
427
+ <char num='222' name='THORN' convertTo='\Thorn' /> <!-- wasysym -->
428
+ <char num='223' name='szlig' convertTo='\ss' />
429
+ <char num='224' name='agrave' convertTo='\`a' />
430
+ <char num='225' name='aacute' convertTo='\@QUOTa' />
431
+ <char num='226' name='acirc' convertTo='\^a' />
432
+ <char num='227' name='atilde' convertTo='\~a' />
433
+ <char num='228' name='auml' convertTo='\@DOUBLEQUOTa' />
434
+ <char num='229' name='aring' convertTo='\aa' />
435
+ <char num='230' name='aelig' convertTo='\ae' />
436
+ <char num='231' name='ccedil' convertTo='\cc' />
437
+ <char num='232' name='egrave' convertTo='\`e' />
438
+ <char num='233' name='eacute' convertTo='\@QUOTe' />
439
+ <char num='234' name='ecirc' convertTo='\^e' />
440
+ <char num='235' name='euml' convertTo='\@DOUBLEQUOTe' />
441
+ <char num='236' name='igrave' convertTo='\`i' />
442
+ <char num='237' name='iacute' convertTo='\@QUOTi' />
443
+ <char num='238' name='icirc' convertTo='\^i' />
444
+ <char num='239' name='iuml' convertTo='\@DOUBLEQUOTi' />
445
+ <char num='240' name='eth' convertTo='$\eth$' /> <!-- -->
446
+ <char num='241' name='ntilde' convertTo='\~n' />
447
+ <char num='242' name='ograve' convertTo='\`o' />
448
+ <char num='243' name='oacute' convertTo='\@QUOTo' />
449
+ <char num='244' name='ocirc' convertTo='\^o' />
450
+ <char num='245' name='otilde' convertTo='\~o' />
451
+ <char num='246' name='ouml' convertTo='\@DOUBLEQUOTo' />
452
+ <char num='247' name='divide' convertTo='$\divide$' />
453
+ <char num='248' name='oslash' convertTo='\o' />
454
+ <char num='249' name='ugrave' convertTo='\`u' />
455
+ <char num='250' name='uacute' convertTo='\@QUOTu' />
456
+ <char num='251' name='ucirc' convertTo='\^u' />
457
+ <char num='252' name='uuml' convertTo='\@DOUBLEQUOTu' />
458
+ <char num='253' name='yacute' convertTo='\@QUOTy' />
459
+ <char num='254' name='thorn' convertTo='\thorn' /> <!-- wasysym -->
460
+ <char num='255' name='yuml' convertTo='\@DOUBLEQUOTy' />
461
+ EOF
462
+ ENTITY_MAP = {}
463
+ ENTITY_CONV_TABLE.split(/\n/).each do |line|
464
+ num = line.scan(/num='(\d+)'/).first.first.to_i
465
+ name = line.scan(/name='(.*?)'/).first.first
466
+ latex = line.scan(/convertTo='(.*?)'/).first.first.gsub(/@AMP/, '&').
467
+ gsub(/@QUOT/, '\'').gsub(/@DOUBLEQUOT/, '"').gsub(/@LT/, '<').gsub(/@GT/, '>') + '{}'
468
+ package = line.scan(/<!--\s*(\w+)/).first
469
+ package = package.first unless package.nil?
470
+ ENTITY_MAP[num] = [latex, package]
471
+ ENTITY_MAP[name] = [latex, package]
472
+ end
473
+
474
+ def convert_entity(el, opts)
475
+ result = ENTITY_MAP[el.value]
476
+ if result
477
+ @doc.conversion_infos[:packages] << result[1] if result[1]
478
+ result[0]
479
+ else
480
+ @doc.warnings << "Couldn't find entity in substitution table!"
481
+ ''
482
+ end
483
+ end
484
+
485
+ TYPOGRAPHIC_SYMS = {
486
+ :mdash => '---', :ndash => '--', :ellipsis => '\ldots{}',
487
+ :laquo_space => '\guillemotleft{}~', :raquo_space => '~\guillemotright{}',
488
+ :laquo => '\guillemotleft{}', :raquo => '\guillemotright{}'
489
+ }
490
+ def convert_typographic_sym(el, opts)
491
+ TYPOGRAPHIC_SYMS[el.value]
492
+ end
493
+
494
+ SMART_QUOTE_SYMS = {:lsquo => '`', :rsquo => '\'', :ldquo => '``', :rdquo => '\'\''}
495
+ def convert_smart_quote(el, opts)
496
+ SMART_QUOTE_SYMS[el.value]
497
+ end
498
+
499
+ ESCAPE_MAP = {
500
+ "^" => "\\^{}",
501
+ "\\" => "\\textbackslash{}",
502
+ "~" => "\\ensuremath{\\sim}",
503
+ "|" => "\\textbar{}",
504
+ "<" => "\\textless{}",
505
+ ">" => "\\textgreater{}"
506
+ }.merge(Hash[*("{}$%&_#".scan(/./).map {|c| [c, "\\#{c}"]}.flatten)])
507
+ ESCAPE_RE = Regexp.union(*ESCAPE_MAP.collect {|k,v| k})
508
+
509
+ def escape(str)
510
+ str.gsub(ESCAPE_RE) {|m| ESCAPE_MAP[m]}
511
+ end
512
+
513
+ end
514
+
515
+ end
516
+ end