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.
- checksums.yaml +7 -0
- data/README.md +84 -0
- data/lib/kramdown/compatibility.rb +36 -0
- data/lib/kramdown/converter/base.rb +259 -0
- data/lib/kramdown/converter/html.rb +461 -0
- data/lib/kramdown/converter/kramdown.rb +423 -0
- data/lib/kramdown/converter/latex.rb +600 -0
- data/lib/kramdown/converter/math_engine/itex2mml.rb +39 -0
- data/lib/kramdown/converter/math_engine/mathjax.rb +33 -0
- data/lib/kramdown/converter/math_engine/ritex.rb +38 -0
- data/lib/kramdown/converter/pdf.rb +624 -0
- data/lib/kramdown/converter/remove_html_tags.rb +53 -0
- data/lib/kramdown/converter/syntax_highlighter/coderay.rb +78 -0
- data/lib/kramdown/converter/syntax_highlighter/rouge.rb +37 -0
- data/lib/kramdown/converter/toc.rb +69 -0
- data/lib/kramdown/converter.rb +69 -0
- data/lib/kramdown/document.rb +144 -0
- data/lib/kramdown/element.rb +515 -0
- data/lib/kramdown/error.rb +17 -0
- data/lib/kramdown/options.rb +584 -0
- data/lib/kramdown/parser/base.rb +130 -0
- data/lib/kramdown/parser/gfm.rb +55 -0
- data/lib/kramdown/parser/html.rb +575 -0
- data/lib/kramdown/parser/kramdown/abbreviation.rb +67 -0
- data/lib/kramdown/parser/kramdown/autolink.rb +37 -0
- data/lib/kramdown/parser/kramdown/blank_line.rb +30 -0
- data/lib/kramdown/parser/kramdown/block_boundary.rb +33 -0
- data/lib/kramdown/parser/kramdown/blockquote.rb +39 -0
- data/lib/kramdown/parser/kramdown/codeblock.rb +56 -0
- data/lib/kramdown/parser/kramdown/codespan.rb +44 -0
- data/lib/kramdown/parser/kramdown/emphasis.rb +61 -0
- data/lib/kramdown/parser/kramdown/eob.rb +26 -0
- data/lib/kramdown/parser/kramdown/escaped_chars.rb +25 -0
- data/lib/kramdown/parser/kramdown/extensions.rb +201 -0
- data/lib/kramdown/parser/kramdown/footnote.rb +56 -0
- data/lib/kramdown/parser/kramdown/header.rb +59 -0
- data/lib/kramdown/parser/kramdown/horizontal_rule.rb +27 -0
- data/lib/kramdown/parser/kramdown/html.rb +160 -0
- data/lib/kramdown/parser/kramdown/html_entity.rb +33 -0
- data/lib/kramdown/parser/kramdown/line_break.rb +25 -0
- data/lib/kramdown/parser/kramdown/link.rb +139 -0
- data/lib/kramdown/parser/kramdown/list.rb +256 -0
- data/lib/kramdown/parser/kramdown/math.rb +54 -0
- data/lib/kramdown/parser/kramdown/paragraph.rb +54 -0
- data/lib/kramdown/parser/kramdown/smart_quotes.rb +174 -0
- data/lib/kramdown/parser/kramdown/table.rb +171 -0
- data/lib/kramdown/parser/kramdown/typographic_symbol.rb +44 -0
- data/lib/kramdown/parser/kramdown.rb +359 -0
- data/lib/kramdown/parser/markdown.rb +56 -0
- data/lib/kramdown/parser.rb +27 -0
- data/lib/kramdown/utils/configurable.rb +44 -0
- data/lib/kramdown/utils/entities.rb +347 -0
- data/lib/kramdown/utils/html.rb +75 -0
- data/lib/kramdown/utils/ordered_hash.rb +87 -0
- data/lib/kramdown/utils/string_scanner.rb +74 -0
- data/lib/kramdown/utils/unidecoder.rb +51 -0
- data/lib/kramdown/utils.rb +58 -0
- data/lib/kramdown/version.rb +15 -0
- data/lib/kramdown.rb +10 -0
- data/lib/motion-kramdown.rb +47 -0
- data/lib/rubymotion/encodings.rb +37 -0
- data/lib/rubymotion/rexml_shim.rb +25 -0
- data/lib/rubymotion/set.rb +1349 -0
- data/lib/rubymotion/version.rb +6 -0
- data/spec/document_tree.rb +48 -0
- data/spec/gfm_to_html.rb +95 -0
- data/spec/helpers/it_behaves_like.rb +27 -0
- data/spec/helpers/option_file.rb +46 -0
- data/spec/helpers/spec_options.rb +37 -0
- data/spec/helpers/tidy.rb +12 -0
- data/spec/html_to_html.rb +40 -0
- data/spec/html_to_kramdown_to_html.rb +46 -0
- data/spec/kramdown_to_xxx.rb +40 -0
- data/spec/test_location.rb +203 -0
- data/spec/test_string_scanner_kramdown.rb +19 -0
- data/spec/text_to_kramdown_to_html.rb +52 -0
- data/spec/text_to_latex.rb +33 -0
- 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
|