wikitext 1.3.2 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/parser.c +70 -48
- data/ext/token.c +2 -1
- data/ext/token.h +2 -1
- data/ext/wikitext.c +1 -2
- data/lib/wikitext/string.rb +1 -1
- data/lib/wikitext/version.rb +1 -1
- data/spec/external_link_spec.rb +28 -1
- data/spec/internal_link_spec.rb +35 -39
- data/spec/link_encoding_spec.rb +6 -4
- data/spec/vim_formatter.rb +41 -0
- data/spec/wikitext_spec.rb +0 -8
- metadata +3 -4
- data/ext/wikitext_ragel.c +0 -2968
- data/spec/#spec_helper.rb# +0 -78
data/ext/parser.c
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
// Copyright 2007-
|
1
|
+
// Copyright 2007-2009 Wincent Colaiuta
|
2
2
|
// This program is free software: you can redistribute it and/or modify
|
3
3
|
// it under the terms of the GNU General Public License as published by
|
4
4
|
// the Free Software Foundation, either version 3 of the License, or
|
@@ -37,9 +37,7 @@ typedef struct
|
|
37
37
|
ary_t *line_buffer; // stack for tracking raw tokens (not scope) on current line
|
38
38
|
VALUE pending_crlf; // boolean (Qtrue or Qfalse)
|
39
39
|
VALUE autolink; // boolean (Qtrue or Qfalse)
|
40
|
-
VALUE treat_slash_as_special; // boolean (Qtrue or Qfalse)
|
41
40
|
VALUE space_to_underscore; // boolean (Qtrue or Qfalse)
|
42
|
-
VALUE special_link; // boolean (Qtrue or Qfalse): is the current link_target a "special" link?
|
43
41
|
str_t *line_ending;
|
44
42
|
int base_indent; // controlled by the :indent option to Wikitext::Parser#parse
|
45
43
|
int current_indent; // fluctuates according to currently nested structures
|
@@ -398,6 +396,10 @@ void _Wikitext_pop_from_stack(parser_t *parser, VALUE target)
|
|
398
396
|
// not an HTML tag; so nothing to emit
|
399
397
|
break;
|
400
398
|
|
399
|
+
case PATH:
|
400
|
+
// not an HTML tag; so nothing to emit
|
401
|
+
break;
|
402
|
+
|
401
403
|
case SPACE:
|
402
404
|
// not an HTML tag (only used to separate an external link target from the link text); so nothing to emit
|
403
405
|
break;
|
@@ -619,7 +621,7 @@ VALUE _Wikitext_parser_trim_link_target(VALUE string)
|
|
619
621
|
// - non-printable (non-ASCII) characters converted to numeric entities
|
620
622
|
// - QUOT and AMP characters converted to named entities
|
621
623
|
// - if rollback is Qtrue, there is no special treatment of spaces
|
622
|
-
// - if rollback is Qfalse, leading and trailing whitespace trimmed
|
624
|
+
// - if rollback is Qfalse, leading and trailing whitespace trimmed
|
623
625
|
VALUE _Wikitext_parser_sanitize_link_target(parser_t *parser, VALUE rollback)
|
624
626
|
{
|
625
627
|
VALUE string = StringValue(parser->link_target); // raises if string is nil or doesn't quack like a string
|
@@ -725,8 +727,6 @@ VALUE Wikitext_parser_sanitize_link_target(VALUE self, VALUE string)
|
|
725
727
|
// ...the [[foo]] is...
|
726
728
|
// to be equivalent to:
|
727
729
|
// thing. [[Foo]] was...
|
728
|
-
// this is also where we check treat_slash_as_special is true and act accordingly
|
729
|
-
// basically any link target matching /\A[a-z]+\/\d+\z/ is flagged as special
|
730
730
|
static void _Wikitext_parser_encode_link_target(parser_t *parser)
|
731
731
|
{
|
732
732
|
VALUE in = StringValue(parser->link_target);
|
@@ -738,28 +738,6 @@ static void _Wikitext_parser_encode_link_target(parser_t *parser)
|
|
738
738
|
char *end = input + len;
|
739
739
|
static char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
740
740
|
|
741
|
-
// this potential shortcut requires an (admittedly cheap) prescan, so only do it when treat_slash_as_special is true
|
742
|
-
parser->special_link = Qfalse;
|
743
|
-
if (parser->treat_slash_as_special == Qtrue)
|
744
|
-
{
|
745
|
-
char *c = input; // \A
|
746
|
-
while (c < end && *c >= 'a' && *c <= 'z') // [a-z]
|
747
|
-
c++; // +
|
748
|
-
if (c > start && c < end && *c++ == '/') // \/
|
749
|
-
{
|
750
|
-
while (c < end && *c >= '0' && *c <= '9') // \d
|
751
|
-
{
|
752
|
-
c++; // +
|
753
|
-
if (c == end) // \z
|
754
|
-
{
|
755
|
-
// matches /\A[a-z]+\/\d+\z/ so no transformation required
|
756
|
-
parser->special_link = Qtrue;
|
757
|
-
return;
|
758
|
-
}
|
759
|
-
}
|
760
|
-
}
|
761
|
-
}
|
762
|
-
|
763
741
|
// to avoid most reallocations start with a destination buffer twice the size of the source
|
764
742
|
// this handles the most common case (where most chars are in the ASCII range and don't require more storage, but there are
|
765
743
|
// often quite a few spaces, which are encoded as "%20" and occupy 3 bytes)
|
@@ -827,7 +805,6 @@ VALUE Wikitext_parser_encode_link_target(VALUE self, VALUE in)
|
|
827
805
|
{
|
828
806
|
parser_t parser;
|
829
807
|
parser.link_target = in;
|
830
|
-
parser.treat_slash_as_special = Qfalse;
|
831
808
|
parser.space_to_underscore = Qfalse;
|
832
809
|
_Wikitext_parser_encode_link_target(&parser);
|
833
810
|
return parser.link_target;
|
@@ -838,7 +815,6 @@ VALUE Wikitext_parser_encode_special_link_target(VALUE self, VALUE in)
|
|
838
815
|
{
|
839
816
|
parser_t parser;
|
840
817
|
parser.link_target = in;
|
841
|
-
parser.treat_slash_as_special = Qtrue;
|
842
818
|
parser.space_to_underscore = Qfalse;
|
843
819
|
_Wikitext_parser_encode_link_target(&parser);
|
844
820
|
return parser.link_target;
|
@@ -906,7 +882,6 @@ VALUE Wikitext_parser_initialize(int argc, VALUE *argv, VALUE self)
|
|
906
882
|
VALUE internal_link_prefix = rb_str_new2("/wiki/");
|
907
883
|
VALUE img_prefix = rb_str_new2("/images/");
|
908
884
|
VALUE space_to_underscore = Qtrue;
|
909
|
-
VALUE treat_slash_as_special = Qtrue;
|
910
885
|
VALUE minimum_fulltext_token_length = INT2NUM(3);
|
911
886
|
|
912
887
|
// process options hash (override defaults)
|
@@ -921,7 +896,6 @@ VALUE Wikitext_parser_initialize(int argc, VALUE *argv, VALUE self)
|
|
921
896
|
internal_link_prefix = OVERRIDE_IF_SET(internal_link_prefix);
|
922
897
|
img_prefix = OVERRIDE_IF_SET(img_prefix);
|
923
898
|
space_to_underscore = OVERRIDE_IF_SET(space_to_underscore);
|
924
|
-
treat_slash_as_special = OVERRIDE_IF_SET(treat_slash_as_special);
|
925
899
|
minimum_fulltext_token_length = OVERRIDE_IF_SET(minimum_fulltext_token_length);
|
926
900
|
}
|
927
901
|
|
@@ -933,7 +907,6 @@ VALUE Wikitext_parser_initialize(int argc, VALUE *argv, VALUE self)
|
|
933
907
|
rb_iv_set(self, "@internal_link_prefix", internal_link_prefix);
|
934
908
|
rb_iv_set(self, "@img_prefix", img_prefix);
|
935
909
|
rb_iv_set(self, "@space_to_underscore", space_to_underscore);
|
936
|
-
rb_iv_set(self, "@treat_slash_as_special", treat_slash_as_special);
|
937
910
|
rb_iv_set(self, "@minimum_fulltext_token_length", minimum_fulltext_token_length);
|
938
911
|
return self;
|
939
912
|
}
|
@@ -1001,9 +974,7 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
1001
974
|
GC_WRAP_ARY(parser->line_buffer, line_buffer_gc);
|
1002
975
|
parser->pending_crlf = Qfalse;
|
1003
976
|
parser->autolink = rb_iv_get(self, "@autolink");
|
1004
|
-
parser->treat_slash_as_special = rb_iv_get(self, "@treat_slash_as_special");
|
1005
977
|
parser->space_to_underscore = rb_iv_get(self, "@space_to_underscore");
|
1006
|
-
parser->special_link = Qfalse;
|
1007
978
|
parser->line_ending = str_new_from_string(line_ending);
|
1008
979
|
GC_WRAP_STR(parser->line_ending, line_ending_gc);
|
1009
980
|
parser->base_indent = base_indent;
|
@@ -1011,6 +982,12 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
1011
982
|
parser->tabulation = str_new();
|
1012
983
|
GC_WRAP_STR(parser->tabulation, tabulation_gc);
|
1013
984
|
|
985
|
+
// this simple looping design leads to a single enormous function,
|
986
|
+
// but it's faster than doing actual recursive descent and also secure in the face of
|
987
|
+
// malicious input that seeks to overflow the stack
|
988
|
+
// (with "<blockquote><blockquote><blockquote>..." times by 10,000, for example)
|
989
|
+
// given that we expect to deal with a lot of malformed input, a recursive descent design is less appropriate
|
990
|
+
// than a straightforward looping translator like this one anyway
|
1014
991
|
token_t _token;
|
1015
992
|
_token.type = NO_TOKEN;
|
1016
993
|
token_t *token = NULL;
|
@@ -1945,13 +1922,58 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
1945
1922
|
}
|
1946
1923
|
break;
|
1947
1924
|
|
1925
|
+
case PATH:
|
1926
|
+
if (IN(NO_WIKI_START) || IN(PRE) || IN(PRE_START))
|
1927
|
+
rb_str_cat(parser->output, token->start, TOKEN_LEN(token));
|
1928
|
+
else if (IN(EXT_LINK_START))
|
1929
|
+
{
|
1930
|
+
if (NIL_P(parser->link_target))
|
1931
|
+
{
|
1932
|
+
// this must be our link target: look ahead to make sure we see the space we're expecting to see
|
1933
|
+
i = TOKEN_TEXT(token);
|
1934
|
+
NEXT_TOKEN();
|
1935
|
+
if (token->type == SPACE)
|
1936
|
+
{
|
1937
|
+
ary_push(parser->scope, PATH);
|
1938
|
+
ary_push(parser->scope, SPACE);
|
1939
|
+
parser->link_target = i;
|
1940
|
+
parser->link_text = rb_str_new2("");
|
1941
|
+
parser->capture = parser->link_text;
|
1942
|
+
token = NULL; // silently consume space
|
1943
|
+
}
|
1944
|
+
else
|
1945
|
+
{
|
1946
|
+
// didn't see the space! this must be an error
|
1947
|
+
_Wikitext_pop_from_stack(parser, Qnil);
|
1948
|
+
_Wikitext_pop_excess_elements(parser);
|
1949
|
+
_Wikitext_start_para_if_necessary(parser);
|
1950
|
+
rb_str_cat(parser->output, ext_link_start, sizeof(ext_link_start) - 1);
|
1951
|
+
rb_str_append(parser->output, i);
|
1952
|
+
}
|
1953
|
+
}
|
1954
|
+
else
|
1955
|
+
{
|
1956
|
+
if (NIL_P(parser->link_text))
|
1957
|
+
// this must be the first part of our link text
|
1958
|
+
parser->link_text = TOKEN_TEXT(token);
|
1959
|
+
else
|
1960
|
+
// add to existing link text
|
1961
|
+
rb_str_cat(parser->link_text, token->start, TOKEN_LEN(token));
|
1962
|
+
}
|
1963
|
+
}
|
1964
|
+
else
|
1965
|
+
{
|
1966
|
+
i = NIL_P(parser->capture) ? parser->output : parser->capture;
|
1967
|
+
_Wikitext_pop_excess_elements(parser);
|
1968
|
+
_Wikitext_start_para_if_necessary(parser);
|
1969
|
+
rb_str_cat(i, token->start, TOKEN_LEN(token));
|
1970
|
+
}
|
1971
|
+
break;
|
1972
|
+
|
1948
1973
|
// internal links (links to other wiki articles) look like this:
|
1949
1974
|
// [[another article]] (would point at, for example, "/wiki/another_article")
|
1950
1975
|
// [[the other article|the link text we'll use for it]]
|
1951
1976
|
// [[the other article | the link text we'll use for it]]
|
1952
|
-
// note that the forward slash is a reserved character which changes the meaning of an internal link;
|
1953
|
-
// this is a link that is external to the wiki but internal to the site as a whole:
|
1954
|
-
// [[bug/12]] (a relative link to "/bug/12")
|
1955
1977
|
// MediaWiki has strict requirements about what it will accept as a link target:
|
1956
1978
|
// all wikitext markup is disallowed:
|
1957
1979
|
// example [[foo ''bar'' baz]]
|
@@ -1968,7 +1990,7 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
1968
1990
|
// example [[foo €]]
|
1969
1991
|
// renders <a href="/wiki/Foo_%E2%82%AC">foo €</a>
|
1970
1992
|
// we'll impose similar restrictions here for the link target; allowed tokens will be:
|
1971
|
-
// SPACE, SPECIAL_URI_CHARS, PRINTABLE, ALNUM, DEFAULT, QUOT and AMP
|
1993
|
+
// SPACE, SPECIAL_URI_CHARS, PRINTABLE, PATH, ALNUM, DEFAULT, QUOT and AMP
|
1972
1994
|
// everything else will be rejected
|
1973
1995
|
case LINK_START:
|
1974
1996
|
i = NIL_P(parser->capture) ? parser->output : parser->capture;
|
@@ -2002,6 +2024,7 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
2002
2024
|
{
|
2003
2025
|
if (type == SPACE ||
|
2004
2026
|
type == SPECIAL_URI_CHARS ||
|
2027
|
+
type == PATH ||
|
2005
2028
|
type == PRINTABLE ||
|
2006
2029
|
type == ALNUM ||
|
2007
2030
|
type == DEFAULT ||
|
@@ -2072,10 +2095,7 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
2072
2095
|
_Wikitext_parser_encode_link_target(parser);
|
2073
2096
|
_Wikitext_pop_from_stack_up_to(parser, i, LINK_START, Qtrue);
|
2074
2097
|
parser->capture = Qnil;
|
2075
|
-
|
2076
|
-
i = _Wikitext_hyperlink(rb_str_new2("/"), parser->link_target, parser->link_text, Qnil);
|
2077
|
-
else
|
2078
|
-
i = _Wikitext_hyperlink(prefix, parser->link_target, parser->link_text, Qnil);
|
2098
|
+
i = _Wikitext_hyperlink(prefix, parser->link_target, parser->link_text, Qnil);
|
2079
2099
|
rb_str_append(parser->output, i);
|
2080
2100
|
parser->link_target = Qnil;
|
2081
2101
|
parser->link_text = Qnil;
|
@@ -2090,6 +2110,7 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
2090
2110
|
|
2091
2111
|
// external links look like this:
|
2092
2112
|
// [http://google.com/ the link text]
|
2113
|
+
// [/other/page/on/site see this page]
|
2093
2114
|
// strings in square brackets which don't match this syntax get passed through literally; eg:
|
2094
2115
|
// he was very angery [sic] about the turn of events
|
2095
2116
|
case EXT_LINK_START:
|
@@ -2129,9 +2150,9 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
2129
2150
|
_Wikitext_pop_excess_elements(parser);
|
2130
2151
|
_Wikitext_start_para_if_necessary(parser);
|
2131
2152
|
|
2132
|
-
// look ahead: expect
|
2153
|
+
// look ahead: expect an absolute URI (with protocol) or "relative" (path) URI
|
2133
2154
|
NEXT_TOKEN();
|
2134
|
-
if (token->type == URI)
|
2155
|
+
if (token->type == URI || token->type == PATH)
|
2135
2156
|
ary_push(parser->scope, EXT_LINK_START); // so far so good, jump back to the top of the loop
|
2136
2157
|
else
|
2137
2158
|
// only get here if there was a syntax error (missing URI)
|
@@ -2155,9 +2176,10 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
2155
2176
|
else
|
2156
2177
|
{
|
2157
2178
|
// success!
|
2179
|
+
j = IN(PATH) ? Qnil : parser->external_link_class;
|
2158
2180
|
_Wikitext_pop_from_stack_up_to(parser, i, EXT_LINK_START, Qtrue);
|
2159
2181
|
parser->capture = Qnil;
|
2160
|
-
i = _Wikitext_hyperlink(Qnil, parser->link_target, parser->link_text,
|
2182
|
+
i = _Wikitext_hyperlink(Qnil, parser->link_target, parser->link_text, j);
|
2161
2183
|
rb_str_append(parser->output, i);
|
2162
2184
|
}
|
2163
2185
|
parser->link_target = Qnil;
|
@@ -2275,13 +2297,13 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
2275
2297
|
_Wikitext_pop_excess_elements(parser);
|
2276
2298
|
_Wikitext_start_para_if_necessary(parser);
|
2277
2299
|
|
2278
|
-
// scan ahead consuming PRINTABLE, ALNUM and SPECIAL_URI_CHARS tokens
|
2300
|
+
// scan ahead consuming PATH, PRINTABLE, ALNUM and SPECIAL_URI_CHARS tokens
|
2279
2301
|
// will cheat here and abuse the link_target capture buffer to accumulate text
|
2280
2302
|
if (NIL_P(parser->link_target))
|
2281
2303
|
parser->link_target = rb_str_new2("");
|
2282
2304
|
while (NEXT_TOKEN(), (type = token->type))
|
2283
2305
|
{
|
2284
|
-
if (type == PRINTABLE || type == ALNUM || type == SPECIAL_URI_CHARS)
|
2306
|
+
if (type == PATH || type == PRINTABLE || type == ALNUM || type == SPECIAL_URI_CHARS)
|
2285
2307
|
rb_str_cat(parser->link_target, token->start, TOKEN_LEN(token));
|
2286
2308
|
else if (type == IMG_END)
|
2287
2309
|
{
|
data/ext/token.c
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
// Copyright 2008 Wincent Colaiuta
|
1
|
+
// Copyright 2008-2009 Wincent Colaiuta
|
2
2
|
// This program is free software: you can redistribute it and/or modify
|
3
3
|
// it under the terms of the GNU General Public License as published by
|
4
4
|
// the Free Software Foundation, either version 3 of the License, or
|
@@ -63,6 +63,7 @@ VALUE Wikitext_parser_token_types(VALUE self)
|
|
63
63
|
SET_TOKEN_TYPE(H1_END);
|
64
64
|
SET_TOKEN_TYPE(URI);
|
65
65
|
SET_TOKEN_TYPE(MAIL);
|
66
|
+
SET_TOKEN_TYPE(PATH);
|
66
67
|
SET_TOKEN_TYPE(LINK_START);
|
67
68
|
SET_TOKEN_TYPE(LINK_END);
|
68
69
|
SET_TOKEN_TYPE(EXT_LINK_START);
|
data/ext/token.h
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
// Copyright 2008 Wincent Colaiuta
|
1
|
+
// Copyright 2008-2009 Wincent Colaiuta
|
2
2
|
// This program is free software: you can redistribute it and/or modify
|
3
3
|
// it under the terms of the GNU General Public License as published by
|
4
4
|
// the Free Software Foundation, either version 3 of the License, or
|
@@ -69,6 +69,7 @@ enum token_types {
|
|
69
69
|
H1_END,
|
70
70
|
URI,
|
71
71
|
MAIL,
|
72
|
+
PATH,
|
72
73
|
LINK_START,
|
73
74
|
LINK_END,
|
74
75
|
EXT_LINK_START,
|
data/ext/wikitext.c
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
// Copyright 2008 Wincent Colaiuta
|
1
|
+
// Copyright 2008-2009 Wincent Colaiuta
|
2
2
|
// This program is free software: you can redistribute it and/or modify
|
3
3
|
// it under the terms of the GNU General Public License as published by
|
4
4
|
// the Free Software Foundation, either version 3 of the License, or
|
@@ -42,7 +42,6 @@ void Init_wikitext()
|
|
42
42
|
rb_define_attr(cWikitextParser, "external_link_class", Qtrue, Qtrue);
|
43
43
|
rb_define_attr(cWikitextParser, "mailto_class", Qtrue, Qtrue);
|
44
44
|
rb_define_attr(cWikitextParser, "autolink", Qtrue, Qtrue);
|
45
|
-
rb_define_attr(cWikitextParser, "treat_slash_as_special", Qtrue, Qtrue);
|
46
45
|
rb_define_attr(cWikitextParser, "space_to_underscore", Qtrue, Qtrue);
|
47
46
|
rb_define_attr(cWikitextParser, "minimum_fulltext_token_length", Qtrue, Qtrue);
|
48
47
|
|
data/lib/wikitext/string.rb
CHANGED
@@ -26,6 +26,6 @@ private
|
|
26
26
|
# if speed later becomes a concern can whip up a Ragel C extension to do it
|
27
27
|
# TODO: make this customizable (accept a lambda that performs preprocessing)
|
28
28
|
def wikitext_preprocess
|
29
|
-
gsub /\b(bug|issue|request|ticket) #(\d+)/i, '[
|
29
|
+
gsub /\b(bug|issue|request|ticket) #(\d+)/i, '[/issues/\2 \1 #\2]'
|
30
30
|
end
|
31
31
|
end
|
data/lib/wikitext/version.rb
CHANGED
data/spec/external_link_spec.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# Copyright 2007-
|
2
|
+
# Copyright 2007-2009 Wincent Colaiuta
|
3
3
|
# This program is free software: you can redistribute it and/or modify
|
4
4
|
# it under the terms of the GNU General Public License as published by
|
5
5
|
# the Free Software Foundation, either version 3 of the License, or
|
@@ -48,6 +48,33 @@ describe Wikitext::Parser, 'external links' do
|
|
48
48
|
@parser.parse('[mailto:user@example.com john]').should == expected
|
49
49
|
end
|
50
50
|
|
51
|
+
it 'should format absolute path links' do
|
52
|
+
expected = %Q{<p><a href="/foo/bar">fb</a></p>\n} # note no "external" class
|
53
|
+
@parser.parse('[/foo/bar fb]').should == expected
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should format deeply nested absolute path links' do
|
57
|
+
expected = %Q{<p><a href="/foo/bar/baz/bing">fb</a></p>\n} # note no "external" class
|
58
|
+
@parser.parse('[/foo/bar/baz/bing fb]').should == expected
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should format minimal absolute path links' do
|
62
|
+
expected = %Q{<p><a href="/">fb</a></p>\n} # note no "external" class
|
63
|
+
@parser.parse('[/ fb]').should == expected
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should format absolute path links with trailing slashes' do
|
67
|
+
expected = %Q{<p><a href="/foo/bar/">fb</a></p>\n} # note no "external" class
|
68
|
+
@parser.parse('[/foo/bar/ fb]').should == expected
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should not format relative path links' do
|
72
|
+
# relative paths don't make sense in wikitext because
|
73
|
+
# they could be displayed anywhere (eg. /wiki/article, /dashboard/ etc)
|
74
|
+
expected = %Q{<p>[foo/bar fb]</p>\n}
|
75
|
+
@parser.parse('[foo/bar fb]').should == expected
|
76
|
+
end
|
77
|
+
|
51
78
|
it 'should treat runs of spaces after the link target as a single space' do
|
52
79
|
expected = %Q{<p><a href="http://google.com/" class="external">Google</a></p>\n}
|
53
80
|
@parser.parse('[http://google.com/ Google]').should == expected
|
data/spec/internal_link_spec.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# Copyright 2007-
|
2
|
+
# Copyright 2007-2009 Wincent Colaiuta
|
3
3
|
# This program is free software: you can redistribute it and/or modify
|
4
4
|
# it under the terms of the GNU General Public License as published by
|
5
5
|
# the Free Software Foundation, either version 3 of the License, or
|
@@ -94,6 +94,11 @@ describe Wikitext::Parser, 'internal links (space to underscore off)' do
|
|
94
94
|
@parser.parse('[[foo, "bar" & baz €]]').should == expected
|
95
95
|
end
|
96
96
|
|
97
|
+
it 'should handle embedded paths' do
|
98
|
+
expected = %Q{<p><a href="/wiki/foo%2fbar">foo/bar</a></p>\n}
|
99
|
+
@parser.parse('[[foo/bar]]').should == expected
|
100
|
+
end
|
101
|
+
|
97
102
|
it 'should handle links in paragraph flows' do
|
98
103
|
expected = %Q{<p>foo <a href="/wiki/bar">bar</a> baz</p>\n}
|
99
104
|
@parser.parse('foo [[bar]] baz').should == expected # was a bug
|
@@ -252,6 +257,11 @@ describe Wikitext::Parser, 'internal links (space to underscore off)' do
|
|
252
257
|
expected = %Q{<p><a href="/wiki/foo">bar ]</a></p>\n}
|
253
258
|
@parser.parse("[[foo|bar <nowiki>]</nowiki>]]").should == expected
|
254
259
|
end
|
260
|
+
|
261
|
+
it 'should handle paths in custom link text' do
|
262
|
+
expected = %Q{<p><a href="/wiki/hello%2fworld">foo/bar</a></p>\n}
|
263
|
+
@parser.parse('[[hello/world|foo/bar]]').should == expected
|
264
|
+
end
|
255
265
|
end
|
256
266
|
|
257
267
|
describe 'overriding the link prefix' do
|
@@ -266,36 +276,30 @@ describe Wikitext::Parser, 'internal links (space to underscore off)' do
|
|
266
276
|
end
|
267
277
|
end
|
268
278
|
|
279
|
+
# "special links" existed in internal links up to and including wikitext version 1.3.2
|
280
|
+
# from version 1.4.0 onwards this feature was changed to instead work with external links
|
281
|
+
# as such, all of these specs have been updated to make sure that the old behaviour was removed
|
269
282
|
describe 'special links' do
|
270
|
-
it 'should recognize links of the form "bug/10" as special links' do
|
271
|
-
@parser.parse('[[bug/10]]').should
|
272
|
-
@parser.parse('[[issue/25]]').should
|
273
|
-
@parser.parse('[[post/7]]').should
|
283
|
+
it 'should no longer recognize links of the form "bug/10" as special links' do
|
284
|
+
@parser.parse('[[bug/10]]').should == %Q{<p><a href="/wiki/bug%2f10">bug/10</a></p>\n}
|
285
|
+
@parser.parse('[[issue/25]]').should == %Q{<p><a href="/wiki/issue%2f25">issue/25</a></p>\n}
|
286
|
+
@parser.parse('[[post/7]]').should == %Q{<p><a href="/wiki/post%2f7">post/7</a></p>\n}
|
274
287
|
end
|
275
288
|
|
276
|
-
it 'should
|
277
|
-
@parser.
|
278
|
-
@parser.parse('[[bug/10]]').should == %Q{<p><a href="/wiki/bug%2f10">bug/10</a></p>\n}
|
279
|
-
@parser.parse('[[issue/25]]').should == %Q{<p><a href="/wiki/issue%2f25">issue/25</a></p>\n}
|
280
|
-
@parser.parse('[[post/7]]').should == %Q{<p><a href="/wiki/post%2f7">post/7</a></p>\n}
|
289
|
+
it 'should no longer accept custom link text in conjunction with special links' do
|
290
|
+
@parser.parse('[[bug/10|bug #10]]').should == %Q{<p><a href="/wiki/bug%2f10">bug #10</a></p>\n}
|
281
291
|
end
|
282
292
|
|
283
|
-
it 'should
|
284
|
-
@parser.parse('[[bug/10|bug #10]]').should == %Q{<p><a href="/bug/10">bug #10</a></p>\n}
|
285
|
-
end
|
286
|
-
|
287
|
-
it 'should ignore link prefix overrides when emitting special links' do
|
293
|
+
it 'should not emit special links regardless of custom internal link prefix overrides' do
|
288
294
|
@parser.internal_link_prefix = '/custom/'
|
289
|
-
@parser.parse('[[bug/10]]').should == %Q{<p><a href="/bug
|
295
|
+
@parser.parse('[[bug/10]]').should == %Q{<p><a href="/custom/bug%2f10">bug/10</a></p>\n}
|
290
296
|
end
|
291
297
|
|
292
|
-
it 'should not classify links as special merely because of the presence of a slash' do
|
293
|
-
# we want the syntax to be tight to minimize false positives
|
298
|
+
it 'should (still) not classify links as special merely because of the presence of a slash' do
|
294
299
|
@parser.parse('[[foo/bar]]').should == %Q{<p><a href="/wiki/foo%2fbar">foo/bar</a></p>\n}
|
295
300
|
end
|
296
301
|
|
297
|
-
it 'should not accept special links which have a leading forward slash' do
|
298
|
-
# this is a syntax error
|
302
|
+
it 'should (still) not accept special links which have a leading forward slash' do
|
299
303
|
@parser.parse('[[/bug/10]]').should == %Q{<p><a href="/wiki/%2fbug%2f10">/bug/10</a></p>\n}
|
300
304
|
end
|
301
305
|
end
|
@@ -694,36 +698,28 @@ describe Wikitext::Parser, 'internal links (space to underscore on)' do
|
|
694
698
|
end
|
695
699
|
end
|
696
700
|
|
701
|
+
# see note above about "special links" being removed from internal links from 1.4.0 onwards
|
697
702
|
describe 'special links' do
|
698
|
-
it 'should recognize links of the form "bug/10" as special links' do
|
699
|
-
@parser.parse('[[bug/10]]').should
|
700
|
-
@parser.parse('[[issue/25]]').should
|
701
|
-
@parser.parse('[[post/7]]').should
|
702
|
-
end
|
703
|
-
|
704
|
-
it 'should not recognize special links when "treat_slash_as_special" is set to false' do
|
705
|
-
@parser.treat_slash_as_special = false
|
706
|
-
@parser.parse('[[bug/10]]').should == %Q{<p><a href="/wiki/bug%2f10">bug/10</a></p>\n}
|
707
|
-
@parser.parse('[[issue/25]]').should == %Q{<p><a href="/wiki/issue%2f25">issue/25</a></p>\n}
|
708
|
-
@parser.parse('[[post/7]]').should == %Q{<p><a href="/wiki/post%2f7">post/7</a></p>\n}
|
703
|
+
it 'should no longer recognize links of the form "bug/10" as special links' do
|
704
|
+
@parser.parse('[[bug/10]]').should == %Q{<p><a href="/wiki/bug%2f10">bug/10</a></p>\n}
|
705
|
+
@parser.parse('[[issue/25]]').should == %Q{<p><a href="/wiki/issue%2f25">issue/25</a></p>\n}
|
706
|
+
@parser.parse('[[post/7]]').should == %Q{<p><a href="/wiki/post%2f7">post/7</a></p>\n}
|
709
707
|
end
|
710
708
|
|
711
|
-
it 'should accept custom link text in conjunction with special links' do
|
712
|
-
@parser.parse('[[bug/10|bug #10]]').should == %Q{<p><a href="/bug
|
709
|
+
it 'should no longer accept custom link text in conjunction with special links' do
|
710
|
+
@parser.parse('[[bug/10|bug #10]]').should == %Q{<p><a href="/wiki/bug%2f10">bug #10</a></p>\n}
|
713
711
|
end
|
714
712
|
|
715
|
-
it 'should
|
713
|
+
it 'should not emit special links regardless of custom internal link prefix overrides' do
|
716
714
|
@parser.internal_link_prefix = '/custom/'
|
717
|
-
@parser.parse('[[bug/10]]').should == %Q{<p><a href="/bug
|
715
|
+
@parser.parse('[[bug/10]]').should == %Q{<p><a href="/custom/bug%2f10">bug/10</a></p>\n}
|
718
716
|
end
|
719
717
|
|
720
|
-
it 'should not classify links as special merely because of the presence of a slash' do
|
721
|
-
# we want the syntax to be tight to minimize false positives
|
718
|
+
it 'should (still) not classify links as special merely because of the presence of a slash' do
|
722
719
|
@parser.parse('[[foo/bar]]').should == %Q{<p><a href="/wiki/foo%2fbar">foo/bar</a></p>\n}
|
723
720
|
end
|
724
721
|
|
725
|
-
it 'should not accept special links which have a leading forward slash' do
|
726
|
-
# this is a syntax error
|
722
|
+
it 'should (still) not accept special links which have a leading forward slash' do
|
727
723
|
@parser.parse('[[/bug/10]]').should == %Q{<p><a href="/wiki/%2fbug%2f10">/bug/10</a></p>\n}
|
728
724
|
end
|
729
725
|
end
|
data/spec/link_encoding_spec.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# Copyright 2007-
|
2
|
+
# Copyright 2007-2009 Wincent Colaiuta
|
3
3
|
# This program is free software: you can redistribute it and/or modify
|
4
4
|
# it under the terms of the GNU General Public License as published by
|
5
5
|
# the Free Software Foundation, either version 3 of the License, or
|
@@ -87,10 +87,12 @@ describe Wikitext, 'encoding a link target' do
|
|
87
87
|
|
88
88
|
# "special" links don't get transformed in any way
|
89
89
|
describe 'special links' do
|
90
|
-
|
90
|
+
|
91
|
+
# as of version 1.4.0 the encode_link_target function no longer handles special links
|
92
|
+
it 'should (no longer) recognize links which match /\A[a-z]+\/\d+\z/ as being special' do
|
91
93
|
string = 'foo/10'
|
92
|
-
Wikitext::Parser.encode_special_link_target(string).should ==
|
93
|
-
Wikitext::Parser.encode_link_target(string).
|
94
|
+
Wikitext::Parser.encode_special_link_target(string).should == 'foo%2f10'
|
95
|
+
Wikitext::Parser.encode_link_target(string).should == 'foo%2f10'
|
94
96
|
end
|
95
97
|
|
96
98
|
it "should not recognize links which don't match at /\A/ as being special" do
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec/runner/formatter/base_text_formatter'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
# Format spec results for display in the Vim quickfix window
|
5
|
+
# Use this custom formatter like this:
|
6
|
+
# spec -r spec/vim_formatter.rb -f Spec::Runner::Formatter::VimFormatter spec
|
7
|
+
module Spec
|
8
|
+
module Runner
|
9
|
+
module Formatter
|
10
|
+
class VimFormatter < BaseTextFormatter
|
11
|
+
|
12
|
+
# TODO: handle pending issues
|
13
|
+
# TODO: vim-side function for printing progress
|
14
|
+
def dump_failure counter, failure
|
15
|
+
path = failure.exception.backtrace.find do |frame|
|
16
|
+
frame =~ %r{\bspec/.*_spec\.rb:\d+\z}
|
17
|
+
end
|
18
|
+
message = failure.exception.message.gsub("\n", ' ')
|
19
|
+
@output.puts "#{relativize_path(path)}: #{message}" if path
|
20
|
+
end
|
21
|
+
|
22
|
+
def dump_pending; end
|
23
|
+
|
24
|
+
def dump_summary duration, example_count, failure_count, pending_count
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def relativize_path path
|
30
|
+
@wd ||= Pathname.new Dir.getwd
|
31
|
+
begin
|
32
|
+
return Pathname.new(path).relative_path_from(@wd)
|
33
|
+
rescue ArgumentError
|
34
|
+
# raised unless both paths relative, or both absolute
|
35
|
+
return path
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end # class VimFormatter
|
39
|
+
end # module Formatter
|
40
|
+
end # module Runner
|
41
|
+
end # module Spec
|
data/spec/wikitext_spec.rb
CHANGED
@@ -49,10 +49,6 @@ describe Wikitext::Parser do
|
|
49
49
|
@parser.space_to_underscore.should == true
|
50
50
|
end
|
51
51
|
|
52
|
-
it 'should treat slash as special by default' do
|
53
|
-
@parser.treat_slash_as_special.should == true
|
54
|
-
end
|
55
|
-
|
56
52
|
describe 'overriding defaults at initialization time' do
|
57
53
|
it 'should allow overriding of autolink' do
|
58
54
|
Wikitext::Parser.new(:autolink => false).autolink.should == false
|
@@ -83,10 +79,6 @@ describe Wikitext::Parser do
|
|
83
79
|
it 'should allow overriding of space-to-underscore' do
|
84
80
|
Wikitext::Parser.new(:space_to_underscore => false).space_to_underscore.should == false
|
85
81
|
end
|
86
|
-
|
87
|
-
it 'should allow overriding of treat slash as special' do
|
88
|
-
Wikitext::Parser.new(:treat_slash_as_special => false).treat_slash_as_special.should == false
|
89
|
-
end
|
90
82
|
end
|
91
83
|
|
92
84
|
describe 'overriding defaults at parse time' do
|
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.
|
4
|
+
version: 1.4.0
|
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-
|
12
|
+
date: 2009-02-02 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -22,7 +22,6 @@ extensions:
|
|
22
22
|
extra_rdoc_files: []
|
23
23
|
|
24
24
|
files:
|
25
|
-
- spec/#spec_helper.rb#
|
26
25
|
- spec/autolinking_spec.rb
|
27
26
|
- spec/blockquote_spec.rb
|
28
27
|
- spec/em_spec.rb
|
@@ -59,6 +58,7 @@ files:
|
|
59
58
|
- spec/tt_spec.rb
|
60
59
|
- spec/ul_spec.rb
|
61
60
|
- spec/version_spec.rb
|
61
|
+
- spec/vim_formatter.rb
|
62
62
|
- spec/wikitext_spec.rb
|
63
63
|
- ext/extconf.rb
|
64
64
|
- ext/ary.c
|
@@ -66,7 +66,6 @@ files:
|
|
66
66
|
- ext/str.c
|
67
67
|
- ext/token.c
|
68
68
|
- ext/wikitext.c
|
69
|
-
- ext/wikitext_ragel.c
|
70
69
|
- ext/ary.h
|
71
70
|
- ext/parser.h
|
72
71
|
- ext/ruby_compat.h
|