maruku 0.2 → 0.2.1

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/docs/todo.md CHANGED
@@ -1,12 +1,3 @@
1
1
 
2
-
3
-
4
-
5
-
6
-
7
- Latex export
8
- ------------
9
-
10
- * Convert HTML entities in the input to the equivalent in Latex.
11
- For example, `$` to `\$`, ` ` to `\ `.
2
+ * include RubyPants
12
3
 
@@ -16,18 +16,25 @@ class Maruku
16
16
  span = MDElement.new
17
17
  span.children = res
18
18
 
19
- # then, encode all escapes
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.map_match(/\[([^\]]+)\]\s?\[([^\]]*)\]/) { |match|
127
- text = match[1]
128
- id = match[2]
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 = text.strip.downcase
150
+ id = children.join.strip.downcase
133
151
  end
134
152
 
135
- e = create_md_element(:link, [text])
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
- span.map_match(/\[([^\]]+)\]\s?\(([^\)]*)\)/) { |match|
143
- text = match[1]
144
- url = match[2]
145
- url = url.strip.downcase
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
- e = create_md_element(:link, [text])
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
- def match_couple_of(marker, &block)
268
- regexp = Regexp.new(Regexp.escape(marker))
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(marker, &block)
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
- match = regexp.match(c)
280
- if not match
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 match.pre_match if
286
- match.pre_match && match.pre_match.size > 0
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 match.post_match if
289
- match.post_match && match.post_match.size>0
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
- match = regexp.match(c)
296
- if not match
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 match.pre_match if
303
- match.pre_match && match.pre_match.size>0
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 match.post_match if
306
- match.post_match && match.post_match.size>0
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 #{marker}"
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 = processed_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
@@ -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
- if color
100
- colorname, declaration = define_color_if_necessary(color)
101
- s+= declaration if declaration
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
- colorname, declaration = define_color_if_necessary(color)
180
- (declaration||'')+
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] [http://www.spellingsociety.org/news/media/poems.php](http://www.spellingsociety.org/news/media/poems.php)
343
- [2] [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)
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)
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.1
7
7
  date: 2006-12-25 00:00:00 +01:00
8
8
  summary: A Markdown interpreter in Ruby
9
9
  require_paths: