motion-kramdown 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +84 -0
  3. data/lib/kramdown/compatibility.rb +36 -0
  4. data/lib/kramdown/converter/base.rb +259 -0
  5. data/lib/kramdown/converter/html.rb +461 -0
  6. data/lib/kramdown/converter/kramdown.rb +423 -0
  7. data/lib/kramdown/converter/latex.rb +600 -0
  8. data/lib/kramdown/converter/math_engine/itex2mml.rb +39 -0
  9. data/lib/kramdown/converter/math_engine/mathjax.rb +33 -0
  10. data/lib/kramdown/converter/math_engine/ritex.rb +38 -0
  11. data/lib/kramdown/converter/pdf.rb +624 -0
  12. data/lib/kramdown/converter/remove_html_tags.rb +53 -0
  13. data/lib/kramdown/converter/syntax_highlighter/coderay.rb +78 -0
  14. data/lib/kramdown/converter/syntax_highlighter/rouge.rb +37 -0
  15. data/lib/kramdown/converter/toc.rb +69 -0
  16. data/lib/kramdown/converter.rb +69 -0
  17. data/lib/kramdown/document.rb +144 -0
  18. data/lib/kramdown/element.rb +515 -0
  19. data/lib/kramdown/error.rb +17 -0
  20. data/lib/kramdown/options.rb +584 -0
  21. data/lib/kramdown/parser/base.rb +130 -0
  22. data/lib/kramdown/parser/gfm.rb +55 -0
  23. data/lib/kramdown/parser/html.rb +575 -0
  24. data/lib/kramdown/parser/kramdown/abbreviation.rb +67 -0
  25. data/lib/kramdown/parser/kramdown/autolink.rb +37 -0
  26. data/lib/kramdown/parser/kramdown/blank_line.rb +30 -0
  27. data/lib/kramdown/parser/kramdown/block_boundary.rb +33 -0
  28. data/lib/kramdown/parser/kramdown/blockquote.rb +39 -0
  29. data/lib/kramdown/parser/kramdown/codeblock.rb +56 -0
  30. data/lib/kramdown/parser/kramdown/codespan.rb +44 -0
  31. data/lib/kramdown/parser/kramdown/emphasis.rb +61 -0
  32. data/lib/kramdown/parser/kramdown/eob.rb +26 -0
  33. data/lib/kramdown/parser/kramdown/escaped_chars.rb +25 -0
  34. data/lib/kramdown/parser/kramdown/extensions.rb +201 -0
  35. data/lib/kramdown/parser/kramdown/footnote.rb +56 -0
  36. data/lib/kramdown/parser/kramdown/header.rb +59 -0
  37. data/lib/kramdown/parser/kramdown/horizontal_rule.rb +27 -0
  38. data/lib/kramdown/parser/kramdown/html.rb +160 -0
  39. data/lib/kramdown/parser/kramdown/html_entity.rb +33 -0
  40. data/lib/kramdown/parser/kramdown/line_break.rb +25 -0
  41. data/lib/kramdown/parser/kramdown/link.rb +139 -0
  42. data/lib/kramdown/parser/kramdown/list.rb +256 -0
  43. data/lib/kramdown/parser/kramdown/math.rb +54 -0
  44. data/lib/kramdown/parser/kramdown/paragraph.rb +54 -0
  45. data/lib/kramdown/parser/kramdown/smart_quotes.rb +174 -0
  46. data/lib/kramdown/parser/kramdown/table.rb +171 -0
  47. data/lib/kramdown/parser/kramdown/typographic_symbol.rb +44 -0
  48. data/lib/kramdown/parser/kramdown.rb +359 -0
  49. data/lib/kramdown/parser/markdown.rb +56 -0
  50. data/lib/kramdown/parser.rb +27 -0
  51. data/lib/kramdown/utils/configurable.rb +44 -0
  52. data/lib/kramdown/utils/entities.rb +347 -0
  53. data/lib/kramdown/utils/html.rb +75 -0
  54. data/lib/kramdown/utils/ordered_hash.rb +87 -0
  55. data/lib/kramdown/utils/string_scanner.rb +74 -0
  56. data/lib/kramdown/utils/unidecoder.rb +51 -0
  57. data/lib/kramdown/utils.rb +58 -0
  58. data/lib/kramdown/version.rb +15 -0
  59. data/lib/kramdown.rb +10 -0
  60. data/lib/motion-kramdown.rb +47 -0
  61. data/lib/rubymotion/encodings.rb +37 -0
  62. data/lib/rubymotion/rexml_shim.rb +25 -0
  63. data/lib/rubymotion/set.rb +1349 -0
  64. data/lib/rubymotion/version.rb +6 -0
  65. data/spec/document_tree.rb +48 -0
  66. data/spec/gfm_to_html.rb +95 -0
  67. data/spec/helpers/it_behaves_like.rb +27 -0
  68. data/spec/helpers/option_file.rb +46 -0
  69. data/spec/helpers/spec_options.rb +37 -0
  70. data/spec/helpers/tidy.rb +12 -0
  71. data/spec/html_to_html.rb +40 -0
  72. data/spec/html_to_kramdown_to_html.rb +46 -0
  73. data/spec/kramdown_to_xxx.rb +40 -0
  74. data/spec/test_location.rb +203 -0
  75. data/spec/test_string_scanner_kramdown.rb +19 -0
  76. data/spec/text_to_kramdown_to_html.rb +52 -0
  77. data/spec/text_to_latex.rb +33 -0
  78. metadata +164 -0
