jeremy-RedCloth 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/CHANGELOG +135 -0
  2. data/COPYING +18 -0
  3. data/Manifest +56 -0
  4. data/README +171 -0
  5. data/Rakefile +205 -0
  6. data/bin/redcloth +28 -0
  7. data/ext/mingw-rbconfig.rb +176 -0
  8. data/ext/redcloth_scan/extconf.rb +9 -0
  9. data/ext/redcloth_scan/redcloth.h +178 -0
  10. data/ext/redcloth_scan/redcloth_attributes.c.rl +56 -0
  11. data/ext/redcloth_scan/redcloth_attributes.java.rl +96 -0
  12. data/ext/redcloth_scan/redcloth_attributes.rl +33 -0
  13. data/ext/redcloth_scan/redcloth_common.c.rl +18 -0
  14. data/ext/redcloth_scan/redcloth_common.java.rl +18 -0
  15. data/ext/redcloth_scan/redcloth_common.rl +111 -0
  16. data/ext/redcloth_scan/redcloth_inline.c.rl +159 -0
  17. data/ext/redcloth_scan/redcloth_inline.java.rl +108 -0
  18. data/ext/redcloth_scan/redcloth_inline.rl +159 -0
  19. data/ext/redcloth_scan/redcloth_scan.c.rl +237 -0
  20. data/ext/redcloth_scan/redcloth_scan.java.rl +573 -0
  21. data/ext/redcloth_scan/redcloth_scan.rl +325 -0
  22. data/extras/ragel_profiler.rb +73 -0
  23. data/lib/case_sensitive_require/RedCloth.rb +6 -0
  24. data/lib/redcloth.rb +37 -0
  25. data/lib/redcloth/erb_extension.rb +27 -0
  26. data/lib/redcloth/formatters/base.rb +57 -0
  27. data/lib/redcloth/formatters/html.rb +353 -0
  28. data/lib/redcloth/formatters/latex.rb +275 -0
  29. data/lib/redcloth/formatters/latex_entities.yml +2414 -0
  30. data/lib/redcloth/textile_doc.rb +103 -0
  31. data/lib/redcloth/version.rb +28 -0
  32. data/setup.rb +1585 -0
  33. data/test/basic.yml +922 -0
  34. data/test/code.yml +229 -0
  35. data/test/definitions.yml +82 -0
  36. data/test/extra_whitespace.yml +64 -0
  37. data/test/filter_html.yml +177 -0
  38. data/test/filter_pba.yml +20 -0
  39. data/test/helper.rb +108 -0
  40. data/test/html.yml +311 -0
  41. data/test/images.yml +254 -0
  42. data/test/instiki.yml +38 -0
  43. data/test/links.yml +275 -0
  44. data/test/lists.yml +283 -0
  45. data/test/poignant.yml +89 -0
  46. data/test/sanitize_html.yml +42 -0
  47. data/test/table.yml +336 -0
  48. data/test/test_custom_tags.rb +58 -0
  49. data/test/test_erb.rb +13 -0
  50. data/test/test_extensions.rb +31 -0
  51. data/test/test_formatters.rb +24 -0
  52. data/test/test_parser.rb +73 -0
  53. data/test/test_restrictions.rb +41 -0
  54. data/test/textism.yml +480 -0
  55. data/test/threshold.yml +772 -0
  56. data/test/validate_fixtures.rb +74 -0
  57. metadata +133 -0
