maruku 0.2 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/marutex +0 -1
- data/docs/Makefile +2 -2
- data/docs/index.html +7 -5
- data/docs/markdown_syntax.log +21 -21
- data/docs/markdown_syntax.pdf +0 -0
- data/docs/markdown_syntax.tex +110 -111
- data/docs/maruku.html +7 -5
- data/docs/maruku.log +30 -54
- data/docs/maruku.md +27 -13
- data/docs/maruku.pdf +0 -0
- data/docs/maruku.tex +75 -60
- data/docs/todo.md +1 -10
- data/lib/maruku/parse_span.rb +109 -38
- data/lib/maruku/to_latex.rb +23 -12
- data/tests/links.md +7 -0
- data/tests/sss06.md +10 -10
- metadata +1 -1
data/docs/todo.md
CHANGED
data/lib/maruku/parse_span.rb
CHANGED
@@ -16,18 +16,25 @@ class Maruku
|
|
16
16
|
span = MDElement.new
|
17
17
|
span.children = res
|
18
18
|
|
19
|
-
#
|
19
|
+
# encode all escapes
|
20
20
|
span.replace_each_string { |s| s.escape_md_special }
|
21
21
|
|
22
|
+
|
23
|
+
# The order of processing is significant:
|
24
|
+
# 1. inline code
|
25
|
+
# 2. immediate links
|
26
|
+
# 3. inline HTML
|
27
|
+
# 4. everything else
|
28
|
+
|
22
29
|
# search for ``code`` markers
|
23
|
-
span.match_couple_of('``') { |children|
|
30
|
+
span.match_couple_of('``') { |children, match1, match2|
|
24
31
|
e = create_md_element(:inline_code)
|
25
32
|
e.meta[:raw_code] = children.join('') # this is now opaque to processing
|
26
33
|
e
|
27
34
|
}
|
28
35
|
|
29
36
|
# Search for `single tick` code markers
|
30
|
-
span.match_couple_of('`') { |children|
|
37
|
+
span.match_couple_of('`') { |children, match1, match2|
|
31
38
|
e = create_md_element(:inline_code)
|
32
39
|
e.meta[:raw_code] = children.join('').unescape_md_special
|
33
40
|
# this is now opaque to processing
|
@@ -122,32 +129,76 @@ class Maruku
|
|
122
129
|
e
|
123
130
|
}
|
124
131
|
|
132
|
+
# an id reference: "[id]", "[ id ]"
|
133
|
+
reg_id_ref = %r{
|
134
|
+
\[ # opening bracket
|
135
|
+
([^\]]*) # 0 or more non-closing bracket (this is too permissive)
|
136
|
+
\] # closing bracket
|
137
|
+
}x
|
138
|
+
|
125
139
|
# Detect any link like [Google engine][google]
|
126
|
-
span.
|
127
|
-
|
128
|
-
|
140
|
+
span.match_couple_of('[', # opening bracket
|
141
|
+
%r{\] # closing bracket
|
142
|
+
[ ]? # optional whitespace
|
143
|
+
#{reg_id_ref} # ref id, with $1 being the reference
|
144
|
+
}x
|
145
|
+
) { |children, match1, match2|
|
146
|
+
id = match2[1]
|
129
147
|
id = id.strip.downcase
|
130
148
|
|
131
149
|
if id.size == 0
|
132
|
-
id =
|
150
|
+
id = children.join.strip.downcase
|
133
151
|
end
|
134
152
|
|
135
|
-
e = create_md_element(:link,
|
153
|
+
e = create_md_element(:link, children)
|
136
154
|
e.meta[:ref_id] = id
|
137
155
|
e
|
138
156
|
}
|
139
157
|
|
158
|
+
# validates a url, only $1 is set to the url
|
159
|
+
reg_url =
|
160
|
+
/((?:\w+):\/\/(?:\w+:{0,1}\w*@)?(?:\S+)(?::[0-9]+)?(?:\/|\/([\w#!:.?+=&%@!\-\/]))?)/
|
161
|
+
reg_url = %r{([^\s\]\)]+)}
|
162
|
+
|
163
|
+
# short_url = /(#?[\w]+)/
|
164
|
+
# reg_url = Regexp::union(long_url, short_url)
|
165
|
+
|
166
|
+
# A string enclosed in quotes.
|
167
|
+
reg_title = %r{
|
168
|
+
" # opening
|
169
|
+
[^"]* # anything = 1
|
170
|
+
" # closing
|
171
|
+
}x
|
172
|
+
|
173
|
+
# (http://www.google.com "Google.com"), (http://www.google.com),
|
174
|
+
reg_url_and_title = %r{
|
175
|
+
\( # opening
|
176
|
+
\s* # whitespace
|
177
|
+
#{reg_url} # url = 1
|
178
|
+
(?:\s+["'](.*)["'])? # optional title = 2
|
179
|
+
\s* # whitespace
|
180
|
+
\) # closing
|
181
|
+
}x
|
182
|
+
|
140
183
|
# Detect any link with immediate url: [Google](http://www.google.com)
|
141
184
|
# a dummy ref is created and put in the symbol table
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
185
|
+
|
186
|
+
span.match_couple_of('[', # opening bracket
|
187
|
+
%r{\] # closing bracket
|
188
|
+
[ ]? # optional whitespace
|
189
|
+
#{reg_url_and_title} # ref id, with $1 being the url and $2 being the title
|
190
|
+
}x
|
191
|
+
) { |children, match1, match2|
|
192
|
+
|
193
|
+
url = match2[1]
|
194
|
+
title = match2[3] # XXX? Is it a bug? I would use [2]
|
195
|
+
|
146
196
|
# create a dummy id
|
147
197
|
id="dummy_#{@refs.size}"
|
148
198
|
@refs[id] = {:url=>url}
|
149
|
-
|
150
|
-
|
199
|
+
@refs[id][:title] = title if title
|
200
|
+
|
201
|
+
e = create_md_element(:link, children)
|
151
202
|
e.meta[:ref_id] = id
|
152
203
|
e
|
153
204
|
}
|
@@ -164,16 +215,16 @@ class Maruku
|
|
164
215
|
# And now the easy stuff
|
165
216
|
|
166
217
|
# search for **strong**
|
167
|
-
span.match_couple_of('**') { |children| create_md_element(:strong, children) }
|
218
|
+
span.match_couple_of('**') { |children,m1,m2| create_md_element(:strong, children) }
|
168
219
|
|
169
220
|
# search for __strong__
|
170
|
-
span.match_couple_of('__') { |children| create_md_element(:strong, children) }
|
221
|
+
span.match_couple_of('__') { |children,m1,m2| create_md_element(:strong, children) }
|
171
222
|
|
172
223
|
# search for *emphasis*
|
173
|
-
span.match_couple_of('*') { |children| create_md_element(:emphasis, children) }
|
224
|
+
span.match_couple_of('*') { |children,m1,m2| create_md_element(:emphasis, children) }
|
174
225
|
|
175
226
|
# search for _emphasis_
|
176
|
-
span.match_couple_of('_') { |children| create_md_element(:emphasis, children) }
|
227
|
+
span.match_couple_of('_') { |children,m1,m2| create_md_element(:emphasis, children) }
|
177
228
|
|
178
229
|
# finally, unescape the special characters
|
179
230
|
span.replace_each_string { |s| s.unescape_md_special}
|
@@ -264,11 +315,20 @@ class MDElement
|
|
264
315
|
end
|
265
316
|
|
266
317
|
# Finds couple of delimiters in a hierarchy of Strings and MDElements
|
267
|
-
|
268
|
-
|
318
|
+
#
|
319
|
+
# Open and close are two delimiters (like '[' and ']'), or two Regexp.
|
320
|
+
#
|
321
|
+
# If you don't pass close, it defaults to open.
|
322
|
+
#
|
323
|
+
# Each block is called with |contained children, match1, match2|
|
324
|
+
def match_couple_of(open, close=nil, &block)
|
325
|
+
close = close || open
|
326
|
+
open_regexp = open.kind_of?(Regexp) ? open : Regexp.new(Regexp.escape(open))
|
327
|
+
close_regexp = close.kind_of?(Regexp) ? close : Regexp.new(Regexp.escape(close))
|
269
328
|
|
329
|
+
# Do the same to children first
|
270
330
|
for c in @children; if c.kind_of? MDElement
|
271
|
-
c.match_couple_of(
|
331
|
+
c.match_couple_of(open_regexp, close_regexp, &block)
|
272
332
|
end end
|
273
333
|
|
274
334
|
processed_children = []
|
@@ -276,37 +336,37 @@ class MDElement
|
|
276
336
|
until @children.empty?
|
277
337
|
c = @children.shift
|
278
338
|
if c.kind_of? String
|
279
|
-
|
280
|
-
if not
|
339
|
+
match1 = open_regexp.match(c)
|
340
|
+
if not match1
|
281
341
|
processed_children << c
|
282
342
|
else # we found opening, now search closing
|
283
343
|
# puts "Found opening (#{marker}) in #{c.inspect}"
|
284
344
|
# pre match is processed
|
285
|
-
processed_children.push
|
286
|
-
|
345
|
+
processed_children.push match1.pre_match if
|
346
|
+
match1.pre_match && match1.pre_match.size > 0
|
287
347
|
# we will process again the post_match
|
288
|
-
@children.unshift
|
289
|
-
|
290
|
-
|
348
|
+
@children.unshift match1.post_match if
|
349
|
+
match1.post_match && match1.post_match.size>0
|
350
|
+
|
291
351
|
contained = []; found_closing = false
|
292
352
|
until @children.empty? || found_closing
|
293
353
|
c = @children.shift
|
294
354
|
if c.kind_of? String
|
295
|
-
|
296
|
-
if not
|
355
|
+
match2 = close_regexp.match(c)
|
356
|
+
if not match2
|
297
357
|
contained << c
|
298
358
|
else
|
299
359
|
# we found closing
|
300
360
|
found_closing = true
|
301
361
|
# pre match is contained
|
302
|
-
contained.push
|
303
|
-
|
362
|
+
contained.push match2.pre_match if
|
363
|
+
match2.pre_match && match2.pre_match.size>0
|
304
364
|
# we will process again the post_match
|
305
|
-
@children.unshift
|
306
|
-
|
365
|
+
@children.unshift match2.post_match if
|
366
|
+
match2.post_match && match2.post_match.size>0
|
307
367
|
|
308
368
|
# And now we call the block
|
309
|
-
substitute = block.call(contained)
|
369
|
+
substitute = block.call(contained, match1, match2)
|
310
370
|
processed_children << substitute
|
311
371
|
|
312
372
|
# puts "Found closing (#{marker}) in #{c.inspect}"
|
@@ -319,8 +379,8 @@ class MDElement
|
|
319
379
|
end
|
320
380
|
|
321
381
|
if not found_closing
|
322
|
-
$stderr.puts "##### Could not find closing for #{
|
323
|
-
processed_children <<
|
382
|
+
# $stderr.puts "##### Could not find closing for #{open}, #{close} -- ignoring"
|
383
|
+
processed_children << match1.to_s
|
324
384
|
contained.reverse.each do |c|
|
325
385
|
@children.unshift c
|
326
386
|
end
|
@@ -331,6 +391,17 @@ class MDElement
|
|
331
391
|
end
|
332
392
|
end
|
333
393
|
|
334
|
-
@children
|
394
|
+
raise "BugBug" unless @children.empty?
|
395
|
+
|
396
|
+
rebuilt = []
|
397
|
+
# rebuild strings
|
398
|
+
processed_children.each do |c|
|
399
|
+
if c.kind_of?(String) && rebuilt.last && rebuilt.last.kind_of?(String)
|
400
|
+
rebuilt.last << c
|
401
|
+
else
|
402
|
+
rebuilt << c
|
403
|
+
end
|
404
|
+
end
|
405
|
+
@children = rebuilt
|
335
406
|
end
|
336
407
|
end
|
data/lib/maruku/to_latex.rb
CHANGED
@@ -78,7 +78,22 @@ class MDElement
|
|
78
78
|
else
|
79
79
|
color
|
80
80
|
end
|
81
|
-
|
81
|
+
end
|
82
|
+
|
83
|
+
# \color[named]{name}
|
84
|
+
# \color[rgb]{1,0.2,0.3}
|
85
|
+
def latex_color(s, command='color')
|
86
|
+
if s =~ /^\#(\w\w)(\w\w)(\w\w)$/
|
87
|
+
r = $1.hex; g = $2.hex; b=$3.hex
|
88
|
+
# convert from 0-255 to 0.0-1.0
|
89
|
+
r = r / 255.0
|
90
|
+
g = g / 255.0
|
91
|
+
b = b / 255.0
|
92
|
+
|
93
|
+
"\\#{command}[rgb]{#{r},#{g},#{b}}"
|
94
|
+
else
|
95
|
+
"\\#{command}{#{s}}"
|
96
|
+
end
|
82
97
|
end
|
83
98
|
|
84
99
|
def to_latex_code;
|
@@ -95,13 +110,10 @@ class MDElement
|
|
95
110
|
s+= "\\lstset{showspaces=false,showtabs=false}\n"
|
96
111
|
end
|
97
112
|
|
98
|
-
color = get_setting(:code_background_color,DEFAULT_CODE_COLOR)
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
s+= "\\lstset{backgroundcolor=\\color{#{colorname}}}\n"
|
103
|
-
end
|
104
|
-
|
113
|
+
color = latex_color get_setting(:code_background_color,DEFAULT_CODE_COLOR)
|
114
|
+
|
115
|
+
s+= "\\lstset{backgroundcolor=#{color}}\n"
|
116
|
+
|
105
117
|
s+= "\\lstset{basicstyle=\\ttfamily\\footnotesize}\n"
|
106
118
|
|
107
119
|
|
@@ -175,10 +187,9 @@ class MDElement
|
|
175
187
|
# Convert to printable latex chars (is much better than using \verb)
|
176
188
|
s=latex_escape(source)
|
177
189
|
|
178
|
-
color = get_setting(:code_background_color,DEFAULT_CODE_COLOR)
|
179
|
-
|
180
|
-
|
181
|
-
"\\colorbox{#{colorname}}{\\tt #{s}}"
|
190
|
+
color = latex_color(get_setting(:code_background_color,DEFAULT_CODE_COLOR),'colorbox')
|
191
|
+
|
192
|
+
"#{color}{\\tt #{s}}"
|
182
193
|
end
|
183
194
|
|
184
195
|
def to_latex_immediate_link
|
data/tests/links.md
CHANGED
@@ -11,6 +11,13 @@ Search on [Google images][]
|
|
11
11
|
|
12
12
|
Search on [Google images][ GoOgle search ]
|
13
13
|
|
14
|
+
Inline: [Google images](http://google.com)
|
15
|
+
|
16
|
+
Inline with title: [Google images](http://google.com "Title")
|
17
|
+
|
18
|
+
Inline with title: [Google images]( http://google.com "Title" )
|
19
|
+
|
20
|
+
|
14
21
|
Search on <http://www.gogole.com> or <http://Here.com> or ask <mailto:bill@google.com>
|
15
22
|
or you might ask bill@google.com.
|
16
23
|
|
data/tests/sss06.md
CHANGED
@@ -339,14 +339,14 @@ And here's the research version:
|
|
339
339
|
References
|
340
340
|
----------
|
341
341
|
|
342
|
-
[1]
|
343
|
-
[2]
|
344
|
-
[3] [http://www.oxfordstory.co.uk](http://www.oxfordstory.co.uk)
|
345
|
-
[4]
|
346
|
-
[5] E. Meijer, M. Fokkinga, R. Paterson. "Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire" (1991)
|
342
|
+
\[1\] [http://www.spellingsociety.org/news/media/poems.php](http://www.spellingsociety.org/news/media/poems.php)
|
343
|
+
\[2\] dde [http://www.flickr.com/photos/censi/236722418/](http://www.flickr.com/photos/censi/236722418/)
|
344
|
+
\[3\] [http://www.oxfordstory.co.uk](http://www.oxfordstory.co.uk)
|
345
|
+
\[4\] [http://www.botanical.com/botanical/mgmh/p/parsni12.html](http://www.botanical.com/botanical/mgmh/p/parsni12.html )
|
346
|
+
\[5\] E. Meijer, M. Fokkinga, R. Paterson. "Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire" (1991)
|
347
347
|
[http://citeseer.ist.psu.edu/meijer91functional.html](http://citeseer.ist.psu.edu/meijer91functional.html)
|
348
|
-
[6] R. Lammel, J. Visser, J. Kort. "Dealing with large bananas" (2000) <http://citeseer.ist.psu.edu/lammel00dealing.html>
|
349
|
-
[7] [http://www.informatik.uni-freiburg.de/~burgard/](http://citeseer.ist.psu.edu/lammel00dealing.html)
|
350
|
-
[8] [http://asl.epfl.ch/~scaramuz/cabaret/cabaret.wmv](http://asl.epfl.ch/~scaramuz/cabaret/cabaret.wmv)
|
351
|
-
[9] [http://www.anth.uconn.edu/faculty/boster/cultvar/euweb/](http://www.anth.uconn.edu/faculty/boster/cultvar/euweb/)
|
352
|
-
[10] [http://www.infonegocio.com/xeron/bruno/italy.html](http://www.infonegocio.com/xeron/bruno/italy.html)
|
348
|
+
\[6\] R. Lammel, J. Visser, J. Kort. "Dealing with large bananas" (2000) <http://citeseer.ist.psu.edu/lammel00dealing.html>
|
349
|
+
\[7\] [http://www.informatik.uni-freiburg.de/~burgard/](http://citeseer.ist.psu.edu/lammel00dealing.html)
|
350
|
+
\[8\] [http://asl.epfl.ch/~scaramuz/cabaret/cabaret.wmv](http://asl.epfl.ch/~scaramuz/cabaret/cabaret.wmv)
|
351
|
+
\[9\] [http://www.anth.uconn.edu/faculty/boster/cultvar/euweb/](http://www.anth.uconn.edu/faculty/boster/cultvar/euweb/)
|
352
|
+
\[10\] [http://www.infonegocio.com/xeron/bruno/italy.html](http://www.infonegocio.com/xeron/bruno/italy.html)
|