RedCloth 4.0.4 → 4.1.0

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.

@@ -0,0 +1,227 @@
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
+ static VALUE
198
+ redcloth_to(self, formatter)
199
+ VALUE self, formatter;
200
+ {
201
+ char *pe, *p;
202
+ int len = 0;
203
+
204
+ rb_funcall(self, rb_intern("delete!"), 1, rb_str_new2("\r"));
205
+ VALUE working_copy = rb_obj_clone(self);
206
+ rb_extend_object(working_copy, formatter);
207
+ if (rb_funcall(working_copy, rb_intern("lite_mode"), 0) == Qtrue) {
208
+ return redcloth_inline2(working_copy, self, rb_hash_new());
209
+ } else {
210
+ return redcloth_transform2(working_copy, self);
211
+ }
212
+ }
213
+
214
+ void Init_redcloth_scan()
215
+ {
216
+ mRedCloth = rb_define_module("RedCloth");
217
+ /* A Textile document that can be converted to other formats. See
218
+ the README for Textile syntax. */
219
+ super_RedCloth = rb_define_class_under(mRedCloth, "TextileDoc", rb_cString);
220
+ rb_define_method(super_RedCloth, "to", redcloth_to, 1);
221
+ super_ParseError = rb_define_class_under(super_RedCloth, "ParseError", rb_eException);
222
+ /* Escaping */
223
+ rb_define_method(super_RedCloth, "html_esc", redcloth_html_esc, -1);
224
+ rb_define_method(super_RedCloth, "latex_esc", redcloth_latex_esc, 1);
225
+ SYM_escape_preformatted = ID2SYM(rb_intern("html_escape_preformatted"));
226
+ SYM_escape_attributes = ID2SYM(rb_intern("html_escape_attributes"));
227
+ }
@@ -0,0 +1,555 @@
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 '!': case '"': case '#': case '$': case '%': case ']': case '[': case '&': case '\'':
112
+ case '*': case '+': case ',': case '-': case '.': case ')': case '(': case ':':
113
+ case ';': case '=': case '?': case '@': case '\\': case '^': case '_':
114
+ case '`': case '|': case '~': p--; break;
115
+ default: punct = false;
116
+ }
117
+ }
118
+ te = p;
119
+ }
120
+
121
+ STORE(T);
122
+
123
+ if(!refs.isNil() && refs.callMethod(runtime.getCurrentContext(), "has_key?", ((RubyHash)regs).aref(runtime.newSymbol(T))).isTrue()) {
124
+ ((RubyHash)regs).aset(runtime.newSymbol(T), ((RubyHash)refs).aref(((RubyHash)regs).aref(runtime.newSymbol(T))));
125
+ }
126
+ }
127
+
128
+ public void red_inc(IRubyObject regs, IRubyObject ref) {
129
+ int aint = 0;
130
+ IRubyObject aval = ((RubyHash)regs).aref(ref);
131
+ if(!aval.isNil()) {
132
+ aint = RubyNumeric.fix2int(aval);
133
+ }
134
+ ((RubyHash)regs).aset(ref, regs.getRuntime().newFixnum(aint+1));
135
+ }
136
+
137
+ public IRubyObject red_blockcode(IRubyObject self, IRubyObject regs, IRubyObject block) {
138
+ Ruby runtime = self.getRuntime();
139
+ IRubyObject btype = ((RubyHash)regs).aref(runtime.newSymbol("type"));
140
+ if(((RubyString)block).getByteList().realSize > 0) {
141
+ ((RubyHash)regs).aset(runtime.newSymbol("text"), block);
142
+ block = self.callMethod(runtime.getCurrentContext(), btype.asJavaString(), regs);
143
+ }
144
+ return block;
145
+ }
146
+
147
+ public IRubyObject red_block(IRubyObject self, IRubyObject regs, IRubyObject block, IRubyObject refs) {
148
+ Ruby runtime = self.getRuntime();
149
+ RubySymbol method;
150
+ IRubyObject sym_text = runtime.newSymbol("text");
151
+ IRubyObject btype = ((RubyHash)regs).aref(runtime.newSymbol("type"));
152
+ block = block.callMethod(runtime.getCurrentContext(), "strip");
153
+
154
+ if(!block.isNil() && !btype.isNil()) {
155
+ method = btype.convertToString().intern();
156
+
157
+ if(method == runtime.newSymbol("notextile")) {
158
+ ((RubyHash)regs).aset(sym_text, block);
159
+ } else {
160
+ ((RubyHash)regs).aset(sym_text, inline2(self, block, refs));
161
+ }
162
+
163
+ if(self.respondsTo(method.asJavaString())) {
164
+ block = self.callMethod(runtime.getCurrentContext(), method.asJavaString(), regs);
165
+ } else {
166
+ IRubyObject fallback = ((RubyHash)regs).aref(runtime.newSymbol("fallback"));
167
+ if(!fallback.isNil()) {
168
+ ((RubyString)fallback).append(((RubyHash)regs).aref(sym_text));
169
+ regs = RubyHash.newHash(runtime);
170
+ ((RubyHash)regs).aset(sym_text, fallback);
171
+ }
172
+ block = self.callMethod(runtime.getCurrentContext(), "p", regs);
173
+ }
174
+ }
175
+
176
+ return block;
177
+ }
178
+
179
+ public void strCatEscaped(IRubyObject self, IRubyObject str, byte[] data, int ts, int te) {
180
+ IRubyObject sourceStr = RubyString.newString(self.getRuntime(), data, ts, te-ts);
181
+ IRubyObject escapedStr = self.callMethod(self.getRuntime().getCurrentContext(), "escape", sourceStr);
182
+ ((RubyString)str).concat(escapedStr);
183
+ }
184
+
185
+ public void strCatEscapedForPreformatted(IRubyObject self, IRubyObject str, byte[] data, int ts, int te) {
186
+ IRubyObject sourceStr = RubyString.newString(self.getRuntime(), data, ts, te-ts);
187
+ IRubyObject escapedStr = self.callMethod(self.getRuntime().getCurrentContext(), "escape_pre", sourceStr);
188
+ ((RubyString)str).concat(escapedStr);
189
+ }
190
+
191
+ public void CLEAR(IRubyObject obj) {
192
+ if(block == obj) {
193
+ block = RubyString.newEmptyString(runtime);
194
+ } else if(html == obj) {
195
+ html = RubyString.newEmptyString(runtime);
196
+ } else if(table == obj) {
197
+ table = RubyString.newEmptyString(runtime);
198
+ }
199
+ }
200
+
201
+ public void ADD_BLOCK() {
202
+ ((RubyString)html).append(red_block(self, regs, block, refs));
203
+ extend = runtime.getNil();
204
+ CLEAR(block);
205
+ CLEAR_REGS();
206
+ }
207
+
208
+ public void CLEAR_REGS() {
209
+ regs = RubyHash.newHash(runtime);
210
+ }
211
+
212
+ public void RESET_REG() {
213
+ reg = -1;
214
+ }
215
+
216
+ public void CAT(IRubyObject H) {
217
+ ((RubyString)H).cat(data, ts, te-ts);
218
+ }
219
+
220
+ public void SET_PLAIN_BLOCK(String T) {
221
+ plain_block = runtime.newString(T);
222
+ }
223
+
224
+ public void RESET_TYPE() {
225
+ ((RubyHash)regs).aset(runtime.newSymbol("type"), plain_block);
226
+ }
227
+
228
+ public void INLINE(IRubyObject H, String T) {
229
+ ((RubyString)H).append(self.callMethod(runtime.getCurrentContext(), T, regs));
230
+ }
231
+
232
+ public void DONE(IRubyObject H) {
233
+ ((RubyString)html).append(H);
234
+ CLEAR(H);
235
+ CLEAR_REGS();
236
+ }
237
+
238
+ public void ADD_EXTENDED_BLOCK() {
239
+ ((RubyString)html).append(red_block(self, regs, block, refs));
240
+ CLEAR(block);
241
+ }
242
+
243
+ public void ADD_BLOCKCODE() {
244
+ ((RubyString)html).append(red_blockcode(self, regs, block));
245
+ CLEAR(block);
246
+ CLEAR_REGS();
247
+ }
248
+
249
+ public void ADD_EXTENDED_BLOCKCODE() {
250
+ ((RubyString)html).append(red_blockcode(self, regs, block));
251
+ CLEAR(block);
252
+ }
253
+
254
+ public void AINC(String T) {
255
+ red_inc(regs, runtime.newSymbol(T));
256
+ }
257
+
258
+ public void END_EXTENDED() {
259
+ extend = runtime.getNil();
260
+ CLEAR_REGS();
261
+ }
262
+
263
+ public boolean IS_NOT_EXTENDED() {
264
+ return extend.isNil();
265
+ }
266
+
267
+ public void ASET(String T, String V) {
268
+ ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.newString(V));
269
+ }
270
+
271
+ public void STORE(String T) {
272
+ if(p > reg && reg >= ts) {
273
+
274
+ IRubyObject str = RubyString.newString(runtime, data, reg, p-reg);
275
+ ((RubyHash)regs).aset(runtime.newSymbol(T), str);
276
+ } else {
277
+ ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.getNil());
278
+ }
279
+ }
280
+
281
+ public void STORE_B(String T) {
282
+ if(p > bck && bck >= ts) {
283
+ IRubyObject str = RubyString.newString(runtime, data, bck, p-bck);
284
+ ((RubyHash)regs).aset(runtime.newSymbol(T), str);
285
+ } else {
286
+ ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.getNil());
287
+ }
288
+ }
289
+
290
+ public IRubyObject self;
291
+ public byte[] data;
292
+ public int p, pe;
293
+ public IRubyObject refs;
294
+
295
+ public Ruby runtime;
296
+ public int orig_p, orig_pe;
297
+ public int cs, act, nest;
298
+ public int ts = -1;
299
+ public int te = -1;
300
+ public int reg = -1;
301
+ public int bck = -1;
302
+ public int eof = -1;
303
+
304
+ public IRubyObject html;
305
+ public IRubyObject table;
306
+ public IRubyObject block;
307
+ public IRubyObject regs;
308
+
309
+ public IRubyObject list_layout;
310
+ public String list_type = null;
311
+ public IRubyObject list_index;
312
+ public int list_continue = 0;
313
+ public IRubyObject plain_block;
314
+ public IRubyObject extend;
315
+ public String listm = "";
316
+ public IRubyObject refs_found;
317
+ }
318
+
319
+ private static class Transformer extends Base {
320
+ %%{
321
+
322
+ machine redcloth_scan;
323
+ include redcloth_common "redcloth_common.java.rl";
324
+
325
+ action extend { extend = ((RubyHash)regs).aref(runtime.newSymbol("type")); }
326
+
327
+ include redcloth_scan "redcloth_scan.rl";
328
+
329
+ }%%
330
+
331
+ %% write data nofinal;
332
+
333
+ public Transformer(IRubyObject self, byte[] data, int p, int pe, IRubyObject refs) {
334
+ if(p+pe > data.length) {
335
+ throw new RuntimeException("BLAHAHA");
336
+ }
337
+ this.self = self;
338
+
339
+ // This is GROSS but necessary for EOF matching
340
+ this.data = new byte[pe+1];
341
+ System.arraycopy(data, p, this.data, 0, pe);
342
+ this.data[pe] = 0;
343
+
344
+ this.p = 0;
345
+ this.pe = pe+1;
346
+ this.eof = this.pe;
347
+ this.orig_p = 0;
348
+ this.orig_pe = this.pe;
349
+
350
+ this.refs = refs;
351
+
352
+ runtime = self.getRuntime();
353
+
354
+ html = RubyString.newEmptyString(runtime);
355
+ table = RubyString.newEmptyString(runtime);
356
+ block = RubyString.newEmptyString(runtime);
357
+ CLEAR_REGS();
358
+
359
+ list_layout = runtime.getNil();
360
+ list_index = runtime.newArray();
361
+ SET_PLAIN_BLOCK("p");
362
+ extend = runtime.getNil();
363
+ refs_found = RubyHash.newHash(runtime);
364
+ }
365
+
366
+ public IRubyObject transform() {
367
+ %% write init;
368
+
369
+ %% write exec;
370
+
371
+ if(((RubyString)block).getByteList().realSize > 0) {
372
+ ADD_BLOCK();
373
+ }
374
+
375
+ if(refs.isNil() && !refs_found.callMethod(runtime.getCurrentContext(), "empty?").isTrue()) {
376
+ return RedclothScanService.transform(self, data, orig_p, orig_pe, refs_found);
377
+ } else {
378
+ self.callMethod(self.getRuntime().getCurrentContext(), "after_transform", html);
379
+ return html;
380
+ }
381
+ }
382
+ }
383
+
384
+ public static IRubyObject transform(IRubyObject self, byte[] data, int p, int pe, IRubyObject refs) {
385
+ return new Transformer(self, data, p, pe, refs).transform();
386
+ }
387
+
388
+ public static IRubyObject inline2(IRubyObject workingCopy, IRubyObject self, IRubyObject refs) {
389
+ return RedclothInline.inline2(workingCopy, self, refs);
390
+ }
391
+
392
+ public static IRubyObject transform2(IRubyObject self, IRubyObject str) {
393
+ RubyString ss = str.convertToString();
394
+ self.callMethod(self.getRuntime().getCurrentContext(), "before_transform", ss);
395
+ return transform(self, ss.getByteList().bytes(), ss.getByteList().begin, ss.getByteList().realSize, self.getRuntime().getNil());
396
+ }
397
+
398
+ @JRubyMethod
399
+ public static IRubyObject to(IRubyObject self, IRubyObject formatter) {
400
+ Ruby runtime = self.getRuntime();
401
+ self.callMethod(runtime.getCurrentContext(), "delete!", runtime.newString("\r"));
402
+ IRubyObject workingCopy = self.rbClone();
403
+
404
+ ((RubyObject)workingCopy).extend(new IRubyObject[]{formatter});
405
+
406
+ if(workingCopy.callMethod(runtime.getCurrentContext(), "lite_mode").isTrue()) {
407
+ return inline2(workingCopy, self, RubyHash.newHash(runtime));
408
+ } else {
409
+ return transform2(workingCopy, self);
410
+ }
411
+ }
412
+
413
+ @JRubyMethod(rest=true)
414
+ public static IRubyObject html_esc(IRubyObject self, IRubyObject[] args) {
415
+ Ruby runtime = self.getRuntime();
416
+ IRubyObject str = runtime.getNil(),
417
+ level = runtime.getNil();
418
+ if(Arity.checkArgumentCount(runtime, args, 1, 2) == 2) {
419
+ level = args[1];
420
+ }
421
+ str = args[0];
422
+
423
+ IRubyObject new_str = RubyString.newEmptyString(runtime);
424
+ if(str.isNil()) {
425
+ return new_str;
426
+ }
427
+
428
+ ByteList bl = str.convertToString().getByteList();
429
+
430
+ if(bl.realSize == 0) {
431
+ return new_str;
432
+ }
433
+
434
+ byte[] bytes = bl.bytes;
435
+ int ts = bl.begin;
436
+ int te = ts + bl.realSize;
437
+ int t = ts, t2 = ts;
438
+ String ch = null;
439
+
440
+ if(te <= ts) {
441
+ return new_str;
442
+ }
443
+
444
+ while(t2 < te) {
445
+ ch = null;
446
+ // normal + pre
447
+ switch(bytes[t2]) {
448
+ case '&': ch = "amp"; break;
449
+ case '>': ch = "gt"; break;
450
+ case '<': ch = "lt"; break;
451
+ }
452
+
453
+ // normal (non-pre)
454
+ if(level != runtime.newSymbol("html_escape_preformatted")) {
455
+ switch(bytes[t2]) {
456
+ case '\n': ch = "br"; break;
457
+ case '"' : ch = "quot"; break;
458
+ case '\'':
459
+ ch = (level == runtime.newSymbol("html_escape_attributes")) ? "apos" : "squot";
460
+ break;
461
+ }
462
+ }
463
+
464
+ if(ch != null) {
465
+ if(t2 > t) {
466
+ ((RubyString)new_str).cat(bytes, t, t2-t);
467
+ }
468
+ ((RubyString)new_str).concat(self.callMethod(runtime.getCurrentContext(), ch, RubyHash.newHash(runtime)));
469
+ t = t2 + 1;
470
+ }
471
+
472
+ t2++;
473
+ }
474
+
475
+
476
+ if(t2 > t) {
477
+ ((RubyString)new_str).cat(bytes, t, t2-t);
478
+ }
479
+
480
+ return new_str;
481
+ }
482
+
483
+ @JRubyMethod
484
+ public static IRubyObject latex_esc(IRubyObject self, IRubyObject str) {
485
+ Ruby runtime = self.getRuntime();
486
+ IRubyObject new_str = RubyString.newEmptyString(runtime);
487
+
488
+ if(str.isNil()) {
489
+ return new_str;
490
+ }
491
+
492
+ ByteList bl = str.convertToString().getByteList();
493
+
494
+ if(bl.realSize == 0) {
495
+ return new_str;
496
+ }
497
+
498
+ byte[] bytes = bl.bytes;
499
+ int ts = bl.begin;
500
+ int te = ts + bl.realSize;
501
+ int t = ts;
502
+ int t2 = ts;
503
+ String ch = null;
504
+
505
+ while(t2 < te) {
506
+ ch = null;
507
+
508
+ switch(bytes[t2]) {
509
+ case '{': ch = "#123"; break;
510
+ case '}': ch = "#125"; break;
511
+ case '\\': ch = "#92"; break;
512
+ case '#': ch = "#35"; break;
513
+ case '$': ch = "#36"; break;
514
+ case '%': ch = "#37"; break;
515
+ case '&': ch = "amp"; break;
516
+ case '_': ch = "#95"; break;
517
+ case '^': ch = "circ"; break;
518
+ case '~': ch = "tilde"; break;
519
+ case '<': ch = "lt"; break;
520
+ case '>': ch = "gt"; break;
521
+ case '\n': ch = "#10"; break;
522
+ }
523
+
524
+ if(ch != null) {
525
+ if(t2 > t) {
526
+ ((RubyString)new_str).cat(bytes, t, t2-t);
527
+ }
528
+ IRubyObject opts = RubyHash.newHash(runtime);
529
+ ((RubyHash)opts).aset(runtime.newSymbol("text"), runtime.newString(ch));
530
+ ((RubyString)new_str).concat(self.callMethod(runtime.getCurrentContext(), "entity", opts));
531
+ t = t2 + 1;
532
+ }
533
+
534
+ t2++;
535
+ }
536
+
537
+ if(t2 > t) {
538
+ ((RubyString)new_str).cat(bytes, t, t2-t);
539
+ }
540
+
541
+ return new_str;
542
+ }
543
+
544
+ public boolean basicLoad(final Ruby runtime) throws IOException {
545
+ Init_redcloth_scan(runtime);
546
+ return true;
547
+ }
548
+
549
+ public static void Init_redcloth_scan(Ruby runtime) {
550
+ RubyModule mRedCloth = runtime.defineModule("RedCloth");
551
+ RubyClass super_RedCloth = mRedCloth.defineClassUnder("TextileDoc", runtime.getString(), runtime.getString().getAllocator());
552
+ super_RedCloth.defineAnnotatedMethods(RedclothScanService.class);
553
+ super_RedCloth.defineClassUnder("ParseError",runtime.getClass("Exception"),runtime.getClass("Exception").getAllocator());
554
+ }
555
+ }