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
more...

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

[View source]

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

[View source]

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

[View source]

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)

[View source]

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

[View source]

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

[View source]

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

[View source]

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

def to_latex
  children_to_latex
end

#to_latex_abbrObject

[View source]

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

def to_latex_abbr
  children_to_latex
end

#to_latex_cellObject

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

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

#to_latex_entityObject

[View source]

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

[View source]

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

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

#to_latex_equationObject

[View source]

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

[View source]

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

[View source]

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

def to_latex_head_cell
  to_latex_cell
end

#to_latex_headerObject

[View source]

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

[View source]

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

def to_latex_hrule
  "\n\\vspace{.5em} \\hrule \\vspace{.5em}\n"
end
[View source]

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

[View source]

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
[View source]

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

[View source]

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

[View source]

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

[View source]

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

[View source]

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

def to_latex_linebreak
  "\\newline "
end
[View source]

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

[View source]

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

def to_latex_ol
  wrap_as_environment('enumerate')
end

#to_latex_paragraphObject

[View source]

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

[View source]

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

[View source]

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

[View source]

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

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

#to_latex_tableObject

[View source]

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

[View source]

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

[View source]

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

[View source]

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

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