motion-kramdown 0.5.0

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 (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