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