wikitext 1.12 → 2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/parser.c +51 -21
- data/ext/wikitext.c +51 -0
- data/lib/wikitext/preprocess.rb +50 -0
- data/lib/wikitext/{rails.rb → rails_template_handler.rb} +32 -9
- data/lib/wikitext/string.rb +2 -10
- data/lib/wikitext/version.rb +1 -1
- data/rails/init.rb +4 -6
- data/spec/blockquote_spec.rb +3 -3
- data/spec/external_link_spec.rb +3 -3
- data/spec/img_spec.rb +80 -30
- data/spec/integration_spec.rb +4 -4
- data/spec/internal_link_spec.rb +6 -6
- data/spec/parser_spec.rb +2 -2
- data/spec/pre_spec.rb +2 -2
- data/spec/rails_spec.rb +109 -41
- data/spec/tt_spec.rb +16 -14
- data/spec/ul_spec.rb +2 -2
- metadata +19 -6
data/ext/parser.c
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
// Copyright 2007-
|
1
|
+
// Copyright 2007-2010 Wincent Colaiuta. All rights reserved.
|
2
2
|
//
|
3
3
|
// Redistribution and use in source and binary forms, with or without
|
4
4
|
// modification, are permitted provided that the following conditions are met:
|
@@ -33,6 +33,9 @@
|
|
33
33
|
#define IN_EITHER_OF(type1, type2) ary_includes2(parser->scope, type1, type2)
|
34
34
|
#define IN_ANY_OF(type1, type2, type3) ary_includes3(parser->scope, type1, type2, type3)
|
35
35
|
|
36
|
+
// output styles
|
37
|
+
enum { HTML_OUTPUT, XML_OUTPUT };
|
38
|
+
|
36
39
|
// poor man's object orientation in C:
|
37
40
|
// instead of passing around multiple parameters between functions in the parser
|
38
41
|
// we pack everything into a struct and pass around only a pointer to that
|
@@ -50,6 +53,7 @@ typedef struct
|
|
50
53
|
VALUE external_link_class; // CSS class applied to external links
|
51
54
|
VALUE mailto_class; // CSS class applied to email (mailto) links
|
52
55
|
VALUE img_prefix; // path prepended when emitting img tags
|
56
|
+
int output_style; // HTML_OUTPUT (default) or XML_OUTPUT
|
53
57
|
int base_indent; // controlled by the :indent option to Wikitext::Parser#parse
|
54
58
|
int current_indent; // fluctuates according to currently nested structures
|
55
59
|
int base_heading_level;
|
@@ -83,8 +87,8 @@ const char strong_start[] = "<strong>";
|
|
83
87
|
const char strong_end[] = "</strong>";
|
84
88
|
const char em_start[] = "<em>";
|
85
89
|
const char em_end[] = "</em>";
|
86
|
-
const char
|
87
|
-
const char
|
90
|
+
const char code_start[] = "<code>";
|
91
|
+
const char code_end[] = "</code>";
|
88
92
|
const char ol_start[] = "<ol>";
|
89
93
|
const char ol_end[] = "</ol>";
|
90
94
|
const char ul_start[] = "<ul>";
|
@@ -125,7 +129,8 @@ const char escaped_blockquote[] = "> ";
|
|
125
129
|
const char ext_link_end[] = "]";
|
126
130
|
const char literal_img_start[] = "{{";
|
127
131
|
const char img_start[] = "<img src=\"";
|
128
|
-
const char
|
132
|
+
const char img_end_xml[] = "\" />";
|
133
|
+
const char img_end_html[] = "\">";
|
129
134
|
const char img_alt[] = "\" alt=\"";
|
130
135
|
const char pre_class_start[] = "<pre class=\"";
|
131
136
|
const char pre_class_end[] = "-syntax\">";
|
@@ -150,6 +155,7 @@ parser_t *parser_new(void)
|
|
150
155
|
parser->external_link_class = Qnil; // caller should set up
|
151
156
|
parser->mailto_class = Qnil; // caller should set up
|
152
157
|
parser->img_prefix = Qnil; // caller should set up
|
158
|
+
parser->output_style = HTML_OUTPUT;
|
153
159
|
parser->base_indent = 0;
|
154
160
|
parser->current_indent = 0;
|
155
161
|
parser->base_heading_level = 0;
|
@@ -310,13 +316,16 @@ void wiki_append_hyperlink(parser_t *parser, VALUE link_prefix, str_t *link_targ
|
|
310
316
|
|
311
317
|
void wiki_append_img(parser_t *parser, char *token_ptr, int token_len)
|
312
318
|
{
|
313
|
-
str_append(parser->output, img_start, sizeof(img_start) - 1);
|
314
|
-
if (!NIL_P(parser->img_prefix) && *token_ptr != '/')
|
319
|
+
str_append(parser->output, img_start, sizeof(img_start) - 1); // <img src="
|
320
|
+
if (!NIL_P(parser->img_prefix) && *token_ptr != '/') // len always > 0
|
315
321
|
str_append_string(parser->output, parser->img_prefix);
|
316
322
|
str_append(parser->output, token_ptr, token_len);
|
317
|
-
str_append(parser->output, img_alt, sizeof(img_alt) - 1);
|
323
|
+
str_append(parser->output, img_alt, sizeof(img_alt) - 1); // " alt="
|
318
324
|
str_append(parser->output, token_ptr, token_len);
|
319
|
-
|
325
|
+
if (parser->output_style == XML_OUTPUT)
|
326
|
+
str_append(parser->output, img_end_xml, sizeof(img_end_xml) - 1); // " />
|
327
|
+
else
|
328
|
+
str_append(parser->output, img_end_html, sizeof(img_end_html) - 1); // ">
|
320
329
|
}
|
321
330
|
|
322
331
|
// will emit indentation only if we are about to emit any of:
|
@@ -422,7 +431,7 @@ void wiki_pop_from_stack(parser_t *parser, str_t *target)
|
|
422
431
|
|
423
432
|
case TT:
|
424
433
|
case TT_START:
|
425
|
-
str_append(target,
|
434
|
+
str_append(target, code_end, sizeof(code_end) - 1);
|
426
435
|
break;
|
427
436
|
|
428
437
|
case OL:
|
@@ -992,6 +1001,7 @@ VALUE Wikitext_parser_initialize(int argc, VALUE *argv, VALUE self)
|
|
992
1001
|
VALUE mailto_class = rb_str_new2("mailto");
|
993
1002
|
VALUE internal_link_prefix = rb_str_new2("/wiki/");
|
994
1003
|
VALUE img_prefix = rb_str_new2("/images/");
|
1004
|
+
VALUE output_style = ID2SYM(rb_intern("html"));
|
995
1005
|
VALUE space_to_underscore = Qtrue;
|
996
1006
|
VALUE minimum_fulltext_token_length = INT2NUM(3);
|
997
1007
|
VALUE base_heading_level = INT2NUM(0);
|
@@ -1007,6 +1017,7 @@ VALUE Wikitext_parser_initialize(int argc, VALUE *argv, VALUE self)
|
|
1007
1017
|
mailto_class = OVERRIDE_IF_SET(mailto_class);
|
1008
1018
|
internal_link_prefix = OVERRIDE_IF_SET(internal_link_prefix);
|
1009
1019
|
img_prefix = OVERRIDE_IF_SET(img_prefix);
|
1020
|
+
output_style = OVERRIDE_IF_SET(output_style);
|
1010
1021
|
space_to_underscore = OVERRIDE_IF_SET(space_to_underscore);
|
1011
1022
|
minimum_fulltext_token_length = OVERRIDE_IF_SET(minimum_fulltext_token_length);
|
1012
1023
|
base_heading_level = OVERRIDE_IF_SET(base_heading_level);
|
@@ -1019,6 +1030,7 @@ VALUE Wikitext_parser_initialize(int argc, VALUE *argv, VALUE self)
|
|
1019
1030
|
rb_iv_set(self, "@mailto_class", mailto_class);
|
1020
1031
|
rb_iv_set(self, "@internal_link_prefix", internal_link_prefix);
|
1021
1032
|
rb_iv_set(self, "@img_prefix", img_prefix);
|
1033
|
+
rb_iv_set(self, "@output_style", output_style);
|
1022
1034
|
rb_iv_set(self, "@space_to_underscore", space_to_underscore);
|
1023
1035
|
rb_iv_set(self, "@minimum_fulltext_token_length", minimum_fulltext_token_length);
|
1024
1036
|
rb_iv_set(self, "@base_heading_level", base_heading_level);
|
@@ -1032,6 +1044,17 @@ VALUE Wikitext_parser_profiling_parse(VALUE self, VALUE string)
|
|
1032
1044
|
return Qnil;
|
1033
1045
|
}
|
1034
1046
|
|
1047
|
+
// convert a Ruby object (:xml, :html etc) into an int output style
|
1048
|
+
int Wikitext_output_style(VALUE output)
|
1049
|
+
{
|
1050
|
+
if (TYPE(output) == T_SYMBOL)
|
1051
|
+
{
|
1052
|
+
if (SYM2ID(output) == rb_intern("xml"))
|
1053
|
+
return XML_OUTPUT;
|
1054
|
+
}
|
1055
|
+
return HTML_OUTPUT; // fall back to default
|
1056
|
+
}
|
1057
|
+
|
1035
1058
|
VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
1036
1059
|
{
|
1037
1060
|
// process arguments
|
@@ -1042,6 +1065,16 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
1042
1065
|
return Qnil;
|
1043
1066
|
string = StringValue(string);
|
1044
1067
|
|
1068
|
+
// access these once per parse
|
1069
|
+
VALUE line_ending = rb_iv_get(self, "@line_ending");
|
1070
|
+
line_ending = StringValue(line_ending);
|
1071
|
+
VALUE link_class = rb_iv_get(self, "@external_link_class");
|
1072
|
+
link_class = NIL_P(link_class) ? Qnil : StringValue(link_class);
|
1073
|
+
VALUE mailto_class = rb_iv_get(self, "@mailto_class");
|
1074
|
+
mailto_class = NIL_P(mailto_class) ? Qnil : StringValue(mailto_class);
|
1075
|
+
VALUE prefix = rb_iv_get(self, "@internal_link_prefix");
|
1076
|
+
int output_style = Wikitext_output_style(rb_iv_get(self, "@output_style"));
|
1077
|
+
|
1045
1078
|
// process options hash
|
1046
1079
|
int base_indent = 0;
|
1047
1080
|
int base_heading_level = NUM2INT(rb_iv_get(self, "@base_heading_level"));
|
@@ -1069,6 +1102,11 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
1069
1102
|
if (rb_funcall(options, has_key, 1, id) == Qtrue)
|
1070
1103
|
base_heading_level = NUM2INT(rb_hash_aref(options, id));
|
1071
1104
|
|
1105
|
+
// :output_style => :html/:xml
|
1106
|
+
id = ID2SYM(rb_intern("output_style"));
|
1107
|
+
if (rb_funcall(options, has_key, 1, id) == Qtrue)
|
1108
|
+
output_style = Wikitext_output_style(rb_hash_aref(options, id));
|
1109
|
+
|
1072
1110
|
// :link_proc => lambda { |link_target| ... }
|
1073
1111
|
id = ID2SYM(rb_intern("link_proc"));
|
1074
1112
|
if (rb_funcall(options, has_key, 1, id) == Qtrue)
|
@@ -1086,15 +1124,6 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
1086
1124
|
long len = RSTRING_LEN(string);
|
1087
1125
|
char *pe = p + len;
|
1088
1126
|
|
1089
|
-
// access these once per parse
|
1090
|
-
VALUE line_ending = rb_iv_get(self, "@line_ending");
|
1091
|
-
line_ending = StringValue(line_ending);
|
1092
|
-
VALUE link_class = rb_iv_get(self, "@external_link_class");
|
1093
|
-
link_class = NIL_P(link_class) ? Qnil : StringValue(link_class);
|
1094
|
-
VALUE mailto_class = rb_iv_get(self, "@mailto_class");
|
1095
|
-
mailto_class = NIL_P(mailto_class) ? Qnil : StringValue(mailto_class);
|
1096
|
-
VALUE prefix = rb_iv_get(self, "@internal_link_prefix");
|
1097
|
-
|
1098
1127
|
// set up parser struct to make passing parameters a little easier
|
1099
1128
|
parser_t *parser = parser_new();
|
1100
1129
|
GC_WRAP_PARSER(parser, parser_gc);
|
@@ -1106,6 +1135,7 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
1106
1135
|
parser->line_ending = str_new_from_string(line_ending);
|
1107
1136
|
parser->base_indent = base_indent;
|
1108
1137
|
parser->base_heading_level = base_heading_level;
|
1138
|
+
parser->output_style = output_style;
|
1109
1139
|
|
1110
1140
|
// this simple looping design leads to a single enormous function,
|
1111
1141
|
// but it's faster than doing actual recursive descent and also secure in the face of
|
@@ -1608,7 +1638,7 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
1608
1638
|
wiki_pop_from_stack_up_to(parser, output, EM_START, true);
|
1609
1639
|
else
|
1610
1640
|
{
|
1611
|
-
// no EM_START in scope, so must interpret the
|
1641
|
+
// no EM_START in scope, so must interpret the EM_END without any special meaning
|
1612
1642
|
wiki_pop_excess_elements(parser);
|
1613
1643
|
wiki_start_para_if_necessary(parser);
|
1614
1644
|
str_append(output, escaped_em_end, sizeof(escaped_em_end) - 1);
|
@@ -1636,7 +1666,7 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
1636
1666
|
// this is a new opening
|
1637
1667
|
wiki_pop_excess_elements(parser);
|
1638
1668
|
wiki_start_para_if_necessary(parser);
|
1639
|
-
str_append(output,
|
1669
|
+
str_append(output, code_start, sizeof(code_start) - 1);
|
1640
1670
|
ary_push(parser->scope, TT);
|
1641
1671
|
ary_push(parser->line, TT);
|
1642
1672
|
}
|
@@ -1658,7 +1688,7 @@ VALUE Wikitext_parser_parse(int argc, VALUE *argv, VALUE self)
|
|
1658
1688
|
{
|
1659
1689
|
wiki_pop_excess_elements(parser);
|
1660
1690
|
wiki_start_para_if_necessary(parser);
|
1661
|
-
str_append(output,
|
1691
|
+
str_append(output, code_start, sizeof(code_start) - 1);
|
1662
1692
|
ary_push(parser->scope, TT_START);
|
1663
1693
|
ary_push(parser->line, TT_START);
|
1664
1694
|
}
|
data/ext/wikitext.c
CHANGED
@@ -29,6 +29,36 @@ VALUE cWikitextParser = 0; // class Wikitext::Parser
|
|
29
29
|
VALUE eWikitextParserError = 0; // class Wikitext::Parser::Error
|
30
30
|
VALUE cWikitextParserToken = 0; // class Wikitext::Parser::Token
|
31
31
|
|
32
|
+
// In order to replicate this Ruby code:
|
33
|
+
//
|
34
|
+
// ActiveSupport.on_load(:action_view) do
|
35
|
+
// require 'wikitext/rails_template_handler'
|
36
|
+
// end
|
37
|
+
//
|
38
|
+
// here in C we have to jump through some hoops using the following two
|
39
|
+
// functions.
|
40
|
+
//
|
41
|
+
// First we have wikitext_on_load_block(), which is a function which defines
|
42
|
+
// the "block" of code that we want to have evaluated.
|
43
|
+
//
|
44
|
+
// To actually pass this block in to the ActiveSupport::on_load method we
|
45
|
+
// need the help of an intermediate helper function,
|
46
|
+
// wikitext_block_forwarder(), which we invoke with the aid of rb_iterate()
|
47
|
+
// later on.
|
48
|
+
//
|
49
|
+
// This works because the rb_funcall() function in wikitext_block_forwarder()
|
50
|
+
// propagates the block through to the called method.
|
51
|
+
VALUE wikitext_on_load_block(VALUE yielded, VALUE other)
|
52
|
+
{
|
53
|
+
return rb_require("wikitext/rails_template_handler");
|
54
|
+
}
|
55
|
+
|
56
|
+
VALUE wikitext_block_forwarder(VALUE receiver)
|
57
|
+
{
|
58
|
+
return rb_funcall(receiver, rb_intern("on_load"), 1,
|
59
|
+
ID2SYM(rb_intern("action_view")));
|
60
|
+
}
|
61
|
+
|
32
62
|
void Init_wikitext()
|
33
63
|
{
|
34
64
|
// Wikitext
|
@@ -53,6 +83,7 @@ void Init_wikitext()
|
|
53
83
|
rb_define_attr(cWikitextParser, "space_to_underscore", Qtrue, Qtrue);
|
54
84
|
rb_define_attr(cWikitextParser, "minimum_fulltext_token_length", Qtrue, Qtrue);
|
55
85
|
rb_define_attr(cWikitextParser, "base_heading_level", Qtrue, Qtrue);
|
86
|
+
rb_define_attr(cWikitextParser, "output_style", Qtrue, Qtrue);
|
56
87
|
|
57
88
|
// Wikitext::Parser::Error
|
58
89
|
eWikitextParserError = rb_define_class_under(cWikitextParser, "Error", rb_eException);
|
@@ -69,4 +100,24 @@ void Init_wikitext()
|
|
69
100
|
rb_define_attr(cWikitextParserToken, "code_point", Qtrue, Qfalse);
|
70
101
|
rb_define_attr(cWikitextParserToken, "token_type", Qtrue, Qfalse);
|
71
102
|
rb_define_attr(cWikitextParserToken, "string_value", Qtrue, Qfalse);
|
103
|
+
|
104
|
+
// check to see if ::ActiveSupport is defined
|
105
|
+
if (rb_funcall(rb_cObject, rb_intern("const_defined?"), 1,
|
106
|
+
ID2SYM(rb_intern("ActiveSupport"))) == Qtrue)
|
107
|
+
{
|
108
|
+
// we are running under Rails
|
109
|
+
rb_require("wikitext/nil_class");
|
110
|
+
rb_require("wikitext/string");
|
111
|
+
|
112
|
+
// now check for Rails version
|
113
|
+
VALUE active_support = rb_const_get(rb_cObject,
|
114
|
+
rb_intern("ActiveSupport"));
|
115
|
+
if (rb_respond_to(active_support, rb_intern("on_load")))
|
116
|
+
// running under Rails 3
|
117
|
+
rb_iterate(wikitext_block_forwarder, active_support,
|
118
|
+
wikitext_on_load_block, Qnil);
|
119
|
+
else
|
120
|
+
// running under Rails 2
|
121
|
+
rb_require("wikitext/rails_template_handler");
|
122
|
+
}
|
72
123
|
}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Copyright 2008-2010 Wincent Colaiuta. All rights reserved.
|
2
|
+
#
|
3
|
+
# Redistribution and use in source and binary forms, with or without
|
4
|
+
# modification, are permitted provided that the following conditions are met:
|
5
|
+
#
|
6
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
7
|
+
# this list of conditions and the following disclaimer.
|
8
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer in the documentation
|
10
|
+
# and/or other materials provided with the distribution.
|
11
|
+
|
12
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
13
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
14
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
15
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
|
16
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
17
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
18
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
19
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
20
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
21
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
22
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
23
|
+
|
24
|
+
class String
|
25
|
+
# This is an example preprocessing method that will be called by the
|
26
|
+
# String#to_wikitext method prior to feeding the markup into the parser.
|
27
|
+
# In this case we take input like this:
|
28
|
+
#
|
29
|
+
# For more info see issue #125, which was filed last week.
|
30
|
+
#
|
31
|
+
# And transform it into:
|
32
|
+
#
|
33
|
+
# For more info see [/issues/125 issue #125], which was filed last week.
|
34
|
+
#
|
35
|
+
# Which in turn is translated into the following HTML by the parser:
|
36
|
+
#
|
37
|
+
# <p>For more info see <a href="/issues/125">issue #125</a>, which was
|
38
|
+
# filed last week.</p>
|
39
|
+
#
|
40
|
+
# Obviously this file is an example designed to work with a specific
|
41
|
+
# application and is optional, so will only come into play if explicitly
|
42
|
+
# required. To provide different behavior, simply define a new definition of
|
43
|
+
# String#wikitext_preprocess.
|
44
|
+
#
|
45
|
+
# For now this is done in pure Ruby; if speed became a concern we could
|
46
|
+
# provide a fast Ragel C extension to do it instead.
|
47
|
+
def wikitext_preprocess
|
48
|
+
gsub /\b(bug|issue|request|ticket) #(\d+)/i, '[/issues/\2 \1 #\2]'
|
49
|
+
end
|
50
|
+
end
|
@@ -24,12 +24,35 @@
|
|
24
24
|
require 'wikitext/nil_class'
|
25
25
|
require 'wikitext/string'
|
26
26
|
|
27
|
-
module
|
28
|
-
class
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
27
|
+
module ActionView
|
28
|
+
class Template
|
29
|
+
module Handlers
|
30
|
+
|
31
|
+
begin
|
32
|
+
|
33
|
+
# assume Rails 3
|
34
|
+
class Wikitext < Handler
|
35
|
+
include Compilable
|
36
|
+
|
37
|
+
def compile template
|
38
|
+
"'" + template.source.w.gsub("'", "\\\\'") + "'"
|
39
|
+
end
|
40
|
+
end # class Wikitext
|
41
|
+
|
42
|
+
rescue NameError
|
43
|
+
|
44
|
+
# fall back to Rails 2
|
45
|
+
class Wikitext
|
46
|
+
def self.call template
|
47
|
+
'template.source.w'
|
48
|
+
end
|
49
|
+
end # class Wikitext
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end # module Handlers
|
54
|
+
end # class Template
|
55
|
+
end # module ActionView
|
56
|
+
|
57
|
+
ActionView::Template.register_template_handler :wikitext,
|
58
|
+
ActionView::Template::Handlers::Wikitext
|
data/lib/wikitext/string.rb
CHANGED
@@ -26,18 +26,10 @@ require 'wikitext/parser'
|
|
26
26
|
class String
|
27
27
|
def to_wikitext options = {}
|
28
28
|
default_options = { :indent => false }
|
29
|
-
|
29
|
+
markup = respond_to?(:wikitext_preprocess) ? wikitext_preprocess : self
|
30
|
+
html = Wikitext::Parser.shared_parser.parse markup,
|
30
31
|
default_options.merge(options)
|
31
32
|
html.respond_to?(:html_safe) ? html.html_safe : html
|
32
33
|
end
|
33
34
|
alias :w :to_wikitext
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
# for now do this in pure Ruby
|
38
|
-
# if speed later becomes a concern can whip up a Ragel C extension to do it
|
39
|
-
# TODO: make this customizable (accept a lambda that performs preprocessing)
|
40
|
-
def wikitext_preprocess
|
41
|
-
gsub /\b(bug|issue|request|ticket) #(\d+)/i, '[/issues/\2 \1 #\2]'
|
42
|
-
end
|
43
35
|
end
|
data/lib/wikitext/version.rb
CHANGED
data/rails/init.rb
CHANGED
@@ -21,11 +21,9 @@
|
|
21
21
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
22
22
|
# POSSIBILITY OF SUCH DAMAGE.
|
23
23
|
|
24
|
-
#
|
25
|
-
# See: https://rails.lighthouseapp.com/projects/8994/tickets/2266
|
24
|
+
# this file evaluated automatically under Rails 2
|
26
25
|
unless $gems_build_rake_task
|
27
|
-
|
28
|
-
|
29
|
-
require
|
30
|
-
require File.join(libdir, 'rails')
|
26
|
+
# avoid Rails bug #2266 by not requiring during "rake gems:build"
|
27
|
+
# see: https://rails.lighthouseapp.com/projects/8994/tickets/2266
|
28
|
+
require 'wikitext'
|
31
29
|
end
|
data/spec/blockquote_spec.rb
CHANGED
@@ -194,7 +194,7 @@ describe Wikitext::Parser, 'standard blockquotes (">" in first column)' do
|
|
194
194
|
END
|
195
195
|
expected = dedent <<-END
|
196
196
|
<blockquote>
|
197
|
-
<p>link to <a href="/wiki/something">something</a>, and <em>other</em> <
|
197
|
+
<p>link to <a href="/wiki/something">something</a>, and <em>other</em> <code>styled</code> <strong>spans</strong>.</p>
|
198
198
|
</blockquote>
|
199
199
|
END
|
200
200
|
@parser.parse(input).should == expected
|
@@ -243,7 +243,7 @@ describe Wikitext::Parser, 'standard blockquotes (">" in first column)' do
|
|
243
243
|
<li>a</li>
|
244
244
|
<li>list</li>
|
245
245
|
</ul>
|
246
|
-
<p>outer para with <em>styled</em> <
|
246
|
+
<p>outer para with <em>styled</em> <code>stuff</code> in it</p>
|
247
247
|
<blockquote>
|
248
248
|
<p>inner blockquote</p>
|
249
249
|
<ol>
|
@@ -268,7 +268,7 @@ describe Wikitext::Parser, 'standard blockquotes (">" in first column)' do
|
|
268
268
|
END
|
269
269
|
expected = dedent <<-END
|
270
270
|
<blockquote>
|
271
|
-
<p>some <
|
271
|
+
<p>some <code>styled</code></p>
|
272
272
|
</blockquote>
|
273
273
|
END
|
274
274
|
@parser.parse(input).should == expected
|
data/spec/external_link_spec.rb
CHANGED
@@ -117,12 +117,12 @@ describe Wikitext::Parser, 'external links' do
|
|
117
117
|
end
|
118
118
|
|
119
119
|
it 'should format a link with <tt></tt> tags in the link text' do
|
120
|
-
expected = %Q{<p><a href="http://google.com/" class="external">Google <
|
120
|
+
expected = %Q{<p><a href="http://google.com/" class="external">Google <code>SOC</code></a></p>\n}
|
121
121
|
@parser.parse("[http://google.com/ Google <tt>SOC</tt>]").should == expected
|
122
122
|
end
|
123
123
|
|
124
124
|
it 'should automatically close unmatched <tt> tags in the link text' do
|
125
|
-
expected = %Q{<p><a href="http://google.com/" class="external">Google <
|
125
|
+
expected = %Q{<p><a href="http://google.com/" class="external">Google <code>SOC</code></a></p>\n}
|
126
126
|
@parser.parse("[http://google.com/ Google <tt>SOC]").should == expected
|
127
127
|
end
|
128
128
|
|
@@ -194,7 +194,7 @@ describe Wikitext::Parser, 'external links' do
|
|
194
194
|
@parser.parse("foo '']'' bar").should == "<p>foo <em>]</em> bar</p>\n" # in EM scope
|
195
195
|
@parser.parse("foo ''']''' bar").should == "<p>foo <strong>]</strong> bar</p>\n" # in STRONG scope
|
196
196
|
@parser.parse("foo ''''']''''' bar").should == "<p>foo <strong><em>]</em></strong> bar</p>\n" # in STRONG_EM scope
|
197
|
-
@parser.parse('foo <tt>]</tt> bar').should == "<p>foo <
|
197
|
+
@parser.parse('foo <tt>]</tt> bar').should == "<p>foo <code>]</code> bar</p>\n" # in TT scope
|
198
198
|
@parser.parse('= foo ] bar =').should == "<h1>foo ] bar</h1>\n" # in H1 scope
|
199
199
|
@parser.parse('== foo ] bar ==').should == "<h2>foo ] bar</h2>\n" # in H2 scope
|
200
200
|
@parser.parse('=== foo ] bar ===').should == "<h3>foo ] bar</h3>\n" # in H3 scope
|
data/spec/img_spec.rb
CHANGED
@@ -30,15 +30,48 @@ describe Wikitext::Parser, 'embedding img tags' do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'should convert valid markup into inline image tags' do
|
33
|
-
|
33
|
+
expected = %Q{<p><img src="/images/foo.png" alt="foo.png"></p>\n}
|
34
|
+
@parser.parse('{{foo.png}}').should == expected
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should produce XML output if passed option at parse time' do
|
38
|
+
expected = %Q{<p><img src="/images/foo.png" alt="foo.png" /></p>\n}
|
39
|
+
@parser.parse('{{foo.png}}', :output_style => :xml).should == expected
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should produce XML output if set via instance variable' do
|
43
|
+
expected = %Q{<p><img src="/images/foo.png" alt="foo.png" /></p>\n}
|
44
|
+
parser = Wikitext::Parser.new
|
45
|
+
parser.output_style = :xml
|
46
|
+
parser.parse('{{foo.png}}').should == expected
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should produce XML output if option set during initialization' do
|
50
|
+
expected = %Q{<p><img src="/images/foo.png" alt="foo.png" /></p>\n}
|
51
|
+
parser = Wikitext::Parser.new :output_style => :xml
|
52
|
+
parser.parse('{{foo.png}}').should == expected
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should produce HTML output if passed unrecognized output style' do
|
56
|
+
expected = %Q{<p><img src="/images/foo.png" alt="foo.png"></p>\n}
|
57
|
+
|
58
|
+
# the _only_ recognized override is :xml (case-sensitive)
|
59
|
+
@parser.parse('{{foo.png}}', :output_style => :html).should == expected
|
60
|
+
@parser.parse('{{foo.png}}', :output_style => false).should == expected
|
61
|
+
@parser.parse('{{foo.png}}', :output_style => nil).should == expected
|
62
|
+
@parser.parse('{{foo.png}}', :output_style => 42).should == expected
|
63
|
+
@parser.parse('{{foo.png}}', :output_style => 'XML').should == expected
|
64
|
+
@parser.parse('{{foo.png}}', :output_style => :XML).should == expected
|
34
65
|
end
|
35
66
|
|
36
67
|
it 'should appear embedded in an inline flow' do
|
37
|
-
|
68
|
+
expected = %Q{<p>before <img src="/images/foo.png" alt="foo.png"> after</p>\n}
|
69
|
+
@parser.parse('before {{foo.png}} after').should == expected
|
38
70
|
end
|
39
71
|
|
40
72
|
it 'should allow images in subdirectories' do
|
41
|
-
|
73
|
+
expected = %Q{<p><img src="/images/foo/bar.png" alt="foo/bar.png"></p>\n}
|
74
|
+
@parser.parse('{{foo/bar.png}}').should == expected
|
42
75
|
end
|
43
76
|
|
44
77
|
it 'should pass through empty image tags unchanged' do
|
@@ -46,14 +79,14 @@ describe Wikitext::Parser, 'embedding img tags' do
|
|
46
79
|
end
|
47
80
|
|
48
81
|
it 'should not append prefix if img src starts with a slash' do
|
49
|
-
|
50
|
-
|
82
|
+
expected = %Q{<p><img src="/foo.png" alt="/foo.png"></p>\n}
|
83
|
+
@parser.parse('{{/foo.png}}').should == expected
|
51
84
|
end
|
52
85
|
|
53
86
|
it 'should work in BLOCKQUOTE blocks' do
|
54
87
|
expected = dedent <<-END
|
55
88
|
<blockquote>
|
56
|
-
<p><img src="/images/foo.png" alt="foo.png"
|
89
|
+
<p><img src="/images/foo.png" alt="foo.png"></p>
|
57
90
|
</blockquote>
|
58
91
|
END
|
59
92
|
@parser.parse('> {{foo.png}}').should == expected
|
@@ -67,9 +100,9 @@ describe Wikitext::Parser, 'embedding img tags' do
|
|
67
100
|
END
|
68
101
|
expected = dedent <<-END
|
69
102
|
<ul>
|
70
|
-
<li><img src="/images/foo.png" alt="foo.png"
|
71
|
-
<li><img src="/images/bar.png" alt="bar.png"
|
72
|
-
<li><img src="/images/baz.png" alt="baz.png"
|
103
|
+
<li><img src="/images/foo.png" alt="foo.png"></li>
|
104
|
+
<li><img src="/images/bar.png" alt="bar.png"></li>
|
105
|
+
<li><img src="/images/baz.png" alt="baz.png"></li>
|
73
106
|
</ul>
|
74
107
|
END
|
75
108
|
@parser.parse(input).should == expected
|
@@ -83,36 +116,42 @@ describe Wikitext::Parser, 'embedding img tags' do
|
|
83
116
|
END
|
84
117
|
expected = dedent <<-END
|
85
118
|
<ol>
|
86
|
-
<li><img src="/images/foo.png" alt="foo.png"
|
87
|
-
<li><img src="/images/bar.png" alt="bar.png"
|
88
|
-
<li><img src="/images/baz.png" alt="baz.png"
|
119
|
+
<li><img src="/images/foo.png" alt="foo.png"></li>
|
120
|
+
<li><img src="/images/bar.png" alt="bar.png"></li>
|
121
|
+
<li><img src="/images/baz.png" alt="baz.png"></li>
|
89
122
|
</ol>
|
90
123
|
END
|
91
124
|
@parser.parse(input).should == expected
|
92
125
|
end
|
93
126
|
|
94
127
|
it 'should work in <h1> headings' do
|
95
|
-
|
128
|
+
expected = %Q{<h1><img src="/images/foo.png" alt="foo.png"></h1>\n}
|
129
|
+
@parser.parse('= {{foo.png}} =').should == expected
|
96
130
|
end
|
97
131
|
|
98
132
|
it 'should work in <h2> headings' do
|
99
|
-
|
133
|
+
expected = %Q{<h2><img src="/images/foo.png" alt="foo.png"></h2>\n}
|
134
|
+
@parser.parse('== {{foo.png}} ==').should == expected
|
100
135
|
end
|
101
136
|
|
102
137
|
it 'should work in <h3> headings' do
|
103
|
-
|
138
|
+
expected = %Q{<h3><img src="/images/foo.png" alt="foo.png"></h3>\n}
|
139
|
+
@parser.parse('=== {{foo.png}} ===').should == expected
|
104
140
|
end
|
105
141
|
|
106
142
|
it 'should work in <h4> headings' do
|
107
|
-
|
143
|
+
expected = %Q{<h4><img src="/images/foo.png" alt="foo.png"></h4>\n}
|
144
|
+
@parser.parse('==== {{foo.png}} ====').should == expected
|
108
145
|
end
|
109
146
|
|
110
147
|
it 'should work in <h5> headings' do
|
111
|
-
|
148
|
+
expected = %Q{<h5><img src="/images/foo.png" alt="foo.png"></h5>\n}
|
149
|
+
@parser.parse('===== {{foo.png}} =====').should == expected
|
112
150
|
end
|
113
151
|
|
114
152
|
it 'should work in <h6> headings' do
|
115
|
-
|
153
|
+
expected = %Q{<h6><img src="/images/foo.png" alt="foo.png"></h6>\n}
|
154
|
+
@parser.parse('====== {{foo.png}} ======').should == expected
|
116
155
|
end
|
117
156
|
|
118
157
|
it 'should pass single curly braces through unaltered' do
|
@@ -124,23 +163,27 @@ describe Wikitext::Parser, 'embedding img tags' do
|
|
124
163
|
end
|
125
164
|
|
126
165
|
it 'should have no effect inside PRE_START blocks' do
|
127
|
-
|
166
|
+
expected = %Q{<pre>{{foo.png}}</pre>\n}
|
167
|
+
@parser.parse('<pre>{{foo.png}}</pre>').should == expected
|
128
168
|
end
|
129
169
|
|
130
170
|
it 'should have no effect inside NO_WIKI spans' do
|
131
|
-
|
171
|
+
expected = %Q{<p>{{foo.png}}</p>\n}
|
172
|
+
@parser.parse('<nowiki>{{foo.png}}</nowiki>').should == expected
|
132
173
|
end
|
133
174
|
|
134
175
|
it 'should be passed through in internal link targets' do
|
135
|
-
|
176
|
+
expected = %Q{<p><a href="/wiki/%7b%7bfoo.png%7d%7d">{{foo.png}}</a></p>\n}
|
177
|
+
@parser.parse('[[{{foo.png}}]]').should == expected
|
136
178
|
end
|
137
179
|
|
138
180
|
it 'should be passed through in internal link text' do
|
139
|
-
|
181
|
+
expected = %Q{<p><a href="/wiki/article">{{foo.png}}</a></p>\n}
|
182
|
+
@parser.parse('[[article|{{foo.png}}]]').should == expected
|
140
183
|
end
|
141
184
|
|
142
185
|
it 'should not be allowed as an external link target' do
|
143
|
-
expected = %Q{<p>[<img src="/images/foo.png" alt="foo.png"
|
186
|
+
expected = %Q{<p>[<img src="/images/foo.png" alt="foo.png"> the link]</p>\n}
|
144
187
|
@parser.parse('[{{foo.png}} the link]').should == expected
|
145
188
|
end
|
146
189
|
|
@@ -150,7 +193,8 @@ describe Wikitext::Parser, 'embedding img tags' do
|
|
150
193
|
end
|
151
194
|
|
152
195
|
it 'should not allow embedded quotes' do
|
153
|
-
|
196
|
+
expected = %Q{<p>{{"fun".png}}</p>\n}
|
197
|
+
@parser.parse('{{"fun".png}}').should == expected
|
154
198
|
end
|
155
199
|
|
156
200
|
it 'should not allow embedded spaces' do
|
@@ -163,31 +207,37 @@ describe Wikitext::Parser, 'embedding img tags' do
|
|
163
207
|
|
164
208
|
it 'should allow overrides of the image prefix at initialization time' do
|
165
209
|
parser = Wikitext::Parser.new(:img_prefix => '/gfx/')
|
166
|
-
|
210
|
+
expected = %Q{<p><img src="/gfx/foo.png" alt="foo.png"></p>\n}
|
211
|
+
parser.parse('{{foo.png}}').should == expected
|
167
212
|
end
|
168
213
|
|
169
214
|
it 'should suppress the image prefix if passed an empty string at initialization time' do
|
170
215
|
parser = Wikitext::Parser.new(:img_prefix => '')
|
171
|
-
|
216
|
+
expected = %Q{<p><img src="foo.png" alt="foo.png"></p>\n}
|
217
|
+
parser.parse('{{foo.png}}').should == expected
|
172
218
|
end
|
173
219
|
|
174
220
|
it 'should suppress image prefix if passed nil at initialization time' do
|
175
221
|
parser = Wikitext::Parser.new(:img_prefix => nil)
|
176
|
-
|
222
|
+
expected = %Q{<p><img src="foo.png" alt="foo.png"></p>\n}
|
223
|
+
parser.parse('{{foo.png}}').should == expected
|
177
224
|
end
|
178
225
|
|
179
226
|
it 'should allow overrides of the image prefix after initialization' do
|
180
227
|
@parser.img_prefix = '/gfx/'
|
181
|
-
|
228
|
+
expected = %Q{<p><img src="/gfx/foo.png" alt="foo.png"></p>\n}
|
229
|
+
@parser.parse('{{foo.png}}').should == expected
|
182
230
|
end
|
183
231
|
|
184
232
|
it 'should suppress image if prefix set to an empty string after initialization' do
|
185
233
|
@parser.img_prefix = ''
|
186
|
-
|
234
|
+
expected = %Q{<p><img src="foo.png" alt="foo.png"></p>\n}
|
235
|
+
@parser.parse('{{foo.png}}').should == expected
|
187
236
|
end
|
188
237
|
|
189
238
|
it 'should suppress image if prefix set to nil after initialization' do
|
190
239
|
@parser.img_prefix = nil
|
191
|
-
|
240
|
+
expected = %Q{<p><img src="foo.png" alt="foo.png"></p>\n}
|
241
|
+
@parser.parse('{{foo.png}}').should == expected
|
192
242
|
end
|
193
243
|
end
|
data/spec/integration_spec.rb
CHANGED
@@ -186,14 +186,14 @@ describe Wikitext::Parser, 'with large slab of input text' do
|
|
186
186
|
syntax as you can see.</pre>
|
187
187
|
</blockquote>
|
188
188
|
<h2>another heading</h2>
|
189
|
-
<p>paragraph within <em>multiple <strong>styles</strong></em> and <
|
189
|
+
<p>paragraph within <em>multiple <strong>styles</strong></em> and <code>tt span</code></p>
|
190
190
|
<p>similar, but with <strong>styles in <em>different</em> order</strong></p>
|
191
191
|
<p>again, a <strong>different <em>order</em></strong></p>
|
192
192
|
<ul>
|
193
193
|
<li>list item 1 [<a href="http://google.com/" class="external">http://google.com/</a> unterminated
|
194
194
|
<ul>
|
195
195
|
<li>nested list item 1 with [[bad link</li>
|
196
|
-
<li>nested list item 2 with unclosed <
|
196
|
+
<li>nested list item 2 with unclosed <code>span</code></li>
|
197
197
|
<li>nested list item 3</li>
|
198
198
|
</ul>
|
199
199
|
</li>
|
@@ -204,7 +204,7 @@ describe Wikitext::Parser, 'with large slab of input text' do
|
|
204
204
|
which would '''otherwise''' have <tt>special</tt> meaning
|
205
205
|
although explicit entities © are passed through unchanged</pre>
|
206
206
|
<p>a normal paragraph again</p>
|
207
|
-
<p><img src="/images/an_image.png" alt="an_image.png"
|
207
|
+
<p><img src="/images/an_image.png" alt="an_image.png"></p>
|
208
208
|
<blockquote>
|
209
209
|
<p>This is another blockquote which demonstrates that we can nest other structures inside of it. For example, here we have a code sample:</p>
|
210
210
|
<pre>line 1
|
@@ -216,7 +216,7 @@ describe Wikitext::Parser, 'with large slab of input text' do
|
|
216
216
|
<li>a</li>
|
217
217
|
<li>list</li>
|
218
218
|
</ul>
|
219
|
-
<p>And here is a link to <a href="/wiki/something">something</a>, and some <em>other</em> <
|
219
|
+
<p>And here is a link to <a href="/wiki/something">something</a>, and some <em>other</em> <code>styled</code> <strong>spans</strong>.</p>
|
220
220
|
<blockquote>
|
221
221
|
<p>Finally we have a nested blockquote.</p>
|
222
222
|
<ol>
|
data/spec/internal_link_spec.rb
CHANGED
@@ -34,7 +34,7 @@ describe Wikitext::Parser, 'internal links (space to underscore off)' do
|
|
34
34
|
@parser.parse("foo '']]'' bar").should == "<p>foo <em>]]</em> bar</p>\n" # in EM scope
|
35
35
|
@parser.parse("foo ''']]''' bar").should == "<p>foo <strong>]]</strong> bar</p>\n" # in STRONG scope
|
36
36
|
@parser.parse("foo ''''']]''''' bar").should == "<p>foo <strong><em>]]</em></strong> bar</p>\n" # in STRONG_EM scope
|
37
|
-
@parser.parse('foo <tt>]]</tt> bar').should == "<p>foo <
|
37
|
+
@parser.parse('foo <tt>]]</tt> bar').should == "<p>foo <code>]]</code> bar</p>\n" # in TT scope
|
38
38
|
@parser.parse('= foo ]] bar =').should == "<h1>foo ]] bar</h1>\n" # in H1 scope
|
39
39
|
@parser.parse('== foo ]] bar ==').should == "<h2>foo ]] bar</h2>\n" # in H2 scope
|
40
40
|
@parser.parse('=== foo ]] bar ===').should == "<h3>foo ]] bar</h3>\n" # in H3 scope
|
@@ -314,12 +314,12 @@ describe Wikitext::Parser, 'internal links (space to underscore off)' do
|
|
314
314
|
end
|
315
315
|
|
316
316
|
it 'should allow tt markup in the custom link text' do
|
317
|
-
expected = %Q{<p><a href="/wiki/foo">bar <
|
317
|
+
expected = %Q{<p><a href="/wiki/foo">bar <code>baz</code></a></p>\n}
|
318
318
|
@parser.parse('[[foo|bar <tt>baz</tt>]]').should == expected
|
319
319
|
end
|
320
320
|
|
321
321
|
it 'should automatically close unclosed tt markup in the custom link text' do
|
322
|
-
expected = %Q{<p><a href="/wiki/foo">bar <
|
322
|
+
expected = %Q{<p><a href="/wiki/foo">bar <code>baz</code></a></p>\n}
|
323
323
|
@parser.parse('[[foo|bar <tt>baz]]').should == expected
|
324
324
|
end
|
325
325
|
|
@@ -579,7 +579,7 @@ describe Wikitext::Parser, 'internal links (space to underscore on)' do
|
|
579
579
|
@parser.parse("foo '']]'' bar").should == "<p>foo <em>]]</em> bar</p>\n" # in EM scope
|
580
580
|
@parser.parse("foo ''']]''' bar").should == "<p>foo <strong>]]</strong> bar</p>\n" # in STRONG scope
|
581
581
|
@parser.parse("foo ''''']]''''' bar").should == "<p>foo <strong><em>]]</em></strong> bar</p>\n" # in STRONG_EM scope
|
582
|
-
@parser.parse('foo <tt>]]</tt> bar').should == "<p>foo <
|
582
|
+
@parser.parse('foo <tt>]]</tt> bar').should == "<p>foo <code>]]</code> bar</p>\n" # in TT scope
|
583
583
|
@parser.parse('= foo ]] bar =').should == "<h1>foo ]] bar</h1>\n" # in H1 scope
|
584
584
|
@parser.parse('== foo ]] bar ==').should == "<h2>foo ]] bar</h2>\n" # in H2 scope
|
585
585
|
@parser.parse('=== foo ]] bar ===').should == "<h3>foo ]] bar</h3>\n" # in H3 scope
|
@@ -854,12 +854,12 @@ describe Wikitext::Parser, 'internal links (space to underscore on)' do
|
|
854
854
|
end
|
855
855
|
|
856
856
|
it 'should allow tt markup in the custom link text' do
|
857
|
-
expected = %Q{<p><a href="/wiki/foo">bar <
|
857
|
+
expected = %Q{<p><a href="/wiki/foo">bar <code>baz</code></a></p>\n}
|
858
858
|
@parser.parse('[[foo|bar <tt>baz</tt>]]').should == expected
|
859
859
|
end
|
860
860
|
|
861
861
|
it 'should automatically close unclosed tt markup in the custom link text' do
|
862
|
-
expected = %Q{<p><a href="/wiki/foo">bar <
|
862
|
+
expected = %Q{<p><a href="/wiki/foo">bar <code>baz</code></a></p>\n}
|
863
863
|
@parser.parse('[[foo|bar <tt>baz]]').should == expected
|
864
864
|
end
|
865
865
|
|
data/spec/parser_spec.rb
CHANGED
@@ -35,7 +35,7 @@ describe Wikitext::Parser do
|
|
35
35
|
original_prefix = '/images/'
|
36
36
|
parser.img_prefix = original_prefix
|
37
37
|
parser.img_prefix.should == original_prefix
|
38
|
-
parser.parse('{{foo.png}}').should == %Q{<p><img src="/images/foo.png" alt="foo.png"
|
38
|
+
parser.parse('{{foo.png}}').should == %Q{<p><img src="/images/foo.png" alt="foo.png"></p>\n}
|
39
39
|
|
40
40
|
# second pass
|
41
41
|
parser = Wikitext::Parser.shared_parser
|
@@ -43,6 +43,6 @@ describe Wikitext::Parser do
|
|
43
43
|
new_prefix = '/totally-different-prefix/'
|
44
44
|
parser.img_prefix = new_prefix
|
45
45
|
parser.img_prefix.should == new_prefix
|
46
|
-
parser.parse('{{bar.png}}').should == %Q{<p><img src="/totally-different-prefix/bar.png" alt="bar.png"
|
46
|
+
parser.parse('{{bar.png}}').should == %Q{<p><img src="/totally-different-prefix/bar.png" alt="bar.png"></p>\n}
|
47
47
|
end
|
48
48
|
end
|
data/spec/pre_spec.rb
CHANGED
@@ -420,7 +420,7 @@ describe Wikitext::Parser, 'parsing PRE_START/PRE_END blocks' do
|
|
420
420
|
|
421
421
|
# `
|
422
422
|
expected = dedent <<-END
|
423
|
-
<p>hello <
|
423
|
+
<p>hello <code>my </code></p>
|
424
424
|
<pre>world</pre>
|
425
425
|
END
|
426
426
|
@parser.parse("hello `my <pre>world</pre>").should == expected
|
@@ -448,7 +448,7 @@ describe Wikitext::Parser, 'parsing PRE_START/PRE_END blocks' do
|
|
448
448
|
|
449
449
|
# <tt>
|
450
450
|
expected = dedent <<-END
|
451
|
-
<p>hello <
|
451
|
+
<p>hello <code>my </code></p>
|
452
452
|
<pre>world</pre>
|
453
453
|
END
|
454
454
|
@parser.parse("hello <tt>my <pre>world</pre>").should == expected
|
data/spec/rails_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2009 Wincent Colaiuta. All rights reserved.
|
1
|
+
# Copyright 2009-2010 Wincent Colaiuta. All rights reserved.
|
2
2
|
#
|
3
3
|
# Redistribution and use in source and binary forms, with or without
|
4
4
|
# modification, are permitted provided that the following conditions are met:
|
@@ -29,10 +29,12 @@ require 'wopen3'
|
|
29
29
|
require 'ostruct'
|
30
30
|
|
31
31
|
module RailsSpecs
|
32
|
-
TRASH_PATH
|
33
|
-
CLONE_PATH
|
34
|
-
|
35
|
-
|
32
|
+
TRASH_PATH = Pathname.new(__FILE__).dirname + 'trash'
|
33
|
+
CLONE_PATH = TRASH_PATH + 'rails.git'
|
34
|
+
RAILS2_BIN_PATH = CLONE_PATH + 'railties' + 'bin' + 'rails'
|
35
|
+
RAILS3_BIN_PATH = CLONE_PATH + 'bin' + 'rails'
|
36
|
+
WIKITEXT_GEM_PATH = TRASH_PATH + '..' + '..'
|
37
|
+
SUCCESSFUL_TEST_RESULT = /1 tests, 3 assertions, 0 failures, 0 errors/
|
36
38
|
|
37
39
|
def run cmd, *args
|
38
40
|
result = OpenStruct.new
|
@@ -51,7 +53,7 @@ module RailsSpecs
|
|
51
53
|
status = $?.exitstatus
|
52
54
|
if status != 0
|
53
55
|
command_string = ([cmd] + args).join(' ')
|
54
|
-
puts "*** COMMAND #{command_string} EXITED WITH NON-ZERO EXIT STATUS (#{status})"
|
56
|
+
puts "\n*** COMMAND #{command_string} EXITED WITH NON-ZERO EXIT STATUS (#{status})"
|
55
57
|
puts "*** STDOUT FOR COMMAND #{command_string}:", result.stdout
|
56
58
|
puts "*** STDERR FOR COMMAND #{command_string}:", result.stderr
|
57
59
|
raise "non-zero exit status (#{status}) for '#{cmd}'"
|
@@ -70,14 +72,20 @@ module RailsSpecs
|
|
70
72
|
end
|
71
73
|
|
72
74
|
def app_path version
|
75
|
+
version = 'edge' if version.nil?
|
76
|
+
version = "v#{version}" if version =~ /\A3\./
|
73
77
|
TRASH_PATH + "#{version}-app"
|
74
78
|
end
|
75
79
|
|
76
|
-
def
|
80
|
+
def create_rails2_app version
|
81
|
+
app = app_path version
|
77
82
|
clone
|
78
83
|
FileUtils.rm_r(app) if File.exist?(app)
|
79
|
-
|
80
|
-
|
84
|
+
FileUtils.cd CLONE_PATH do
|
85
|
+
run 'git', 'checkout', '-f', "v#{version}"
|
86
|
+
run 'git', 'clean', '-f'
|
87
|
+
end
|
88
|
+
run 'ruby', RAILS2_BIN_PATH, app
|
81
89
|
vendor = app + 'vendor'
|
82
90
|
gems = vendor + 'gems'
|
83
91
|
FileUtils.cd vendor do
|
@@ -89,13 +97,22 @@ module RailsSpecs
|
|
89
97
|
end
|
90
98
|
end
|
91
99
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
100
|
+
# if version is nil will create an "Edge" app
|
101
|
+
def create_rails3_app version
|
102
|
+
app = app_path version
|
103
|
+
clone
|
104
|
+
FileUtils.rm_r(app) if File.exist?(app)
|
105
|
+
FileUtils.cd CLONE_PATH do
|
106
|
+
if version
|
107
|
+
run 'git', 'checkout', '-f', "v#{version}"
|
108
|
+
else # "Edge"
|
109
|
+
run 'git', 'checkout', '-f', 'master'
|
110
|
+
run 'git', 'merge', 'origin/master'
|
97
111
|
end
|
112
|
+
run 'git', 'clean', '-f'
|
98
113
|
end
|
114
|
+
run 'ruby', RAILS3_BIN_PATH, 'new', app, '--skip-activerecord', '--dev'
|
115
|
+
create_gemfile app
|
99
116
|
end
|
100
117
|
|
101
118
|
def insert text, after, infile
|
@@ -112,10 +129,25 @@ module RailsSpecs
|
|
112
129
|
raise "text '#{after}' not found" unless found
|
113
130
|
end
|
114
131
|
|
132
|
+
# Rails 2 only
|
115
133
|
def add_text_to_initializer text, infile
|
116
134
|
insert text, 'Rails::Initializer.run do', infile
|
117
135
|
end
|
118
136
|
|
137
|
+
# Rails 3 only
|
138
|
+
def add_text_to_routes text, infile
|
139
|
+
insert text, 'Application.routes.draw', infile
|
140
|
+
end
|
141
|
+
|
142
|
+
def create_gemfile app
|
143
|
+
File.open(app + 'Gemfile', 'w') do |f|
|
144
|
+
f.write <<-GEMFILE
|
145
|
+
gem 'rails', :path => "#{CLONE_PATH.realpath}"
|
146
|
+
gem 'wikitext', :path => "#{WIKITEXT_GEM_PATH.realpath}"
|
147
|
+
GEMFILE
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
119
151
|
def create_controller app
|
120
152
|
File.open(app + 'app' + 'controllers' + 'wiki_controller.rb', 'w') do |f|
|
121
153
|
f.write 'class WikiController < ApplicationController; end'
|
@@ -150,16 +182,7 @@ TEST
|
|
150
182
|
end
|
151
183
|
end
|
152
184
|
|
153
|
-
|
154
|
-
create_base_app_and_symlinks EDGE_APP_PATH do
|
155
|
-
FileUtils.cd CLONE_PATH do
|
156
|
-
run 'git', 'checkout', 'master'
|
157
|
-
run 'git', 'merge', 'origin/master'
|
158
|
-
run 'git', 'clean', '-f'
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
185
|
+
# Rails 2 only
|
163
186
|
def update_environment app
|
164
187
|
environment = app + 'config' + 'environment.rb'
|
165
188
|
add_text_to_initializer " config.gem 'wikitext', :version => '#{Wikitext::VERSION}'", environment
|
@@ -168,21 +191,32 @@ TEST
|
|
168
191
|
end
|
169
192
|
end
|
170
193
|
|
171
|
-
|
172
|
-
|
173
|
-
|
194
|
+
# Rails 3 only
|
195
|
+
def update_routes app
|
196
|
+
routes = app + 'config' + 'routes.rb'
|
197
|
+
add_text_to_routes 'match "/wiki" => "wiki#index"', routes
|
198
|
+
end
|
199
|
+
|
200
|
+
def setup_rails2_app version
|
201
|
+
create_rails2_app version
|
202
|
+
path = app_path version
|
174
203
|
update_environment path
|
175
204
|
create_controller path
|
176
205
|
create_template path
|
177
206
|
create_test path
|
178
207
|
end
|
179
208
|
|
209
|
+
def setup_rails3_app version = nil
|
210
|
+
create_rails3_app version
|
211
|
+
path = app_path version
|
212
|
+
update_routes path
|
213
|
+
create_controller path
|
214
|
+
create_template path
|
215
|
+
create_test path
|
216
|
+
end
|
217
|
+
|
180
218
|
def setup_edge_app
|
181
|
-
|
182
|
-
update_environment EDGE_APP_PATH
|
183
|
-
create_controller EDGE_APP_PATH
|
184
|
-
create_template EDGE_APP_PATH
|
185
|
-
create_test EDGE_APP_PATH
|
219
|
+
setup_rails3_app
|
186
220
|
end
|
187
221
|
|
188
222
|
def run_integration_test app
|
@@ -192,29 +226,63 @@ TEST
|
|
192
226
|
end
|
193
227
|
end # module RailsSpecs
|
194
228
|
|
195
|
-
describe 'Template handler in Rails 2.
|
229
|
+
describe 'Template handler in Rails 2.3.0' do
|
196
230
|
include RailsSpecs
|
197
|
-
version = '2.2.2'
|
198
231
|
|
199
|
-
before
|
200
|
-
|
201
|
-
@path = app_path
|
232
|
+
before :all do
|
233
|
+
setup_rails2_app '2.3.0'
|
234
|
+
@path = app_path '2.3.0'
|
202
235
|
end
|
203
236
|
|
204
237
|
it 'should process the template using the wikitext module' do
|
205
|
-
|
238
|
+
pending 'Rack::Lint::LintError'
|
239
|
+
# Rack::Lint::LintError: a header value must be a String, but the value of
|
240
|
+
# 'Set-Cookie' is a Array
|
241
|
+
run_integration_test(@path).should =~ RailsSpecs::SUCCESSFUL_TEST_RESULT
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# test other Rails 2 versions
|
246
|
+
%w{2.2.2 2.2.3 2.3.1 2.3.2 2.3.2.1 2.3.3 2.3.3.1 2.3.4 2.3.5 2.3.6
|
247
|
+
2.3.7 2.3.8}.each do |version|
|
248
|
+
describe "Template handler in Rails #{version}" do
|
249
|
+
include RailsSpecs
|
250
|
+
|
251
|
+
before :all do
|
252
|
+
setup_rails2_app version
|
253
|
+
@path = app_path version
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'should process the template using the wikitext module' do
|
257
|
+
run_integration_test(@path).should =~ RailsSpecs::SUCCESSFUL_TEST_RESULT
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
%w{3.0.0.beta4}.each do |version|
|
263
|
+
describe "Template handler in Rails #{version}" do
|
264
|
+
include RailsSpecs
|
265
|
+
|
266
|
+
before :all do
|
267
|
+
setup_rails3_app version
|
268
|
+
@path = app_path version
|
269
|
+
end
|
270
|
+
|
271
|
+
it 'should process the template using the wikitext module' do
|
272
|
+
run_integration_test(@path).should =~ RailsSpecs::SUCCESSFUL_TEST_RESULT
|
273
|
+
end
|
206
274
|
end
|
207
275
|
end
|
208
276
|
|
209
277
|
describe 'Template handler in Edge Rails' do
|
210
278
|
include RailsSpecs
|
211
279
|
|
212
|
-
before
|
280
|
+
before :all do
|
213
281
|
setup_edge_app
|
214
|
-
@path =
|
282
|
+
@path = app_path nil
|
215
283
|
end
|
216
284
|
|
217
285
|
it 'should process the template using the wikitext module' do
|
218
|
-
run_integration_test(@path).should =~
|
286
|
+
run_integration_test(@path).should =~ RailsSpecs::SUCCESSFUL_TEST_RESULT
|
219
287
|
end
|
220
288
|
end
|
data/spec/tt_spec.rb
CHANGED
@@ -31,21 +31,23 @@ describe Wikitext::Parser, 'parsing <tt> spans' do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'should recognize paired <tt> and </tt> tags' do
|
34
|
-
|
34
|
+
# note how in version 2.0 and above, we output <code> tags instead of <tt>
|
35
|
+
# tags, seeing as the latter have been removed from HTML5
|
36
|
+
@parser.parse('foo <tt>bar</tt> baz').should == "<p>foo <code>bar</code> baz</p>\n"
|
35
37
|
end
|
36
38
|
|
37
39
|
it 'should recognize <tt> tags case-insensitively' do
|
38
|
-
@parser.parse('foo <TT>bar</tT> baz').should == "<p>foo <
|
39
|
-
@parser.parse('foo <tT>bar</Tt> baz').should == "<p>foo <
|
40
|
-
@parser.parse('foo <Tt>bar</TT> baz').should == "<p>foo <
|
40
|
+
@parser.parse('foo <TT>bar</tT> baz').should == "<p>foo <code>bar</code> baz</p>\n"
|
41
|
+
@parser.parse('foo <tT>bar</Tt> baz').should == "<p>foo <code>bar</code> baz</p>\n"
|
42
|
+
@parser.parse('foo <Tt>bar</TT> baz').should == "<p>foo <code>bar</code> baz</p>\n"
|
41
43
|
end
|
42
44
|
|
43
45
|
it 'should automatically insert missing closing tags' do
|
44
|
-
@parser.parse('foo <tt>bar').should == "<p>foo <
|
46
|
+
@parser.parse('foo <tt>bar').should == "<p>foo <code>bar</code></p>\n"
|
45
47
|
end
|
46
48
|
|
47
49
|
it 'should automatically close unclosed spans upon hitting newline' do
|
48
|
-
@parser.parse("foo <tt>bar\nbaz").should == "<p>foo <
|
50
|
+
@parser.parse("foo <tt>bar\nbaz").should == "<p>foo <code>bar</code> baz</p>\n"
|
49
51
|
end
|
50
52
|
|
51
53
|
it 'should convert unexpected closing tags into entities' do
|
@@ -53,11 +55,11 @@ describe Wikitext::Parser, 'parsing <tt> spans' do
|
|
53
55
|
end
|
54
56
|
|
55
57
|
it 'should handle (illegal) nested <tt> spans' do
|
56
|
-
@parser.parse('foo <tt>bar <tt>inner</tt></tt> baz').should == "<p>foo <
|
58
|
+
@parser.parse('foo <tt>bar <tt>inner</tt></tt> baz').should == "<p>foo <code>bar <tt>inner</code></tt> baz</p>\n"
|
57
59
|
end
|
58
60
|
|
59
61
|
it 'should handle (illegal) interleaved spans' do
|
60
|
-
@parser.parse("foo <tt>bar '''inner</tt> baz'''").should == "<p>foo <
|
62
|
+
@parser.parse("foo <tt>bar '''inner</tt> baz'''").should == "<p>foo <code>bar <strong>inner</strong></code> baz<strong></strong></p>\n"
|
61
63
|
end
|
62
64
|
|
63
65
|
it 'should have no effect inside <pre> blocks' do
|
@@ -69,7 +71,7 @@ describe Wikitext::Parser, 'parsing <tt> spans' do
|
|
69
71
|
end
|
70
72
|
|
71
73
|
it 'should have no effect if a backtick span is already open' do
|
72
|
-
@parser.parse('foo `<tt>bar</tt>` baz').should == "<p>foo <
|
74
|
+
@parser.parse('foo `<tt>bar</tt>` baz').should == "<p>foo <code><tt>bar</tt></code> baz</p>\n"
|
73
75
|
end
|
74
76
|
end
|
75
77
|
|
@@ -79,19 +81,19 @@ describe Wikitext::Parser, 'parsing backtick spans' do
|
|
79
81
|
end
|
80
82
|
|
81
83
|
it 'should recognize paired backticks' do
|
82
|
-
@parser.parse('foo `bar` baz').should == "<p>foo <
|
84
|
+
@parser.parse('foo `bar` baz').should == "<p>foo <code>bar</code> baz</p>\n"
|
83
85
|
end
|
84
86
|
|
85
87
|
it 'should automatically insert missing closing backtick' do
|
86
|
-
@parser.parse('foo `bar').should == "<p>foo <
|
88
|
+
@parser.parse('foo `bar').should == "<p>foo <code>bar</code></p>\n"
|
87
89
|
end
|
88
90
|
|
89
91
|
it 'should automatically close unclosed spans upon hitting newline' do
|
90
|
-
@parser.parse("foo `bar\nbaz").should == "<p>foo <
|
92
|
+
@parser.parse("foo `bar\nbaz").should == "<p>foo <code>bar</code> baz</p>\n"
|
91
93
|
end
|
92
94
|
|
93
95
|
it 'should handle (illegal) interleaved spans' do
|
94
|
-
@parser.parse("foo `bar '''inner` baz'''").should == "<p>foo <
|
96
|
+
@parser.parse("foo `bar '''inner` baz'''").should == "<p>foo <code>bar <strong>inner</strong></code> baz<strong></strong></p>\n"
|
95
97
|
end
|
96
98
|
|
97
99
|
it 'should have no effect inside <pre> blocks' do
|
@@ -103,7 +105,7 @@ describe Wikitext::Parser, 'parsing backtick spans' do
|
|
103
105
|
end
|
104
106
|
|
105
107
|
it 'should have no effect if a <tt> span is already open' do
|
106
|
-
@parser.parse('foo <tt>`bar`</tt> baz').should == "<p>foo <
|
108
|
+
@parser.parse('foo <tt>`bar`</tt> baz').should == "<p>foo <code>`bar`</code> baz</p>\n"
|
107
109
|
end
|
108
110
|
end
|
109
111
|
|
data/spec/ul_spec.rb
CHANGED
@@ -223,7 +223,7 @@ describe Wikitext::Parser, 'parsing unordered lists' do
|
|
223
223
|
END
|
224
224
|
expected = dedent <<-END
|
225
225
|
<ul>
|
226
|
-
<li><
|
226
|
+
<li><code>hello</code></li>
|
227
227
|
<li>world</li>
|
228
228
|
</ul>
|
229
229
|
END
|
@@ -237,7 +237,7 @@ describe Wikitext::Parser, 'parsing unordered lists' do
|
|
237
237
|
END
|
238
238
|
expected = dedent <<-END
|
239
239
|
<ul>
|
240
|
-
<li><
|
240
|
+
<li><code>hello</code></li>
|
241
241
|
<li>world</li>
|
242
242
|
</ul>
|
243
243
|
END
|
metadata
CHANGED
@@ -3,9 +3,9 @@ name: wikitext
|
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
|
-
-
|
7
|
-
-
|
8
|
-
version: "
|
6
|
+
- 2
|
7
|
+
- 0
|
8
|
+
version: "2.0"
|
9
9
|
platform: ruby
|
10
10
|
authors:
|
11
11
|
- Wincent Colaiuta
|
@@ -13,7 +13,7 @@ autorequire:
|
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
15
|
|
16
|
-
date: 2010-06-
|
16
|
+
date: 2010-06-13 00:00:00 +02:00
|
17
17
|
default_executable:
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
type: :development
|
30
30
|
version_requirements: *id001
|
31
31
|
- !ruby/object:Gem::Dependency
|
32
|
-
name:
|
32
|
+
name: thor
|
33
33
|
prerelease: false
|
34
34
|
requirement: &id002 !ruby/object:Gem::Requirement
|
35
35
|
requirements:
|
@@ -40,6 +40,18 @@ dependencies:
|
|
40
40
|
version: "0"
|
41
41
|
type: :development
|
42
42
|
version_requirements: *id002
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: wopen3
|
45
|
+
prerelease: false
|
46
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
segments:
|
51
|
+
- 0
|
52
|
+
version: "0"
|
53
|
+
type: :development
|
54
|
+
version_requirements: *id003
|
43
55
|
description: " Wikitext is a fast wikitext-to-HTML translator written in C.\n"
|
44
56
|
email: win@wincent.com
|
45
57
|
executables:
|
@@ -67,7 +79,8 @@ files:
|
|
67
79
|
- ext/depend
|
68
80
|
- lib/wikitext/nil_class.rb
|
69
81
|
- lib/wikitext/parser.rb
|
70
|
-
- lib/wikitext/
|
82
|
+
- lib/wikitext/preprocess.rb
|
83
|
+
- lib/wikitext/rails_template_handler.rb
|
71
84
|
- lib/wikitext/string.rb
|
72
85
|
- lib/wikitext/version.rb
|
73
86
|
- rails/init.rb
|