Module: MaRuKu::Out::Latex

Included in:
MDElement
Defined in:
lib/maruku.rb,
lib/maruku/output/to_latex.rb,
lib/maruku/ext/math/to_latex.rb

Defined Under Namespace

Modules: MDDocumentExtensions

Constant Summary collapse

Latex_preamble_enc_cjk =
"\\usepackage[C40]{fontenc}
\\usepackage[cjkjis]{ucs}
\\usepackage[utf8x]{inputenc}"
Latex_preamble_enc_utf8 =
"\\usepackage{ucs}
\\usepackage[utf8x]{inputenc}"
SAFE_CHARS =
Set.new(('a'..'z').to_a + ('A'..'Z').to_a)
LATEX_ADD_SLASH =

These are TeX’s special characters

%w({ } $ & # _ %)
LATEX_TO_CHARCODE =

These, we transform to char<ascii code>

%w(^ ~ > <)
OtherGoodies =

other things that are good on the eyes

{
  /(\s)LaTeX/ => '\1\\LaTeX\\xspace ', # XXX not if already \LaTeX
}

Instance Method Summary collapse

Instance Method Details

#array_to_latex(array, join_char = '') ⇒ Object



532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
# File 'lib/maruku/output/to_latex.rb', line 532

def array_to_latex(array, join_char='')
  e = []
  array.each do |c|
    if c.kind_of?(String)
      e << string_to_latex(c)
    else method = c.kind_of?(Maruku::MDElement) ? "to_latex_#{c.node_type}" : "to_latex"
      next unless c.respond_to?(method)

      h =  c.send(method)

      unless h
        raise "Nil latex for #{c.inspect} created with method #{method}"
      end

      if h.kind_of? Array
        e.concat h
      else
        e << h
      end
    end
  end
  e.join(join_char)
end

#children_to_latexObject

Convert each child to html



528
529
530
# File 'lib/maruku/output/to_latex.rb', line 528

def children_to_latex
  array_to_latex(@children)
end

#latex_color(s, command = 'color') ⇒ Object

colorname colorMaRuKu::Out::Latex.1,01,0.2,01,0.2,0.3



162
163
164
165
166
167
168
169
170
# File 'lib/maruku/output/to_latex.rb', line 162

def latex_color(s, command='color')
  if s =~ /\A\#([1-9A-F]{1,2})([1-9A-F]{1,2})([1-9A-F]{1,2})\z/i
    # convert from 0-255 or 0-15 to 0.0-1.0
    r, g, b = [$1, $2, $3].map {|c| c.hex / (c.length == 1 ? 15.0 : 255.0) }
    "\\#{command}[rgb]{%0.2f,%0.2f,%0.2f}" % [r, g, b]
  else
    "\\#{command}{#{s}}"
  end
end

#latex_escape(source) ⇒ Object

the ultimate escaping (is much better than using verb)



319
320
321
322
323
324
325
326
327
328
329
# File 'lib/maruku/output/to_latex.rb', line 319

def latex_escape(source)
  source.chars.inject('') do |s, b|
    s << if b == '\\'
           '~'
         elsif SAFE_CHARS.include? b
           b
         else
           "\\char%d" % b[0].ord
         end
  end
end

#render_latex_signatureObject



127
128
129
130
131
132
133
134
# File 'lib/maruku/output/to_latex.rb', line 127

def render_latex_signature
  "\\vfill
\\hrule
\\vspace{1.2mm}
\\begin{tiny}
Created by \\href{#{MaRuKu::MARUKU_URL}}{Maruku} #{self.nice_date}.
\\end{tiny}"
end

#string_to_latex(s) ⇒ Object

escapes special characters



563
564
565
566
567
568
569
# File 'lib/maruku/output/to_latex.rb', line 563

def string_to_latex(s)
  s = escape_to_latex(s)
  OtherGoodies.each do |k, v|
    s.gsub!(k, v)
  end
  s
end

#to_latexObject

Render as a LaTeX fragment



29
30
31
# File 'lib/maruku/output/to_latex.rb', line 29

def to_latex
  children_to_latex
end

#to_latex_abbrObject



484
485
486
# File 'lib/maruku/output/to_latex.rb', line 484

def to_latex_abbr
  children_to_latex
end

#to_latex_cellObject



439
440
441
442
443
444
445
446
447
# File 'lib/maruku/output/to_latex.rb', line 439

def to_latex_cell
  s=""
  if @attributes.has_key?(:colspan)
    # TODO figure out how to set the alignment (defaulting to left for now)
    s="\\multicolumn {"<< @attributes[:colspan]<<"}{|l|}{"<<children_to_latex<<"}"
  else
    children_to_latex
  end
end

#to_latex_citationObject



24
25
26
# File 'lib/maruku/ext/math/to_latex.rb', line 24

def to_latex_citation
  "\\cite{#{self.cites.join(',')}}"
end

#to_latex_codeObject

begin maruku_doc

Attribute: latex_use_listings Scope: document Output: latex Summary: Support for ‘listings` package. Related: code_show_spaces, code_background_color, lang, code_lang

If the ‘latex_use_listings` attribute is specified, then code block are rendered using the `listings` package. Otherwise, a standard `verbatim` environment is used.

  • If the ‘lang` attribute for the code block has been specified, it gets passed to the `listings` package using the `lstset` macro. The default lang for code blocks is specified through the `code_lang` attribute.

    \lstset{language=ruby}
    

    Please refer to the documentation of the ‘listings` package for supported languages.

    If a language is not supported, the ‘listings` package will emit a warning during the compilation. Just press enter and nothing wrong will happen.

  • If the ‘code_show_spaces` is specified, than spaces and tabs will be shown using the macro:

    \lstset{showspaces=true,showtabs=true}
    
  • The background color is given by ‘code_background_color`.

end



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/maruku/output/to_latex.rb', line 231

def to_latex_code
  if get_setting(:latex_use_listings)
    @doc.latex_require_package('listings')

    s = "\\lstset{columns=fixed,frame=shadowbox}"

    if get_setting(:code_show_spaces)
      s << "\\lstset{showspaces=true,showtabs=true}\n"
    else
      s << "\\lstset{showspaces=false,showtabs=false}\n"
    end

    color = latex_color get_setting(:code_background_color)

    s << "\\lstset{backgroundcolor=#{color}}\n"

    s << "\\lstset{basicstyle=\\ttfamily\\footnotesize}\n"


    lang = self.attributes[:lang] || @doc.attributes[:code_lang] || '{}'
    s << "\\lstset{language=#{lang}}\n" if lang

    "#{s}\n\\begin{lstlisting}\n#{self.raw_code}\n\\end{lstlisting}"
  else
    "\\begin{verbatim}#{self.raw_code}\\end{verbatim}\n"
  end
end

#to_latex_definitionObject



470
471
472
473
474
475
476
477
478
479
480
481
482
# File 'lib/maruku/output/to_latex.rb', line 470

def to_latex_definition
  s = ""

  self.terms.each do |t|
    s << "\n\\item[#{t.children_to_latex}] "
  end

  self.definitions.each do |d|
    s << "#{d.children_to_latex} \n"
  end

  s
end

#to_latex_definition_listObject

Definition lists ###



464
465
466
467
468
# File 'lib/maruku/output/to_latex.rb', line 464

def to_latex_definition_list
  s = "\\begin{description}\n"
  s << children_to_latex
  s << "\\end{description}\n"
end

#to_latex_divObject



502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
# File 'lib/maruku/output/to_latex.rb', line 502

def to_latex_div
  type = self.attributes[:class]
  id = self.attributes[:id]
  case type
  when /^un_(\w*)/
    @children.shift
    s = "\\begin{u#{$1}}\n"
    s << children_to_latex
    s << "\\end{u#{$1}}\n"
  when /^num_(\w*)/
    @children.delete_at(0)
    s = "\\begin{#{$1}}"
    s << "\n\\label{#{id}}\\hypertarget{#{id}}{}\n"
    s << children_to_latex
    s << "\\end{#{$1}}\n"
  when /^proof/
    @children.delete_at(0)
    s = "\\begin{proof}\n"
    s << children_to_latex
    s << "\\end{proof}\n"
  else
    children_to_latex
  end
end

#to_latex_divrefObject



20
21
22
# File 'lib/maruku/ext/math/to_latex.rb', line 20

def to_latex_divref
  "\\ref{#{self.refid}}"
end

#to_latex_documentObject

Render as a complete LaTeX document



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/maruku/output/to_latex.rb', line 45

def to_latex_document
  body = to_latex

  if get_setting(:maruku_signature)
    body << render_latex_signature
  end

  required = self.latex_required_packages.map do |p|
    "\\usepackage{#{p}}\n"
  end.join

  #=begin maruku_doc
  # Attribute: latex_cjk
  # Scope:     document
  # Output:    latex
  # Summary:   Support for CJK characters.
  #
  # If the `latex_cjk` attribute is specified, then appropriate headers
  # are added to the LaTeX preamble to support Japanese fonts.
  # You have to have these fonts installed -- and this can be a pain.
  #
  # If `latex_cjk` is specified, this is added to the preamble:
  #
  # <?mrk puts "ciao" ?>
  #
  # <?mrk md_codeblock(Maruku::MDDocument::Latex_preamble_enc_cjk) ?>
  #
  #
  # while the default is to add this:
  #
  # <?mrk md_codeblock(Maruku::MDDocument::Latex_preamble_enc_utf8) ?>
  #
  #=end

  encoding = get_setting(:latex_cjk) ? Latex_preamble_enc_cjk : Latex_preamble_enc_utf8

  #=begin maruku_doc
  # Attribute: latex_preamble
  # Scope:     document
  # Output:    latex
  # Summary:   User-defined preamble.
  #
  # If the `latex_preamble` attribute is specified, then its value
  # will be used as a custom preamble.
  #
  # For example:
  #
  #   Title: My document
  #   Latex preamble: preamble.tex
  #
  # will produce:
  #
  #   ...
  #   \input{preamble.tex}
  #   ...
  #
  #=end

  user_preamble = (file = @doc.attributes[:latex_preamble]) ? "\\input{#{file}}\n" : ""

  "\\documentclass{article}

% Packages required to support encoding
#{encoding}

% Packages required by code
#{required}

% Packages always used
\\usepackage{hyperref}
\\usepackage{xspace}
\\usepackage[usenames,dvipsnames]{color}
\\hypersetup{colorlinks=true,urlcolor=blue}

#{user_preamble}

\\begin{document}
#{body}
\\end{document}
"
end

#to_latex_email_addressObject



406
407
408
# File 'lib/maruku/output/to_latex.rb', line 406

def to_latex_email_address
  "\\href{mailto:#{self.email}}{#{latex_escape(self.email)}}"
end

#to_latex_emphasisObject



301
302
303
# File 'lib/maruku/output/to_latex.rb', line 301

def to_latex_emphasis
  "\\emph{#{children_to_latex}}"
end

#to_latex_entityObject



331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'lib/maruku/output/to_latex.rb', line 331

def to_latex_entity
  entity_name = self.entity_name

  entity = MaRuKu::Out::EntityTable.instance.entity(entity_name)
  unless entity
    maruku_error "I don't know how to translate entity '#{entity_name}' to LaTeX."
    return ""
  end

  replace = entity.latex_string
  @doc.latex_require_package entity.latex_package if entity.latex_package

  if replace
    if replace.start_with?("\\") && !replace.end_with?('$', '}')
      replace + "{}"
    else
      replace
    end
  else
    tell_user "Cannot translate entity #{entity_name.inspect} to LaTeX."
    entity_name
  end
end

#to_latex_eqrefObject



16
17
18
# File 'lib/maruku/ext/math/to_latex.rb', line 16

def to_latex_eqref
  "\\eqref{#{self.eqid}}"
end

#to_latex_equationObject



8
9
10
11
12
13
14
# File 'lib/maruku/ext/math/to_latex.rb', line 8

def to_latex_equation
  if self.label
    fix_latex("\\begin{equation}\n#{self.math.strip}\n\\label{#{self.label}}\\end{equation}\n")
  else
    fix_latex("\\begin{displaymath}\n#{self.math.strip}\n\\end{displaymath}\n")
  end
end

#to_latex_footnote_referenceObject



449
450
451
452
453
454
455
456
# File 'lib/maruku/output/to_latex.rb', line 449

def to_latex_footnote_reference
  id = self.footnote_id
  if f = @doc.footnotes[id]
    "\\footnote{#{f.children_to_latex.strip}} "
  else
    $stderr.puts "Could not find footnote '#{id}'"
  end
end

#to_latex_head_cellObject



435
436
437
# File 'lib/maruku/output/to_latex.rb', line 435

def to_latex_head_cell
  to_latex_cell
end

#to_latex_headerObject



259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/maruku/output/to_latex.rb', line 259

def to_latex_header
  header_levels = %w(section subsection subsubsection)
  h = header_levels[self.level - 1] || 'paragraph'

  title = children_to_latex
  if number = section_number
    title = number + title
  end

  if id = self.attributes[:id]
    # drop '#' at the beginning
    id = id[1..-1] if id.start_with? '#'
    %{\\hypertarget{%s}{}\\%s*{{%s}}\\label{%s}\n\n} % [ id, h, title, id ]
  else
    %{\\%s*{%s}\n\n} % [ h, title]
  end
end

#to_latex_hruleObject



136
137
138
# File 'lib/maruku/output/to_latex.rb', line 136

def to_latex_hrule
  "\n\\vspace{.5em} \\hrule \\vspace{.5em}\n"
end


377
378
379
380
381
382
383
384
385
386
# File 'lib/maruku/output/to_latex.rb', line 377

def to_latex_im_link
  url = self.url

  if url.start_with? '#'
    url = url[1..-1]
    "\\hyperlink{#{url}}{#{children_to_latex}}"
  else
    "\\href{#{url}}{#{children_to_latex}}"
  end
end

#to_latex_imageObject



488
489
490
491
492
493
494
495
496
497
498
499
500
# File 'lib/maruku/output/to_latex.rb', line 488

def to_latex_image
  id = self.ref_id
  ref = @doc.refs[sanitize_ref_id(id)] || @doc.refs[sanitize_ref_id(children_to_s)]
  if ref
    url = ref[:url]
    $stderr.puts "Images not supported yet (#{url})"
    ""
  else
    maruku_error "Could not find ref #{id.inspect} for image.\n"+
      "Available are: #{@docs.refs.keys.inspect}"
    ""
  end
end


365
366
367
368
369
370
371
372
373
374
375
# File 'lib/maruku/output/to_latex.rb', line 365

def to_latex_immediate_link
  url = self.url
  text = url.gsub(/^mailto:/,'') # don't show mailto
  text = latex_escape(text)
  if url.start_with? '#'
    url = url[1..-1]
    "\\hyperlink{#{url}}{#{text}}"
  else
    "\\href{#{url}}{#{text}}"
  end
end

#to_latex_inline_codeObject



355
356
357
358
359
360
361
362
363
# File 'lib/maruku/output/to_latex.rb', line 355

def to_latex_inline_code
  # Convert to printable latex chars
  s = latex_escape(self.raw_code)

  color = get_setting(:code_background_color)
  colorspec = latex_color(color, 'colorbox')

  "{#{colorspec}{\\tt #{s}}}"
end

#to_latex_inline_mathObject



4
5
6
# File 'lib/maruku/ext/math/to_latex.rb', line 4

def to_latex_inline_math
  fix_latex("$#{self.math.strip}$")
end

#to_latex_liObject



293
294
295
# File 'lib/maruku/output/to_latex.rb', line 293

def to_latex_li
  "\\item #{children_to_latex}\n"
end

#to_latex_linebreakObject



140
141
142
# File 'lib/maruku/output/to_latex.rb', line 140

def to_latex_linebreak
  "\\newline "
end


388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/maruku/output/to_latex.rb', line 388

def to_latex_link
  id = self.ref_id || children_to_s
  ref = @doc.refs[sanitize_ref_id(id)] || @doc.refs[sanitize_ref_id(children_to_s)]
  if ref
    url = ref[:url]

    if url.start_with? '#'
      url = url[1..-1]
      "\\hyperlink{#{url}}{#{children_to_latex}}"
    else
      "\\href{#{url}}{#{children_to_latex}}"
    end
  else
    $stderr.puts "Could not find id = '#{id}'"
    children_to_latex
  end
end

#to_latex_olObject



289
290
291
# File 'lib/maruku/output/to_latex.rb', line 289

def to_latex_ol
  wrap_as_environment('enumerate')
end

#to_latex_paragraphObject



144
145
146
# File 'lib/maruku/output/to_latex.rb', line 144

def to_latex_paragraph
  children_to_latex + "\n\n"
end

#to_latex_quoteObject



285
286
287
# File 'lib/maruku/output/to_latex.rb', line 285

def to_latex_quote
  wrap_as_environment('quote')
end

#to_latex_raw_htmlObject



458
459
460
461
# File 'lib/maruku/output/to_latex.rb', line 458

def to_latex_raw_html
  # Raw HTML removed in latex version
  ""
end

#to_latex_strongObject



297
298
299
# File 'lib/maruku/output/to_latex.rb', line 297

def to_latex_strong
  "\\textbf{#{children_to_latex}}"
end

#to_latex_tableObject



410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
# File 'lib/maruku/output/to_latex.rb', line 410

def to_latex_table
  num_columns = self.align.size

  head, *rows = @children

  h = { :center => 'c' , :left => 'l' , :right => 'r'}
  align_string = self.align.map {|a| h[a] }.join('|')

  s = "\\begin{tabular}{#{align_string}}\n"

  s << array_to_latex(head, '&') + "\\\\" + "\n"

  s << "\\hline \n"

  rows.each do |row|
    s << array_to_latex(row, '&') + "\\\\" + "\n"
  end

  s << "\\end{tabular}"

  # puts table in its own paragraph
  s << "\n\n"
end

#to_latex_ulObject



277
278
279
280
281
282
283
# File 'lib/maruku/output/to_latex.rb', line 277

def to_latex_ul
  if self.attributes[:toc]
    @doc.toc.to_latex
  else
    wrap_as_environment('itemize')
  end
end

#wrap_as_environment(name) ⇒ Object



309
310
311
312
313
# File 'lib/maruku/output/to_latex.rb', line 309

def wrap_as_environment(name)
  "\\begin{#{name}}%
#{children_to_latex}
\\end{#{name}}\n"
end

#wrap_as_span(c) ⇒ Object



305
306
307
# File 'lib/maruku/output/to_latex.rb', line 305

def wrap_as_span(c)
  "{#{c} #{children_to_latex}}"
end