maruku 0.2.4 → 0.2.5

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