maruku 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/marutex +3 -0
- data/docs/markdown_syntax.md +14 -22
- data/docs/maruku.md +83 -37
- data/docs/todo.md +7 -1
- data/lib/maruku.rb +6 -0
- data/lib/maruku/parse_block.rb +61 -25
- data/lib/maruku/string_utils.rb +16 -1
- data/lib/maruku/structures.rb +28 -2
- data/lib/maruku/to_html.rb +84 -3
- data/lib/maruku/to_latex.rb +33 -45
- data/lib/maruku/to_latex_strings.rb +12 -1
- data/lib/maruku/to_s.rb +22 -0
- data/lib/maruku/toc.rb +147 -0
- metadata +3 -1
data/bin/marutex
CHANGED
data/docs/markdown_syntax.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
|
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
|
-
|
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
|
|
data/docs/maruku.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
Title: Maruku, a Markdown interpreter
|
2
1
|
CSS: style.css
|
3
|
-
|
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
|
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
|
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
|
-
|
30
|
-
|
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
|
-
|
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
|
-
|
51
|
+
Table of contents: (**auto-generated by Maruku!**)
|
52
|
+
|
53
|
+
@toc
|
44
54
|
|
45
|
-
*
|
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`
|
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
|
115
|
+
* `maruku` converts Markdown to HTML:
|
115
116
|
|
116
|
-
|
117
|
+
$ maruku file.md # creates file.html
|
117
118
|
|
118
|
-
`marutex` converts Markdown
|
119
|
+
* `marutex` converts Markdown to TeX, then calls `pdfLaTeX` to
|
119
120
|
transform to PDF:
|
120
121
|
|
121
|
-
|
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
|
-
##
|
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]:
|
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
|
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)
|
311
|
+
: (document, HTML) If set, use the [`syntax` library][syntax] to add source highlighting.
|
300
312
|
|
301
313
|
**`latex_use_listings`**
|
302
|
-
: (document,
|
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
|
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
|
-
|
data/docs/todo.md
CHANGED
data/lib/maruku.rb
CHANGED
@@ -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'
|
data/lib/maruku/parse_block.rb
CHANGED
@@ -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
|
-
|
95
|
-
|
96
|
-
|
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
|
-
|
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
|
423
|
-
|
424
|
-
hash[k] = v
|
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
|
|
data/lib/maruku/string_utils.rb
CHANGED
@@ -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
|
-
|
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)
|
data/lib/maruku/structures.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
|
2
2
|
class MDElement
|
3
|
-
# Allowed: :document, :paragraph, :ul, :ol, :li, :li_span, :strong, :emphasis, :
|
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
|
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
|
data/lib/maruku/to_html.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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(/&/,'&')
|
data/lib/maruku/to_latex.rb
CHANGED
@@ -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
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
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,
|
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,
|
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;
|
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
|
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
|
-
|
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
|
-
|
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
|
|
data/lib/maruku/to_s.rb
ADDED
@@ -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
|
data/lib/maruku/toc.rb
ADDED
@@ -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.
|
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
|