@@ -0,0 +1,600 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ # RM require 'set'
11
+
12
+ module Kramdown
13
+
14
+ module Converter
15
+
16
+ # Converts an element tree to LaTeX.
17
+ #
18
+ # This converter uses ideas from other Markdown-to-LaTeX converters like Pandoc and Maruku.
19
+ #
20
+ # You can customize this converter by sub-classing it and overriding the +convert_NAME+ methods.
21
+ # Each such method takes the following parameters:
22
+ #
23
+ # [+el+] The element of type +NAME+ to be converted.
24
+ #
25
+ # [+opts+] A hash containing processing options that are passed down from parent elements. The
26
+ # key :parent is always set and contains the parent element as value.
27
+ #
28
+ # The return value of such a method has to be a string containing the element +el+ formatted
29
+ # correctly as LaTeX markup.
30
+ class Latex < Base
31
+
32
+ # Initialize the LaTeX converter with the +root+ element and the conversion +options+.
33
+ def initialize(root, options)
34
+ super
35
+ @data[:packages] = Set.new
36
+ end
37
+
38
+ # Dispatch the conversion of the element +el+ to a +convert_TYPE+ method using the +type+ of
39
+ # the element.
40
+ def convert(el, opts = {})
41
+ send("convert_#{el.type}", el, opts)
42
+ end
43
+
44
+ # Return the converted content of the children of +el+ as a string.
45
+ def inner(el, opts)
46
+ result = ''
47
+ options = opts.dup.merge(:parent => el)
48
+ el.children.each_with_index do |inner_el, index|
49
+ options[:index] = index
50
+ options[:result] = result
51
+ result << send("convert_#{inner_el.type}", inner_el, options)
52
+ end
53
+ result
54
+ end
55
+
56
+ def convert_root(el, opts)
57
+ inner(el, opts)
58
+ end
59
+
60
+ def convert_blank(el, opts)
61
+ opts[:result] =~ /\n\n\Z|\A\Z/ ? "" : "\n"
62
+ end
63
+
64
+ def convert_text(el, opts)
65
+ escape(el.value)
66
+ end
67
+
68
+ def convert_p(el, opts)
69
+ if el.children.size == 1 && el.children.first.type == :img && !(img = convert_img(el.children.first, opts)).empty?
70
+ convert_standalone_image(el, opts, img)
71
+ else
72
+ "#{latex_link_target(el)}#{inner(el, opts)}\n\n"
73
+ end
74
+ end
75
+
76
+ # Helper method used by +convert_p+ to convert a paragraph that only contains a single :img
77
+ # element.
78
+ def convert_standalone_image(el, opts, img)
79
+ attrs = attribute_list(el)
80
+ "\\begin{figure}#{attrs}\n\\begin{center}\n#{img}\n\\end{center}\n\\caption{#{escape(el.children.first.attr['alt'])}}\n#{latex_link_target(el, true)}\n\\end{figure}#{attrs}\n"
81
+ end
82
+
83
+ def convert_codeblock(el, opts)
84
+ show_whitespace = el.attr['class'].to_s =~ /\bshow-whitespaces\b/
85
+ lang = extract_code_language(el.attr)
86
+ if show_whitespace || lang
87
+ options = []
88
+ options << "showspaces=%s,showtabs=%s" % (show_whitespace ? ['true', 'true'] : ['false', 'false'])
89
+ options << "language=#{lang}" if lang
90
+ options << "basicstyle=\\ttfamily\\footnotesize,columns=fixed,frame=tlbr"
91
+ id = el.attr['id']
92
+ options << "label=#{id}" if id
93
+ attrs = attribute_list(el)
94
+ "#{latex_link_target(el)}\\begin{lstlisting}[#{options.join(',')}]\n#{el.value}\n\\end{lstlisting}#{attrs}\n"
95
+ else
96
+ "#{latex_link_target(el)}\\begin{verbatim}#{el.value}\\end{verbatim}\n"
97
+ end
98
+ end
99
+
100
+ def convert_blockquote(el, opts)
101
+ latex_environment(el.children.size > 1 ? 'quotation' : 'quote', el, inner(el, opts))
102
+ end
103
+
104
+ def convert_header(el, opts)
105
+ type = @options[:latex_headers][output_header_level(el.options[:level]) - 1]
106
+ if ((id = el.attr['id']) ||
107
+ (@options[:auto_ids] && (id = generate_id(el.options[:raw_text])))) && in_toc?(el)
108
+ "\\#{type}{#{inner(el, opts)}}\\hypertarget{#{id}}{}\\label{#{id}}\n\n"
109
+ else
110
+ "\\#{type}*{#{inner(el, opts)}}\n\n"
111
+ end
112
+ end
113
+
114
+ def convert_hr(el, opts)
115
+ attrs = attribute_list(el)
116
+ "#{latex_link_target(el)}\\begin{center}#{attrs}\n\\rule{3in}{0.4pt}\n\\end{center}#{attrs}\n"
117
+ end
118
+
119
+ def convert_ul(el, opts)
120
+ if !@data[:has_toc] && (el.options[:ial] && (el.options[:ial][:refs] || []).include?('toc')) # RM can't use rescue nil
121
+ @data[:has_toc] = true
122
+ '\tableofcontents'
123
+ else
124
+ latex_environment(el.type == :ul ? 'itemize' : 'enumerate', el, inner(el, opts))
125
+ end
126
+ end
127
+ alias :convert_ol :convert_ul
128
+
129
+ def convert_dl(el, opts)
130
+ latex_environment('description', el, inner(el, opts))
131
+ end
132
+
133
+ def convert_li(el, opts)
134
+ "\\item #{latex_link_target(el, true)}#{inner(el, opts).sub(/\n+\Z/, '')}\n"
135
+ end
136
+
137
+ def convert_dt(el, opts)
138
+ "\\item[#{inner(el, opts)}] "
139
+ end
140
+
141
+ def convert_dd(el, opts)
142
+ "#{latex_link_target(el)}#{inner(el, opts)}\n\n"
143
+ end
144
+
145
+ def convert_html_element(el, opts)
146
+ if el.value == 'i' || el.value == 'em'
147
+ "\\emph{#{inner(el, opts)}}"
148
+ elsif el.value == 'b' || el.value == 'strong'
149
+ "\\textbf{#{inner(el, opts)}}"
150
+ else
151
+ warning("Can't convert HTML element")
152
+ ''
153
+ end
154
+ end
155
+
156
+ def convert_xml_comment(el, opts)
157
+ el.value.split(/\n/).map {|l| "% #{l}"}.join("\n") + "\n"
158
+ end
159
+
160
+ def convert_xml_pi(el, opts)
161
+ warning("Can't convert XML PI")
162
+ ''
163
+ end
164
+
165
+ TABLE_ALIGNMENT_CHAR = {:default => 'l', :left => 'l', :center => 'c', :right => 'r'} # :nodoc:
166
+
167
+ def convert_table(el, opts)
168
+ @data[:packages] << 'longtable'
169
+ align = el.options[:alignment].map {|a| TABLE_ALIGNMENT_CHAR[a]}.join('|')
170
+ attrs = attribute_list(el)
171
+ "#{latex_link_target(el)}\\begin{longtable}{|#{align}|}#{attrs}\n\\hline\n#{inner(el, opts)}\\hline\n\\end{longtable}#{attrs}\n\n"
172
+ end
173
+
174
+ def convert_thead(el, opts)
175
+ "#{inner(el, opts)}\\hline\n"
176
+ end
177
+
178
+ def convert_tbody(el, opts)
179
+ inner(el, opts)
180
+ end
181
+
182
+ def convert_tfoot(el, opts)
183
+ "\\hline \\hline \n#{inner(el, opts)}"
184
+ end
185
+
186
+ def convert_tr(el, opts)
187
+ el.children.map {|c| send("convert_#{c.type}", c, opts)}.join(' & ') << "\\\\\n"
188
+ end
189
+
190
+ def convert_td(el, opts)
191
+ inner(el, opts)
192
+ end
193
+
194
+ def convert_comment(el, opts)
195
+ el.value.split(/\n/).map {|l| "% #{l}"}.join("\n") << "\n"
196
+ end
197
+
198
+ def convert_br(el, opts)
199
+ res = "\\newline"
200
+ res << "\n" if (c = opts[:parent].children[opts[:index]+1]) && (c.type != :text || c.value !~ /^\s*\n/)
201
+ res
202
+ end
203
+
204
+ def convert_a(el, opts)
205
+ url = el.attr['href']
206
+ if url.start_with?('#')
207
+ "\\hyperlink{#{escape(url[1..-1])}}{#{inner(el, opts)}}"
208
+ else
209
+ "\\href{#{escape(url)}}{#{inner(el, opts)}}"
210
+ end
211
+ end
212
+
213
+ def convert_img(el, opts)
214
+ line = el.options[:location]
215
+ if el.attr['src'] =~ /^(https?|ftps?):\/\//
216
+ warning("Cannot include non-local image#{line ? " (line #{line})" : ''}")
217
+ ''
218
+ elsif !el.attr['src'].empty?
219
+ @data[:packages] << 'graphicx'
220
+ "#{latex_link_target(el)}\\includegraphics{#{el.attr['src']}}"
221
+ else
222
+ warning("Cannot include image with empty path#{line ? " (line #{line})" : ''}")
223
+ ''
224
+ end
225
+ end
226
+
227
+ def convert_codespan(el, opts)
228
+ "{\\tt #{latex_link_target(el)}#{escape(el.value)}}"
229
+ end
230
+
231
+ def convert_footnote(el, opts)
232
+ @data[:packages] << 'fancyvrb'
233
+ "\\footnote{#{inner(el.value, opts).rstrip}}"
234
+ end
235
+
236
+ def convert_raw(el, opts)
237
+ if !el.options[:type] || el.options[:type].empty? || el.options[:type].include?('latex')
238
+ el.value + (el.options[:category] == :block ? "\n" : '')
239
+ else
240
+ ''
241
+ end
242
+ end
243
+
244
+ def convert_em(el, opts)
245
+ "\\emph{#{latex_link_target(el)}#{inner(el, opts)}}"
246
+ end
247
+
248
+ def convert_strong(el, opts)
249
+ "\\textbf{#{latex_link_target(el)}#{inner(el, opts)}}"
250
+ end
251
+
252
+ # Inspired by Maruku: entity conversion table based on the one from htmltolatex
253
+ # (http://sourceforge.net/projects/htmltolatex/), with some small adjustments/additions
254
+ ENTITY_CONV_TABLE = {
255
+ 913 => ['$A$'],
256
+ 914 => ['$B$'],
257
+ 915 => ['$\Gamma$'],
258
+ 916 => ['$\Delta$'],
259
+ 917 => ['$E$'],
260
+ 918 => ['$Z$'],
261
+ 919 => ['$H$'],
262
+ 920 => ['$\Theta$'],
263
+ 921 => ['$I$'],
264
+ 922 => ['$K$'],
265
+ 923 => ['$\Lambda$'],
266
+ 924 => ['$M$'],
267
+ 925 => ['$N$'],
268
+ 926 => ['$\Xi$'],
269
+ 927 => ['$O$'],
270
+ 928 => ['$\Pi$'],
271
+ 929 => ['$P$'],
272
+ 931 => ['$\Sigma$'],
273
+ 932 => ['$T$'],
274
+ 933 => ['$Y$'],
275
+ 934 => ['$\Phi$'],
276
+ 935 => ['$X$'],
277
+ 936 => ['$\Psi$'],
278
+ 937 => ['$\Omega$'],
279
+ 945 => ['$\alpha$'],
280
+ 946 => ['$\beta$'],
281
+ 947 => ['$\gamma$'],
282
+ 948 => ['$\delta$'],
283
+ 949 => ['$\epsilon$'],
284
+ 950 => ['$\zeta$'],
285
+ 951 => ['$\eta$'],
286
+ 952 => ['$\theta$'],
287
+ 953 => ['$\iota$'],
288
+ 954 => ['$\kappa$'],
289
+ 955 => ['$\lambda$'],
290
+ 956 => ['$\mu$'],
291
+ 957 => ['$\nu$'],
292
+ 958 => ['$\xi$'],
293
+ 959 => ['$o$'],
294
+ 960 => ['$\pi$'],
295
+ 961 => ['$\rho$'],
296
+ 963 => ['$\sigma$'],
297
+ 964 => ['$\tau$'],
298
+ 965 => ['$\upsilon$'],
299
+ 966 => ['$\phi$'],
300
+ 967 => ['$\chi$'],
301
+ 968 => ['$\psi$'],
302
+ 969 => ['$\omega$'],
303
+ 962 => ['$\varsigma$'],
304
+ 977 => ['$\vartheta$'],
305
+ 982 => ['$\varpi$'],
306
+ 8230 => ['\ldots'],
307
+ 8242 => ['$\prime$'],
308
+ 8254 => ['-'],
309
+ 8260 => ['/'],
310
+ 8472 => ['$\wp$'],
311
+ 8465 => ['$\Im$'],
312
+ 8476 => ['$\Re$'],
313
+ 8501 => ['$\aleph$'],
314
+ 8226 => ['$\bullet$'],
315
+ 8482 => ['$^{\rm TM}$'],
316
+ 8592 => ['$\leftarrow$'],
317
+ 8594 => ['$\rightarrow$'],
318
+ 8593 => ['$\uparrow$'],
319
+ 8595 => ['$\downarrow$'],
320
+ 8596 => ['$\leftrightarrow$'],
321
+ 8629 => ['$\hookleftarrow$'],
322
+ 8657 => ['$\Uparrow$'],
323
+ 8659 => ['$\Downarrow$'],
324
+ 8656 => ['$\Leftarrow$'],
325
+ 8658 => ['$\Rightarrow$'],
326
+ 8660 => ['$\Leftrightarrow$'],
327
+ 8704 => ['$\forall$'],
328
+ 8706 => ['$\partial$'],
329
+ 8707 => ['$\exists$'],
330
+ 8709 => ['$\emptyset$'],
331
+ 8711 => ['$\nabla$'],
332
+ 8712 => ['$\in$'],
333
+ 8715 => ['$\ni$'],
334
+ 8713 => ['$\notin$'],
335
+ 8721 => ['$\sum$'],
336
+ 8719 => ['$\prod$'],
337
+ 8722 => ['$-$'],
338
+ 8727 => ['$\ast$'],
339
+ 8730 => ['$\surd$'],
340
+ 8733 => ['$\propto$'],
341
+ 8734 => ['$\infty$'],
342
+ 8736 => ['$\angle$'],
343
+ 8743 => ['$\wedge$'],
344
+ 8744 => ['$\vee$'],
345
+ 8745 => ['$\cup$'],
346
+ 8746 => ['$\cap$'],
347
+ 8747 => ['$\int$'],
348
+ 8756 => ['$\therefore$', 'amssymb'],
349
+ 8764 => ['$\sim$'],
350
+ 8776 => ['$\approx$'],
351
+ 8773 => ['$\cong$'],
352
+ 8800 => ['$\neq$'],
353
+ 8801 => ['$\equiv$'],
354
+ 8804 => ['$\leq$'],
355
+ 8805 => ['$\geq$'],
356
+ 8834 => ['$\subset$'],
357
+ 8835 => ['$\supset$'],
358
+ 8838 => ['$\subseteq$'],
359
+ 8839 => ['$\supseteq$'],
360
+ 8836 => ['$\nsubset$', 'amssymb'],
361
+ 8853 => ['$\oplus$'],
362
+ 8855 => ['$\otimes$'],
363
+ 8869 => ['$\perp$'],
364
+ 8901 => ['$\cdot$'],
365
+ 8968 => ['$\rceil$'],
366
+ 8969 => ['$\lceil$'],
367
+ 8970 => ['$\lfloor$'],
368
+ 8971 => ['$\rfloor$'],
369
+ 9001 => ['$\rangle$'],
370
+ 9002 => ['$\langle$'],
371
+ 9674 => ['$\lozenge$', 'amssymb'],
372
+ 9824 => ['$\spadesuit$'],
373
+ 9827 => ['$\clubsuit$'],
374
+ 9829 => ['$\heartsuit$'],
375
+ 9830 => ['$\diamondsuit$'],
376
+ 38 => ['\&'],
377
+ 34 => ['"'],
378
+ 39 => ['\''],
379
+ 169 => ['\copyright'],
380
+ 60 => ['\textless'],
381
+ 62 => ['\textgreater'],
382
+ 338 => ['\OE'],
383
+ 339 => ['\oe'],
384
+ 352 => ['\v{S}'],
385
+ 353 => ['\v{s}'],
386
+ 376 => ['\"Y'],
387
+ 710 => ['\textasciicircum'],
388
+ 732 => ['\textasciitilde'],
389
+ 8211 => ['--'],
390
+ 8212 => ['---'],
391
+ 8216 => ['`'],
392
+ 8217 => ['\''],
393
+ 8220 => ['``'],
394
+ 8221 => ['\'\''],
395
+ 8224 => ['\dag'],
396
+ 8225 => ['\ddag'],
397
+ 8240 => ['\permil', 'wasysym'],
398
+ 8364 => ['\euro', 'eurosym'],
399
+ 8249 => ['\guilsinglleft'],
400
+ 8250 => ['\guilsinglright'],
401
+ 8218 => ['\quotesinglbase', 'mathcomp'],
402
+ 8222 => ['\quotedblbase', 'mathcomp'],
403
+ 402 => ['\textflorin', 'mathcomp'],
404
+ 381 => ['\v{Z}'],
405
+ 382 => ['\v{z}'],
406
+ 160 => ['~'],
407
+ 161 => ['\textexclamdown'],
408
+ 163 => ['\pounds'],
409
+ 164 => ['\currency', 'wasysym'],
410
+ 165 => ['\textyen', 'textcomp'],
411
+ 166 => ['\brokenvert', 'wasysym'],
412
+ 167 => ['\S'],
413
+ 171 => ['\guillemotleft'],
414
+ 187 => ['\guillemotright'],
415
+ 174 => ['\textregistered'],
416
+ 170 => ['\textordfeminine'],
417
+ 172 => ['$\neg$'],
418
+ 173 => ['\-'],
419
+ 176 => ['$\degree$', 'mathabx'],
420
+ 177 => ['$\pm$'],
421
+ 180 => ['\''],
422
+ 181 => ['$\mu$'],
423
+ 182 => ['\P'],
424
+ 183 => ['$\cdot$'],
425
+ 186 => ['\textordmasculine'],
426
+ 162 => ['\cent', 'wasysym'],
427
+ 185 => ['$^1$'],
428
+ 178 => ['$^2$'],
429
+ 179 => ['$^3$'],
430
+ 189 => ['$\frac{1}{2}$'],
431
+ 188 => ['$\frac{1}{4}$'],
432
+ 190 => ['$\frac{3}{4}'],
433
+ 192 => ['\`A'],
434
+ 193 => ['\\\'A'],
435
+ 194 => ['\^A'],
436
+ 195 => ['\~A'],
437
+ 196 => ['\"A'],
438
+ 197 => ['\AA'],
439
+ 198 => ['\AE'],
440
+ 199 => ['\cC'],
441
+ 200 => ['\`E'],
442
+ 201 => ['\\\'E'],
443
+ 202 => ['\^E'],
444
+ 203 => ['\"E'],
445
+ 204 => ['\`I'],
446
+ 205 => ['\\\'I'],
447
+ 206 => ['\^I'],
448
+ 207 => ['\"I'],
449
+ 208 => ['$\eth$', 'amssymb'],
450
+ 209 => ['\~N'],
451
+ 210 => ['\`O'],
452
+ 211 => ['\\\'O'],
453
+ 212 => ['\^O'],
454
+ 213 => ['\~O'],
455
+ 214 => ['\"O'],
456
+ 215 => ['$\times$'],
457
+ 216 => ['\O'],
458
+ 217 => ['\`U'],
459
+ 218 => ['\\\'U'],
460
+ 219 => ['\^U'],
461
+ 220 => ['\"U'],
462
+ 221 => ['\\\'Y'],
463
+ 222 => ['\Thorn', 'wasysym'],
464
+ 223 => ['\ss'],
465
+ 224 => ['\`a'],
466
+ 225 => ['\\\'a'],
467
+ 226 => ['\^a'],
468
+ 227 => ['\~a'],
469
+ 228 => ['\"a'],
470
+ 229 => ['\aa'],
471
+ 230 => ['\ae'],
472
+ 231 => ['\cc'],
473
+ 232 => ['\`e'],
474
+ 233 => ['\\\'e'],
475
+ 234 => ['\^e'],
476
+ 235 => ['\"e'],
477
+ 236 => ['\`i'],
478
+ 237 => ['\\\'i'],
479
+ 238 => ['\^i'],
480
+ 239 => ['\"i'],
481
+ 240 => ['$\eth$'],
482
+ 241 => ['\~n'],
483
+ 242 => ['\`o'],
484
+ 243 => ['\\\'o'],
485
+ 244 => ['\^o'],
486
+ 245 => ['\~o'],
487
+ 246 => ['\"o'],
488
+ 247 => ['$\divide$'],
489
+ 248 => ['\o'],
490
+ 249 => ['\`u'],
491
+ 250 => ['\\\'u'],
492
+ 251 => ['\^u'],
493
+ 252 => ['\"u'],
494
+ 253 => ['\\\'y'],
495
+ 254 => ['\thorn', 'wasysym'],
496
+ 255 => ['\"y'],
497
+ 8201 => ['\thinspace'],
498
+ 8194 => ['\hskip .5em\relax'],
499
+ 8195 => ['\quad'],
500
+ } # :nodoc:
501
+ ENTITY_CONV_TABLE.each {|k,v| ENTITY_CONV_TABLE[k][0].insert(-1, '{}')}
502
+
503
+ def entity_to_latex(entity)
504
+ text, package = ENTITY_CONV_TABLE[entity.code_point]
505
+ if text
506
+ @data[:packages] << package if package
507
+ text
508
+ else
509
+ warning("Couldn't find entity with code #{entity.code_point} in substitution table!")
510
+ ''
511
+ end
512
+ end
513
+
514
+ def convert_entity(el, opts)
515
+ entity_to_latex(el.value)
516
+ end
517
+
518
+ TYPOGRAPHIC_SYMS = {
519
+ :mdash => '---', :ndash => '--', :hellip => '\ldots{}',
520
+ :laquo_space => '\guillemotleft{}~', :raquo_space => '~\guillemotright{}',
521
+ :laquo => '\guillemotleft{}', :raquo => '\guillemotright{}'
522
+ } # :nodoc:
523
+ def convert_typographic_sym(el, opts)
524
+ TYPOGRAPHIC_SYMS[el.value]
525
+ end
526
+
527
+ def convert_smart_quote(el, opts)
528
+ res = entity_to_latex(smart_quote_entity(el)).chomp('{}')
529
+ res << "{}" if ((nel = opts[:parent].children[opts[:index]+1]) && nel.type == :smart_quote) || res =~ /\w$/
530
+ res
531
+ end
532
+
533
+ def convert_math(el, opts)
534
+ @data[:packages] += %w[amssymb amsmath amsthm amsfonts]
535
+ if el.options[:category] == :block
536
+ if el.value =~ /\A\s*\\begin\{/
537
+ el.value
538
+ else
539
+ latex_environment('displaymath', el, el.value)
540
+ end
541
+ else
542
+ "$#{el.value}$"
543
+ end
544
+ end
545
+
546
+ def convert_abbreviation(el, opts)
547
+ @data[:packages] += %w[acronym]
548
+ "\\ac{#{normalize_abbreviation_key(el.value)}}"
549
+ end
550
+
551
+ # Normalize the abbreviation key so that it only contains allowed ASCII character
552
+ def normalize_abbreviation_key(key)
553
+ key.gsub(/\W/) {|m| m.unpack('H*').first}
554
+ end
555
+
556
+ # Wrap the +text+ inside a LaTeX environment of type +type+. The element +el+ is passed on to
557
+ # the method #attribute_list -- the resulting string is appended to both the \\begin and the
558
+ # \\end lines of the LaTeX environment for easier post-processing of LaTeX environments.
559
+ def latex_environment(type, el, text)
560
+ attrs = attribute_list(el)
561
+ "\\begin{#{type}}#{latex_link_target(el)}#{attrs}\n#{text.rstrip}\n\\end{#{type}}#{attrs}\n"
562
+ end
563
+
564
+ # Return a string containing a valid \hypertarget command if the element has an ID defined, or
565
+ # +nil+ otherwise. If the parameter +add_label+ is +true+, a \label command will also be used
566
+ # additionally to the \hypertarget command.
567
+ def latex_link_target(el, add_label = false)
568
+ if (id = el.attr['id'])
569
+ "\\hypertarget{#{id}}{}" << (add_label ? "\\label{#{id}}" : '')
570
+ else
571
+ nil
572
+ end
573
+ end
574
+
575
+ # Return a LaTeX comment containing all attributes as 'key="value"' pairs.
576
+ def attribute_list(el)
577
+ attrs = el.attr.map {|k,v| v.nil? ? '' : " #{k}=\"#{v.to_s}\""}.compact.sort.join('')
578
+ attrs = " % #{attrs}" if !attrs.empty?
579
+ attrs
580
+ end
581
+
582
+ ESCAPE_MAP = {
583
+ "^" => "\\^{}",
584
+ "\\" => "\\textbackslash{}",
585
+ "~" => "\\ensuremath{\\sim}",
586
+ "|" => "\\textbar{}",
587
+ "<" => "\\textless{}",
588
+ ">" => "\\textgreater{}"
589
+ }.merge(Hash[*("{}$%&_#".scan(/./).map {|c| [c, "\\#{c}"]}.flatten)]) # :nodoc:
590
+ ESCAPE_RE = Regexp.union(*ESCAPE_MAP.collect {|k,v| k}) # :nodoc:
591
+
592
+ # Escape the special LaTeX characters in the string +str+.
593
+ def escape(str)
594
+ str.gsub(ESCAPE_RE) {|m| ESCAPE_MAP[m]}
595
+ end
596
+
597
+ end
598
+
599
+ end
600
+ end
@@ -0,0 +1,39 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ module Kramdown::Converter::MathEngine
11
+
12
+ # Uses the Itex2MML library for converting math formulas to MathML.
13
+ module Itex2MML
14
+
15
+ begin
16
+ # RM require 'itextomml'
17
+
18
+ # Itex2MML is available if this constant is +true+.
19
+ AVAILABLE = true
20
+ rescue LoadError
21
+ AVAILABLE = false # :nodoc:
22
+ end
23
+
24
+ def self.call(converter, el, opts)
25
+ type = el.options[:category]
26
+ parser = ::Itex2MML::Parser.new
27
+ result = (type == :block ? parser.block_filter(el.value) : parser.inline_filter(el.value))
28
+
29
+ attr = el.attr.dup
30
+ attr.delete('xmlns')
31
+ attr.delete('display')
32
+ result.insert("<math".length, converter.html_attributes(attr))
33
+
34
+ (type == :block ? "#{' '*opts[:indent]}#{result}\n" : result)
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ module Kramdown::Converter::MathEngine
11
+
12
+ # Uses the MathJax javascript library for displaying math.
13
+ #
14
+ # Note that the javascript library itself is not include or linked, this has to be done
15
+ # separately. Only the math content is marked up correctly.
16
+ module Mathjax
17
+
18
+ def self.call(converter, el, opts)
19
+ type = el.options[:category]
20
+ text = (el.value =~ /<|&/ ? "% <![CDATA[\n#{el.value} %]]>" : el.value)
21
+ text.gsub!(/<\/?script>?/, '')
22
+
23
+ attr = {:type => "math/tex#{type == :block ? '; mode=display' : ''}"}
24
+ if type == :block
25
+ converter.format_as_block_html('script', attr, text, opts[:indent])
26
+ else
27
+ converter.format_as_span_html('script', attr, text)
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ end