]> git.wincent.com - wikitext.git/commitdiff
Handle empty (whitespace-only) link targets
authorWincent Colaiuta <win@wincent.com>
Tue, 28 Apr 2009 10:11:57 +0000 (12:11 +0200)
committerWincent Colaiuta <win@wincent.com>
Tue, 28 Apr 2009 10:11:57 +0000 (12:11 +0200)
Previously we accepted buggy input like "[[ ]]", "[[  ]]"
and "[[   |foo]]" and dutifully turned it into empty links
like:

  <a href="/wiki/"></a>

And:

  <a href="/wiki/">foo</a>

It clearly makes no sense for a bad link like "[[  ]]" to
take the user back to the wiki index, so now we spit out
these bad links verbatim to provide feedback to the user
that there's something wrong with their input.

Signed-off-by: Wincent Colaiuta <win@wincent.com>
ext/parser.c
spec/regressions_spec.rb

index cc759612c80cf263a06a1651b319b1ecc573b9d5..a4d84b47514dd8d504283312bf75fd6000c13cb9 100644 (file)
@@ -846,6 +846,22 @@ VALUE Wikitext_parser_encode_special_link_target(VALUE self, VALUE in)
     return parser.link_target;
 }
 
+// returns 1 (true) if supplied string is blank (nil, empty, or all whitespace)
+// returns 0 (false) otherwise
+int _Wikitext_blank(VALUE str)
+{
+    if (NIL_P(str) || RSTRING_LEN(str) == 0)
+        return 1;
+    for (char *ptr = RSTRING_PTR(str),
+        *end = RSTRING_PTR(str) + RSTRING_LEN(str);
+        ptr < end; ptr++)
+    {
+        if (*ptr != ' ')
+            return 0;
+    }
+    return 1;
+}
+
 void _Wikitext_rollback_failed_link(parser_t *parser)
 {
     if (!IN(LINK_START))
@@ -2164,9 +2180,15 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
                 else if (IN(EXT_LINK_START))
                     // already in external link scope! (and in fact, must be capturing link_text right now)
                     rb_str_cat(i, link_end, sizeof(link_end) - 1);
-                else if (IN(LINK_START))
+                else if (IN(LINK_START)) // in internal link scope!
                 {
-                    // in internal link scope!
+                    if (_Wikitext_blank(parser->link_target))
+                    {
+                        // special case for inputs like "[[    ]]"
+                        _Wikitext_rollback_failed_link(parser);
+                        rb_str_cat(parser->output, link_end, sizeof(link_end) - 1);
+                        break;
+                    }
                     if (NIL_P(parser->link_text) || RSTRING_LEN(parser->link_text) == 0)
                         // use link target as link text
                         parser->link_text = _Wikitext_parser_sanitize_link_target(parser, Qfalse);
index 299389a28ff851e0d8f32235d8257f7a8ac62f9b..e466a16e65f168e72a46ca3cf02b4b41061ea887 100755 (executable)
@@ -849,8 +849,12 @@ describe Wikitext::Parser, 'regressions' do
 
   it 'should handle empty (whitespace only) link targets' do
     # no exception raised, but clearly not desirable behaviour
-    pending
-    @parser.parse('[[ ]]').should == "<p>[[ ]]</p>\n" # <p><a href="/wiki/"></a></p>\n
-    @parser.parse('[[  ]]').should == "<p>[[  ]]</p>\n" # <p><a href="/wiki/"></a></p>\n
+    # formerly these all returned: <p><a href="/wiki/"></a></p>\n
+    @parser.parse('[[ ]]').should == "<p>[[ ]]</p>\n"
+    @parser.parse('[[  ]]').should == "<p>[[  ]]</p>\n"
+    @parser.parse('[[  |]]').should == "<p>[[  |]]</p>\n"
+
+    # and this one returned: <p><a href="/wiki/">foo</a></p>\n
+    @parser.parse('[[  |foo]]').should == "<p>[[  |foo]]</p>\n"
   end
 end