maruku 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,7 +22,10 @@ if File.basename($0) =~ /^marutex/
22
22
 
23
23
  File.open(filename,'w') do |f| f.puts latex end
24
24
 
25
+ # run twice for cross references
25
26
  system "pdflatex '#{job}'"
27
+ system "pdflatex '#{job}'"
28
+
26
29
  # system "open #{job}.pdf"
27
30
  end
28
31
  end
@@ -1,6 +1,8 @@
1
- CSS: style.css
1
+ css: style.css
2
2
  latex_use_listings: true
3
3
  html_use_syntax: true
4
+ use_numbered_headers: true
5
+
4
6
 
5
7
  Markdown: Syntax
6
8
  ================
@@ -14,28 +16,18 @@ This copy is translated using [Maruku][].
14
16
  [Here](http://daringfireball.net/projects/markdown/syntax) you can find
15
17
  the original by `Markdown.pl`.
16
18
 
19
+ > [This document in Markdown](http://maruku.rubyforge.org/markdown_syntax.md)
20
+ >
21
+ > [This document in HTML](http://maruku.rubyforge.org/markdown_syntax.html)
22
+ >
23
+ > [This document in PDF](http://maruku.rubyforge.org/markdown_syntax.pdf)
24
+
25
+
26
+ Table of contents: (**auto-generated by Maruku!**)
27
+
28
+ @toc
17
29
 
18
- @ class: toc
19
-
20
- * [Overview](#overview)
21
- * [Philosophy](#philosophy)
22
- * [Inline HTML](#html)
23
- * [Automatic Escaping for Special Characters](#autoescape)
24
- * [Block Elements](#block)
25
- * [Paragraphs and Line Breaks](#p)
26
- * [Headers](#header)
27
- * [Blockquotes](#blockquote)
28
- * [Lists](#list)
29
- * [Code Blocks](#precode)
30
- * [Horizontal Rules](#hr)
31
- * [Span Elements](#span)
32
- * [Links](#link)
33
- * [Emphasis](#em)
34
- * [Code](#code)
35
- * [Images](#img)
36
- * [Miscellaneous](#misc)
37
- * [Backslash Escapes](#backslash)
38
- * [Automatic Links](#autolink)
30
+ * This list will contain the toc (it doesn't matter what you write here)
39
31
 
40
32
 
41
33
 
@@ -1,7 +1,7 @@
1
- Title: Maruku, a Markdown interpreter
2
1
  CSS: style.css
3
- latex_use_listings: true
2
+ LaTeX_use_listings: true
4
3
  html_use_syntax: true
4
+ use_numbered_headers: true
5
5
 
6
6
  Mar**u**k**u**: a Markdown interpreter
7
7
  ======================================
@@ -18,18 +18,26 @@ Then it can be translated to HTML:
18
18
 
19
19
  > [This document in HTML](http://maruku.rubyforge.org/maruku.html)
20
20
 
21
- or Latex, which is then converted to PDF:
21
+ or LaTeX, which is then converted to PDF:
22
22
 
23
23
  > [This document in PDF](http://maruku.rubyforge.org/maruku.pdf)
24
24
 
25
- Maruku implements the original [Markdown syntax][]
25
+ Maruku implements:
26
+
27
+ * the original [Markdown syntax][]
26
28
  ([HTML](http://maruku.rubyforge.org/markdown_syntax.html) or
27
29
  [PDF](http://maruku.rubyforge.org/markdown_syntax.pdf), translated by Maruku).
28
30
 
29
- Markdown implements also all the improvements
30
- in [PHP Markdown Extra][].
31
+ * all the improvements in [PHP Markdown Extra][].
32
+
33
+ * a new [meta-data syntax](#meta)
34
+
35
+ * some ideas from [MultiMarkdown][]
36
+ * attributes in image links
31
37
 
32
- Moreover, it implements ideas from [MultiMarkdown][].
38
+ The [test directory][tests] is quite messy but it shows every capability.
39
+
40
+ [tests]: http://maruku.rubyforge.org/tests/
33
41
 
34
42
  ### Authors ###
35
43
 
@@ -40,17 +48,11 @@ Contributors are most welcome!
40
48
 
41
49
  * * *
42
50
 
43
- *Table of contents*:
51
+ Table of contents: (**auto-generated by Maruku!**)
52
+
53
+ @toc
44
54
 
45
- * [Download](#download)
46
- * [Usage](#usage)
47
- * [Examples of PHP Markdown extra syntax](#extra)
48
- * [New metadata syntax](#meta)
49
- * [List of metadata](#metalist)
50
- * [Maruku and Bluecloth](#maruku-and-bluecloth)
51
- * [Future developments](#future)
52
- * [Export to other formats](#future-export)
53
- * [Syntax additions](#future-syntax)
55
+ * This list will contain the toc (it doesn't matter what you write here)
54
56
 
55
57
  * * *
56
58
 
@@ -61,7 +63,6 @@ Download {#download}
61
63
 
62
64
  The development site is <http://rubyforge.org/projects/maruku/>.
63
65
 
64
-
65
66
  Install with:
66
67
 
67
68
  $ gem install maruku
@@ -95,7 +96,7 @@ This is the basic usage:
95
96
  doc = Maruku.new(markdown_string)
96
97
  puts doc.to_html
97
98
 
98
- The method `to_html` outputs only an HTML fragment, while the method `to_html_document` output a complete XHTML 1.0 document:
99
+ The method `to_html` outputs only an HTML fragment, while the method `to_html_document` outputs a complete XHTML 1.0 document:
99
100
 
100
101
  @ lang: ruby
101
102
 
@@ -109,16 +110,16 @@ You can have the REXML document tree with:
109
110
 
110
111
  ### From the command line ###
111
112
 
112
- There are two command-line programs installed: `maruku` and `marutex`
113
+ There are two command-line programs installed: `maruku` and `marutex`.
113
114
 
114
- `maruku` converts Markdown in HTML:
115
+ * `maruku` converts Markdown to HTML:
115
116
 
116
- $ maruku file.md # creates file.html
117
+ $ maruku file.md # creates file.html
117
118
 
118
- `marutex` converts Markdown in TeX, then calls `pdflatex` to
119
+ * `marutex` converts Markdown to TeX, then calls `pdfLaTeX` to
119
120
  transform to PDF:
120
121
 
121
- $ marutex file.md # creates file.tex and file.pdf
122
+ $ marutex file.md # creates file.tex and file.pdf
122
123
 
123
124
 
124
125
  Examples of PHP Markdown Extra syntax {#extra}
@@ -159,9 +160,14 @@ Examples of PHP Markdown Extra syntax {#extra}
159
160
 
160
161
 
161
162
  * header ids
162
- ## Header ## {#id}
163
+ ## Download ## {#download}
163
164
  For example, [a link to the download](#download) header.
164
165
 
166
+ Note that you can use also the new [meta-data syntax](#meta) for the same purpose:
167
+
168
+ @ id: download
169
+ ## Header ##
170
+
165
171
  * definition lists
166
172
 
167
173
  Definition list
@@ -172,7 +178,7 @@ Examples of PHP Markdown Extra syntax {#extra}
172
178
 
173
179
  * abbreviations or ABB for short.
174
180
 
175
- *[ABB]: Simple an abbreviation
181
+ *[ABB]: Simply an abbreviation
176
182
 
177
183
 
178
184
 
@@ -258,7 +264,7 @@ You can add more by separating with a `;`:
258
264
  A meta-data declaration is composed of
259
265
 
260
266
  1. newline
261
- 2. an at-symbol '@'
267
+ 2. an at-symbol `@`
262
268
  3. a series of name-value pairs. Each name-value is separated
263
269
  by a colon `:`, pairs are separated by semi-colons `;`
264
270
 
@@ -280,26 +286,34 @@ Also, if the value is not present, it defaults to `true`:
280
286
 
281
287
  @ test
282
288
 
283
- This paragraph has the attribute 'test' set.
289
+ This paragraph has the attribute `test` set to `true`.
290
+
291
+
292
+
284
293
 
285
294
  * * *
286
295
 
287
- List of meta-data {#metalist}
288
- -----------------
289
296
 
290
297
 
291
298
 
299
+ ### List of meta-data ### {#metalist}
300
+
292
301
  **`title`, `subject`**
293
302
  : (document) Sets the title of the document (HTML: used in the `TITLE` element).
294
303
 
304
+ **`use_numbered_headers`**
305
+ : (document) If `true`, headers are numbered (just like this document). Default is `false`.
306
+
295
307
  **`css`**
296
308
  : (document, HTML) Url of stylesheet.
297
309
 
298
310
  **`html_use_syntax`**
299
- : (document, HTML) Use the [`syntax` library][syntax] to add source highlighting.
311
+ : (document, HTML) If set, use the [`syntax` library][syntax] to add source highlighting.
300
312
 
301
313
  **`latex_use_listings`**
302
- : (document, LaTex) Use fancy `listing` package for better displaying code blocks.
314
+ : (document, LaTeX) If set, use fancy `listing` package for better displaying code blocks.
315
+
316
+ If not set, use standard `verbatim` environment.
303
317
 
304
318
  **`style`, `id`, `class`**
305
319
  : (any block object, HTML) Standard CSS attributes are copied.
@@ -322,7 +336,7 @@ List of meta-data {#metalist}
322
336
  property of the block.
323
337
 
324
338
  * for **LaTeX output**, if it is a named color, it must be a color accepted
325
- by the latex `color` packages. If it is of the form `#ff00ff`, Maruku
339
+ by the LaTeX `color` packages. If it is of the form `#ff00ff`, Maruku
326
340
  defines a color using the `\color[rgb]{r,g,b}` macro.
327
341
 
328
342
  For example, for `#0000ff`, the macro is called as: `\color[rgb]{0,0,1}`.
@@ -374,8 +388,41 @@ produces:
374
388
  @ lang: xml
375
389
  <div style="text-align:center">Div</div>
376
390
 
391
+
392
+
377
393
  * * *
378
394
 
395
+ Other Features
396
+ --------------
397
+
398
+ ### Automatic generation of the table of contents ###
399
+
400
+ If you create a list, and the set the `toc` attribute, when rendering
401
+ Maruku will create an auto-generated table of contents.
402
+
403
+ @ toc
404
+ * This will become a table of contents
405
+
406
+ You can see an example of this at the beginning of this document.
407
+
408
+ ### This header contains *emphasis* **strong text** and `code` ####
409
+
410
+ Note that this header contains formatting and it still works, also
411
+ in the table of contents.
412
+
413
+ TODO list
414
+ --------------------------
415
+
416
+
417
+ * Export to HTML
418
+ * Include RubyPants
419
+
420
+ * Export to PDF
421
+ * support for images
422
+
423
+ * Export to Markdown (pretty-printing)
424
+
425
+
379
426
  Future developments {#future}
380
427
  -------------------
381
428
 
@@ -384,6 +431,9 @@ However, they are written in Haskell and Perl, respectively.
384
431
  I would love to have an equivalent in Ruby.
385
432
 
386
433
 
434
+ [Pandoc]: http://sophos.berkeley.edu/macfarlane/pandoc/
435
+ [MultiMarkdown]: http://fletcher.freeshell.org/wiki/MultiMarkdown
436
+
387
437
  ### Syntax improvements ### {#future-syntax}
388
438
 
389
439
  Things I'm thinking about:
@@ -404,7 +454,3 @@ Things I'm thinking about:
404
454
  This is a reference to equation: please see (eq:1)
405
455
 
406
456
 
407
-
408
- [Pandoc]: http://sophos.berkeley.edu/macfarlane/pandoc/
409
- [MultiMarkdown]: http://fletcher.freeshell.org/wiki/MultiMarkdown
410
-
@@ -1,3 +1,9 @@
1
1
 
2
- * include RubyPants
2
+ * Export to HTML
3
+ * Include RubyPants
4
+
5
+ * Export to PDF
6
+ * support for images
7
+
8
+ * Export to Markdown (pretty-printing)
3
9
 
@@ -11,6 +11,9 @@ require 'maruku/parse_span'
11
11
  # Ugly things kept in a closet
12
12
  require 'maruku/string_utils'
13
13
 
14
+ # Code for creating a table of contents
15
+ require 'maruku/toc'
16
+
14
17
 
15
18
  # Exporting to html
16
19
  require 'maruku/to_html'
@@ -18,3 +21,6 @@ require 'maruku/to_html'
18
21
  # Exporting to latex
19
22
  require 'maruku/to_latex'
20
23
  require 'maruku/to_latex_strings'
24
+
25
+ # Exporting to text: strips all formatting (not complete)
26
+ require 'maruku/to_s'
@@ -21,6 +21,20 @@ class Maruku
21
21
 
22
22
  self.search_abbreviations
23
23
  self.substitute_markdown_inside_raw_html
24
+
25
+ toc = create_toc
26
+
27
+ # use title if not set
28
+ if not self.meta[:title] and toc.header_element
29
+ title = toc.header_element.to_s
30
+ self.meta[:title] = title
31
+ puts "Set document title to #{title}"
32
+ end
33
+
34
+ # save for later use
35
+ self.toc = toc
36
+
37
+ #puts toc.inspect
24
38
  end
25
39
 
26
40
  def search_abbreviations
@@ -91,18 +105,9 @@ class Maruku
91
105
  (next_line && next_line =~ TableSeparator)
92
106
  output << read_table
93
107
  elsif [:header1,:header2].include? next_line_node_type
94
- e = create_md_element(:header)
95
- line = shift_line.strip
96
- if line =~ HeaderWithId
97
- line = $1.strip
98
- e.meta[:id] = $2
99
- end
100
- e.children = parse_lines_as_span [ line ]
101
-
102
- e.meta[:level] = cur_line_node_type == :header2 ? 2 : 1
103
- shift_line
104
-
105
- output << e
108
+ output << read_header12
109
+
110
+
106
111
  elsif eventually_comes_a_def_list
107
112
  definition = read_definition
108
113
  if output.last && output.last.node_type == :definition_list
@@ -119,16 +124,7 @@ class Maruku
119
124
  shift_line
120
125
  output << create_md_element(:hrule)
121
126
  when :header3
122
- e = create_md_element(:header)
123
- line = shift_line.strip
124
- if line =~ HeaderWithId
125
- line = $1.strip
126
- e.meta[:id] = $2
127
- end
128
-
129
- e.meta[:level] = num_leading_hashes(line)
130
- e.children = parse_lines_as_span [strip_hashes(line)]
131
- output << e
127
+ output << read_header3
132
128
  when :ulist, :olist
133
129
  list_type = cur_line_node_type == :ulist ? :ul : :ol
134
130
  li = read_list_item
@@ -205,6 +201,43 @@ class Maruku
205
201
  def next_line; top.empty? ? nil : top[1] end
206
202
  def next_line_node_type; (top.size >= 2) ? line_node_type(top[1]) : nil end
207
203
  def shift_line; top.shift; end
204
+
205
+ # reads a header (with ----- or ========)
206
+ def read_header12
207
+ e = create_md_element(:header)
208
+ line = shift_line.strip
209
+ if line =~ HeaderWithId
210
+ line = $1.strip
211
+ e.meta[:id] = $2
212
+ end
213
+ e.children = parse_lines_as_span [ line ]
214
+
215
+ e.meta[:level] = cur_line_node_type == :header2 ? 2 : 1
216
+ shift_line
217
+
218
+ # generate an id if one is not provided
219
+ e.meta[:id] = e.generate_id if not e.meta[:id]
220
+
221
+ e
222
+ end
223
+
224
+ # reads a header like '#### header ####'
225
+ def read_header3
226
+ e = create_md_element(:header)
227
+ line = shift_line.strip
228
+ if line =~ HeaderWithId
229
+ line = $1.strip
230
+ e.meta[:id] = $2
231
+ end
232
+
233
+ e.meta[:level] = num_leading_hashes(line)
234
+ e.children = parse_lines_as_span [strip_hashes(line)]
235
+
236
+ # generate an id if one is not provided
237
+ e.meta[:id] = e.generate_id if not e.meta[:id]
238
+
239
+ e
240
+ end
208
241
 
209
242
 
210
243
  def read_raw_html
@@ -413,19 +446,22 @@ class Maruku
413
446
  end
414
447
 
415
448
  # parse one metadata line
449
+ # TODO: read quote-delimited values
416
450
  def parse_metadata(l)
417
451
  hash = {}
418
452
  # remove leading '@'
419
453
  l = l[1, l.size].strip
420
454
  l.split(';').each do |kv|
421
455
  k, v = kv.split(':')
422
- v ||= 'true'
423
- k = k.strip.to_sym
424
- hash[k] = v.strip
456
+ k, v = normalize_key_and_value(k, v)
457
+
458
+ hash[k.to_sym] = v
425
459
  end
426
460
  hash
427
461
  end
428
462
 
463
+
464
+
429
465
  def read_ref
430
466
  line = shift_line
431
467
 
@@ -21,12 +21,27 @@ class Maruku
21
21
  headers = $1
22
22
  headers.split("\n").each do |l|
23
23
  k, v = l.split(':')
24
- keys[k.strip.downcase.to_sym] = v.strip
24
+ k, v = normalize_key_and_value(k, v)
25
+ k = k.to_sym
26
+ # puts "K = #{k}, V=#{v}"
27
+ keys[k] = v
25
28
  end
26
29
  end
27
30
  keys
28
31
  end
29
32
 
33
+ def normalize_key_and_value(k,v)
34
+ v = v ? v.strip : true # no value defaults to true
35
+
36
+ # check synonyms
37
+ v = true if ['yes','true'].include?(v.to_s.downcase)
38
+ v = false if ['no','false'].include?(v.to_s.downcase)
39
+
40
+ k = k.strip.downcase.gsub(' ','_')
41
+
42
+ return k, v
43
+ end
44
+
30
45
  # Returns the number of leading spaces, considering that
31
46
  # a tab counts as `TabSize` spaces.
32
47
  def number_of_leading_spaces(s)
@@ -1,6 +1,6 @@
1
1
 
2
2
  class MDElement
3
- # Allowed: :document, :paragraph, :ul, :ol, :li, :li_span, :strong, :emphasis, :link1
3
+ # Allowed: :document, :paragraph, :ul, :ol, :li, :li_span, :strong, :emphasis, :link
4
4
  attr_accessor :node_type
5
5
  # Children are either Strings or MDElement
6
6
  attr_accessor :children
@@ -22,10 +22,36 @@ class MDElement
22
22
 
23
23
  end
24
24
 
25
- # The Maruku class holds static data for the document
25
+ # The Maruku class represent the whole document
26
+ # and holds global data.
26
27
 
27
28
  class Maruku < MDElement
28
29
  attr_accessor :refs
29
30
  attr_accessor :footnotes
30
31
  attr_accessor :abbreviations
32
+ # an instance of Section (see below)
33
+ attr_accessor :toc
34
+ end
35
+
36
+ class MDElement
37
+ class Section
38
+ attr_accessor :section_level # a Fixnum, is == header_element.meta[:level]
39
+
40
+ # An array of fixnum, like [1,2,5] for Section 1.2.5
41
+ attr_accessor :section_number
42
+
43
+ # reference to header (header has h.meta[:section] to self)
44
+ attr_accessor :header_element
45
+
46
+ # Array of immediate children of this element
47
+ attr_accessor :immediate_children
48
+ # Array of Section inside this section
49
+ attr_accessor :section_children
50
+
51
+
52
+ def initialize
53
+ @immediate_children = []
54
+ @section_children = []
55
+ end
56
+ end
31
57
  end
@@ -82,7 +82,10 @@ class Maruku
82
82
  if @doc.meta[:footnotes_used]
83
83
  body << render_footnotes
84
84
  end
85
-
85
+
86
+ # When we are rendering a whole document, we add a signature
87
+ # at the bottom.
88
+ body << maruku_html_signature
86
89
 
87
90
  root << head
88
91
  root << body
@@ -90,6 +93,40 @@ class Maruku
90
93
  doc
91
94
  end
92
95
 
96
+ # returns "st","nd","rd" or "th" as appropriate
97
+ def day_suffix(day)
98
+ case day%10
99
+ when 1; 'st'
100
+ when 2; 'nd'
101
+ when 3; 'rd'
102
+ else 'th'
103
+ end
104
+ end
105
+
106
+ # formats a nice date
107
+ def nice_date
108
+ t = Time.now
109
+ t.strftime(" at %H:%M on ")+
110
+ t.strftime("%A, %B %d")+
111
+ day_suffix(t.day)+
112
+ t.strftime(", %Y")
113
+ end
114
+
115
+ def maruku_html_signature
116
+ div = Element.new 'div'
117
+ div.attributes['class'] = 'maruku_signature'
118
+ Element.new 'hr', div
119
+ span = Element.new 'span', div
120
+ span.attributes['style'] = 'font-size: small; font-style: italic'
121
+ span << Text.new('Created by ')
122
+ a = Element.new('a', span)
123
+ a.attributes['href'] = 'http://maruku.rubyforge.org'
124
+ a.attributes['title'] = 'Maruku: a Markdown interpreter'
125
+ a << Text.new('Maruku')
126
+ span << Text.new(nice_date+".")
127
+ div
128
+ end
129
+
93
130
  def render_footnotes
94
131
  div = Element.new 'div'
95
132
  div.attributes['class'] = 'footnotes'
@@ -147,14 +184,58 @@ class MDElement
147
184
  end
148
185
 
149
186
  def to_html_paragraph; wrap_as_element('p') end
150
- def to_html_ul; wrap_as_element('ul') end
187
+
188
+ def to_html_ul
189
+ if @meta[:toc]
190
+ # render toc
191
+ html_toc = @doc.toc.to_html
192
+ return html_toc
193
+ else
194
+ wrap_as_element('ul')
195
+ end
196
+ end
197
+
198
+
151
199
  def to_html_ol; wrap_as_element('ol') end
152
200
  def to_html_li; wrap_as_element('li') end
153
201
  def to_html_li_span; wrap_as_element('li') end
154
202
  def to_html_quote; wrap_as_element('blockquote') end
155
203
  def to_html_strong; wrap_as_element('strong') end
156
204
  def to_html_emphasis; wrap_as_element('em') end
157
- def to_html_header; wrap_as_element "h#{@meta[:level]}" end
205
+
206
+ # nil if not applicable, else string
207
+ def section_number
208
+ return nil if not @doc.meta[:use_numbered_headers]
209
+
210
+ if (s = @meta[:section]) and not s.section_number.empty?
211
+ s.section_number.join('.')+". "
212
+ else
213
+ nil
214
+ end
215
+ end
216
+
217
+ # nil if not applicable, else SPAN element
218
+ def render_section_number
219
+ # if we are bound to a section, add section number
220
+ if num = section_number
221
+ span = Element.new 'span'
222
+ span.attributes['class'] = 'maruku_section_number'
223
+ span << Text.new(section_number)
224
+ span
225
+ else
226
+ nil
227
+ end
228
+ end
229
+
230
+ def to_html_header
231
+ element_name = "h#{@meta[:level]}"
232
+ h = wrap_as_element element_name
233
+
234
+ if span = render_section_number
235
+ h.insert_before(h.children.first, span)
236
+ end
237
+ h
238
+ end
158
239
 
159
240
  def source2html(source)
160
241
  source = source.gsub(/&/,'&amp;')
@@ -16,12 +16,9 @@ class Maruku
16
16
  end
17
17
 
18
18
  body = to_latex
19
-
20
- # I found a fix!! :-)
21
- # ## xxx only if `...` is used in footnotes
22
- # header += "\\usepackage{fancyvrb}\n"
23
- # body = "\\VerbatimFootnotes\n"+body
24
19
 
20
+ body += render_latex_signature
21
+
25
22
  "\\documentclass{article}
26
23
 
27
24
  #{header}
@@ -35,6 +32,16 @@ class Maruku
35
32
  \\end{document}
36
33
  "
37
34
  end
35
+
36
+
37
+ def render_latex_signature
38
+ "\\vfill
39
+ \\hrule
40
+ \\vspace{1.2mm}
41
+ \\begin{tiny}
42
+ Created by \\href{http://maruku.rubyforge.org}{Maruku} #{self.nice_date}.
43
+ \\end{tiny}"
44
+ end
38
45
 
39
46
  end
40
47
 
@@ -55,32 +62,6 @@ class MDElement
55
62
  self.meta[name] || @doc.meta[name] || default
56
63
  end
57
64
 
58
- # Returns the name to use and possibly a declaration to append
59
- def define_color_if_necessary(color)
60
- if color =~ /^\#(\w\w)(\w\w)(\w\w)$/
61
- # init colors hash in document
62
- hash = (@doc.meta[:defined_colors] ||= {})
63
- if hash[color] then
64
- return hash[color], nil
65
- else
66
- r = $1.hex; g = $2.hex; b=$3.hex
67
-
68
- colorname = "maruku_color#{hash.size}"
69
-
70
- # convert from 0-255 to 0.0-1.0
71
- r = r / 255.0
72
- g = g / 255.0
73
- b = b / 255.0
74
- declaration = "\\definecolor{#{colorname}}{rgb}{#{r},#{g},#{b}}\n"
75
- hash[color] = colorname
76
-
77
- return colorname, declaration
78
- end
79
- else
80
- color
81
- end
82
- end
83
-
84
65
  # \color[named]{name}
85
66
  # \color[rgb]{1,0.2,0.3}
86
67
  def latex_color(s, command='color')
@@ -137,23 +118,31 @@ class MDElement
137
118
 
138
119
  def to_latex_header
139
120
  h = TexHeaders[@meta[:level]] || 'paragraph'
140
- s =
141
- # \hyperdef{category}{name}{text}
142
-
143
- if @meta[:id]
144
- id = @meta[:id]
121
+
122
+ title = children_to_latex
123
+ if number = section_number
124
+ title = number + title
125
+ end
126
+
127
+ if id = @meta[:id]
128
+ # drop '#' at the beginning
145
129
  if id[0,1] == '#' then id = [1,id.size] end
146
- %{\\hypertarget{%s}{}\\%s*{{%s}}\n\n} % [ id,h, children_to_latex]
147
-
148
- # s + "\\hypertarget{user}{#{id}}{link}"
130
+ %{\\hypertarget{%s}{}\\%s*{{%s}}\\label{%s}\n\n} % [ id, h, title, id ]
149
131
  else
150
- %{\\%s*{%s}\n\n} % [ h, children_to_latex]
132
+ %{\\%s*{%s}\n\n} % [ h, title]
151
133
  end
152
134
  end
153
135
 
154
- def to_latex_quote; wrap_as_environment('quote') end
155
136
 
156
- def to_latex_ul; wrap_as_environment('itemize') end
137
+ def to_latex_ul;
138
+ if @meta[:toc]
139
+ @doc.toc.to_latex
140
+ else
141
+ wrap_as_environment('itemize')
142
+ end
143
+ end
144
+
145
+ def to_latex_quote; wrap_as_environment('quote') end
157
146
  def to_latex_ol; wrap_as_environment('enumerate') end
158
147
  def to_latex_li;
159
148
  "\\item #{children_to_latex}\n"
@@ -203,7 +192,7 @@ class MDElement
203
192
  ref = @doc.refs[id]
204
193
  if not ref
205
194
  $stderr.puts "Could not find id = '#{id}'"
206
- return title.to_latex
195
+ return children_to_latex
207
196
  else
208
197
  url = ref[:url]
209
198
  #title = ref[:title] || 'no title'
@@ -298,8 +287,7 @@ class MDElement
298
287
 
299
288
  s
300
289
  end
301
- # def to_latex_definition_term; "" end
302
- # def to_latex_definition_data; "" end
290
+
303
291
 
304
292
  def to_latex_abbreviation
305
293
  children_to_latex
@@ -2,6 +2,7 @@ require 'rexml/document'
2
2
 
3
3
 
4
4
  class String
5
+
5
6
  # escapes special characters
6
7
  def to_latex
7
8
  s = self
@@ -10,10 +11,20 @@ class String
10
11
  # better yet, we should use the catcode for {}
11
12
  s = String.convert_entities(s)
12
13
  s = s.gsub(/([\$\&\%\#\_])/) { |m| "\\#{m}" }
13
- # s = s.gsub(/([\$\&\%\#\_\{\}])/) { |m| "\\#{m}" }
14
+
15
+ OtherGoodies.each do |k, v|
16
+ s.gsub!(k, v)
17
+ end
14
18
  s
15
19
  end
16
20
 
21
+ # other things that are good on the eyes
22
+ OtherGoodies = {
23
+ 'LaTeX' => '\\LaTeX', # XXX not if already \latex
24
+ 'HTML' => '\\textsc{html}',
25
+ 'PDF' => '\\textsc{pdf}'
26
+ }
27
+
17
28
  def String.convert_entities(s)
18
29
  init_tables
19
30
 
@@ -0,0 +1,22 @@
1
+
2
+
3
+ class MDElement
4
+
5
+ # Strips all formatting from the string
6
+ def to_s
7
+ children_to_s
8
+ end
9
+
10
+ def children_to_s
11
+ @children.join
12
+ end
13
+
14
+ # Generate an id for headers. Assumes @children is set.
15
+ def generate_id
16
+ title = children_to_s
17
+ title.gsub!(/ /,'_')
18
+ title.downcase!
19
+ title.gsub!(/[^\w_]/,'')
20
+ title
21
+ end
22
+ end
@@ -0,0 +1,147 @@
1
+ require 'rexml/document'
2
+
3
+ class MDElement
4
+ class Section
5
+ def inspect(indent=1)
6
+ s = ""
7
+ if @header_element
8
+ s += "\_"*indent + "(#{@section_level})>\t #{@section_number.join('.')} : "
9
+ s += @header_element.children_to_s + " (id: '#{@header_element.meta[:id]}')\n"
10
+ else
11
+ s += "Master\n"
12
+ end
13
+
14
+ @section_children.each do |c|
15
+ s+=c.inspect(indent+1)
16
+ end
17
+ s
18
+ end
19
+
20
+ # Numerate this section and its children
21
+ def numerate(a=[])
22
+ self.section_number = a
23
+ section_children.each_with_index do |c,i|
24
+ c.numerate(a.clone.push(i+1))
25
+ end
26
+ end
27
+
28
+ include REXML
29
+ # Creates an HTML toc.
30
+ # Call this on the root
31
+ def to_html
32
+ div = Element.new 'div'
33
+ div.attributes['class'] = 'maruku_toc'
34
+ div << create_toc
35
+ div
36
+ end
37
+
38
+ def create_toc
39
+ ul = Element.new 'ul'
40
+ # let's remove the bullets
41
+ ul.attributes['style'] = 'list-style: none;'
42
+ @section_children.each do |c|
43
+ li = Element.new 'li'
44
+ if span = c.header_element.render_section_number
45
+ li << span
46
+ end
47
+ a = c.header_element.wrap_as_element('a')
48
+ a.delete_attribute 'id'
49
+ a.attributes['href'] = "##{c.header_element.meta[:id]}"
50
+ li << a
51
+ li << c.create_toc if c.section_children.size>0
52
+ ul << li
53
+ end
54
+ ul
55
+ end
56
+
57
+ # Creates a latex toc.
58
+ # Call this on the root
59
+ def to_latex
60
+ to_latex_rec + "\n\n"
61
+ end
62
+
63
+ def to_latex_rec
64
+ s = ""
65
+ @section_children.each do |c|
66
+ s += "\\noindent"
67
+ number = c.header_element.section_number
68
+ s += number if number
69
+ text = c.header_element.children_to_latex
70
+ id = c.header_element.meta[:id]
71
+ s += "\\hyperlink{#{id}}{#{text}}"
72
+ s += "\\dotfill \\pageref*{#{id}} \\linebreak\n"
73
+ s += c.to_latex_rec if c.section_children.size>0
74
+
75
+ end
76
+ s
77
+ end
78
+
79
+ end
80
+ end
81
+
82
+
83
+ class MDElement
84
+
85
+
86
+ def create_toc
87
+ stack = []
88
+
89
+ # the ancestor section
90
+ s = Section.new
91
+ s.section_level = 0
92
+
93
+ stack.push s
94
+
95
+ i = 0;
96
+ while i < @children.size
97
+
98
+ while i < @children.size
99
+ if @children[i].node_type == :header
100
+ level = @children[i].meta[:level]
101
+ break if level <= stack.last.section_level+1
102
+ end
103
+
104
+ stack.last.immediate_children.push @children[i]
105
+ i += 1
106
+ end
107
+
108
+ break if i>=@children.size
109
+
110
+ header = @children[i]
111
+ level = header.meta[:level]
112
+
113
+ if level > stack.last.section_level
114
+ # this level is inside
115
+
116
+ s2 = Section.new
117
+ s2.section_level = level
118
+ s2.header_element = header
119
+ header.meta[:section] = s2
120
+
121
+ stack.last.section_children.push s2
122
+ stack.push s2
123
+
124
+ i+=1
125
+ elsif level == stack.last.section_level
126
+ # this level is a sibling
127
+ stack.pop
128
+ else
129
+ # this level is a parent
130
+ stack.pop
131
+ end
132
+
133
+ end
134
+
135
+ # If there is only one big header, then assume
136
+ # it is the master
137
+ if s.section_children.size == 1
138
+ s = s.section_children.first
139
+ end
140
+
141
+ # Assign section numbers
142
+ s.numerate
143
+
144
+ s
145
+ end
146
+
147
+ end
metadata CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: maruku
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.2.4
6
+ version: 0.2.5
7
7
  date: 2006-12-26 00:00:00 +01:00
8
8
  summary: A Markdown interpreter in Ruby
9
9
  require_paths:
@@ -37,6 +37,8 @@ files:
37
37
  - lib/maruku/to_html.rb
38
38
  - lib/maruku/to_latex.rb
39
39
  - lib/maruku/to_latex_strings.rb
40
+ - lib/maruku/to_s.rb
41
+ - lib/maruku/toc.rb
40
42
  - docs/markdown_syntax.md
41
43
  - docs/maruku.md
42
44
  - docs/todo.md