wikitext 1.8 → 1.9

Sign up to get free protection for your applications and to get access to all the features.
data/ext/parser.c CHANGED
@@ -1042,12 +1042,15 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
1042
1042
  // process options hash
1043
1043
  int base_indent = 0;
1044
1044
  int base_heading_level = NUM2INT(rb_iv_get(self, "@base_heading_level"));
1045
+ VALUE link_proc = Qnil;
1045
1046
  if (!NIL_P(options) && TYPE(options) == T_HASH)
1046
1047
  {
1047
1048
  // :indent => 0 (or more)
1048
- if (rb_funcall(options, rb_intern("has_key?"), 1, ID2SYM(rb_intern("indent"))) == Qtrue)
1049
+ ID has_key = rb_intern("has_key?");
1050
+ ID id = ID2SYM(rb_intern("indent"));
1051
+ if (rb_funcall(options, has_key, 1, id) == Qtrue)
1049
1052
  {
1050
- VALUE indent = rb_hash_aref(options, ID2SYM(rb_intern("indent")));
1053
+ VALUE indent = rb_hash_aref(options, id);
1051
1054
  if (indent == Qfalse)
1052
1055
  base_indent = -1; // indentation disabled
1053
1056
  else
@@ -1059,8 +1062,14 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
1059
1062
  }
1060
1063
 
1061
1064
  // :base_heading_level => 0/1/2/3/4/5/6
1062
- if (rb_funcall(options, rb_intern("has_key?"), 1, ID2SYM(rb_intern("base_heading_level"))) == Qtrue)
1063
- base_heading_level = NUM2INT(rb_hash_aref(options, ID2SYM(rb_intern("base_heading_level"))));
1065
+ id = ID2SYM(rb_intern("base_heading_level"));
1066
+ if (rb_funcall(options, has_key, 1, id) == Qtrue)
1067
+ base_heading_level = NUM2INT(rb_hash_aref(options, id));
1068
+
1069
+ // :link_proc => lambda { |link_target| ... }
1070
+ id = ID2SYM(rb_intern("link_proc"));
1071
+ if (rb_funcall(options, has_key, 1, id) == Qtrue)
1072
+ link_proc = rb_hash_aref(options, id);
1064
1073
  }
1065
1074
 
1066
1075
  // normalize, regardless of whether this came from instance variable or override
@@ -2144,10 +2153,23 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
2144
2153
  }
2145
2154
  else
2146
2155
  wiki_trim_link_text(parser);
2156
+
2157
+ // perform "redlink" check before manipulating link_target
2158
+ if (NIL_P(link_proc))
2159
+ j = Qnil;
2160
+ else
2161
+ {
2162
+ j = rb_funcall(link_proc, rb_intern("call"), 1, string_from_str(parser->link_target));
2163
+ if (!NIL_P(j))
2164
+ {
2165
+ VALUE l = j; // can't cast inside StringValue macro
2166
+ j = StringValue(l);
2167
+ }
2168
+ }
2147
2169
  wiki_encode_link_target(parser);
2148
2170
  wiki_pop_from_stack_up_to(parser, output, LINK_START, true);
2149
2171
  parser->capture = NULL;
2150
- wiki_append_hyperlink(parser, prefix, parser->link_target, parser->link_text, Qnil, false);
2172
+ wiki_append_hyperlink(parser, prefix, parser->link_target, parser->link_text, j, false);
2151
2173
  str_clear(parser->link_target);
2152
2174
  str_clear(parser->link_text);
2153
2175
  }
@@ -25,7 +25,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'ext',
25
25
  'wikitext'))
26
26
 
27
27
  class NilClass
28
- def to_wikitext
28
+ def to_wikitext options = {}
29
29
  ''
30
30
  end
31
31
  alias :w :to_wikitext
@@ -22,5 +22,5 @@
22
22
  # POSSIBILITY OF SUCH DAMAGE.
23
23
 
24
24
  module Wikitext
