WikiCreole 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/Changelog CHANGED
@@ -1,3 +1,12 @@
1
+ 2009-02-05 (0.1.3)
2
+ * nono on github made the Ruby more idiomatic and fixed a section
3
+ which had eluded Gordon earlier. He also added profiling, which
4
+ can be run using "rake profiling" then opening profiling.html
5
+ in a browser.
6
+ * Raphael Knaus found an infinite loop error while parsing a nested
7
+ list. He provided a quick fix, but both he and I are dissatisfied
8
+ by the current workaround.
9
+
1
10
  2008-12-12 (0.1.2)
2
11
  * Made the usage more clear by adding the "require 'rubygems'" before
3
12
  the require 'wiki_creole' command
data/Rakefile CHANGED
@@ -14,4 +14,10 @@ Rake::TestTask.new(:test_all) do |t|
14
14
  t.libs << 'lib'
15
15
  t.warning = true
16
16
  t.test_files = FileList['test/test_all.rb']
17
+ end
18
+
19
+ Rake::TestTask.new(:profiling) do |t|
20
+ t.libs << 'lib'
21
+ t.warning = true
22
+ t.test_files = FileList['test/profiling.rb']
17
23
  end
@@ -1,12 +1,12 @@
1
- # WikiCreole implements the Wiki Creole markup language,
1
+ # WikiCreole implements the Wiki Creole markup language,
2
2
  # version 1.0, as described at http://www.wikicreole.org. It
3
3
  # reads Creole 1.0 markup and returns XHTML.
4
4
  #
5
5
  # Author:: Gordon McCreight (mailto:wikicreole.to.gordon@mccreight.com)
6
6
  # Copyright:: Copyright (c) 2008 Gordon McCreight
7
7
  # License:: Distributes under the same terms as Ruby (see the LICENSE file)
8
- # Version:: 0.1.2
9
- # Date:: 2008-12-12
8
+ # Version:: 0.1.3
9
+ # Date:: 2009-02-05
10
10
  #
11
11
  # == Synopsis
12
12
  # Most likely you'll just want to do:
@@ -18,7 +18,7 @@
18
18
  #
19
19
  # == Official Markup
20
20
  #
21
- # Here is a summary of the official Creole 1.0 markup
21
+ # Here is a summary of the official Creole 1.0 markup
22
22
  # elements. See http://www.wikicreole.org for the full
23
23
  # details.
24
24
  #
@@ -62,7 +62,7 @@
62
62
  # ~** not bold ** -> ** not bold **
63
63
  # tilde: ~~ -> tilde: ~
64
64
  #
65
- # Paragraphs are separated by other blocks and blank lines.
65
+ # Paragraphs are separated by other blocks and blank lines.
66
66
  # Inline markup can usually be combined, overlapped, etc. List
67
67
  # items and plugin text can span lines.
68
68
  #
@@ -104,7 +104,7 @@
104
104
  # converter which can be found here:
105
105
  # http://search.cpan.org/~jburnett/Text-WikiCreole/
106
106
  # He, in turn, acknowledges the Document::Parser perl module.
107
- #
107
+ #
108
108
  # Also, some of the tests are taken from Lars Christensen's implementation of
109
109
  # the Creole parser. You can find his code at:
110
110
  # http://github.com/larsch/creole/tree/master
@@ -113,83 +113,67 @@
113
113
  # http://www.wikicreole.org/
114
114
 
115
115
  class WikiCreole
116
-
116
+
117
117
  # Reads Creole 1.0 markup and return XHTML.
118
118
  #
119
119
  # xhtml = WikiCreole.creole_parse(wiki_creole_markup)
120
120
  def self.creole_parse(s)
121
- return "" if s.class.to_s != "String"
122
- return "" if s.length < 1
121
+ return "" unless String === s
122
+ return "" if s.empty?
123
123
 
124
124
  init
125
- return parse(s, :top)
125
+ parse(s, :top)
126
126
  end
127
-
127
+
128
128
  # Creole 1.0 supports two plugin syntaxes: << plugin content >> and
129
129
  # <<< plugin content >>>
130
- #
131
- # Write a function that receives the text between the <<>>
132
- # delimiters (not including the delimiters) and
133
- # returns the text to be displayed. For example, here is a
130
+ #
131
+ # Write a function that receives the text between the <<>>
132
+ # delimiters (not including the delimiters) and
133
+ # returns the text to be displayed. For example, here is a
134
134
  # simple plugin that converts plugin text to uppercase:
135
135
  #
136
- # uppercase = Proc.new {|s|
137
- # s.upcase!
138
- # s
139
- # }
140
- # WikiCreole.creole_plugin(uppercase)
136
+ # WikiCreole.creole_plugin {|s| s.upcase }
141
137
  #
142
138
  # If you do not register a plugin function, plugin markup will be left
143
139
  # as is, including the surrounding << >>.
144
- def self.creole_plugin(func)
145
- @plugin_function = func
140
+ def self.creole_plugin(&blk)
141
+ @plugin_function = blk
146
142
  end
147
143
 
148
144
  # You may wish to customize [[ links ]], such as to prefix a hostname,
149
145
  # port, etc.
150
146
  #
151
147
  # Write a function, similar to the plugin function, which receives the
152
- # URL part of the link (with leading and trailing whitespace stripped)
153
- # and returns the customized link. For example, to prepend
148
+ # URL part of the link (with leading and trailing whitespace stripped)
149
+ # and returns the customized link. For example, to prepend
154
150
  # http://my.domain/
