WikiCreole 0.1.2 → 0.1.3

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