@@ -0,0 +1,159 @@
1
+ /*
2
+ * redcloth_inline.rl
3
+ *
4
+ * Copyright (C) 2008 Jason Garber
5
+ */
6
+ %%{
7
+
8
+ machine redcloth_inline;
9
+
10
+ # links
11
+ mtext_noquotes = mtext -- '"' ;
12
+ quoted_mtext = '"' mtext_noquotes '"' ;
13
+ mtext_including_quotes = (mtext_noquotes ' "' mtext_noquotes '" ' mtext_noquotes?)+ ;
14
+ link_says = ( C_noactions "."* " "* ((quoted_mtext | mtext_including_quotes | mtext_noquotes) -- '":') ) >A %{ STORE("link_text"); } ;
15
+ link_says_noquotes_noactions = ( C_noquotes_noactions "."* " "* ((mtext_noquotes) -- '":') ) ;
16
+ link = ( '"' link_says '":' %A uri %{ STORE_URL("href"); } ) >X ;
17
+ link_noquotes_noactions = ( '"' link_says_noquotes_noactions '":' uri ) ;
18
+ bracketed_link = ( '["' link_says '":' %A uri %{ STORE("href"); } :> "]" ) >X ;
19
+
20
+ # images
21
+ image_src = ( uri ) >A %{ STORE("src"); } ;
22
+ image_is = ( A2 C ". "? image_src :> title? ) ;
23
+ image_link = ( ":" uri >A %{ STORE_URL("href"); } ) ;
24
+ image = ( "!" image_is "!" %A image_link? ) >X ;
25
+ bracketed_image = ( "[!" image_is "!" %A image_link? "]" ) >X ;
26
+
27
+ # footnotes
28
+ footno = "[" >X %A digit+ %T "]" ;
29
+
30
+ # markup
31
+ end_markup_phrase = (" " | PUNCT | EOF | LF) @{ fhold; };
32
+ code = "["? "@" >X mtext >A %T :> "@" "]"? ;
33
+ code_tag_start = "<code" [^>]* ">" ;
34
+ code_tag_end = "</code>" ;
35
+ script_tag = ( "<script" [^>]* ">" (default+ -- "</script>") "</script>" LF? ) >X >A %T ;
36
+ notextile = "<notextile>" >X (default+ -- "</notextile>") >A %T "</notextile>";
37
+ strong = "["? "*" >X mtext >A %T :> "*" "]"? ;
38
+ b = "["? "**" >X mtext >A %T :> "**" "]"? ;
39
+ em = "["? "_" >X mtext >A %T :> "_" "]"? ;
40
+ i = "["? "__" >X mtext >A %T :> "__" "]"? ;
41
+ del = "[-" >X C ( mtext ) >A %T :>> "-]" ;
42
+ emdash_parenthetical_phrase_with_spaces = " -- " mtext " -- " ;
43
+ del_phrase = (( " " >A %{ STORE("beginning_space"); } "-") >X C ( mtext ) >A %T :>> ( "-" end_markup_phrase )) - emdash_parenthetical_phrase_with_spaces ;
44
+ ins = "["? "+" >X mtext >A %T :> "+" "]"? ;
45
+ sup = "[^" >X mtext >A %T :> "^]" ;
46
+ sup_phrase = ( "^" when starts_phrase) >X ( mtext ) >A %T :>> ( "^" end_markup_phrase ) ;
47
+ sub = "[~" >X mtext >A %T :> "~]" ;
48
+ sub_phrase = ( "~" when starts_phrase) >X ( mtext ) >A %T :>> ( "~" end_markup_phrase ) ;
49
+ span = "[%" >X mtext >A %T :> "%]" ;
50
+ span_phrase = (("%" when starts_phrase) >X ( mtext ) >A %T :>> ( "%" end_markup_phrase )) ;
51
+ cite = "["? "??" >X mtext >A %T :> "??" "]"? ;
52
+ ignore = "["? "==" >X %A mtext %T :> "==" "]"? ;
53
+ snip = "["? "```" >X %A mtext %T :> "```" "]"? ;
54
+
55
+ # quotes
56
+ quote1 = "'" >X %A mtext %T :> "'" ;
57
+ non_quote_chars_or_link = (chars -- '"') | link_noquotes_noactions ;
58
+ mtext_inside_quotes = ( non_quote_chars_or_link (mspace non_quote_chars_or_link)* ) ;
59
+ html_tag_up_to_attribute_quote = "<" Name space+ NameAttr space* "=" space* ;
60
+ quote2 = ('"' >X %A ( mtext_inside_quotes - (mtext_inside_quotes html_tag_up_to_attribute_quote ) ) %T :> '"' ) ;
61
+ multi_paragraph_quote = (('"' when starts_line) >X %A ( chars -- '"' ) %T );
62
+
63
+ # html
64
+ start_tag = ( "<" Name space+ AttrSet* (AttrEnd)? ">" | "<" Name ">" ) >X >A %T ;
65
+ empty_tag = ( "<" Name space+ AttrSet* (AttrEnd)? "/>" | "<" Name "/>" ) >X >A %T ;
66
+ end_tag = ( "</" Name space* ">" ) >X >A %T ;
67
+ html_comment = ("<!--" (default+) :>> "-->") >X >A %T;
68
+
69
+ # glyphs
70
+ ellipsis = ( " "? >A %T "..." ) >X ;
71
+ emdash = "--" ;
72
+ arrow = "->" ;
73
+ endash = " - " ;
74
+ acronym = ( [A-Z] >A [A-Z0-9]{2,} %T "(" default+ >A %{ STORE("title"); } :> ")" ) >X ;
75
+ caps_noactions = upper{3,} ;
76
+ caps = ( caps_noactions >A %*T ) >X ;
77
+ dim_digit = [0-9.]+ ;
78
+ prime = ("'" | '"')?;
79
+ dim_noactions = dim_digit prime (("x" | " x ") dim_digit prime) %T (("x" | " x ") dim_digit prime)? ;
80
+ dim = dim_noactions >X >A %T ;
81
+ tm = [Tt] [Mm] ;
82
+ trademark = " "? ( "[" tm "]" | "(" tm ")" ) ;
83
+ reg = [Rr] ;
84
+ registered = " "? ( "[" reg "]" | "(" reg ")" ) ;
85
+ cee = [Cc] ;
86
+ copyright = ( "[" cee "]" | "(" cee ")" ) ;
87
+ entity = ( "&" %A ( '#' digit+ | ( alpha ( alpha | digit )+ ) ) %T ';' ) >X ;
88
+
89
+ # info
90
+ redcloth_version = "[RedCloth::VERSION]" ;
91
+
92
+ other_phrase = phrase -- dim_noactions;
93
+
94
+ code_tag := |*
95
+ code_tag_end { CAT(block); fgoto main; };
96
+ default => esc_pre;
97
+ *|;
98
+
99
+ main := |*
100
+
101
+ image { INLINE(block, "image"); };
102
+ bracketed_image { INLINE(block, "image"); };
103
+
104
+ link { PARSE_LINK_ATTR("link_text"); PASS(block, "name", "link"); };
105
+ bracketed_link { PARSE_LINK_ATTR("link_text"); PASS(block, "name", "link"); };
106
+
107
+ code { PARSE_ATTR("text"); PASS_CODE(block, "text", "code", opts); };
108
+ code_tag_start { CAT(block); fgoto code_tag; };
109
+ notextile { INLINE(block, "notextile"); };
110
+ strong { PARSE_ATTR("text"); PASS(block, "text", "strong"); };
111
+ b { PARSE_ATTR("text"); PASS(block, "text", "b"); };
112
+ em { PARSE_ATTR("text"); PASS(block, "text", "em"); };
113
+ i { PARSE_ATTR("text"); PASS(block, "text", "i"); };
114
+ del { PASS(block, "text", "del"); };
115
+ del_phrase { PASS(block, "text", "del_phrase"); };
116
+ ins { PARSE_ATTR("text"); PASS(block, "text", "ins"); };
117
+ sup { PARSE_ATTR("text"); PASS(block, "text", "sup"); };
118
+ sup_phrase { PARSE_ATTR("text"); PASS(block, "text", "sup_phrase"); };
119
+ sub { PARSE_ATTR("text"); PASS(block, "text", "sub"); };
120
+ sub_phrase { PARSE_ATTR("text"); PASS(block, "text", "sub_phrase"); };
121
+ span { PARSE_ATTR("text"); PASS(block, "text", "span"); };
122
+ span_phrase { PARSE_ATTR("text"); PASS(block, "text", "span_phrase"); };
123
+ cite { PARSE_ATTR("text"); PASS(block, "text", "cite"); };
124
+ ignore => ignore;
125
+ snip { PASS(block, "text", "snip"); };
126
+ quote1 { PASS(block, "text", "quote1"); };
127
+ quote2 { PASS(block, "text", "quote2"); };
128
+ multi_paragraph_quote { PASS(block, "text", "multi_paragraph_quote"); };
129
+
130
+ ellipsis { INLINE(block, "ellipsis"); };
131
+ emdash { INLINE(block, "emdash"); };
132
+ endash { INLINE(block, "endash"); };
133
+ arrow { INLINE(block, "arrow"); };
134
+ caps { INLINE(block, "caps"); };
135
+ acronym { INLINE(block, "acronym"); };
136
+ dim { INLINE(block, "dim"); };
137
+ trademark { INLINE(block, "trademark"); };
138
+ registered { INLINE(block, "registered"); };
139
+ copyright { INLINE(block, "copyright"); };
140
+ footno { PASS(block, "text", "footno"); };
141
+ entity { INLINE(block, "entity"); };
142
+
143
+ script_tag { INLINE(block, "inline_html"); };
144
+ start_tag { INLINE(block, "inline_html"); };
145
+ end_tag { INLINE(block, "inline_html"); };
146
+ empty_tag { INLINE(block, "inline_html"); };
147
+ html_comment { INLINE(block, "inline_html"); };
148
+
149
+ redcloth_version { INLINE(block, "inline_redcloth_version"); };
150
+
151
+ other_phrase => esc;
152
+ PUNCT => esc;
153
+ space => esc;
154
+
155
+ EOF;
156
+
157
+ *|;
158
+
159
+ }%%;
@@ -0,0 +1,237 @@
1
+ /*
2
+ * redcloth_scan.c.rl
3
+ *
4
+ * Copyright (C) 2008 Jason Garber
5
+ */
6
+ #define redcloth_scan_c
7
+
8
+ #include <ruby.h>
9
+ #include "redcloth.h"
10
+
11
+ VALUE mRedCloth, super_ParseError, super_RedCloth, super_HTML, super_LATEX;
12
+ int SYM_escape_preformatted, SYM_escape_attributes;
13
+
14
+ %%{
15
+
16
+ machine redcloth_scan;
17
+ include redcloth_common "redcloth_common.c.rl";
18
+
19
+ action extend { extend = rb_hash_aref(regs, ID2SYM(rb_intern("type"))); }
20
+
21
+ include redcloth_scan "redcloth_scan.rl";
22
+
23
+ }%%
24
+
25
+ %% write data nofinal;
26
+
27
+ VALUE
28
+ redcloth_transform(self, p, pe, refs)
29
+ VALUE self;
30
+ char *p, *pe;
31
+ VALUE refs;
32
+ {
33
+ char *orig_p = p, *orig_pe = pe;
34
+ int cs, act, nest;
35
+ char *ts = NULL, *te = NULL, *reg = NULL, *bck = NULL, *eof = NULL;
36
+ VALUE html = rb_str_new2("");
37
+ VALUE table = rb_str_new2("");
38
+ VALUE block = rb_str_new2("");
39
+ VALUE regs; CLEAR_REGS()
40
+
41
+
42
+ VALUE list_layout = Qnil;
43
+ char *list_type = NULL;
44
+ VALUE list_index = rb_ary_new();
45
+ int list_continue = 0;
46
+ VALUE plain_block; SET_PLAIN_BLOCK("p");
47
+ VALUE extend = Qnil;
48
+ char listm[10] = "";
49
+ VALUE refs_found = rb_hash_new();
50
+
51
+ %% write init;
52
+
53
+ %% write exec;
54
+
55
+ if (RSTRING_LEN(block) > 0)
56
+ {
57
+ ADD_BLOCK();
58
+ }
59
+
60
+ if ( NIL_P(refs) && rb_funcall(refs_found, rb_intern("empty?"), 0) == Qfalse ) {
61
+ return redcloth_transform(self, orig_p, orig_pe, refs_found);
62
+ } else {
63
+ rb_funcall(self, rb_intern("after_transform"), 1, html);
64
+ return html;
65
+ }
66
+ }
67
+
68
+ VALUE
69
+ redcloth_transform2(self, str)
70
+ VALUE self, str;
71
+ {
72
+ StringValue(str);
73
+ rb_funcall(self, rb_intern("before_transform"), 1, str);
74
+ return redcloth_transform(self, RSTRING_PTR(str), RSTRING_PTR(str) + RSTRING_LEN(str) + 1, Qnil);
75
+ }
76
+
77
+ /*
78
+ * Converts special characters into HTML entities.
79
+ */
80
+ static VALUE
81
+ redcloth_html_esc(int argc, VALUE* argv, VALUE self) //(self, str, level)
82
+ {
83
+ VALUE str, level;
84
+
85
+ rb_scan_args(argc, argv, "11", &str, &level);
86
+
87
+ VALUE new_str = rb_str_new2("");
88
+ if (str == Qnil)
89
+ return new_str;
90
+
91
+ StringValue(str);
92
+
93
+ if (RSTRING_LEN(str) == 0)
94
+ return new_str;
95
+
96
+ char *ts = RSTRING_PTR(str), *te = RSTRING_PTR(str) + RSTRING_LEN(str);
97
+ char *t = ts, *t2 = ts, *ch = NULL;
98
+ if (te <= ts) return;
99
+
100
+ while (t2 < te) {
101
+ ch = NULL;
102
+
103
+ // normal + pre
104
+ switch (*t2)
105
+ {
106
+ case '&': ch = "amp"; break;
107
+ case '>': ch = "gt"; break;
108
+ case '<': ch = "lt"; break;
109
+ }
110
+
111
+ // normal (non-pre)
112
+ if (level != SYM_escape_preformatted) {
113
+ switch (*t2)
114
+ {
115
+ case '\n': ch = "br"; break;
116
+ case '"' : ch = "quot"; break;
117
+ case '\'':
118
+ ch = (level == SYM_escape_attributes) ? "apos" : "squot";
119
+ break;
120
+ }
121
+ }
122
+
123
+ if (ch != NULL)
124
+ {
125
+ if (t2 > t)
126
+ rb_str_cat(new_str, t, t2-t);
127
+ rb_str_concat(new_str, rb_funcall(self, rb_intern(ch), 1, rb_hash_new()));
128
+ t = t2 + 1;
129
+ }
130
+
131
+ t2++;
132
+ }
133
+ if (t2 > t)
134
+ rb_str_cat(new_str, t, t2-t);
135
+
136
+ return new_str;
137
+ }
138
+
139
+ /*
140
+ * Converts special characters into LaTeX entities.
141
+ */
142
+ static VALUE
143
+ redcloth_latex_esc(VALUE self, VALUE str)
144
+ {
145
+ VALUE new_str = rb_str_new2("");
146
+
147
+ if (str == Qnil)
148
+ return new_str;
149
+
150
+ StringValue(str);
151
+
152
+ if (RSTRING_LEN(str) == 0)
153
+ return new_str;
154
+
155
+ char *ts = RSTRING_PTR(str), *te = RSTRING_PTR(str) + RSTRING_LEN(str);
156
+ char *t = ts, *t2 = ts, *ch = NULL;
157
+ if (te <= ts) return;
158
+
159
+ while (t2 < te) {
160
+ ch = NULL;
161
+
162
+ switch (*t2)
163
+ {
164
+ case '{': ch = "#123"; break;
165
+ case '}': ch = "#125"; break;
166
+ case '\\': ch = "#92"; break;
167
+ case '#': ch = "#35"; break;
168
+ case '$': ch = "#36"; break;
169
+ case '%': ch = "#37"; break;
170
+ case '&': ch = "amp"; break;
171
+ case '_': ch = "#95"; break;
172
+ case '^': ch = "circ"; break;
173
+ case '~': ch = "tilde"; break;
174
+ case '<': ch = "lt"; break;
175
+ case '>': ch = "gt"; break;
176
+ case '\n': ch = "#10"; break;
177
+ }
178
+
179
+ if (ch != NULL)
180
+ {
181
+ if (t2 > t)
182
+ rb_str_cat(new_str, t, t2-t);
183
+ VALUE opts = rb_hash_new();
184
+ rb_hash_aset(opts, ID2SYM(rb_intern("text")), rb_str_new2(ch));
185
+ rb_str_concat(new_str, rb_funcall(self, rb_intern("entity"), 1, opts));
186
+ t = t2 + 1;
187
+ }
188
+
189
+ t2++;
190
+ }
191
+ if (t2 > t)
192
+ rb_str_cat(new_str, t, t2-t);
193
+
194
+ return new_str;
195
+ }
196
+
197
+ /*
198
+ * Transforms a Textile document with +formatter+
199
+ */
200
+ static VALUE
201
+ redcloth_to(self, formatter)
202
+ VALUE self, formatter;
203
+ {
204
+ char *pe, *p;
205
+ int len = 0;
206
+
207
+ rb_funcall(self, rb_intern("delete!"), 1, rb_str_new2("\r"));
208
+ VALUE working_copy = rb_obj_clone(self);
209
+ rb_extend_object(working_copy, formatter);
210
+
211
+ VALUE working_copy_methods = rb_funcall(working_copy, rb_intern("methods"), 0);
212
+ VALUE class_instance_methods = rb_funcall(rb_obj_class(working_copy),rb_intern("instance_methods"), 0);
213
+ VALUE custom_tags = rb_funcall(working_copy_methods, rb_intern("-"), 1, class_instance_methods);
214
+ rb_iv_set(working_copy, "@custom_tags", custom_tags);
215
+
216
+
217
+ if (rb_funcall(working_copy, rb_intern("lite_mode"), 0) == Qtrue) {
218
+ return redcloth_inline2(working_copy, self, rb_hash_new());
219
+ } else {
220
+ return redcloth_transform2(working_copy, self);
221
+ }
222
+ }
223
+
224
+ void Init_redcloth_scan()
225
+ {
226
+ mRedCloth = rb_define_module("RedCloth");
227
+ /* A Textile document that can be converted to other formats. See
228
+ the README for Textile syntax. */
229
+ super_RedCloth = rb_define_class_under(mRedCloth, "TextileDoc", rb_cString);
230
+ rb_define_method(super_RedCloth, "to", redcloth_to, 1);
231
+ super_ParseError = rb_define_class_under(super_RedCloth, "ParseError", rb_eException);
232
+ /* Escaping */
233
+ rb_define_method(super_RedCloth, "html_esc", redcloth_html_esc, -1);
234
+ rb_define_method(super_RedCloth, "latex_esc", redcloth_latex_esc, 1);
235
+ SYM_escape_preformatted = ID2SYM(rb_intern("html_escape_preformatted"));
236
+ SYM_escape_attributes = ID2SYM(rb_intern("html_escape_attributes"));
237
+ }
@@ -0,0 +1,573 @@
1
+ /*
2
+ * redcloth_scan.java.rl
3
+ *
4
+ * Copyright (C) 2008 Jason Garber
5
+ */
6
+ import java.io.IOException;
7
+
8
+ import org.jruby.Ruby;
9
+ import org.jruby.RubyArray;
10
+ import org.jruby.RubyClass;
11
+ import org.jruby.RubyHash;
12
+ import org.jruby.RubyModule;
13
+ import org.jruby.RubyNumeric;
14
+ import org.jruby.RubyObject;
15
+ import org.jruby.RubyString;
16
+ import org.jruby.RubySymbol;
17
+ import org.jruby.anno.JRubyMethod;
18
+ import org.jruby.runtime.Arity;
19
+ import org.jruby.runtime.Block;
20
+ import org.jruby.runtime.CallbackFactory;
21
+ import org.jruby.runtime.builtin.IRubyObject;
22
+ import org.jruby.exceptions.RaiseException;
23
+ import org.jruby.runtime.load.BasicLibraryService;
24
+ import org.jruby.util.ByteList;
25
+
26
+ public class RedclothScanService implements BasicLibraryService {
27
+
28
+ public static class Base {
29
+
30
+ public void CLEAR_LIST() {
31
+ list_layout = runtime.newArray();
32
+ }
33
+
34
+ public void LIST_ITEM() {
35
+ int aint = 0;
36
+ IRubyObject aval = ((RubyArray)list_index).entry(nest-1);
37
+ if(!aval.isNil()) { aint = RubyNumeric.fix2int(aval); }
38
+ if(list_type.equals("ol")) {
39
+ ((RubyArray)list_index).store(nest-1, runtime.newFixnum(aint + 1));
40
+ }
41
+
42
+ if(nest > ((RubyArray)list_layout).getLength()) {
43
+ listm = list_type + "_open";
44
+ if(list_continue == 1) {
45
+ list_continue = 0;
46
+ ((RubyHash)regs).aset(runtime.newSymbol("start"), ((RubyArray)list_index).entry(nest-1));
47
+ } else {
48
+ IRubyObject start = ((RubyHash)regs).aref(runtime.newSymbol("start"));
49
+ if(start.isNil()) {
50
+ ((RubyArray)list_index).store(nest-1, runtime.newFixnum(1));
51
+ } else {
52
+ IRubyObject start_num = start.callMethod(runtime.getCurrentContext(), "to_i");
53
+ ((RubyArray)list_index).store(nest-1, start_num);
54
+ }
55
+ }
56
+ ((RubyHash)regs).aset(runtime.newSymbol("nest"), runtime.newFixnum(nest));
57
+ ((RubyString)html).append(self.callMethod(runtime.getCurrentContext(), listm, regs));
58
+ ((RubyArray)list_layout).store(nest-1, runtime.newString(list_type));
59
+ regs = RubyHash.newHash(runtime);
60
+ ASET("first", "true");
61
+ }
62
+ LIST_CLOSE();
63
+ ((RubyHash)regs).aset(runtime.newSymbol("nest"), ((RubyArray)list_layout).length());
64
+ ASET("type", "li_open");
65
+ }
66
+
67
+ public void LIST_CLOSE() {
68
+ while(nest < ((RubyArray)list_layout).getLength()) {
69
+ ((RubyHash)regs).aset(runtime.newSymbol("nest"), ((RubyArray)list_layout).length());
70
+ IRubyObject end_list = ((RubyArray)list_layout).pop(runtime.getCurrentContext());
71
+ if(!end_list.isNil()) {
72
+ String s = end_list.convertToString().toString();
73
+ listm = s + "_close";
74
+ ((RubyString)html).append(self.callMethod(runtime.getCurrentContext(), listm, regs));
75
+ }
76
+ }
77
+ }
78
+
79
+ public void TRANSFORM(String T) {
80
+ if(p > reg && reg >= ts) {
81
+ IRubyObject str = RedclothScanService.transform(self, data, reg, p-reg, refs);
82
+ ((RubyHash)regs).aset(runtime.newSymbol(T), str);
83
+ } else {
84
+ ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.getNil());
85
+ }
86
+ }
87
+
88
+ public IRubyObject red_pass(IRubyObject self, IRubyObject regs, IRubyObject ref, String meth, IRubyObject refs) {
89
+ IRubyObject txt = ((RubyHash)regs).aref(ref);
90
+ if(!txt.isNil()) {
91
+ ((RubyHash)regs).aset(ref, inline2(self, txt, refs));
92
+ }
93
+ return self.callMethod(self.getRuntime().getCurrentContext(), meth, regs);
94
+ }
95
+
96
+
97
+ public void PASS(IRubyObject H, String A, String T) {
98
+ ((RubyString)H).append(red_pass(self, regs, runtime.newSymbol(A), T, refs));
99
+ }
100
+
101
+
102
+ public void STORE_LINK_ALIAS() {
103
+ ((RubyHash)refs_found).aset(((RubyHash)regs).aref(runtime.newSymbol("text")), ((RubyHash)regs).aref(runtime.newSymbol("href")));
104
+ }
105
+
106
+ public void STORE_URL(String T) {
107
+ if(p > reg && reg >= ts) {
108
+ boolean punct = true;
109
+ while(p > reg && punct) {
110
+ switch(data[p - 1]) {
111
+ case ')':
112
+ int tempP = p - 1;
113
+ int level = -1;
114
+ while(tempP > reg) {
115
+ switch(data[tempP - 1]) {
116
+ case '(': ++level; break;
117
+ case ')': --level; break;
118
+ }
119
+ --tempP;
120
+ }
121
+ if (level == 0) { punct = false; } else { --p; }
122
+ break;
123
+ case '!': case '"': case '#': case '$': case '%': case ']': case '[': case '&': case '\'':
124
+ case '*': case '+': case ',': case '-': case '.': case '(': case ':':
125
+ case ';': case '=': case '?': case '@': case '\\': case '^': case '_':
126
+ case '`': case '|': case '~': p--; break;
127
+ default: punct = false;
128
+ }
129
+ }
130
+ te = p;
131
+ }
132
+
133
+ STORE(T);
134
+
135
+ if(!refs.isNil() && refs.callMethod(runtime.getCurrentContext(), "has_key?", ((RubyHash)regs).aref(runtime.newSymbol(T))).isTrue()) {
136
+ ((RubyHash)regs).aset(runtime.newSymbol(T), ((RubyHash)refs).aref(((RubyHash)regs).aref(runtime.newSymbol(T))));
137
+ }
138
+ }
139
+
140
+ public void red_inc(IRubyObject regs, IRubyObject ref) {
141
+ int aint = 0;
142
+ IRubyObject aval = ((RubyHash)regs).aref(ref);
143
+ if(!aval.isNil()) {
144
+ aint = RubyNumeric.fix2int(aval);
145
+ }
146
+ ((RubyHash)regs).aset(ref, regs.getRuntime().newFixnum(aint+1));
147
+ }
148
+
149
+ public IRubyObject red_blockcode(IRubyObject self, IRubyObject regs, IRubyObject block) {
150
+ Ruby runtime = self.getRuntime();
151
+ IRubyObject btype = ((RubyHash)regs).aref(runtime.newSymbol("type"));
152
+ if(((RubyString)block).getByteList().realSize > 0) {
153
+ ((RubyHash)regs).aset(runtime.newSymbol("text"), block);
154
+ block = self.callMethod(runtime.getCurrentContext(), btype.asJavaString(), regs);
155
+ }
156
+ return block;
157
+ }
158
+
159
+ public IRubyObject red_block(IRubyObject self, IRubyObject regs, IRubyObject block, IRubyObject refs) {
160
+ Ruby runtime = self.getRuntime();
161
+ RubySymbol method;
162
+ IRubyObject sym_text = runtime.newSymbol("text");
163
+ IRubyObject btype = ((RubyHash)regs).aref(runtime.newSymbol("type"));
164
+ block = block.callMethod(runtime.getCurrentContext(), "strip");
165
+
166
+ if(!block.isNil() && !btype.isNil()) {
167
+ method = btype.convertToString().intern();
168
+
169
+ if(method == runtime.newSymbol("notextile")) {
170
+ ((RubyHash)regs).aset(sym_text, block);
171
+ } else {
172
+ ((RubyHash)regs).aset(sym_text, inline2(self, block, refs));
173
+ }
174
+
175
+ IRubyObject customTags = ((RubyObject)self).getInstanceVariable("@custom_tags");
176
+ if( ((RubyArray)customTags).includes(runtime.getCurrentContext(), btype) ) {
177
+ block = self.callMethod(runtime.getCurrentContext(), method.asJavaString(), regs);
178
+ } else {
179
+ IRubyObject fallback = ((RubyHash)regs).aref(runtime.newSymbol("fallback"));
180
+ if(!fallback.isNil()) {
181
+ ((RubyString)fallback).append(((RubyHash)regs).aref(sym_text));
182
+ regs = RubyHash.newHash(runtime);
183
+ ((RubyHash)regs).aset(sym_text, fallback);
184
+ }
185
+ block = self.callMethod(runtime.getCurrentContext(), "p", regs);
186
+ }
187
+ }
188
+
189
+ return block;
190
+ }
191
+
192
+ public void strCatEscaped(IRubyObject self, IRubyObject str, byte[] data, int ts, int te) {
193
+ IRubyObject sourceStr = RubyString.newString(self.getRuntime(), data, ts, te-ts);
194
+ IRubyObject escapedStr = self.callMethod(self.getRuntime().getCurrentContext(), "escape", sourceStr);
195
+ ((RubyString)str).concat(escapedStr);
196
+ }
197
+
198
+ public void strCatEscapedForPreformatted(IRubyObject self, IRubyObject str, byte[] data, int ts, int te) {
199
+ IRubyObject sourceStr = RubyString.newString(self.getRuntime(), data, ts, te-ts);
200
+ IRubyObject escapedStr = self.callMethod(self.getRuntime().getCurrentContext(), "escape_pre", sourceStr);
201
+ ((RubyString)str).concat(escapedStr);
202
+ }
203
+
204
+ public void CLEAR(IRubyObject obj) {
205
+ if(block == obj) {
206
+ block = RubyString.newEmptyString(runtime);
207
+ } else if(html == obj) {
208
+ html = RubyString.newEmptyString(runtime);
209
+ } else if(table == obj) {
210
+ table = RubyString.newEmptyString(runtime);
211
+ }
212
+ }
213
+
214
+ public void ADD_BLOCK() {
215
+ ((RubyString)html).append(red_block(self, regs, block, refs));
216
+ extend = runtime.getNil();
217
+ CLEAR(block);
218
+ CLEAR_REGS();
219
+ }
220
+
221
+ public void CLEAR_REGS() {
222
+ regs = RubyHash.newHash(runtime);
223
+ }
224
+
225
+ public void RESET_REG() {
226
+ reg = -1;
227
+ }
228
+
229
+ public void CAT(IRubyObject H) {
230
+ ((RubyString)H).cat(data, ts, te-ts);
231
+ }
232
+
233
+ public void SET_PLAIN_BLOCK(String T) {
234
+ plain_block = runtime.newString(T);
235
+ }
236
+
237
+ public void RESET_TYPE() {
238
+ ((RubyHash)regs).aset(runtime.newSymbol("type"), plain_block);
239
+ }
240
+
241
+ public void INLINE(IRubyObject H, String T) {
242
+ ((RubyString)H).append(self.callMethod(runtime.getCurrentContext(), T, regs));
243
+ }
244
+
245
+ public void DONE(IRubyObject H) {
246
+ ((RubyString)html).append(H);
247
+ CLEAR(H);
248
+ CLEAR_REGS();
249
+ }
250
+
251
+ public void ADD_EXTENDED_BLOCK() {
252
+ ((RubyString)html).append(red_block(self, regs, block, refs));
253
+ CLEAR(block);
254
+ }
255
+
256
+ public void ADD_BLOCKCODE() {
257
+ ((RubyString)html).append(red_blockcode(self, regs, block));
258
+ CLEAR(block);
259
+ CLEAR_REGS();
260
+ }
261
+
262
+ public void ADD_EXTENDED_BLOCKCODE() {
263
+ ((RubyString)html).append(red_blockcode(self, regs, block));
264
+ CLEAR(block);
265
+ }
266
+
267
+ public void AINC(String T) {
268
+ red_inc(regs, runtime.newSymbol(T));
269
+ }
270
+
271
+ public void END_EXTENDED() {
272
+ extend = runtime.getNil();
273
+ CLEAR_REGS();
274
+ }
275
+
276
+ public boolean IS_NOT_EXTENDED() {
277
+ return extend.isNil();
278
+ }
279
+
280
+ public void ASET(String T, String V) {
281
+ ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.newString(V));
282
+ }
283
+
284
+ public void STORE(String T) {
285
+ if(p > reg && reg >= ts) {
286
+
287
+ IRubyObject str = RubyString.newString(runtime, data, reg, p-reg);
288
+ ((RubyHash)regs).aset(runtime.newSymbol(T), str);
289
+ } else {
290
+ ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.getNil());
291
+ }
292
+ }
293
+
294
+ public void STORE_B(String T) {
295
+ if(p > bck && bck >= ts) {
296
+ IRubyObject str = RubyString.newString(runtime, data, bck, p-bck);
297
+ ((RubyHash)regs).aset(runtime.newSymbol(T), str);
298
+ } else {
299
+ ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.getNil());
300
+ }
301
+ }
302
+
303
+ public IRubyObject self;
304
+ public byte[] data;
305
+ public int p, pe;
306
+ public IRubyObject refs;
307
+
308
+ public Ruby runtime;
309
+ public int orig_p, orig_pe;
310
+ public int cs, act, nest;
311
+ public int ts = -1;
312
+ public int te = -1;
313
+ public int reg = -1;
314
+ public int bck = -1;
315
+ public int eof = -1;
316
+
317
+ public IRubyObject html;
318
+ public IRubyObject table;
319
+ public IRubyObject block;
320
+ public IRubyObject regs;
321
+
322
+ public IRubyObject list_layout;
323
+ public String list_type = null;
324
+ public IRubyObject list_index;
325
+ public int list_continue = 0;
326
+ public IRubyObject plain_block;
327
+ public IRubyObject extend;
328
+ public String listm = "";
329
+ public IRubyObject refs_found;
330
+ }
331
+
332
+ private static class Transformer extends Base {
333
+ %%{
334
+
335
+ machine redcloth_scan;
336
+ include redcloth_common "redcloth_common.java.rl";
337
+
338
+ action extend { extend = ((RubyHash)regs).aref(runtime.newSymbol("type")); }
339
+
340
+ include redcloth_scan "redcloth_scan.rl";
341
+
342
+ }%%
343
+
344
+ %% write data nofinal;
345
+
346
+ public Transformer(IRubyObject self, byte[] data, int p, int pe, IRubyObject refs) {
347
+ if(p+pe > data.length) {
348
+ throw new RuntimeException("BLAHAHA");
349
+ }
350
+ this.self = self;
351
+
352
+ // This is GROSS but necessary for EOF matching
353
+ this.data = new byte[pe+1];
354
+ System.arraycopy(data, p, this.data, 0, pe);
355
+ this.data[pe] = 0;
356
+
357
+ this.p = 0;
358
+ this.pe = pe+1;
359
+ this.eof = this.pe;
360
+ this.orig_p = 0;
361
+ this.orig_pe = this.pe;
362
+
363
+ this.refs = refs;
364
+
365
+ runtime = self.getRuntime();
366
+
367
+ html = RubyString.newEmptyString(runtime);
368
+ table = RubyString.newEmptyString(runtime);
369
+ block = RubyString.newEmptyString(runtime);
370
+ CLEAR_REGS();
371
+
372
+ list_layout = runtime.getNil();
373
+ list_index = runtime.newArray();
374
+ SET_PLAIN_BLOCK("p");
375
+ extend = runtime.getNil();
376
+ refs_found = RubyHash.newHash(runtime);
377
+ }
378
+
379
+ public IRubyObject transform() {
380
+ %% write init;
381
+
382
+ %% write exec;
383
+
384
+ if(((RubyString)block).getByteList().realSize > 0) {
385
+ ADD_BLOCK();
386
+ }
387
+
388
+ if(refs.isNil() && !refs_found.callMethod(runtime.getCurrentContext(), "empty?").isTrue()) {
389
+ return RedclothScanService.transform(self, data, orig_p, orig_pe, refs_found);
390
+ } else {
391
+ self.callMethod(self.getRuntime().getCurrentContext(), "after_transform", html);
392
+ return html;
393
+ }
394
+ }
395
+ }
396
+
397
+ public static IRubyObject transform(IRubyObject self, byte[] data, int p, int pe, IRubyObject refs) {
398
+ return new Transformer(self, data, p, pe, refs).transform();
399
+ }
400
+
401
+ public static IRubyObject inline2(IRubyObject workingCopy, IRubyObject self, IRubyObject refs) {
402
+ return RedclothInline.inline2(workingCopy, self, refs);
403
+ }
404
+
405
+ public static IRubyObject transform2(IRubyObject self, IRubyObject str) {
406
+ RubyString ss = str.convertToString();
407
+ self.callMethod(self.getRuntime().getCurrentContext(), "before_transform", ss);
408
+ return transform(self, ss.getByteList().bytes(), ss.getByteList().begin, ss.getByteList().realSize, self.getRuntime().getNil());
409
+ }
410
+
411
+ @JRubyMethod
412
+ public static IRubyObject to(IRubyObject self, IRubyObject formatter) {
413
+ Ruby runtime = self.getRuntime();
414
+ self.callMethod(runtime.getCurrentContext(), "delete!", runtime.newString("\r"));
415
+ IRubyObject workingCopy = self.rbClone();
416
+
417
+ ((RubyObject)workingCopy).extend(new IRubyObject[]{formatter});
418
+
419
+ IRubyObject workingCopyMethods = workingCopy.callMethod(runtime.getCurrentContext(), "methods");
420
+ IRubyObject classInstanceMethods = workingCopy.getType().callMethod(runtime.getCurrentContext(), "instance_methods");
421
+ IRubyObject customTags = workingCopyMethods.callMethod(runtime.getCurrentContext(), "-", classInstanceMethods);
422
+ ((RubyObject)workingCopy).setInstanceVariable("@custom_tags", customTags);
423
+
424
+ if(workingCopy.callMethod(runtime.getCurrentContext(), "lite_mode").isTrue()) {
425
+ return inline2(workingCopy, self, RubyHash.newHash(runtime));
426
+ } else {
427
+ return transform2(workingCopy, self);
428
+ }
429
+ }
430
+
431
+ @JRubyMethod(rest=true)
432
+ public static IRubyObject html_esc(IRubyObject self, IRubyObject[] args) {
433
+ Ruby runtime = self.getRuntime();
434
+ IRubyObject str = runtime.getNil(),
435
+ level = runtime.getNil();
436
+ if(Arity.checkArgumentCount(runtime, args, 1, 2) == 2) {
437
+ level = args[1];
438
+ }
439
+ str = args[0];
440
+
441
+ IRubyObject new_str = RubyString.newEmptyString(runtime);
442
+ if(str.isNil()) {
443
+ return new_str;
444
+ }
445
+
446
+ ByteList bl = str.convertToString().getByteList();
447
+
448
+ if(bl.realSize == 0) {
449
+ return new_str;
450
+ }
451
+
452
+ byte[] bytes = bl.bytes;
453
+ int ts = bl.begin;
454
+ int te = ts + bl.realSize;
455
+ int t = ts, t2 = ts;
456
+ String ch = null;
457
+
458
+ if(te <= ts) {
459
+ return new_str;
460
+ }
461
+
462
+ while(t2 < te) {
463
+ ch = null;
464
+ // normal + pre
465
+ switch(bytes[t2]) {
466
+ case '&': ch = "amp"; break;
467
+ case '>': ch = "gt"; break;
468
+ case '<': ch = "lt"; break;
469
+ }
470
+
471
+ // normal (non-pre)
472
+ if(level != runtime.newSymbol("html_escape_preformatted")) {
473
+ switch(bytes[t2]) {
474
+ case '\n': ch = "br"; break;
475
+ case '"' : ch = "quot"; break;
476
+ case '\'':
477
+ ch = (level == runtime.newSymbol("html_escape_attributes")) ? "apos" : "squot";
478
+ break;
479
+ }
480
+ }
481
+
482
+ if(ch != null) {
483
+ if(t2 > t) {
484
+ ((RubyString)new_str).cat(bytes, t, t2-t);
485
+ }
486
+ ((RubyString)new_str).concat(self.callMethod(runtime.getCurrentContext(), ch, RubyHash.newHash(runtime)));
487
+ t = t2 + 1;
488
+ }
489
+
490
+ t2++;
491
+ }
492
+
493
+
494
+ if(t2 > t) {
495
+ ((RubyString)new_str).cat(bytes, t, t2-t);
496
+ }
497
+
498
+ return new_str;
499
+ }
500
+
501
+ @JRubyMethod
502
+ public static IRubyObject latex_esc(IRubyObject self, IRubyObject str) {
503
+ Ruby runtime = self.getRuntime();
504
+ IRubyObject new_str = RubyString.newEmptyString(runtime);
505
+
506
+ if(str.isNil()) {
507
+ return new_str;
508
+ }
509
+
510
+ ByteList bl = str.convertToString().getByteList();
511
+
512
+ if(bl.realSize == 0) {
513
+ return new_str;
514
+ }
515
+
516
+ byte[] bytes = bl.bytes;
517
+ int ts = bl.begin;
518
+ int te = ts + bl.realSize;
519
+ int t = ts;
520
+ int t2 = ts;
521
+ String ch = null;
522
+
523
+ while(t2 < te) {
524
+ ch = null;
525
+
526
+ switch(bytes[t2]) {
527
+ case '{': ch = "#123"; break;
528
+ case '}': ch = "#125"; break;
529
+ case '\\': ch = "#92"; break;
530
+ case '#': ch = "#35"; break;
531
+ case '$': ch = "#36"; break;
532
+ case '%': ch = "#37"; break;
533
+ case '&': ch = "amp"; break;
534
+ case '_': ch = "#95"; break;
535
+ case '^': ch = "circ"; break;
536
+ case '~': ch = "tilde"; break;
537
+ case '<': ch = "lt"; break;
538
+ case '>': ch = "gt"; break;
539
+ case '\n': ch = "#10"; break;
540
+ }
541
+
542
+ if(ch != null) {
543
+ if(t2 > t) {
544
+ ((RubyString)new_str).cat(bytes, t, t2-t);
545
+ }
546
+ IRubyObject opts = RubyHash.newHash(runtime);
547
+ ((RubyHash)opts).aset(runtime.newSymbol("text"), runtime.newString(ch));
548
+ ((RubyString)new_str).concat(self.callMethod(runtime.getCurrentContext(), "entity", opts));
549
+ t = t2 + 1;
550
+ }
551
+
552
+ t2++;
553
+ }
554
+
555
+ if(t2 > t) {
556
+ ((RubyString)new_str).cat(bytes, t, t2-t);
557
+ }
558
+
559
+ return new_str;
560
+ }
561
+
562
+ public boolean basicLoad(final Ruby runtime) throws IOException {
563
+ Init_redcloth_scan(runtime);
564
+ return true;
565
+ }
566
+
567
+ public static void Init_redcloth_scan(Ruby runtime) {
568
+ RubyModule mRedCloth = runtime.defineModule("RedCloth");
569
+ RubyClass super_RedCloth = mRedCloth.defineClassUnder("TextileDoc", runtime.getString(), runtime.getString().getAllocator());
570
+ super_RedCloth.defineAnnotatedMethods(RedclothScanService.class);
571
+ super_RedCloth.defineClassUnder("ParseError",runtime.getClass("Exception"),runtime.getClass("Exception").getAllocator());
572
+ }
573
+ }