155
151
  # to pagename:
156
152
  #
157
- # mylink = Proc.new {|s|
158
- # s = "http://my.domain/" + s
159
- # s
160
- # }
161
- # WikiCreole.creole_link(mylink)
162
- def self.creole_link(func)
163
- @link_function = func
153
+ # WikiCreole.creole_link {|s| "http://my.domain/#{s}" }
154
+ def self.creole_link(&blk)
155
+ @link_function = blk
164
156
  end
165
-
157
+
166
158
  # Same purpose as creole_link, but for "bare" link markup. Bare links are
167
159
  # the links which are in the text but not surrounded by brackets.
168
160
  #
169
- # mybarelink = Proc.new {|s|
170
- # s = s + ".html"
171
- # s
172
- # }
173
- # WikiCreole.creole_barelink(mybarelink)
174
- def self.creole_barelink(func)
175
- @barelink_function = func
161
+ # WikiCreole.creole_barelink {|s| "#{s}.html" }
162
+ def self.creole_barelink(&blk)
163
+ @barelink_function = blk
176
164
  end
177
165
 
178
166
  # Same purpose as creole_link, but for image URLs.
179
167
  #
180
- # myimg = Proc.new {|s|
181
- # s = "http://my.domain/" + s
182
- # s
183
- # }
184
- # WikiCreole.creole_img(myimg)
185
- def self.creole_img(func)
186
- @img_function = func
168
+ # WikiCreole.creole_img {|s| "http://my.domain/#{s}" }
169
+ def self.creole_img(&blk)
170
+ @img_function = blk
187
171
  end
188
-
172
+
189
173
  # If you want complete control over links, rather than just modifying
190
174
  # the URL, register your link markup function with WikiCreole.creole_link()
191
175
  # as above and then call creole_customlinks(). Now your function will receive
192
- # the entire link markup chunk, such as <tt>[[ some_wiki_page | page description ]]</tt>
176
+ # the entire link markup chunk, such as <tt>[[ some_wiki_page | page description ]]</tt>
193
177
  # and must return HTML.
194
178
  #
195
179
  # This has no effect on "bare" link markup, such as
@@ -200,10 +184,8 @@ class WikiCreole
200
184
  @@chunks_hash[:link][:open] = ""
201
185
  @@chunks_hash[:link][:close] = ""
202
186
  @@chunks_hash[:link].delete(:contains)