25
- VERSION = '1.8'
25
+ VERSION = '1.9'
26
26
  end # module Wikitext
@@ -114,6 +114,119 @@ describe Wikitext::Parser, 'internal links (space to underscore off)' do
114
114
  @parser.parse('foo [[bar]] baz').should == expected # was a bug
115
115
  end
116
116
 
117
+ describe '"red link" support' do
118
+ it 'should accept a Proc object via the optional "link_proc" parameter' do
119
+ @parser.parse('foo', :link_proc => Proc.new { }).should == %Q{<p>foo</p>\n}
120
+ end
121
+
122
+ it 'should accept a lambda via the optional "link_proc" parameter' do
123
+ @parser.parse('foo', :link_proc => lambda { }).should == %Q{<p>foo</p>\n}
124
+ end
125
+
126
+ it 'should apply custom link CSS when supplied (Proc object version)' do
127
+ link_proc = Proc.new { |target| target == 'bar' ? 'redlink' : nil }
128
+ expected = %Q{<p><a href="/wiki/foo">foo</a> <a href="/wiki/bar" class="redlink">bar</a></p>\n}
129
+ @parser.parse('[[foo]] [[bar]]', :link_proc => link_proc).should == expected
130
+ end
131
+
132
+ it 'should apply custom link CSS when supplied (lambda version)' do
133
+ link_proc = lambda { |target| target == 'bar' ? 'redlink' : nil }
134
+ expected = %Q{<p><a href="/wiki/foo">foo</a> <a href="/wiki/bar" class="redlink">bar</a></p>\n}
135
+ @parser.parse('[[foo]] [[bar]]', :link_proc => link_proc).should == expected
136
+ end
137
+
138
+ it 'should apply no custom link CSS when supplied nil (Proc object version)' do
139
+ expected = %Q{<p><a href="/wiki/foo">foo</a></p>\n}
140
+ @parser.parse('[[foo]]', :link_proc => Proc.new { |target| nil }).should == expected
141
+ end
142
+
143
+ it 'should apply no custom link CSS when supplied nil (lambda version)' do
144
+ expected = %Q{<p><a href="/wiki/foo">foo</a></p>\n}
145
+ @parser.parse('[[foo]]', :link_proc => lambda { |target| nil }).should == expected
146
+ end
147
+
148
+ it 'should let exceptions bubble up from the link proc (Proc object version)' do
149
+ lambda { @parser.parse('[[foo]]', :link_proc => Proc.new { |target| raise 'bar' }) }.should raise_error(RuntimeError, /bar/)
150
+ end
151
+
152
+ it 'should let exceptions bubble up from the link proc (lambda version)' do
153
+ lambda { @parser.parse('[[foo]]', :link_proc => lambda { |target| raise 'bar' }) }.should raise_error(RuntimeError, /bar/)
154
+ end
155
+
156
+ it 'should complain if the link proc returns a non-stringy object (Proc object version)' do
157
+ lambda {
158
+ @parser.parse '[[foo]]', :link_proc => Proc.new { 1 }
159
+ }.should raise_error(TypeError, /can't convert/)
160
+ end
161
+
162
+ it 'should complain if the link proc returns a non-stringy object (lambda version)' do
163
+ lambda {
164
+ @parser.parse '[[foo]]', :link_proc => lambda { 1 }
165
+ }.should raise_error(TypeError, /can't convert/)
166
+ end
167
+
168
+ # a couple of Ruby's idiosynchrasies: different behaviour of lambdas and Procs
169
+ it 'should not complain if the Proc object accepts too many arguments' do
170
+ lambda {
171
+ @parser.parse '[[foo]]', :link_proc => Proc.new { |a,b| }
172
+ }.should_not raise_error(ArgumentError, /wrong number/)
173
+ end
174
+
175
+ it 'should complain if the lambda accepts too many arguments' do
176
+ lambda {
177
+ @parser.parse '[[foo]]', :link_proc => lambda { |a,b| }
178
+ }.should raise_error(ArgumentError, /wrong number/)
179
+ end
180
+
181
+ it 'should complain when "return" is used inside a "Proc.new" block' do
182
+ lambda {
183
+ @parser.parse '[[foo]]', :link_proc => Proc.new { return 'bar' }
184
+ }.should raise_error(LocalJumpError)
185
+ end
186
+
187
+ it 'should not complain when "return" is used inside a lambda' do
188
+ lambda {
189
+ @parser.parse '[[foo]]', :link_proc => lambda { return 'bar' }
190
+ }.should_not raise_error(LocalJumpError)
191
+ end
192
+
193
+ it 'should interact correctly with spaces in link targets (Proc object version)' do
194
+ link_proc = Proc.new { |target| target == 'bar b' ? 'redlink' : nil }
195
+ expected = %Q{<p><a href="/wiki/foo%20a">foo a</a> <a href="/wiki/bar%20b" class="redlink">bar b</a></p>\n}
196
+ @parser.parse('[[foo a]] [[bar b]]', :link_proc => link_proc).should == expected
197
+ end
198
+
199
+ it 'should interact correctly with spaces in link targets (lambda version)' do
200
+ link_proc = lambda { |target| target == 'bar b' ? 'redlink' : nil }
201
+ expected = %Q{<p><a href="/wiki/foo%20a">foo a</a> <a href="/wiki/bar%20b" class="redlink">bar b</a></p>\n}
202
+ @parser.parse('[[foo a]] [[bar b]]', :link_proc => link_proc).should == expected
203
+ end
204
+
205
+ it 'should interact correctly with explicit link text (Proc object version)' do
206
+ link_proc = Proc.new { |target| target == 'bar b' ? 'redlink' : nil }
207
+ expected = %Q{<p><a href="/wiki/foo%20a">hello</a> <a href="/wiki/bar%20b" class="redlink">world</a></p>\n}
208
+ @parser.parse('[[foo a|hello]] [[bar b|world]]', :link_proc => link_proc).should == expected
209
+ end
210
+
211
+ it 'should interact correctly with explicit link text (lambda version)' do
212
+ link_proc = lambda { |target| target == 'bar b' ? 'redlink' : nil }
213
+ expected = %Q{<p><a href="/wiki/foo%20a">hello</a> <a href="/wiki/bar%20b" class="redlink">world</a></p>\n}
214
+ @parser.parse('[[foo a|hello]] [[bar b|world]]', :link_proc => link_proc).should == expected
215
+ end
216
+
217
+ it 'should handle link targets with encoded parts (Proc object version)' do
218
+ link_proc = Proc.new { |target| target == 'información' ? 'redlink' : nil }
219
+ expected = %Q{<p><a href="/wiki/informaci%c3%b3n" class="redlink">informaci&#x00f3;n</a> <a href="/wiki/bar">bar</a></p>\n}
220
+ @parser.parse('[[información]] [[bar]]', :link_proc => link_proc).should == expected
221
+ end
222
+
223
+ it 'should handle link targets with encoded parts (lambda version)' do
224
+ link_proc = lambda { |target| target == 'información' ? 'redlink' : nil }
225
+ expected = %Q{<p><a href="/wiki/informaci%c3%b3n" class="redlink">informaci&#x00f3;n</a> <a href="/wiki/bar">bar</a></p>\n}
226
+ @parser.parse('[[información]] [[bar]]', :link_proc => link_proc).should == expected
227
+ end
228
+ end
229
+
117
230
  describe 'custom link text' do
118
231
  it 'should recognize link text placed after the separator' do
119
232
  @parser.parse('[[foo|bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
@@ -541,6 +654,119 @@ describe Wikitext::Parser, 'internal links (space to underscore on)' do
541
654
  @parser.parse('foo [[bar]] baz').should == expected # was a bug
542
655
  end
543
656
 
657
+ describe '"red link" support' do
658
+ it 'should accept a Proc object via the optional "link_proc" parameter' do
659
+ @parser.parse('foo', :link_proc => Proc.new { }).should == %Q{<p>foo</p>\n}
660
+ end
661
+
662
+ it 'should accept a lambda via the optional "link_proc" parameter' do
663
+ @parser.parse('foo', :link_proc => lambda { }).should == %Q{<p>foo</p>\n}
664
+ end
665
+
666
+ it 'should apply custom link CSS when supplied (Proc object version)' do
667
+ link_proc = Proc.new { |target| target == 'bar' ? 'redlink' : nil }
668
+ expected = %Q{<p><a href="/wiki/foo">foo</a> <a href="/wiki/bar" class="redlink">bar</a></p>\n}
669
+ @parser.parse('[[foo]] [[bar]]', :link_proc => link_proc).should == expected
670
+ end
671
+
672
+ it 'should apply custom link CSS when supplied (lambda version)' do
673
+ link_proc = lambda { |target| target == 'bar' ? 'redlink' : nil }
674
+ expected = %Q{<p><a href="/wiki/foo">foo</a> <a href="/wiki/bar" class="redlink">bar</a></p>\n}
675
+ @parser.parse('[[foo]] [[bar]]', :link_proc => link_proc).should == expected
676
+ end
677
+
678
+ it 'should apply no custom link CSS when supplied nil (Proc object version)' do
679
+ expected = %Q{<p><a href="/wiki/foo">foo</a></p>\n}
680
+ @parser.parse('[[foo]]', :link_proc => Proc.new { |target| nil }).should == expected
681
+ end
682
+
683
+ it 'should apply no custom link CSS when supplied nil (lambda version)' do
684
+ expected = %Q{<p><a href="/wiki/foo">foo</a></p>\n}
685
+ @parser.parse('[[foo]]', :link_proc => lambda { |target| nil }).should == expected
686
+ end
687
+
688
+ it 'should let exceptions bubble up from the link proc (Proc object version)' do
689
+ lambda { @parser.parse('[[foo]]', :link_proc => Proc.new { |target| raise 'bar' }) }.should raise_error(RuntimeError, /bar/)
690
+ end
691
+
692
+ it 'should let exceptions bubble up from the link proc (lambda version)' do
693
+ lambda { @parser.parse('[[foo]]', :link_proc => lambda { |target| raise 'bar' }) }.should raise_error(RuntimeError, /bar/)
694
+ end
695
+
696
+ it 'should complain if the link proc returns a non-stringy object (Proc object version)' do
697
+ lambda {
698
+ @parser.parse '[[foo]]', :link_proc => Proc.new { 1 }
699
+ }.should raise_error(TypeError, /can't convert/)
700
+ end
701
+
702
+ it 'should complain if the link proc returns a non-stringy object (lambda version)' do
703
+ lambda {
704
+ @parser.parse '[[foo]]', :link_proc => lambda { 1 }
705
+ }.should raise_error(TypeError, /can't convert/)
706
+ end
707
+
708
+ # a couple of Ruby's idiosynchrasies: different behaviour of lambdas and Procs
709
+ it 'should not complain if the Proc object accepts too many arguments' do
710
+ lambda {
711
+ @parser.parse '[[foo]]', :link_proc => Proc.new { |a,b| }
712
+ }.should_not raise_error(ArgumentError, /wrong number/)
713
+ end
714
+
715
+ it 'should complain if the lambda accepts too many arguments' do
716
+ lambda {
717
+ @parser.parse '[[foo]]', :link_proc => lambda { |a,b| }
718
+ }.should raise_error(ArgumentError, /wrong number/)
719
+ end
720
+
721
+ it 'should complain when "return" is used inside a "Proc.new" block' do
722
+ lambda {
723
+ @parser.parse '[[foo]]', :link_proc => Proc.new { return 'bar' }
724
+ }.should raise_error(LocalJumpError)
725
+ end
726
+
727
+ it 'should not complain when "return" is used inside a lambda' do
728
+ lambda {
729
+ @parser.parse '[[foo]]', :link_proc => lambda { return 'bar' }
730
+ }.should_not raise_error(LocalJumpError)
731
+ end
732
+
733
+ it 'should interact correctly with spaces in link targets (Proc object version)' do
734
+ link_proc = Proc.new { |target| target == 'bar b' ? 'redlink' : nil }
735
+ expected = %Q{<p><a href="/wiki/foo_a">foo a</a> <a href="/wiki/bar_b" class="redlink">bar b</a></p>\n}
736
+ @parser.parse('[[foo a]] [[bar b]]', :link_proc => link_proc).should == expected
737
+ end
738
+
739
+ it 'should interact correctly with spaces in link targets (lambda version)' do
740
+ link_proc = lambda { |target| target == 'bar b' ? 'redlink' : nil }
741
+ expected = %Q{<p><a href="/wiki/foo_a">foo a</a> <a href="/wiki/bar_b" class="redlink">bar b</a></p>\n}
742
+ @parser.parse('[[foo a]] [[bar b]]', :link_proc => link_proc).should == expected
743
+ end
744
+
745
+ it 'should interact correctly with explicit link text (Proc object version)' do
746
+ link_proc = Proc.new { |target| target == 'bar b' ? 'redlink' : nil }
747
+ expected = %Q{<p><a href="/wiki/foo_a">hello</a> <a href="/wiki/bar_b" class="redlink">world</a></p>\n}
748
+ @parser.parse('[[foo a|hello]] [[bar b|world]]', :link_proc => link_proc).should == expected
749
+ end
750
+
751
+ it 'should interact correctly with explicit link text (lambda version)' do
752
+ link_proc = lambda { |target| target == 'bar b' ? 'redlink' : nil }
753
+ expected = %Q{<p><a href="/wiki/foo_a">hello</a> <a href="/wiki/bar_b" class="redlink">world</a></p>\n}
754
+ @parser.parse('[[foo a|hello]] [[bar b|world]]', :link_proc => link_proc).should == expected
755
+ end
756
+
757
+ it 'should handle link targets with encoded parts (Proc object version)' do
758
+ link_proc = Proc.new { |target| target == 'información' ? 'redlink' : nil }
759
+ expected = %Q{<p><a href="/wiki/informaci%c3%b3n" class="redlink">informaci&#x00f3;n</a> <a href="/wiki/bar">bar</a></p>\n}
760
+ @parser.parse('[[información]] [[bar]]', :link_proc => link_proc).should == expected
761
+ end
762
+
763
+ it 'should handle link targets with encoded parts (lambda version)' do
764
+ link_proc = lambda { |target| target == 'información' ? 'redlink' : nil }
765
+ expected = %Q{<p><a href="/wiki/informaci%c3%b3n" class="redlink">informaci&#x00f3;n</a> <a href="/wiki/bar">bar</a></p>\n}
766
+ @parser.parse('[[información]] [[bar]]', :link_proc => link_proc).should == expected
767
+ end
768
+ end
769
+
544
770
  describe 'custom link text' do
545
771
  it 'should recognize link text placed after the separator' do
546
772
  @parser.parse('[[foo|bar]]').should == %Q{<p><a href="/wiki/foo">bar</a></p>\n}
@@ -33,4 +33,8 @@ describe NilClass, 'wikitext extensions' do
33
33
  it 'should provide a w method on the nil singleton' do
34
34
  nil.w.should == ''
35
35
  end
36
+
37
+ it 'should accept and ignore an optional options hash' do
38
+ lambda { nil.w :base_heading_level => 3 }.should_not raise_error
39
+ end
36
40
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wikitext
3
3
  version: !ruby/object:Gem::Version
4
- version: "1.8"
4
+ version: "1.9"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wincent Colaiuta
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-27 00:00:00 +02:00
12
+ date: 2009-08-06 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies: []
15
15