RedCloth 4.1.1-universal-java → 4.1.9-universal-java

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of RedCloth might be problematic. Click here for more details.

@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * redcloth_attributes.c.rl
3
3
  *
4
- * Copyright (C) 2008 Jason Garber
4
+ * Copyright (C) 2009 Jason Garber
5
5
  */
6
6
  #include <ruby.h>
7
7
  #include "redcloth.h"
@@ -24,9 +24,8 @@ redcloth_attribute_parser(machine, self, p, pe)
24
24
  char *p, *pe;
25
25
  {
26
26
  int cs, act;
27
- char *ts, *te, *reg, *bck, *eof;
27
+ char *ts = 0, *te = 0, *reg = 0, *bck = NULL, *eof = NULL;
28
28
  VALUE regs = rb_hash_new();
29
- VALUE buf = Qnil;
30
29
 
31
30
  %% write init;
32
31
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * redcloth_attributes.rl
3
3
  *
4
- * Copyright (C) 2008 Jason Garber
4
+ * Copyright (C) 2009 Jason Garber
5
5
  */
6
6
  import java.io.IOException;
7
7
 
@@ -43,14 +43,12 @@ public class RedclothAttributes extends RedclothScanService.Base {
43
43
  }
44
44
 
45
45
  public void SET_ATTRIBUTE(String B, String A) {
46
- buf = ((RubyHash)regs).aref(runtime.newSymbol(B));
47
- if(!buf.isNil()) {
48
- ((RubyHash)regs).aset(runtime.newSymbol(A), buf);
46
+ if(!((RubyHash)regs).aref(runtime.newSymbol(B)).isNil()) {
47
+ ((RubyHash)regs).aset(runtime.newSymbol(A), ((RubyHash)regs).aref(runtime.newSymbol(B)));
49
48
  }
50
49
  }
51
50
 
52
51
  private int machine;
53
- private IRubyObject buf;
54
52
 
55
53
  public RedclothAttributes(int machine, IRubyObject self, byte[] data, int p, int pe) {
56
54
  this.runtime = self.getRuntime();
@@ -68,7 +66,6 @@ public class RedclothAttributes extends RedclothScanService.Base {
68
66
  this.orig_pe = this.pe;
69
67
 
70
68
  this.regs = RubyHash.newHash(runtime);
71
- this.buf = runtime.getNil();
72
69
  this.machine = machine;
73
70
  }
74
71
 
@@ -89,6 +86,8 @@ public class RedclothAttributes extends RedclothScanService.Base {
89
86
  }
90
87
 
91
88
  public static IRubyObject link_attributes(IRubyObject self, IRubyObject str) {
89
+ Ruby runtime = self.getRuntime();
90
+
92
91
  ByteList bl = str.convertToString().getByteList();
93
92
  int cs = redcloth_attributes_en_link_says;
94
93
  return new RedclothAttributes(cs, self, bl.bytes, bl.begin, bl.realSize).parse();
@@ -1,14 +1,14 @@
1
1
  /*
2
2
  * redcloth_attributes.rl
3
3
  *
4
- * Copyright (C) 2008 Jason Garber
4
+ * Copyright (C) 2009 Jason Garber
5
5
  */
6
6
  %%{
7
7
 
8
8
  machine redcloth_attributes;
9
9
 
10
10
  C2_CLAS = ( "(" ( [^)#]+ >A %{ STORE("class_buf"); } )? ("#" [^)]+ >A %{STORE("id_buf");} )? ")" ) ;
11
- C2_LNGE = ( "[" [^\]]+ >A %{ STORE("lang_buf"); } "]" ) ;
11
+ C2_LNGE = ( "[" [^\[\]]+ >A %{ STORE("lang_buf"); } "]" ) ;
12
12
  C2_STYL = ( "{" [^}]+ >A %{ STORE("style_buf"); } "}" ) ;
13
13
  C2 = ( C2_CLAS | C2_STYL | C2_LNGE )+ ;
14
14
 
@@ -77,7 +77,11 @@
77
77
  script_tag_start = ( "<script" [^>]* ">" ) >X >A %T ;
78
78
  script_tag_end = ( "</script>" >A %T LF? ) >X ;
79
79
 
80
-
80
+ code_tag_start = "<code" [^>]* ">" ;
81
+ code_tag_end = "</code>" ;
82
+
83
+ notextile = "<notextile>" >X (default+ -- "</notextile>") >A %T "</notextile>";
84
+
81
85
  # URI tokens (lifted from Mongrel)
82
86
  CTL = (cntrl | 127);
83
87
  safe = ("$" | "-" | "_" | ".");
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * redcloth_inline.c.rl
3
3
  *
4
- * Copyright (C) 2008 Jason Garber
4
+ * Copyright (C) 2009 Jason Garber
5
5
  */
6
6
  #include <ruby.h>
7
7
  #include "redcloth.h"
@@ -36,16 +36,52 @@ VALUE
36
36
  red_parse_link_attr(VALUE self, VALUE regs, VALUE ref)
37
37
  {
38
38
  VALUE txt = rb_hash_aref(regs, ref);
39
- VALUE new_regs = redcloth_link_attributes(self, txt);
39
+ VALUE new_regs = red_parse_title(redcloth_link_attributes(self, txt), ref);
40
+
40
41
  return rb_funcall(regs, rb_intern("update"), 1, new_regs);
41
42
  }
42
43
 
44
+ VALUE
45
+ red_parse_image_attr(VALUE self, VALUE regs, VALUE ref)
46
+ {
47
+
48
+ return red_parse_title(regs, ref);
49
+ }
50
+
51
+ VALUE
52
+ red_parse_title(VALUE regs, VALUE ref)
53
+ {
54
+ // Store title/alt
55
+ VALUE txt = rb_hash_aref(regs, ref);
56
+ if ( txt != Qnil ) {
57
+ char *p = RSTRING_PTR(txt) + RSTRING_LEN(txt);
58
+ if (*(p - 1) == ')') {
59
+ char level = -1;
60
+ p--;
61
+ while (p > RSTRING_PTR(txt) && level < 0) {
62
+ switch(*(p - 1)) {
63
+ case '(': ++level; break;
64
+ case ')': --level; break;
65
+ }
66
+ --p;
67
+ }
68
+ VALUE title = STR_NEW(p + 1, RSTRING_PTR(txt) + RSTRING_LEN(txt) - 2 - p );
69
+ if (p > RSTRING_PTR(txt) && *(p - 1) == ' ') --p;
70
+ if (p != RSTRING_PTR(txt)) {
71
+ rb_hash_aset(regs, ref, STR_NEW(RSTRING_PTR(txt), p - RSTRING_PTR(txt) ));
72
+ rb_hash_aset(regs, ID2SYM(rb_intern("title")), title);
73
+ }
74
+ }
75
+ }
76
+ return regs;
77
+ }
78
+
43
79
  VALUE
44
80
  red_pass_code(VALUE self, VALUE regs, VALUE ref, ID meth)
45
81
  {
46
82
  VALUE txt = rb_hash_aref(regs, ref);
47
83
  if (!NIL_P(txt)) {
48
- VALUE txt2 = rb_str_new2("");
84
+ VALUE txt2 = STR_NEW2("");
49
85
  rb_str_cat_escaped_for_preformatted(self, txt2, RSTRING_PTR(txt), RSTRING_PTR(txt) + RSTRING_LEN(txt));
50
86
  rb_hash_aset(regs, ref, txt2);
51
87
  }
@@ -62,14 +98,14 @@ red_block(VALUE self, VALUE regs, VALUE block, VALUE refs)
62
98
  block = rb_funcall(block, rb_intern("strip"), 0);
63
99
  if ((!NIL_P(block)) && !NIL_P(btype))
64
100
  {
65
- method = rb_intern(RSTRING_PTR(btype));
66
- if (method == rb_intern("notextile")) {
101
+ method = rb_str_intern(btype);
102
+ if (method == ID2SYM(rb_intern("notextile"))) {
67
103
  rb_hash_aset(regs, sym_text, block);
68
104
  } else {
69
105
  rb_hash_aset(regs, sym_text, redcloth_inline2(self, block, refs));
70
106
  }
71
- if (rb_respond_to(self, method)) {
72
- block = rb_funcall(self, method, 1, regs);
107
+ if (rb_ary_includes(rb_funcall(self, rb_intern("formatter_methods"), 0), method)) {
108
+ block = rb_funcall(self, SYM2ID(method), 1, regs);
73
109
  } else {
74
110
  fallback = rb_hash_aref(regs, ID2SYM(rb_intern("fallback")));
75
111
  if (!NIL_P(fallback)) {
@@ -111,12 +147,10 @@ redcloth_inline(self, p, pe, refs)
111
147
  VALUE refs;
112
148
  {
113
149
  int cs, act;
114
- char *ts, *te, *reg, *eof;
115
- char *orig_p = p, *orig_pe = pe;
116
- VALUE block = rb_str_new2("");
150
+ char *ts = NULL, *te = NULL, *reg = NULL, *eof = NULL;
151
+ char *orig_p = p;
152
+ VALUE block = STR_NEW2("");
117
153
  VALUE regs = Qnil;
118
- unsigned int opts = 0;
119
- VALUE buf = Qnil;
120
154
 
121
155
  %% write init;
122
156
 
@@ -135,7 +169,7 @@ rb_str_cat_escaped(self, str, ts, te)
135
169
  VALUE self, str;
136
170
  char *ts, *te;
137
171
  {
138
- VALUE source_str = rb_str_new(ts, te-ts);
172
+ VALUE source_str = STR_NEW(ts, te-ts);
139
173
  VALUE escaped_str = rb_funcall(self, rb_intern("escape"), 1, source_str);
140
174
  rb_str_concat(str, escaped_str);
141
175
  }
@@ -145,7 +179,7 @@ rb_str_cat_escaped_for_preformatted(self, str, ts, te)
145
179
  VALUE self, str;
146
180
  char *ts, *te;
147
181
  {
148
- VALUE source_str = rb_str_new(ts, te-ts);
182
+ VALUE source_str = STR_NEW(ts, te-ts);
149
183
  VALUE escaped_str = rb_funcall(self, rb_intern("escape_pre"), 1, source_str);
150
184
  rb_str_concat(str, escaped_str);
151
185
  }
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * redcloth_inline.rl
3
3
  *
4
- * Copyright (C) 2008 Jason Garber
4
+ * Copyright (C) 2009 Jason Garber
5
5
  */
6
6
  import java.io.IOException;
7
7
 
@@ -53,10 +53,40 @@ public class RedclothInline extends RedclothScanService.Base {
53
53
 
54
54
  public IRubyObject red_parse_link_attr(IRubyObject self, IRubyObject regs, IRubyObject ref) {
55
55
  IRubyObject txt = ((RubyHash)regs).aref(ref);
56
- IRubyObject new_regs = RedclothAttributes.link_attributes(self, txt);
56
+ IRubyObject new_regs = red_parse_title(RedclothAttributes.link_attributes(self, txt), ref);
57
57
  return regs.callMethod(runtime.getCurrentContext(), "update", new_regs);
58
58
  }
59
59
 
60
+ public IRubyObject red_parse_image_attr(IRubyObject self, IRubyObject regs, IRubyObject ref) {
61
+ return red_parse_title(regs, ref);
62
+ }
63
+
64
+ public IRubyObject red_parse_title(IRubyObject regs, IRubyObject ref) {
65
+ IRubyObject name = ((RubyHash)regs).aref(ref);
66
+ if ( !name.isNil() ) {
67
+ String s = name.convertToString().toString();
68
+ int p = s.length();
69
+ if (s.charAt(p - 1) == ')') {
70
+ int level = -1;
71
+ p--;
72
+ while (p > 0 && level < 0) {
73
+ switch(s.charAt(p - 1)) {
74
+ case '(': ++level; break;
75
+ case ')': --level; break;
76
+ }
77
+ --p;
78
+ }
79
+ IRubyObject title = runtime.newString(s.substring(p + 1, s.length() - 1));
80
+ if(p > 0 && s.charAt(p - 1) == ' ') --p;
81
+ if(p != 0) {
82
+ ((RubyHash)regs).aset(ref, runtime.newString(s.substring(0, p)));
83
+ ((RubyHash)regs).aset(runtime.newSymbol("title"), title);
84
+ }
85
+ }
86
+ }
87
+ return regs;
88
+ }
89
+
60
90
  public void PASS_CODE(IRubyObject H, String A, String T, int O) {
61
91
  ((RubyString)H).append(red_pass_code(self, regs, runtime.newSymbol(A), T));
62
92
  }
@@ -69,8 +99,11 @@ public class RedclothInline extends RedclothScanService.Base {
69
99
  red_parse_link_attr(self, regs, runtime.newSymbol(A));
70
100
  }
71
101
 
102
+ public void PARSE_IMAGE_ATTR(String A) {
103
+ red_parse_image_attr(self, regs, runtime.newSymbol(A));
104
+ }
105
+
72
106
  private int opts;
73
- private IRubyObject buf;
74
107
 
75
108
  public RedclothInline(IRubyObject self, byte[] data, int p, int pe, IRubyObject refs) {
76
109
  this.runtime = self.getRuntime();
@@ -90,7 +123,6 @@ public class RedclothInline extends RedclothScanService.Base {
90
123
  this.block = RubyString.newEmptyString(runtime);
91
124
  this.regs = runtime.getNil();
92
125
  this.opts = 0;
93
- this.buf = runtime.getNil();
94
126
  }
95
127
 
96
128
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * redcloth_inline.rl
3
3
  *
4
- * Copyright (C) 2008 Jason Garber
4
+ * Copyright (C) 2009 Jason Garber
5
5
  */
6
6
  %%{
7
7
 
@@ -11,17 +11,18 @@
11
11
  mtext_noquotes = mtext -- '"' ;
12
12
  quoted_mtext = '"' mtext_noquotes '"' ;
13
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"); } ;
14
+ link_says = ( C_noactions "."* " "* ((quoted_mtext | mtext_including_quotes | mtext_noquotes) -- '":') ) >A %{ STORE("name"); } ;
15
15
  link_says_noquotes_noactions = ( C_noquotes_noactions "."* " "* ((mtext_noquotes) -- '":') ) ;
16
16
  link = ( '"' link_says '":' %A uri %{ STORE_URL("href"); } ) >X ;
17
17
  link_noquotes_noactions = ( '"' link_says_noquotes_noactions '":' uri ) ;
18
18
  bracketed_link = ( '["' link_says '":' %A uri %{ STORE("href"); } :> "]" ) >X ;
19
19
 
20
20
  # images
21
- image_src = ( uri ) >A %{ STORE("src"); } ;
22
- image_is = ( A2 C ". "? image_src :> title? ) ;
21
+ image_title = ( '(' mtext ')' ) ;
22
+ image_is = ( A2 C ". "? (uri image_title?) >A %{ STORE("src"); } ) ;
23
23
  image_link = ( ":" uri >A %{ STORE_URL("href"); } ) ;
24
- image = ( "["? "!" image_is "!" %A image_link? "]"? ) >X ;
24
+ image = ( "!" image_is "!" %A image_link? ) >X ;
25
+ bracketed_image = ( "[!" image_is "!" %A image_link? "]" ) >X ;
25
26
 
26
27
  # footnotes
27
28
  footno = "[" >X %A digit+ %T "]" ;
@@ -29,17 +30,14 @@
29
30
  # markup
30
31
  end_markup_phrase = (" " | PUNCT | EOF | LF) @{ fhold; };
31
32
  code = "["? "@" >X mtext >A %T :> "@" "]"? ;
32
- code_tag_start = "<code" [^>]* ">" ;
33
- code_tag_end = "</code>" ;
34
33
  script_tag = ( "<script" [^>]* ">" (default+ -- "</script>") "</script>" LF? ) >X >A %T ;
35
- notextile = "<notextile>" >X (default+ -- "</notextile>") >A %T "</notextile>";
36
34
  strong = "["? "*" >X mtext >A %T :> "*" "]"? ;
37
35
  b = "["? "**" >X mtext >A %T :> "**" "]"? ;
38
36
  em = "["? "_" >X mtext >A %T :> "_" "]"? ;
39
37
  i = "["? "__" >X mtext >A %T :> "__" "]"? ;
40
38
  del = "[-" >X C ( mtext ) >A %T :>> "-]" ;
41
39
  emdash_parenthetical_phrase_with_spaces = " -- " mtext " -- " ;
42
- del_phrase = (( " " >A %{ STORE("beginning_space"); } "-") >X C ( mtext ) >A %T :>> ( "-" end_markup_phrase )) - emdash_parenthetical_phrase_with_spaces ;
40
+ del_phrase = (( " " >A %{ STORE("beginning_space"); } "-" | "-" when starts_line) >X C ( mtext ) >A %T :>> ( "-" end_markup_phrase )) - emdash_parenthetical_phrase_with_spaces ;
43
41
  ins = "["? "+" >X mtext >A %T :> "+" "]"? ;
44
42
  sup = "[^" >X mtext >A %T :> "^]" ;
45
43
  sup_phrase = ( "^" when starts_phrase) >X ( mtext ) >A %T :>> ( "^" end_markup_phrase ) ;
@@ -97,10 +95,11 @@
97
95
 
98
96
  main := |*
99
97
 
100
- image { INLINE(block, "image"); };
98
+ image { PARSE_IMAGE_ATTR("src"); INLINE(block, "image"); };
99
+ bracketed_image { PARSE_IMAGE_ATTR("src"); INLINE(block, "image"); };
101
100
 
102
- link { PARSE_LINK_ATTR("link_text"); PASS(block, "name", "link"); };
103
- bracketed_link { PARSE_LINK_ATTR("link_text"); PASS(block, "name", "link"); };
101
+ link { PARSE_LINK_ATTR("name"); PASS(block, "name", "link"); };
102
+ bracketed_link { PARSE_LINK_ATTR("name"); PASS(block, "name", "link"); };
104
103
 
105
104
  code { PARSE_ATTR("text"); PASS_CODE(block, "text", "code", opts); };
106
105
  code_tag_start { CAT(block); fgoto code_tag; };
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * redcloth_scan.c.rl
3
3
  *
4
- * Copyright (C) 2008 Jason Garber
4
+ * Copyright (C) 2009 Jason Garber
5
5
  */
6
6
  #define redcloth_scan_c
7
7
 
@@ -31,11 +31,11 @@ redcloth_transform(self, p, pe, refs)
31
31
  VALUE refs;
32
32
  {
33
33
  char *orig_p = p, *orig_pe = pe;
34
- int cs, act, nest;
34
+ int cs, act, nest = 0;
35
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("");
36
+ VALUE html = STR_NEW2("");
37
+ VALUE table = STR_NEW2("");
38
+ VALUE block = STR_NEW2("");
39
39
  VALUE regs; CLEAR_REGS()
40
40
 
41
41
 
@@ -84,7 +84,7 @@ redcloth_html_esc(int argc, VALUE* argv, VALUE self) //(self, str, level)
84
84
 
85
85
  rb_scan_args(argc, argv, "11", &str, &level);
86
86
 
87
- VALUE new_str = rb_str_new2("");
87
+ VALUE new_str = STR_NEW2("");
88
88
  if (str == Qnil)
89
89
  return new_str;
90
90
 
@@ -95,7 +95,7 @@ redcloth_html_esc(int argc, VALUE* argv, VALUE self) //(self, str, level)
95
95
 
96
96
  char *ts = RSTRING_PTR(str), *te = RSTRING_PTR(str) + RSTRING_LEN(str);
97
97
  char *t = ts, *t2 = ts, *ch = NULL;
98
- if (te <= ts) return;
98
+ if (te <= ts) return Qnil;
99
99
 
100
100
  while (t2 < te) {
101
101
  ch = NULL;
@@ -142,7 +142,7 @@ redcloth_html_esc(int argc, VALUE* argv, VALUE self) //(self, str, level)
142
142
  static VALUE
143
143
  redcloth_latex_esc(VALUE self, VALUE str)
144
144
  {
145
- VALUE new_str = rb_str_new2("");
145
+ VALUE new_str = STR_NEW2("");
146
146
 
147
147
  if (str == Qnil)
148
148
  return new_str;
@@ -154,7 +154,7 @@ redcloth_latex_esc(VALUE self, VALUE str)
154
154
 
155
155
  char *ts = RSTRING_PTR(str), *te = RSTRING_PTR(str) + RSTRING_LEN(str);
156
156
  char *t = ts, *t2 = ts, *ch = NULL;
157
- if (te <= ts) return;
157
+ if (te <= ts) return Qnil;
158
158
 
159
159
  while (t2 < te) {
160
160
  ch = NULL;
@@ -181,7 +181,7 @@ redcloth_latex_esc(VALUE self, VALUE str)
181
181
  if (t2 > t)
182
182
  rb_str_cat(new_str, t, t2-t);
183
183
  VALUE opts = rb_hash_new();
184
- rb_hash_aset(opts, ID2SYM(rb_intern("text")), rb_str_new2(ch));
184
+ rb_hash_aset(opts, ID2SYM(rb_intern("text")), STR_NEW2(ch));
185
185
  rb_str_concat(new_str, rb_funcall(self, rb_intern("entity"), 1, opts));
186
186
  t = t2 + 1;
187
187
  }
@@ -201,12 +201,10 @@ static VALUE
201
201
  redcloth_to(self, formatter)
202
202
  VALUE self, formatter;
203
203
  {
204
- char *pe, *p;
205
- int len = 0;
206
-
207
- rb_funcall(self, rb_intern("delete!"), 1, rb_str_new2("\r"));
204
+ rb_funcall(self, rb_intern("delete!"), 1, STR_NEW2("\r"));
208
205
  VALUE working_copy = rb_obj_clone(self);
209
206
  rb_extend_object(working_copy, formatter);
207
+
210
208
  if (rb_funcall(working_copy, rb_intern("lite_mode"), 0) == Qtrue) {
211
209
  return redcloth_inline2(working_copy, self, rb_hash_new());
212
210
  } else {
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * redcloth_scan.java.rl
3
3
  *
4
- * Copyright (C) 2008 Jason Garber
4
+ * Copyright (C) 2009 Jason Garber
5
5
  */
6
6
  import java.io.IOException;
7
7
 
@@ -108,8 +108,20 @@ public class RedclothScanService implements BasicLibraryService {
108
108
  boolean punct = true;
109
109
  while(p > reg && punct) {
110
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;
111
123
  case '!': case '"': case '#': case '$': case '%': case ']': case '[': case '&': case '\'':
112
- case '*': case '+': case ',': case '-': case '.': case ')': case '(': case ':':
124
+ case '*': case '+': case ',': case '-': case '.': case '(': case ':':
113
125
  case ';': case '=': case '?': case '@': case '\\': case '^': case '_':
114
126
  case '`': case '|': case '~': p--; break;
115
127
  default: punct = false;
@@ -160,7 +172,8 @@ public class RedclothScanService implements BasicLibraryService {
160
172
  ((RubyHash)regs).aset(sym_text, inline2(self, block, refs));
161
173
  }
162
174
 
163
- if(self.respondsTo(method.asJavaString())) {
175
+ IRubyObject formatterMethods = ((RubyObject)self).callMethod(runtime.getCurrentContext(), "formatter_methods");
176
+ if( ((RubyArray)formatterMethods).includes(runtime.getCurrentContext(), method) ) {
164
177
  block = self.callMethod(runtime.getCurrentContext(), method.asJavaString(), regs);
165
178
  } else {
166
179
  IRubyObject fallback = ((RubyHash)regs).aref(runtime.newSymbol("fallback"));
@@ -229,6 +242,10 @@ public class RedclothScanService implements BasicLibraryService {
229
242
  ((RubyString)H).append(self.callMethod(runtime.getCurrentContext(), T, regs));
230
243
  }
231
244
 
245
+ public void RSTRIP_BANG(IRubyObject H) {
246
+ ((RubyString)H).callMethod(runtime.getCurrentContext(), "rstrip!");
247
+ }
248
+
232
249
  public void DONE(IRubyObject H) {
233
250
  ((RubyString)html).append(H);
234
251
  CLEAR(H);
@@ -403,6 +420,11 @@ public class RedclothScanService implements BasicLibraryService {
403
420
 
404
421
  ((RubyObject)workingCopy).extend(new IRubyObject[]{formatter});
405
422
 
423
+ IRubyObject workingCopyMethods = workingCopy.callMethod(runtime.getCurrentContext(), "methods");
424
+ IRubyObject classInstanceMethods = workingCopy.getType().callMethod(runtime.getCurrentContext(), "instance_methods");
425
+ IRubyObject customTags = workingCopyMethods.callMethod(runtime.getCurrentContext(), "-", classInstanceMethods);
426
+ ((RubyObject)workingCopy).setInstanceVariable("@custom_tags", customTags);
427
+
406
428
  if(workingCopy.callMethod(runtime.getCurrentContext(), "lite_mode").isTrue()) {
407
429
  return inline2(workingCopy, self, RubyHash.newHash(runtime));
408
430
  } else {