203
- @@chunks_hash[:link][:filter] = Proc.new {|s|
204
- if @link_function
205
- s = @link_function.call(s)
206
- end
187
+ @@chunks_hash[:link][:filter] = Proc.new {|s|
188
+ s = @link_function.call(s) if @link_function
207
189
  s
208
190
  }
209
191
  end
@@ -212,10 +194,8 @@ class WikiCreole
212
194
  def self.creole_custombarelinks
213
195
  @@chunks_hash[:ilink][:open] = ""
214
196
  @@chunks_hash[:ilink][:close] = ""
215
- @@chunks_hash[:ilink][:filter] = Proc.new {|s|
216
- if @barelink_function
217
- s = @barelink_function.call(s)
218
- end
197
+ @@chunks_hash[:ilink][:filter] = Proc.new {|s|
198
+ s = @barelink_function.call(s) if @barelink_function
219
199
  s
220
200
  }
221
201
  end
@@ -225,28 +205,23 @@ class WikiCreole
225
205
  @@chunks_hash[:img][:open] = ""
226
206
  @@chunks_hash[:img][:close] = ""
227
207
  @@chunks_hash[:img].delete(:contains)
228
- @@chunks_hash[:img][:filter] = Proc.new {|s|
229
- if @img_function
230
- s = @img_function.call(s)
231
- end
208
+ @@chunks_hash[:img][:filter] = Proc.new {|s|
209
+ s = @img_function.call(s) if @img_function
232
210
  s
233
211
  }
234
212
  end
235
-
213
+
236
214
  # You may wish to customize the opening and/or closing tags
237
215
  # for the various bits of Creole markup. For example, to
238
216
  # assign a CSS class to list items:
239
217
  # WikiCreole.creole_tag(:li, :open, "<li class=myclass>")
240
218
  #
241
- # Or to see all current tags:
242
- # puts WikiCreole.creole_tag()
243
- #
244
219
  # The tags that may be of interest are:
245
220
  #
246
221
  # br dd dl
247
222
  # dt em h1
248
223
  # h2 h3 h4
249
- # h5 h6 hr
224
+ # h5 h6 hr
250
225
  # ilink img inowiki
251
226
  # ip li link
252
227
  # mono nowiki ol
@@ -258,71 +233,68 @@ class WikiCreole
258
233
  # Those should be self-explanatory, except for inowiki (inline nowiki),
259
234
  # ilink (bare links, e.g.
260
235
  # http://www.cpan.org
261
- # and ip (indented paragraph).
262
- def self.creole_tag(*args)
263
-
264
- # I bet a good Ruby hacker would know a way around this little chunk...
265
- tag = args.length > 0 ? args[0] : nil
266
- type = args.length > 1 ? args[1] : nil
267
- text = args.length > 2 ? args[2] : nil
268
-
269
- if tag.nil?
270
- tags = ""
271
- for key in @@chunks_hash.keys.collect{|x| x.to_s}.sort
272
- key = key.to_sym
273
- o = @@chunks_hash[key][:open]
274
- c = @@chunks_hash[key][:close]
275
- next if o.nil? || !o.index(/</m)
276
- o = o.gsub(/\n/m,"\\n")
277
- c = c.gsub(/\n/m,"\\n") if c
278
- c = "" if c.nil?
279
- this_tag = "#{key}: open(#{o}) close(#{c})\n"
280
- tags += this_tag
281
- end
282
- return tags
283
- else
284
- return if ! type
285
- type = type.to_sym
286
- return if type != :open && type != :close
287
- return if !@@chunks_hash.has_key?(tag)
288
- @@chunks_hash[tag][type] = text ? text : ""
236
+ # ) and ip (indented paragraph).
237
+ def self.creole_tag(tag, type, text="")
238
+ type = type.to_sym
239
+ return unless [:open, :close].include?(type)
240
+ return unless @@chunks_hash.has_key?(tag)
241
+ @@chunks_hash[tag][type] = text
242
+ end
243
+
244
+ # See all current tags:
245
+ # puts WikiCreole.creole_tags()
246
+ #
247
+ def self.creole_tags
248
+ tags = []
249
+ keys = @@chunks_hash.keys.collect{|x| x.to_s}.sort
250
+ keys.each do |key|
251
+ key = key.to_sym
252
+ o = @@chunks_hash[key][:open] || ""
253
+ c = @@chunks_hash[key][:close] || ""
254
+ next if o !~ /</m
255
+ o, c = [o, c].map {|x| x.gsub(/\n/m,"\\n") }
256
+ this_tag = "#{key}: open(#{o}) close(#{c})\n"
257
+ tags << this_tag
289
258
  end
259
+ tags.join
290
260
  end
291
-
292
- private
293
-
261
+
262
+ private
263
+
294
264
  # characters that may indicate inline wiki markup
295
- @@specialchars = ['^', '\\', '*', '/', '_', ',', '{', '[',
296
- '<', '~', '|', "\n", '#', ':', ';', '(', '-', '.']
297
-
298
- # plain characters - auto-generated below (ascii printable minus @specialchars)
299
- @@plainchars = []
265
+ SPECIALCHARS = ['^', '\\', '*', '/', '_', ',', '{', '[',
266
+ '<', '~', '|', "\n", '#', ':', ';', '(', '-', '.']
267
+
268
+ # plain characters
269
+ # build an array of "plain content" characters by subtracting SPECIALCHARS
270
+ # from ascii printable (ascii 32 to 126)
271
+ PLAINCHARS = (32..126).map{|c| c.chr}.reject{|c| SPECIALCHARS.index(c)}
300
272
 
301
273
  # non-plain text inline widgets
302
- @@inline = %w{strong em br esc img link ilink inowiki
303
- sub sup mono u plug plug2 tm reg copy ndash ellipsis amp}
304
-
305
- @@all_inline = [@@inline, 'plain', 'any'].flatten # including plain text
274
+ INLINE = %w{strong em br esc img link ilink inowiki
275
+ sub sup mono u plug plug2 tm reg copy ndash ellipsis amp}
276
+
277
+ ALL_INLINE = [INLINE, 'plain', 'any'].flatten # including plain text
278
+
279
+ BLOCKS = %w{h1 h2 h3 hr nowiki h4 h5 h6 ul ol table p ip dl plug plug2 blank}
306
280
 
307
- @@blocks = %w{h1 h2 h3 hr nowiki h4 h5 h6 ul ol table p ip dl plug plug2 blank}
308
-
309
281
  # handy - used several times in %chunks
310
- @@eol = '(?:\n|$)'; # end of line (or string)
311
-
282
+ EOL = '(?:\n|$)'.freeze # end of line (or string)
283
+
312
284
  @plugin_function = nil
313
285
  @barelink_function = nil
314
286
  @link_function = nil
315
287
  @img_function = nil
316
-
288
+
317
289
  @is_initialized = false
318
290
 
319
291
  @@chunks_hash = {
320
292
  :top => {
321
- :contains => @@blocks,
293
+ :contains => BLOCKS,
322
294
  },
323
295
  :blank => {
324
- :curpat => "(?= *#{@@eol})",
325
- :fwpat => "(?=(?:^|\n) *#{@@eol})",
296
+ :curpat => "(?= *#{EOL})",
297
+ :fwpat => "(?=(?:^|\n) *#{EOL})",
326
298
  :stops => '(?=\S)',
327
299
  :hint => ["\n"],
328
300
  :filter => Proc.new { "" }, # whitespace into the bit bucket
@@ -331,8 +303,8 @@ class WikiCreole
331
303
  :p => {
332
304
  :curpat => '(?=.)',
333
305
  :stops => ['blank', 'ip', 'h', 'hr', 'nowiki', 'ul', 'ol', 'dl', 'table'],
334
- :hint => @@plainchars,
335
- :contains => @@all_inline,
306
+ :hint => PLAINCHARS,
307
+ :contains => ALL_INLINE,
336
308
  :filter => Proc.new {|s| s.chomp },
337
309
  :open => "<p>", :close => "</p>\n\n",
338
310
  },
@@ -362,7 +334,7 @@ class WikiCreole
362
334
  :fwpat => '\n(?=;)',
363
335
  :stops => '(?=:|\n)',
364
336
  :hint => [';'],
365
- :contains => @@all_inline,
337
+ :contains => ALL_INLINE,
366
338
  :filter => Proc.new {|s|
367
339
  s.sub!(/^;\s*/, '')
368
340
  s
@@ -372,9 +344,9 @@ class WikiCreole
372
344
  :dd => {
373
345
  :curpat => '(?=\n|:)',
374
346
  :fwpat => '(?:\n|:)',
375
- :stops => '(?=:)|\n(?=;)',
347
+ :stops => '.(?=:)|\n(?=;)',
376
348
  :hint => [':', "\n"],
377
- :contains => @@all_inline,
349
+ :contains => ALL_INLINE,
378
350
  :filter => Proc.new {|s|
379
351
  s.sub!(/(?:\n|:)\s*/m, '')
380
352
  s.sub!(/\s*$/m, '')
@@ -406,7 +378,7 @@ class WikiCreole
406
378
  :curpat => '(?=\|[^=])',
407
379
  # this gnarly regex fixes ambiguous '|' for links/imgs/nowiki in tables
408
380
  :stops => '[^~](?=\|(?!(?:[^\[]*\]\])|(?:[^\{]*\}\})))',
409
- :contains => @@all_inline,
381
+ :contains => ALL_INLINE,
410
382
  :hint => ['|'],
411
383
  :filter => Proc.new {|s|
412
384
  s.sub!(/^ *\| */, '')
@@ -419,7 +391,7 @@ class WikiCreole
419
391
  :curpat => '(?=\|=)',
420
392
  # this gnarly regex fixes ambiguous '|' for links/imgs/nowiki in tables
421
393
  :stops => '[^~](?=\|(?!(?:[^\[]*\]\])|(?:[^\{]*\}\})))',
422
- :contains => @@all_inline,
394
+ :contains => ALL_INLINE,
423
395
  :hint => ['|'],
424
396
  :filter => Proc.new {|s|
425
397
  s.sub!(/^ *\|= */, '')
@@ -462,13 +434,13 @@ class WikiCreole
462
434
  s.chomp!
463
435
  s
464
436
  },
465
- :contains => @@all_inline,
437
+ :contains => ALL_INLINE,
466
438
  :open => " <li>", :close => "</li>\n",
467
439
  },
468
440
  :nowiki => {
469
441
  :curpat => '(?=\{\{\{ *\n)',
470
442
  :fwpat => '\n(?=\{\{\{ *\n)',
471
- :stops => "\n\\}\\}\\} *#{@@eol}",
443
+ :stops => "\n\\}\\}\\} *#{EOL}",
472
444
  :hint => ['{'],
473
445
  :filter => Proc.new {|s|
474
446
  s[0,3] = ''
@@ -481,19 +453,19 @@ class WikiCreole
481
453
  :open => "<pre>", :close => "</pre>\n\n",
482
454
  },
483
455
  :hr => {
484
- :curpat => "(?= *-{4,} *#{@@eol})",
485
- :fwpat => "\n(?= *-{4,} *#{@@eol})",
456
+ :curpat => "(?= *-{4,} *#{EOL})",
457
+ :fwpat => "\n(?= *-{4,} *#{EOL})",
486
458
  :hint => ['-', ' '],
487
- :stops => @@eol,
459
+ :stops => EOL,
488
460
  :open => "<hr />\n\n", :close => "",
489
461
  :filter => Proc.new { "" } # ----- into the bit bucket
490
462
  },
491
463
  :h => { :curpat => '(?=(?:^|\n) *=)' }, # matches any heading
492
464
  :h1 => {
493
465
  :curpat => '(?= *=[^=])',
494
- :hint => ['=', ' '],
466
+ :hint => ['=', ' '],
495
467
  :stops => '\n',
496
- :contains => @@all_inline,
468
+ :contains => ALL_INLINE,
497
469
  :open => "<h1>", :close => "</h1>\n\n",
498
470
  :filter => Proc.new {|s|
499
471
  s = strip_leading_and_trailing_eq_and_whitespace(s)
@@ -502,9 +474,9 @@ class WikiCreole
502
474
  },
503
475
  :h2 => {
504
476
  :curpat => '(?= *={2}[^=])',
505
- :hint => ['=', ' '],
477
+ :hint => ['=', ' '],
506
478
  :stops => '\n',
507
- :contains => @@all_inline,
479
+ :contains => ALL_INLINE,
508
480
  :open => "<h2>", :close => "</h2>\n\n",
509
481
  :filter => Proc.new {|s|
510
482
  s = strip_leading_and_trailing_eq_and_whitespace(s)
@@ -513,9 +485,9 @@ class WikiCreole
513
485
  },
514
486
  :h3 => {
515
487
  :curpat => '(?= *={3}[^=])',
516
- :hint => ['=', ' '],
488
+ :hint => ['=', ' '],
517
489
  :stops => '\n',
518
- :contains => @@all_inline,
490
+ :contains => ALL_INLINE,
519
491
  :open => "<h3>", :close => "</h3>\n\n",
520
492
  :filter => Proc.new {|s|
521
493
  s = strip_leading_and_trailing_eq_and_whitespace(s)
@@ -524,9 +496,9 @@ class WikiCreole
524
496
  },
525
497
  :h4 => {
526
498
  :curpat => '(?= *={4}[^=])',
527
- :hint => ['=', ' '],
499
+ :hint => ['=', ' '],
528
500
  :stops => '\n',
529
- :contains => @@all_inline,
501
+ :contains => ALL_INLINE,
530
502
  :open => "<h4>", :close => "</h4>\n\n",
531
503
  :filter => Proc.new {|s|
532
504
  s = strip_leading_and_trailing_eq_and_whitespace(s)
@@ -535,9 +507,9 @@ class WikiCreole
535
507
  },
536
508
  :h5 => {
537
509
  :curpat => '(?= *={5}[^=])',
538
- :hint => ['=', ' '],
510
+ :hint => ['=', ' '],
539
511
  :stops => '\n',
540
- :contains => @@all_inline,
512
+ :contains => ALL_INLINE,
541
513
  :open => "<h5>", :close => "</h5>\n\n",
542
514
  :filter => Proc.new {|s|
543
515
  s = strip_leading_and_trailing_eq_and_whitespace(s)
@@ -546,9 +518,9 @@ class WikiCreole
546
518
  },
547
519
  :h6 => {
548
520
  :curpat => '(?= *={6,})',
549
- :hint => ['=', ' '],
521
+ :hint => ['=', ' '],
550
522
  :stops => '\n',
551
- :contains => @@all_inline,
523
+ :contains => ALL_INLINE,
552
524
  :open => "<h6>", :close => "</h6>\n\n",
553
525
  :filter => Proc.new {|s|
554
526
  s = strip_leading_and_trailing_eq_and_whitespace(s)
@@ -557,13 +529,13 @@ class WikiCreole
557
529
  },
558
530
  :plain => {
559
531
  :curpat => '(?=[^\*\/_\,\^\\\\{\[\<\|])',
560
- :stops => @@inline,
561
- :hint => @@plainchars,
532
+ :stops => INLINE,
533
+ :hint => PLAINCHARS,
562
534
  :open => '', :close => ''
563
535
  },
564
536
  :any => { # catch-all
565
537
  :curpat => '(?=.)',
566
- :stops => @@inline,
538
+ :stops => INLINE,
567
539
  :open => '', :close => ''
568
540
  },
569
541
  :br => {
@@ -604,7 +576,7 @@ class WikiCreole
604
576
  :filter => Proc.new {|s|
605
577
  s[0,3] = ''
606
578
  s.sub!(/\>{3}$/, '')
607
- if !@plugin_function.nil?
579
+ if @plugin_function
608
580
  s = @plugin_function.call(s)
609
581
  else
610
582
  s = "<<<#{s}>>>"
@@ -620,7 +592,7 @@ class WikiCreole
620
592
  :filter => Proc.new {|s|
621
593
  s[0,2] = ''
622
594
  s.sub!(/\>{2}$/, '')
623
- if !@plugin_function.nil?
595
+ if @plugin_function
624
596
  s = @plugin_function.call(s)
625
597
  else
626
598
  s = "<<#{s}>>"
@@ -640,9 +612,9 @@ class WikiCreole
640
612
  :filter => Proc.new {|s|
641
613
  s.sub!(/^\s*/, '')
642
614
  s.sub!(/\s*$/, '')
643
- if !@barelink_function.nil?
615
+ if @barelink_function
644
616
  s = @barelink_function.call(s)
645
- end
617
+ end
646
618
  s = "href=\"#{s}\">#{s}"
647
619
  s
648
620
  },
@@ -657,7 +629,7 @@ class WikiCreole
657
629
  s[0,2] = ''
658
630
  s[-2,2] = ''
659
631
  s += "|#{s}" if ! s.index(/\|/) # text = url unless given
660
- s
632
+ s
661
633
  },
662
634
  :open => "<a ", :close => "</a>",
663
635
  },
@@ -667,7 +639,7 @@ class WikiCreole
667
639
  :filter => Proc.new {|s|
668
640
  s.sub!(/^\s*/, '')
669
641
  s.sub!(/\s*$/, '')
670
- if !@link_function.nil?
642
+ if @link_function
671
643
  s = @link_function.call(s)
672
644
  end
673
645
  s
@@ -678,7 +650,7 @@ class WikiCreole
678
650
  :curpat => '(?=\|)',
679
651
  :stops => '\n',
680
652
  :hint => ['|'],
681
- :contains => @@all_inline,
653
+ :contains => ALL_INLINE,
682
654
  :filter => Proc.new {|s|
683
655
  s.sub!(/^\|\s*/, '')
684
656
  s.sub!(/\s*$/, '')
@@ -715,7 +687,7 @@ class WikiCreole
715
687
  :filter => Proc.new {|s|
716
688
  s.sub!(/^\|\s*/, '')
717
689
  s.sub!(/\s*$/, '')
718
- if !@img_function.nil?
690
+ if @img_function
719
691
  s = @img_function.call(s)
720
692
  end
721
693
  s
@@ -726,7 +698,7 @@ class WikiCreole
726
698
  :curpat => '(?=\*\*)',
727
699
  :stops => '\*\*.*?\*\*',
728
700
  :hint => ['*'],
729
- :contains => @@all_inline,
701
+ :contains => ALL_INLINE,
730
702
  :filter => Proc.new {|s|
731
703
  s[0,2] = ''
732
704
  s.sub!(/\*\*$/, '')
@@ -737,7 +709,7 @@ class WikiCreole
737
709
  :em => {
738
710
  # This could use a negative lookback assertion to let you know whether
739
711
  # it's part of a URL or not. That would be helpful if the URL had been
740
- # escaped. Currently, it will just become italic after the // since
712
+ # escaped. Currently, it will just become italic after the // since
741
713
  # it didn't process the URL.
742
714
  :curpat => '(?=\/\/)',
743
715
  # Removed a negative lookback assertion (?<!:) from the Perl version
@@ -746,7 +718,7 @@ class WikiCreole
746
718
  # I had to do it.
747
719
  :stops => '\/\/.*?[^:]\/\/',
748
720
  :hint => ['/'],
749
- :contains => @@all_inline,
721
+ :contains => ALL_INLINE,
750
722
  :filter => Proc.new {|s|
751
723
  s[0,2] = ''
752
724
  s.sub!(/\/\/$/, '')
@@ -758,7 +730,7 @@ class WikiCreole
758
730
  :curpat => '(?=\#\#)',
759
731
  :stops => '\#\#.*?\#\#',
760
732
  :hint => ['#'],
761
- :contains => @@all_inline,
733
+ :contains => ALL_INLINE,
762
734
  :filter => Proc.new {|s|
763
735
  s[0,2] = ''
764
736
  s.sub!(/\#\#$/, '')
@@ -770,7 +742,7 @@ class WikiCreole
770
742
  :curpat => '(?=,,)',
771
743
  :stops => ',,.*?,,',
772
744
  :hint => [','],
773
- :contains => @@all_inline,
745
+ :contains => ALL_INLINE,
774
746
  :filter => Proc.new {|s|
775
747
  s[0,2] = ''
776
748
  s.sub!(/\,\,$/, '')
@@ -782,7 +754,7 @@ class WikiCreole
782
754
  :curpat => '(?=\^\^)',
783
755
  :stops => '\^\^.*?\^\^',
784
756
  :hint => ['^'],
785
- :contains => @@all_inline,
757
+ :contains => ALL_INLINE,
786
758
  :filter => Proc.new {|s|
787
759
  s[0,2] = ''
788
760
  s.sub!(/\^\^$/, '')
@@ -794,7 +766,7 @@ class WikiCreole
794
766
  :curpat => '(?=__)',
795
767
  :stops => '__.*?__',
796
768
  :hint => ['_'],
797
- :contains => @@all_inline,
769
+ :contains => ALL_INLINE,
798
770
  :filter => Proc.new {|s|
799
771
  s[0,2] = ''
800
772
  s.sub!(/__$/, '')
@@ -845,93 +817,77 @@ class WikiCreole
845
817
  :open => "", :close => "",
846
818
  },
847
819
  }
848
-
820
+
849
821
  def self.strip_leading_and_trailing_eq_and_whitespace(s)
850
822
  s.sub!(/^\s*=*\s*/, '')
851
823
  s.sub!(/\s*=*\s*$/, '')
852
- return s
824
+ s
853
825
  end
854
826
 
855
827
  def self.strip_list(s)
856
828
  s.sub!(/(?:`*| *)[\*\#]/, '`')
857
829
  s.gsub!(/\n(?:`*| *)[\*\#]/m, "\n`")
858
- return s
830
+ s
859
831
  end
860
-
832
+
861
833
  def self.filter_string_x_with_chunk_filter_y(str, chunk)
862
- return @@chunks_hash[chunk][:filter].call(str)
834
+ @@chunks_hash[chunk][:filter].call(str)
863
835
  end
864
-
836
+
865
837
  def self.parse(tref, chunk)
866
-
838
+
867
839
  sub_chunk = nil
868
840
  pos = 0
869
841
  last_pos = 0
870
- html = ""
842
+ html = []
843
+ first_try = true
871
844
 
872
845
  loop do
873
846
 
874
847
  if sub_chunk # we've determined what type of sub_chunk this is
875
-
876
- if sub_chunk == :dd
877
- # Yuck... I don't exactly understand why I need this section, but
878
- # without it the parser will go into an infinite loop on the :dd's in
879
- # the test suite. Please, if you're a most excellent Ruby hacker,
880
- # find the issue, clean this up, and remove the comment here, m'kay?
881
-
882
- while tref.index(Regexp.compile('\G.*' + @@chunks_hash[sub_chunk][:delim], Regexp::MULTILINE), pos)
883
- end_of_match = Regexp.last_match.end(0)
884
- if end_of_match == pos
885
- break
886
- else
887
- pos = end_of_match
888
- end
889
- end
890
848
 
891
- if pos == last_pos
892
- pos = tref.length
893
- end
849
+ # This is a little slower than it could be. The delim should be
850
+ # pre-compiled, but see the issue in the comment above.
851
+ if tref.index(@@chunks_hash[sub_chunk][:delim], pos)
852
+ pos = Regexp.last_match.end(0)
894
853
  else
895
- # This is a little slower than it could be. The delim should be
896
- # pre-compiled, but see the issue in the comment above.
897
- if tref.index(Regexp.compile(@@chunks_hash[sub_chunk][:delim], Regexp::MULTILINE), pos)
898
- pos = Regexp.last_match.end(0)
899
- else
900
- pos = tref.length
901
- end
854
+ pos = tref.length
902
855
  end
903
856
 
904
- html += @@chunks_hash[sub_chunk][:open]
857
+ html << @@chunks_hash[sub_chunk][:open]
905
858
 
906
859
  t = tref[last_pos, pos - last_pos] # grab the chunk
907
860
 
908
861
  if @@chunks_hash[sub_chunk].has_key?(:filter) # filter it, if applicable
909
862
  t = @@chunks_hash[sub_chunk][:filter].call(t)
910
863
  end
911
-
864
+
912
865
  last_pos = pos # remember where this chunk ends (where next begins)
913
-
866
+
914
867
  if t && @@chunks_hash[sub_chunk].has_key?(:contains) # if it contains other chunks...
915
- html += parse(t, sub_chunk) # recurse.
868
+ html << parse(t, sub_chunk) # recurse.
916
869
  else
917
- html += t # otherwise, print it
870
+ html << t # otherwise, print it
918
871
  end
872
+
873
+ html << @@chunks_hash[sub_chunk][:close] # print the close tag
919
874
 
920
- html += @@chunks_hash[sub_chunk][:close] # print the close tag
921
-
875
+ else
876
+ if !first_try
877
+ $stderr.puts "ERROR: endless loop detected"
878
+ break
879
+ end
880
+ first_try = false
922
881
  end
923
882
 
924
- if pos && pos == tref.length # we've eaten the whole string
925
- break
926
- else ## more string to come
927
- sub_chunk = get_sub_chunk_for(tref, chunk, pos)
928
- end
929
-
883
+ break if pos && pos == tref.length # we've eaten the whole string
884
+ sub_chunk = get_sub_chunk_for(tref, chunk, pos) # more string to come
885
+
930
886
  end
931
-
932
- return html
887
+
888
+ html.join
933
889
  end
934
-
890
+
935
891
  def self.get_sub_chunk_for(tref, chunk, pos)
936
892
 
937
893
  first_char = tref[pos, 1] # get a hint about the next chunk
@@ -949,17 +905,17 @@ class WikiCreole
949
905
  return contained_chunk.to_sym
950
906
  end
951
907
  end
952
-
953
- return nil
908
+
909
+ nil
954
910
  end
955
-
911
+
956
912
  # compile a regex that matches any of the patterns that interrupt the
957
913
  # current chunk.
958
914
  def self.delim(chunk)
959
915
  chunk = @@chunks_hash[chunk]
960
- if chunk[:stops].class.to_s == "Array"
916
+ if Array === chunk[:stops]
961
917
  regex = ''
962
- for stop in chunk[:stops]
918
+ chunk[:stops].each do |stop|
963
919
  stop = stop.to_sym
964
920
  if @@chunks_hash[stop].has_key?(:fwpat)
965
921
  regex += @@chunks_hash[stop][:fwpat] + "|"
@@ -968,59 +924,42 @@ class WikiCreole
968
924
  end
969
925
  end
970
926
  regex.chop!
971
- return regex
927
+ regex
972
928
  else
973
- return chunk[:stops]
929
+ chunk[:stops]
974
930
  end
975
931
  end
976
-
932
+
977
933
  # one-time optimization of the grammar - speeds the parser up a ton
978
- def self.init
934
+ def self.init
979
935
  return if @is_initialized
980
936
 
981
937
  @is_initialized = true
982
938
 
983
- # build an array of "plain content" characters by subtracting @specialchars
984
- # from ascii printable (ascii 32 to 126)
985
- for charnum in 32..126 do
986
- char = charnum.chr
987
- if @@specialchars.index(char).nil?
988
- @@plainchars << char
989
- end
990
- end
991
-
992
- # precompile a bunch of regexes
993
- for k in @@chunks_hash.keys do
939
+ # precompile a bunch of regexes
940
+ @@chunks_hash.keys.each do |k|
994
941
  c = @@chunks_hash[k]
995
942
  if c.has_key?(:curpat)
996
943
  c[:curpatcmp] = Regexp.compile('\G' + c[:curpat], Regexp::MULTILINE)
997
944
  end
998
-
945
+
999
946
  if c.has_key?(:stops)
1000
- c[:delim] = delim(k)
947
+ c[:delim] = Regexp.compile(delim(k), Regexp::MULTILINE)
1001
948
  end
1002
-
949
+
1003
950
  if c.has_key?(:contains) # store hints about each chunk to speed id
1004
951
  c[:calculated_hint_array_for] = {}
1005
-
1006
- for ct in c[:contains]
952
+
953
+ c[:contains].each do |ct|
1007
954
  ct = ct.to_sym
1008
-
1009
- if @@chunks_hash[ct].has_key?(:hint)
1010
- for hint in @@chunks_hash[ct][:hint]
1011
- if !c[:calculated_hint_array_for].has_key?(hint)
1012
- c[:calculated_hint_array_for][hint] = []
1013
- end
1014
- c[:calculated_hint_array_for][hint] << ct
1015
- end
955
+
956
+ (@@chunks_hash[ct][:hint] || []).each do |hint|
957
+ (c[:calculated_hint_array_for][hint] ||= []) << ct
1016
958
  end
1017
959
 
1018
960
  end
1019
961
  end
1020
962
  end
1021
-
1022
963
  end
1023
-
1024
-
1025
964
 
1026
- end
965
+ end
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'wiki_creole'
5
+ require 'ruby-prof'
6
+
7
+ WikiCreole.init
8
+
9
+ result = RubyProf.profile do
10
+ 10.times do
11
+ %w(amp block escape inline specialchars jsp_wiki).each do |name|
12
+ markup = File.read("./test/test_#{name}.markup")
13
+ parsed = WikiCreole.parse(markup, :top)
14
+ end
15
+ end
16
+ end
17
+
18
+ printer = RubyProf::GraphHtmlPrinter.new(result)
19
+ File.open("profiling.html", "w") do |file|
20
+ printer.print(file)
21
+ end
22
+
@@ -119,11 +119,7 @@ class TC_WikiCreole < Test::Unit::TestCase
119
119
 
120
120
  def test_user_supplied_creole_link_function
121
121
 
122
- uppercase = Proc.new {|s|
123
- s.upcase!
124
- s
125
- }
126
- WikiCreole.creole_link(uppercase)
122
+ WikiCreole.creole_link {|s| s.upcase }
127
123
 
128
124
  markup = "This is a paragraph with an uppercased [[ link ]].\nCheck it out."
129
125
  goodhtml = %Q{<p>This is a paragraph with an uppercased <a href="LINK">link</a>.\nCheck it out.</p>\n\n}
@@ -132,12 +128,12 @@ class TC_WikiCreole < Test::Unit::TestCase
132
128
 
133
129
  # set the link function back to being nil so that the rest of the tests
134
130
  # are not affected by the custom link function
135
- WikiCreole.creole_link(nil)
131
+ WikiCreole.creole_link
136
132
 
137
133
  end
138
134
 
139
135
  def test_puts_existing_creole_tags
140
- tags = WikiCreole.creole_tag()
136
+ tags = WikiCreole.creole_tags
141
137
  assert tags.index(/u: open\(<u>\) close\(<\/u>\)/)
142
138
  end
143
139
 
@@ -152,11 +148,7 @@ class TC_WikiCreole < Test::Unit::TestCase
152
148
  end
153
149
 
154
150
  def test_user_supplied_plugin_function
155
- uppercase = Proc.new {|s|
156
- s.upcase!
157
- s
158
- }
159
- WikiCreole.creole_plugin(uppercase)
151
+ WikiCreole.creole_plugin {|s| s.upcase }
160
152
 
161
153
  markup = "This is a paragraph with an uppercasing << plugin >>.\nCheck it out."
162
154
  goodhtml = %Q{<p>This is a paragraph with an uppercasing PLUGIN .\nCheck it out.</p>\n\n}
@@ -165,7 +157,7 @@ class TC_WikiCreole < Test::Unit::TestCase
165
157
 
166
158
  # set the link function back to being nil so that the rest of the tests
167
159
  # are not affected by the custom link function
168
- WikiCreole.creole_plugin(nil)
160
+ WikiCreole.creole_plugin
169
161
  end
170
162
 
171
163
  #-----------------------------------------------------------------------------
@@ -198,6 +190,10 @@ class TC_WikiCreole < Test::Unit::TestCase
198
190
  # are the same as they were in the original test.
199
191
  run_testfile("jsp_wiki")
200
192
  end
193
+
194
+ def test_nested_lists
195
+ run_testfile("nested_lists")
196
+ end
201
197
 
202
198
  def run_testfile(name)
203
199
  name = "test_" + name
@@ -0,0 +1,10 @@
1
+ <ul>
2
+ <li>correctly start with first level</li>
3
+ <ul>
4
+ <li>correctly continue with second level</li>
5
+ <ul>
6
+ <li>correctly enter third level</li>
7
+ </ul>
8
+ </ul>
9
+ <li>bug: jump back to first level</li>
10
+ </ul>
@@ -0,0 +1,4 @@
1
+ * correctly start with first level
2
+ ** correctly continue with second level
3
+ *** correctly enter third level
4
+ * bug: jump back to first level
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: WikiCreole
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gordon McCreight
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-12 00:00:00 -08:00
12
+ date: 2009-02-05 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -28,19 +28,22 @@ files:
28
28
  - LICENSE
29
29
  - Rakefile
30
30
  - lib/wiki_creole.rb
31
+ - test/profiling.rb
31
32
  - test/test_all.rb
32
- - test/test_escape.html
33
- - test/test_jsp_wiki.markup
34
- - test/test_amp.html
35
- - test/test_escape.markup
36
- - test/test_specialchars.html
37
33
  - test/test_amp.markup
38
- - test/test_inline.html
39
- - test/test_specialchars.markup
34
+ - test/test_amp.html
35
+ - test/test_block.markup
40
36
  - test/test_block.html
37
+ - test/test_escape.markup
38
+ - test/test_escape.html
41
39
  - test/test_inline.markup
42
- - test/test_block.markup
40
+ - test/test_inline.html
41
+ - test/test_jsp_wiki.markup
43
42
  - test/test_jsp_wiki.html
43
+ - test/test_nested_lists.markup
44
+ - test/test_nested_lists.html
45
+ - test/test_specialchars.markup
46
+ - test/test_specialchars.html
44
47
  has_rdoc: true
45
48
  homepage: http://github.com/gmccreight/wikicreole/tree/master
46
49
  post_install_message:
@@ -62,8 +65,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
62
65
  version:
63
66
  requirements: []
64
67
 
65
- rubyforge_project:
66
- rubygems_version: 1.2.0
68
+ rubyforge_project: wikicreole
69
+ rubygems_version: 1.3.1
67
70
  signing_key:
68
71
  specification_version: 2
69
72
  summary: A Creole-to-XHTML converter written in pure Ruby