diff --git a/Rakefile b/Rakefile
index 016ffce8..04e653a8 100644
--- a/Rakefile
+++ b/Rakefile
@@ -267,6 +267,8 @@ namespace "jruby" do
ensure_ragel_version("RedclothScanService.java") do
puts "compiling with ragel version #{@ragel_v}"
sh %{ragel -J -o ext/redcloth_scan/RedclothScanService.java ext/redcloth_scan/redcloth_scan.java.rl}
+ sh %{ragel -J -o ext/redcloth_scan/RedclothAttributes.java ext/redcloth_scan/redcloth_attributes.java.rl}
+ sh %{ragel -J -o ext/redcloth_scan/RedclothInline.java ext/redcloth_scan/redcloth_inline.java.rl}
end
end
@@ -282,14 +284,14 @@ namespace "jruby" do
classpath ? "-cp #{classpath}" : ""
end
- def compile_java(filename, jarname)
- sh %{javac -source 1.5 -target 1.5 #{java_classpath_arg} #{filename}}
+ def compile_java(filenames, jarname)
+ sh %{javac -source 1.5 -target 1.5 #{java_classpath_arg} #{filenames.join(" ")}}
sh %{jar cf #{jarname} *.class}
end
task :redcloth_scan_java => [:ragel_java] do
Dir.chdir "ext/redcloth_scan" do
- compile_java("RedclothScanService.java", "redcloth_scan.jar")
+ compile_java(["RedclothAttributes.java", "RedclothInline.java", "RedclothScanService.java"], "redcloth_scan.jar")
end
cp "ext/redcloth_scan/redcloth_scan.jar", "lib"
end
diff --git a/ext/redcloth_scan/redcloth_attributes.java.rl b/ext/redcloth_scan/redcloth_attributes.java.rl
new file mode 100644
index 00000000..7db3e379
--- /dev/null
+++ b/ext/redcloth_scan/redcloth_attributes.java.rl
@@ -0,0 +1,111 @@
+/*
+ * redcloth_attributes.rl
+ *
+ * Copyright (C) 2008 Jason Garber
+ */
+import java.io.IOException;
+
+import org.jruby.Ruby;
+import org.jruby.RubyArray;
+import org.jruby.RubyClass;
+import org.jruby.RubyHash;
+import org.jruby.RubyModule;
+import org.jruby.RubyNumeric;
+import org.jruby.RubyObject;
+import org.jruby.RubyString;
+import org.jruby.RubySymbol;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.CallbackFactory;
+import org.jruby.runtime.builtin.IRubyObject;
+import org.jruby.exceptions.RaiseException;
+import org.jruby.runtime.load.BasicLibraryService;
+
+import org.jruby.util.ByteList;
+
+public class RedclothAttributes extends RedclothScanService.Base {
+
+%%{
+
+ machine redcloth_attributes;
+ include redcloth_common "redcloth_common.java.rl";
+
+ C2_CLAS = ( "(" ( [^)#]+ >A %{ STORE("class_buf"); } )? ("#" [^)]+ >A %{STORE("id_buf");} )? ")" ) ;
+ C2_LNGE = ( "[" [^\]]+ >A %{ STORE("lang_buf"); } "]" ) ;
+ C2_STYL = ( "{" [^}]+ >A %{ STORE("style_buf"); } "}" ) ;
+ C2 = ( C2_CLAS | C2_STYL | C2_LNGE )+ ;
+
+ mtext_with_attributes = ( C2 mtext >A %T ) >X ;
+
+ inline := |*
+
+ mtext_with_attributes { SET_ATTRIBUTES(); } ;
+
+ *|;
+
+ link_text_with_attributes = C2 "."* " "* ( mtext+ ) >A %{ STORE("name"); } ;
+ link_text_without_attributes = ( mtext+ ) >B %{ STORE_B("name_without_attributes"); } ;
+
+ link_says := |*
+
+ link_text_with_attributes { SET_ATTRIBUTES(); } ;
+ link_text_without_attributes { SET_ATTRIBUTE("name_without_attributes", "name"); } ;
+
+ *|;
+
+}%%
+
+%% write data nofinal;
+
+ public void SET_ATTRIBUTES() {
+ SET_ATTRIBUTE("class_buf", "class");
+ SET_ATTRIBUTE("id_buf", "id");
+ SET_ATTRIBUTE("lang_buf", "lang");
+ SET_ATTRIBUTE("style_buf", "style");
+ }
+
+ public void SET_ATTRIBUTE(String B, String A) {
+ buf = ((RubyHash)regs).aref(runtime.newSymbol(B));
+ if(!buf.isNil()) {
+ ((RubyHash)regs).aset(runtime.newSymbol(A), buf);
+ }
+ }
+
+ private int machine;
+ private IRubyObject buf;
+
+ public RedclothAttributes(int machine, IRubyObject self, byte[] data, int p, int pe) {
+// System.err.println("RedclothAttributes(data.len: " + data.length + ", p: " + p + ", pe: " + pe + ")");
+ this.runtime = self.getRuntime();
+ this.self = self;
+ this.data = data;
+ this.p = p;
+ this.pe = p+pe;
+ this.eof = p+pe;
+ this.regs = RubyHash.newHash(runtime);
+ this.buf = runtime.getNil();
+ this.machine = machine;
+ }
+
+ public IRubyObject parse() {
+ %% write init;
+
+ cs = machine;
+
+ %% write exec;
+
+ return regs;
+ }
+
+ public static IRubyObject attributes(IRubyObject self, IRubyObject str) {
+ ByteList bl = str.convertToString().getByteList();
+ int cs = redcloth_attributes_en_inline;
+ return new RedclothAttributes(cs, self, bl.bytes, bl.begin, bl.realSize).parse();
+ }
+
+ public static IRubyObject link_attributes(IRubyObject self, IRubyObject str) {
+ ByteList bl = str.convertToString().getByteList();
+ int cs = redcloth_attributes_en_link_says;
+ return new RedclothAttributes(cs, self, bl.bytes, bl.begin, bl.realSize).parse();
+ }
+}
diff --git a/ext/redcloth_scan/redcloth_common.java.rl b/ext/redcloth_scan/redcloth_common.java.rl
index e2952322..a1c21116 100644
--- a/ext/redcloth_scan/redcloth_common.java.rl
+++ b/ext/redcloth_scan/redcloth_common.java.rl
@@ -112,10 +112,10 @@
# conditionals
action starts_line {
- p == orig_p || *(p-1) == '\r' || *(p-1) == '\n' || *(p-1) == '\f'
+ p == orig_p || data[(p-1)] == '\r' || data[(p-1)] == '\n' || data[(p-1)] == '\f'
}
action starts_phrase {
- p == orig_p || *(p-1) == '\r' || *(p-1) == '\n' || *(p-1) == '\f' || *(p-1) == ' '
+ p == orig_p || data[(p-1)] == '\r' || data[(p-1)] == '\n' || data[(p-1)] == '\f' || data[(p-1)] == ' '
}
}%%;
diff --git a/ext/redcloth_scan/redcloth_inline.java.rl b/ext/redcloth_scan/redcloth_inline.java.rl
new file mode 100644
index 00000000..fd51a7c3
--- /dev/null
+++ b/ext/redcloth_scan/redcloth_inline.java.rl
@@ -0,0 +1,247 @@
+/*
+ * redcloth_inline.rl
+ *
+ * Copyright (C) 2008 Jason Garber
+ */
+import java.io.IOException;
+
+import org.jruby.Ruby;
+import org.jruby.RubyArray;
+import org.jruby.RubyClass;
+import org.jruby.RubyHash;
+import org.jruby.RubyModule;
+import org.jruby.RubyNumeric;
+import org.jruby.RubyObject;
+import org.jruby.RubyString;
+import org.jruby.RubySymbol;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.CallbackFactory;
+import org.jruby.runtime.builtin.IRubyObject;
+import org.jruby.exceptions.RaiseException;
+import org.jruby.runtime.load.BasicLibraryService;
+
+import org.jruby.util.ByteList;
+
+public class RedclothInline extends RedclothScanService.Base {
+
+%%{
+
+ machine redcloth_inline;
+ include redcloth_common "redcloth_common.java.rl";
+
+ # links
+ mtext_noquotes = mtext -- '"' ;
+ quoted_mtext = '"' mtext_noquotes '"' ;
+ mtext_including_quotes = (mtext_noquotes ' "' mtext_noquotes '" ' mtext_noquotes?)+ ;
+ link_says = ( C_noactions "."* " "* ((quoted_mtext | mtext_including_quotes | mtext_noquotes) -- '":') ) >A %{ STORE("link_text"); } ;
+ link_says_noquotes_noactions = ( C_noquotes_noactions "."* " "* ((mtext_noquotes) -- '":') ) ;
+ link = ( '"' link_says '":' %A uri %{ STORE_URL("href"); } ) >X ;
+ link_noquotes_noactions = ( '"' link_says_noquotes_noactions '":' uri ) ;
+ bracketed_link = ( '["' link_says '":' %A uri %{ STORE("href"); } :> "]" ) >X ;
+
+ # images
+ image_src = ( uri ) >A %{ STORE("src"); } ;
+ image_is = ( A2 C ". "? image_src :> title? ) ;
+ image_link = ( ":" uri >A %{ STORE_URL("href"); } ) ;
+ image = ( "["? "!" image_is "!" %A image_link? "]"? ) >X ;
+
+ # footnotes
+ footno = "[" >X %A digit+ %T "]" ;
+
+ # markup
+ end_markup_phrase = (" " | PUNCT | EOF | LF) @{ fhold; };
+ code = "["? "@" >X mtext >A %T :> "@" "]"? ;
+ code_tag_start = "]* ">" ;
+ code_tag_end = "
" ;
+ script_tag = ( "") "" LF? ) >X >A %T ;
+ notextile = "" >X (default+ -- "") >A %T "";
+ strong = "["? "*" >X mtext >A %T :> "*" "]"? ;
+ b = "["? "**" >X mtext >A %T :> "**" "]"? ;
+ em = "["? "_" >X mtext >A %T :> "_" "]"? ;
+ i = "["? "__" >X mtext >A %T :> "__" "]"? ;
+ del = "[-" >X C ( mtext ) >A %T :>> "-]" ;
+ emdash_parenthetical_phrase_with_spaces = " -- " mtext " -- " ;
+ del_phrase = (( " " >A %{ STORE("beginning_space"); } "-") >X C ( mtext ) >A %T :>> ( "-" end_markup_phrase )) - emdash_parenthetical_phrase_with_spaces ;
+ ins = "["? "+" >X mtext >A %T :> "+" "]"? ;
+ sup = "[^" >X mtext >A %T :> "^]" ;
+ sup_phrase = ( "^" when starts_phrase) >X ( mtext ) >A %T :>> ( "^" end_markup_phrase ) ;
+ sub = "[~" >X mtext >A %T :> "~]" ;
+ sub_phrase = ( "~" when starts_phrase) >X ( mtext ) >A %T :>> ( "~" end_markup_phrase ) ;
+ span = "[%" >X mtext >A %T :> "%]" ;
+ span_phrase = (("%" when starts_phrase) >X ( mtext ) >A %T :>> ( "%" end_markup_phrase )) ;
+ cite = "["? "??" >X mtext >A %T :> "??" "]"? ;
+ ignore = "["? "==" >X %A mtext %T :> "==" "]"? ;
+ snip = "["? "```" >X %A mtext %T :> "```" "]"? ;
+
+ # quotes
+ quote1 = "'" >X %A mtext %T :> "'" ;
+ non_quote_chars_or_link = (chars -- '"') | link_noquotes_noactions ;
+ mtext_inside_quotes = ( non_quote_chars_or_link (mspace non_quote_chars_or_link)* ) ;
+ html_tag_up_to_attribute_quote = "<" Name space+ NameAttr space* "=" space* ;
+ quote2 = ('"' >X %A ( mtext_inside_quotes - (mtext_inside_quotes html_tag_up_to_attribute_quote ) ) %T :> '"' ) ;
+ multi_paragraph_quote = (('"' when starts_line) >X %A ( chars -- '"' ) %T );
+
+ # html
+ start_tag = ( "<" Name space+ AttrSet* (AttrEnd)? ">" | "<" Name ">" ) >X >A %T ;
+ empty_tag = ( "<" Name space+ AttrSet* (AttrEnd)? "/>" | "<" Name "/>" ) >X >A %T ;
+ end_tag = ( "" Name space* ">" ) >X >A %T ;
+ html_comment = ("") >X >A %T;
+
+ # glyphs
+ ellipsis = ( " "? >A %T "..." ) >X ;
+ emdash = "--" ;
+ arrow = "->" ;
+ endash = " - " ;
+ acronym = ( [A-Z] >A [A-Z0-9]{2,} %T "(" default+ >A %{ STORE("title"); } :> ")" ) >X ;
+ caps_noactions = upper{3,} ;
+ caps = ( caps_noactions >A %*T ) >X ;
+ dim_digit = [0-9.]+ ;
+ prime = ("'" | '"')?;
+ dim_noactions = dim_digit prime (("x" | " x ") dim_digit prime) %T (("x" | " x ") dim_digit prime)? ;
+ dim = dim_noactions >X >A %T ;
+ tm = [Tt] [Mm] ;
+ trademark = " "? ( "[" tm "]" | "(" tm ")" ) ;
+ reg = [Rr] ;
+ registered = " "? ( "[" reg "]" | "(" reg ")" ) ;
+ cee = [Cc] ;
+ copyright = ( "[" cee "]" | "(" cee ")" ) ;
+ entity = ( "&" %A ( '#' digit+ | ( alpha ( alpha | digit )+ ) ) %T ';' ) >X ;
+
+ # info
+ redcloth_version = "[RedCloth::VERSION]" ;
+
+ other_phrase = phrase -- dim_noactions;
+
+ code_tag := |*
+ code_tag_end { CAT(block); fgoto main; };
+ default => esc_pre;
+ *|;
+
+ main := |*
+
+ image { INLINE(block, "image"); };
+
+ link { PARSE_LINK_ATTR("link_text"); PASS(block, "name", "link"); };
+ bracketed_link { PARSE_LINK_ATTR("link_text"); PASS(block, "name", "link"); };
+
+ code { PARSE_ATTR("text"); PASS_CODE(block, "text", "code", opts); };
+ code_tag_start { CAT(block); fgoto code_tag; };
+ notextile { INLINE(block, "notextile"); };
+ strong { PARSE_ATTR("text"); PASS(block, "text", "strong"); };
+ b { PARSE_ATTR("text"); PASS(block, "text", "b"); };
+ em { PARSE_ATTR("text"); PASS(block, "text", "em"); };
+ i { PARSE_ATTR("text"); PASS(block, "text", "i"); };
+ del { PASS(block, "text", "del"); };
+ del_phrase { PASS(block, "text", "del_phrase"); };
+ ins { PARSE_ATTR("text"); PASS(block, "text", "ins"); };
+ sup { PARSE_ATTR("text"); PASS(block, "text", "sup"); };
+ sup_phrase { PARSE_ATTR("text"); PASS(block, "text", "sup_phrase"); };
+ sub { PARSE_ATTR("text"); PASS(block, "text", "sub"); };
+ sub_phrase { PARSE_ATTR("text"); PASS(block, "text", "sub_phrase"); };
+ span { PARSE_ATTR("text"); PASS(block, "text", "span"); };
+ span_phrase { PARSE_ATTR("text"); PASS(block, "text", "span_phrase"); };
+ cite { PARSE_ATTR("text"); PASS(block, "text", "cite"); };
+ ignore => ignore;
+ snip { PASS(block, "text", "snip"); };
+ quote1 { PASS(block, "text", "quote1"); };
+ quote2 { PASS(block, "text", "quote2"); };
+ multi_paragraph_quote { PASS(block, "text", "multi_paragraph_quote"); };
+
+ ellipsis { INLINE(block, "ellipsis"); };
+ emdash { INLINE(block, "emdash"); };
+ endash { INLINE(block, "endash"); };
+ arrow { INLINE(block, "arrow"); };
+ caps { INLINE(block, "caps"); };
+ acronym { INLINE(block, "acronym"); };
+ dim { INLINE(block, "dim"); };
+ trademark { INLINE(block, "trademark"); };
+ registered { INLINE(block, "registered"); };
+ copyright { INLINE(block, "copyright"); };
+ footno { PASS(block, "text", "footno"); };
+ entity { INLINE(block, "entity"); };
+
+ script_tag { INLINE(block, "inline_html"); };
+ start_tag { INLINE(block, "inline_html"); };
+ end_tag { INLINE(block, "inline_html"); };
+ empty_tag { INLINE(block, "inline_html"); };
+ html_comment { INLINE(block, "inline_html"); };
+
+ redcloth_version { INLINE(block, "inline_redcloth_version"); };
+
+ other_phrase => esc;
+ PUNCT => esc;
+ space => esc;
+
+ EOF;
+
+ *|;
+
+}%%
+
+%% write data nofinal;
+
+ public IRubyObject red_pass_code(IRubyObject self, IRubyObject regs, IRubyObject ref, String meth) {
+ IRubyObject txt = ((RubyHash)regs).aref(ref);
+ if(!txt.isNil()) {
+ IRubyObject txt2 = RubyString.newEmptyString(runtime);
+ strCatEscapedForPreformatted(self, txt2, ((RubyString)txt).getByteList().bytes, ((RubyString)txt).getByteList().begin, ((RubyString)txt).getByteList().begin + ((RubyString)txt).getByteList().realSize);
+ ((RubyHash)regs).aset(ref, txt2);
+ }
+ return self.callMethod(runtime.getCurrentContext(), meth, regs);
+ }
+
+ public IRubyObject red_parse_attr(IRubyObject self, IRubyObject regs, IRubyObject ref) {
+ IRubyObject txt = ((RubyHash)regs).aref(ref);
+ IRubyObject new_regs = RedclothAttributes.attributes(self, txt);
+ return regs.callMethod(runtime.getCurrentContext(), "update", new_regs);
+ }
+
+ public IRubyObject red_parse_link_attr(IRubyObject self, IRubyObject regs, IRubyObject ref) {
+ IRubyObject txt = ((RubyHash)regs).aref(ref);
+ IRubyObject new_regs = RedclothAttributes.link_attributes(self, txt);
+ return regs.callMethod(runtime.getCurrentContext(), "update", new_regs);
+ }
+
+ public void PASS_CODE(IRubyObject H, String A, String T, int O) {
+ ((RubyString)H).append(red_pass_code(self, regs, runtime.newSymbol(A), T));
+ }
+
+ public void PARSE_ATTR(String A) {
+ red_parse_attr(self, regs, runtime.newSymbol(A));
+ }
+
+ public void PARSE_LINK_ATTR(String A) {
+ red_parse_link_attr(self, regs, runtime.newSymbol(A));
+ }
+
+ private int opts;
+ private IRubyObject buf;
+
+ public RedclothInline(IRubyObject self, byte[] data, int p, int pe, IRubyObject refs) {
+// System.err.println("RedclothInline(data.len: " + data.length + ", p: " + p + ", pe: " + pe + ")");
+ this.runtime = self.getRuntime();
+ this.self = self;
+ this.data = data;
+ this.p = p;
+ this.pe = p+pe;
+ this.eof = p+pe;
+ this.refs = refs;
+ this.block = RubyString.newEmptyString(runtime);
+ this.regs = runtime.getNil();
+ this.opts = 0;
+ this.buf = runtime.getNil();
+ }
+
+
+ public IRubyObject inline() {
+ %% write init;
+ %% write exec;
+ return block;
+ }
+
+ public static IRubyObject inline2(IRubyObject self, IRubyObject str, IRubyObject refs) {
+ ByteList bl = str.convertToString().getByteList();
+ return new RedclothInline(self, bl.bytes, bl.begin, bl.realSize, refs).inline();
+ }
+}
diff --git a/ext/redcloth_scan/redcloth_scan.java.rl b/ext/redcloth_scan/redcloth_scan.java.rl
index c7537c79..b4456eb4 100644
--- a/ext/redcloth_scan/redcloth_scan.java.rl
+++ b/ext/redcloth_scan/redcloth_scan.java.rl
@@ -15,15 +15,277 @@ import org.jruby.RubyObject;
import org.jruby.RubyString;
import org.jruby.RubySymbol;
import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.CallbackFactory;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.exceptions.RaiseException;
import org.jruby.runtime.load.BasicLibraryService;
+import org.jruby.util.ByteList;
public class RedclothScanService implements BasicLibraryService {
- private static class Transformer {
+ public static class Base {
+ public void LIST_ITEM() {
+ int aint = 0;
+ IRubyObject aval = ((RubyArray)list_index).entry(nest-1);
+ if(!aval.isNil()) { aint = RubyNumeric.fix2int(aval); }
+ if(list_type.equals("ol")) {
+ ((RubyArray)list_index).store(nest-1, runtime.newFixnum(aint + 1));
+ }
+
+ if(nest > ((RubyArray)list_layout).getLength()) {
+ listm = list_type + "_open";
+ if(list_continue == 1) {
+ list_continue = 0;
+ ((RubyHash)regs).aset(runtime.newSymbol("start"), ((RubyArray)list_index).entry(nest-1));
+ } else {
+ IRubyObject start = ((RubyHash)regs).aref(runtime.newSymbol("start"));
+ if(start.isNil()) {
+ ((RubyArray)list_index).store(nest-1, runtime.newFixnum(1));
+ } else {
+ IRubyObject start_num = start.callMethod(runtime.getCurrentContext(), "to_i");
+ ((RubyArray)list_index).store(nest-1, start_num);
+ }
+ }
+ ((RubyHash)regs).aset(runtime.newSymbol("nest"), runtime.newFixnum(nest));
+ ((RubyString)html).append(self.callMethod(runtime.getCurrentContext(), listm, regs));
+ ((RubyArray)list_layout).store(nest-1, runtime.newString(list_type));
+ CLEAR_REGS();
+ ASET("first", "true");
+ }
+ LIST_CLOSE();
+ ((RubyHash)regs).aset(runtime.newSymbol("nest"), ((RubyArray)list_layout).length());
+ ASET("type", "li_open");
+ }
+
+ public void LIST_CLOSE() {
+ while(nest < ((RubyArray)list_layout).getLength()) {
+ ((RubyHash)regs).aset(runtime.newSymbol("nest"), ((RubyArray)list_layout).length());
+ IRubyObject end_list = ((RubyArray)list_layout).pop(runtime.getCurrentContext());
+ if(!end_list.isNil()) {
+ String s = end_list.convertToString().toString();
+ listm = s + "_close";
+ ((RubyString)html).append(self.callMethod(runtime.getCurrentContext(), listm, regs));
+ }
+ }
+ }
+
+ public void TRANSFORM(String T) {
+ if(p > reg && reg >= ts) {
+ IRubyObject str = RedclothScanService.transform(self, data, reg, p-reg, refs);
+ ((RubyHash)regs).aset(runtime.newSymbol(T), str);
+ } else {
+ ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.getNil());
+ }
+ }
+
+ public IRubyObject red_pass(IRubyObject self, IRubyObject regs, IRubyObject ref, String meth, IRubyObject refs) {
+ IRubyObject txt = ((RubyHash)regs).aref(ref);
+ if(!txt.isNil()) {
+ ((RubyHash)regs).aset(ref, inline2(self, txt, refs));
+ }
+ return self.callMethod(self.getRuntime().getCurrentContext(), meth, regs);
+ }
+
+
+ public void PASS(IRubyObject H, String A, String T) {
+ ((RubyString)H).append(red_pass(self, regs, runtime.newSymbol(A), T, refs));
+ }
+
+ public void STORE_URL(String T) {
+ if(p > reg && reg >= ts) {
+ boolean punct = true;
+ while(p > reg && punct) {
+ switch(data[p - 1]) {
+ case '!': case '"': case '#': case '$': case '%': case ']': case '[': case '&': case '\'':
+ case '*': case '+': case ',': case '-': case '.': case ')': case '(': case ':':
+ case ';': case '=': case '?': case '@': case '\\': case '^': case '_':
+ case '`': case '|': case '~': p--; break;
+ default: punct = false;
+ }
+ }
+ te = p;
+ }
+ STORE(T);
+ if(!refs.isNil() && refs.callMethod(runtime.getCurrentContext(), "has_key?", ((RubyHash)regs).aref(runtime.newSymbol(T))).isTrue()) {
+ ((RubyHash)regs).aset(runtime.newSymbol(T), ((RubyHash)refs).aref(((RubyHash)refs).aref(runtime.newSymbol(T))));
+ }
+ }
+
+ public void red_inc(IRubyObject regs, IRubyObject ref) {
+ int aint = 0;
+ IRubyObject aval = ((RubyHash)regs).aref(ref);
+ if(!aval.isNil()) {
+ aint = RubyNumeric.fix2int(aval);
+ }
+ ((RubyHash)regs).aset(ref, regs.getRuntime().newFixnum(aint+1));
+ }
+
+ public IRubyObject red_blockcode(IRubyObject self, IRubyObject regs, IRubyObject block) {
+ Ruby runtime = self.getRuntime();
+ IRubyObject btype = ((RubyHash)regs).aref(runtime.newSymbol("type"));
+ block = block.callMethod(runtime.getCurrentContext(), "strip");
+ if(((RubyString)block).getByteList().realSize > 0) {
+ ((RubyHash)regs).aset(runtime.newSymbol("text"), block);
+ block = self.callMethod(runtime.getCurrentContext(), btype.asJavaString(), regs);
+ }
+ return block;
+ }
+
+ public IRubyObject red_block(IRubyObject self, IRubyObject regs, IRubyObject block, IRubyObject refs) {
+ Ruby runtime = self.getRuntime();
+ RubySymbol method;
+ IRubyObject sym_text = runtime.newSymbol("text");
+ IRubyObject btype = ((RubyHash)regs).aref(runtime.newSymbol("type"));
+ block = block.callMethod(runtime.getCurrentContext(), "strip");
+ if(!block.isNil() && !btype.isNil()) {
+ method = btype.convertToString().intern();
+ if(method == runtime.newSymbol("notextile")) {
+ ((RubyHash)regs).aset(sym_text, block);
+ } else {
+ ((RubyHash)regs).aset(sym_text, inline2(self, block, refs));
+ }
+ if(self.respondsTo(method.asJavaString())) {
+ block = self.callMethod(runtime.getCurrentContext(), method.asJavaString(), regs);
+ } else {
+ IRubyObject fallback = ((RubyHash)regs).aref(runtime.newSymbol("fallback"));
+ if(!fallback.isNil()) {
+ ((RubyString)fallback).append(((RubyHash)regs).aref(sym_text));
+ CLEAR_REGS();
+ ((RubyHash)regs).aset(sym_text, fallback);
+ }
+ block = self.callMethod(runtime.getCurrentContext(), "p", regs);
+ }
+ }
+
+ return block;
+ }
+
+ public void strCatEscaped(IRubyObject self, IRubyObject str, byte[] data, int ts, int te) {
+ IRubyObject sourceStr = RubyString.newString(self.getRuntime(), data, ts, te-ts);
+ IRubyObject escapedStr = self.callMethod(self.getRuntime().getCurrentContext(), "escape", sourceStr);
+ ((RubyString)str).concat(escapedStr);
+ }
+
+ public void strCatEscapedForPreformatted(IRubyObject self, IRubyObject str, byte[] data, int ts, int te) {
+ IRubyObject sourceStr = RubyString.newString(self.getRuntime(), data, ts, te-ts);
+ IRubyObject escapedStr = self.callMethod(self.getRuntime().getCurrentContext(), "escape_pre", sourceStr);
+ ((RubyString)str).concat(escapedStr);
+ }
+
+ public void CLEAR(IRubyObject obj) {
+ if(block == obj) {
+ block = RubyString.newEmptyString(runtime);
+ } else if(html == obj) {
+ html = RubyString.newEmptyString(runtime);
+ } else if(table == obj) {
+ table = RubyString.newEmptyString(runtime);
+ }
+ }
+
+ public void ADD_BLOCK() {
+ ((RubyString)html).append(red_block(self, regs, block, refs));
+ extend = runtime.getNil();
+ CLEAR(block);
+ CLEAR_REGS();
+ }
+
+ public void CLEAR_REGS() {
+ regs = RubyHash.newHash(runtime);
+ }
+
+ public void CAT(IRubyObject H) {
+ ((RubyString)H).cat(data, ts, te-ts);
+ }
+
+ public void INLINE(IRubyObject H, String T) {
+ ((RubyString)H).append(self.callMethod(runtime.getCurrentContext(), T, regs));
+ }
+
+ public void DONE(IRubyObject H) {
+ ((RubyString)html).append(H);
+ CLEAR(H);
+ CLEAR_REGS();
+ }
+
+ public void ADD_EXTENDED_BLOCK() {
+ ((RubyString)html).append(red_block(self, regs, block, refs));
+ CLEAR(block);
+ }
+
+ public void ADD_BLOCKCODE() {
+ ((RubyString)html).append(red_blockcode(self, regs, block));
+ CLEAR(block);
+ CLEAR_REGS();
+ }
+
+ public void ADD_EXTENDED_BLOCKCODE() {
+ ((RubyString)html).append(red_blockcode(self, regs, block));
+ CLEAR(block);
+ }
+
+ public void AINC(String T) {
+ red_inc(regs, runtime.newSymbol(T));
+ }
+
+ public void END_EXTENDED() {
+ extend = runtime.getNil();
+ CLEAR_REGS();
+ }
+
+ public void ASET(String T, String V) {
+ ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.newString(V));
+ }
+
+ public void STORE(String T) {
+ if(p > reg && reg >= ts) {
+ IRubyObject str = RubyString.newString(runtime, data, reg, p-reg);
+ ((RubyHash)regs).aset(runtime.newSymbol(T), str);
+ } else {
+ ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.getNil());
+ }
+ }
+
+ public void STORE_B(String T) {
+ if(p > bck && bck >= ts) {
+ IRubyObject str = RubyString.newString(runtime, data, bck, p-bck);
+ ((RubyHash)regs).aset(runtime.newSymbol(T), str);
+ } else {
+ ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.getNil());
+ }
+ }
+
+ public IRubyObject self;
+ public byte[] data;
+ public int p, pe;
+ public IRubyObject refs;
+
+ public Ruby runtime;
+ public int orig_p, orig_pe;
+ public int cs, act, nest;
+ public int ts = -1;
+ public int te = -1;
+ public int reg = -1;
+ public int bck = -1;
+ public int eof = -1;
+
+ public IRubyObject html;
+ public IRubyObject table;
+ public IRubyObject block;
+ public IRubyObject regs;
+
+ public IRubyObject list_layout;
+ public String list_type = null;
+ public IRubyObject list_index;
+ public int list_continue = 0;
+ public IRubyObject plain_block;
+ public IRubyObject extend;
+ public String listm = "";
+ public IRubyObject refs_found;
+ }
+
+ private static class Transformer extends Base {
%%{
machine redcloth_scan;
@@ -348,271 +610,18 @@ public class RedclothScanService implements BasicLibraryService {
%% write data nofinal;
- public void LIST_ITEM() {
- int aint = 0;
- IRubyObject aval = ((RubyArray)list_index).entry(nest-1);
- if(!aval.isNil()) { aint = RubyNumeric.fix2int(aval); }
- if(list_type.equals("ol")) {
- ((RubyArray)list_index).store(nest-1, runtime.newFixnum(aint + 1));
- }
-
- if(nest > ((RubyArray)list_layout).getLength()) {
- listm = list_type + "_open";
- if(list_continue == 1) {
- list_continue = 0;
- ((RubyHash)regs).aset(runtime.newSymbol("start"), ((RubyArray)list_index).entry(nest-1));
- } else {
- IRubyObject start = ((RubyHash)regs).aref(runtime.newSymbol("start"));
- if(start.isNil()) {
- ((RubyArray)list_index).store(nest-1, runtime.newFixnum(1));
- } else {
- IRubyObject start_num = start.callMethod(runtime.getCurrentContext(), "to_i");
- ((RubyArray)list_index).store(nest-1, start_num);
- }
- }
- ((RubyHash)regs).aset(runtime.newSymbol("nest"), runtime.newFixnum(nest));
- ((RubyString)html).append(self.callMethod(runtime.getCurrentContext(), listm, regs));
- ((RubyArray)list_layout).store(nest-1, runtime.newString(list_type));
- CLEAR_REGS();
- ASET("first", "true");
- }
- LIST_CLOSE();
- ((RubyHash)regs).aset(runtime.newSymbol("nest"), ((RubyArray)list_layout).length());
- ASET("type", "li_open");
- }
-
- public void LIST_CLOSE() {
- while(nest < ((RubyArray)list_layout).getLength()) {
- ((RubyHash)regs).aset(runtime.newSymbol("nest"), ((RubyArray)list_layout).length());
- IRubyObject end_list = ((RubyArray)list_layout).pop(runtime.getCurrentContext());
- if(!end_list.isNil()) {
- String s = end_list.convertToString().toString();
- listm = s + "_close";
- ((RubyString)html).append(self.callMethod(runtime.getCurrentContext(), listm, regs));
- }
- }
- }
-
- public void TRANSFORM(String T) {
- if(p > reg && reg >= ts) {
- IRubyObject str = RedclothScanService.transform(self, data, reg, p, refs);
- ((RubyHash)regs).aset(runtime.newSymbol(T), str);
- } else {
- ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.getNil());
- }
- }
-
- public IRubyObject red_pass(IRubyObject self, IRubyObject regs, IRubyObject ref, String meth, IRubyObject refs) {
- IRubyObject txt = ((RubyHash)regs).aref(ref);
- if(!txt.isNil()) {
- ((RubyHash)regs).aset(ref, inline2(self, txt, refs));
- }
- return self.callMethod(self.getRuntime().getCurrentContext(), meth, regs);
- }
-
-
- public void PASS(IRubyObject H, String A, String T) {
- ((RubyString)H).append(red_pass(self, regs, runtime.newSymbol(A), T, refs));
- }
-
- public void STORE_URL(String T) {
- if(p > reg && reg >= ts) {
- boolean punct = true;
- while(p > reg && punct) {
- switch(data[p - 1]) {
- case '!': case '"': case '#': case '$': case '%': case ']': case '[': case '&': case '\'':
- case '*': case '+': case ',': case '-': case '.': case ')': case '(': case ':':
- case ';': case '=': case '?': case '@': case '\\': case '^': case '_':
- case '`': case '|': case '~': p--; break;
- default: punct = false;
- }
- }
- te = p;
- }
- STORE(T);
- if(!refs.isNil() && refs.callMethod(runtime.getCurrentContext(), "has_key?", ((RubyHash)regs).aref(runtime.newSymbol(T))).isTrue()) {
- ((RubyHash)regs).aset(runtime.newSymbol(T), ((RubyHash)refs).aref(((RubyHash)refs).aref(runtime.newSymbol(T))));
- }
- }
-
- public void red_inc(IRubyObject regs, IRubyObject ref) {
- int aint = 0;
- IRubyObject aval = ((RubyHash)regs).aref(ref);
- if(!aval.isNil()) {
- aint = RubyNumeric.fix2int(aval);
- }
- ((RubyHash)regs).aset(ref, regs.getRuntime().newFixnum(aint+1));
- }
-
- public IRubyObject red_blockcode(IRubyObject self, IRubyObject regs, IRubyObject block) {
- Ruby runtime = self.getRuntime();
- IRubyObject btype = ((RubyHash)regs).aref(runtime.newSymbol("type"));
- block = block.callMethod(runtime.getCurrentContext(), "strip");
- if(((RubyString)block).getByteList().realSize > 0) {
- ((RubyHash)regs).aset(runtime.newSymbol("text"), block);
- block = self.callMethod(runtime.getCurrentContext(), btype.asJavaString(), regs);
- }
- return block;
- }
-
- public IRubyObject red_block(IRubyObject self, IRubyObject regs, IRubyObject block, IRubyObject refs) {
- Ruby runtime = self.getRuntime();
- RubySymbol method;
- IRubyObject sym_text = runtime.newSymbol("text");
- IRubyObject btype = ((RubyHash)regs).aref(runtime.newSymbol("type"));
- block = block.callMethod(runtime.getCurrentContext(), "strip");
- if(!block.isNil() && !btype.isNil()) {
- method = btype.convertToString().intern();
- if(method == runtime.newSymbol("notextile")) {
- ((RubyHash)regs).aset(sym_text, block);
- } else {
- ((RubyHash)regs).aset(sym_text, inline2(self, block, refs));
- }
- if(self.respondsTo(method.asJavaString())) {
- block = self.callMethod(runtime.getCurrentContext(), method.asJavaString(), regs);
- } else {
- IRubyObject fallback = ((RubyHash)regs).aref(runtime.newSymbol("fallback"));
- if(!fallback.isNil()) {
- ((RubyString)fallback).append(((RubyHash)regs).aref(sym_text));
- CLEAR_REGS();
- ((RubyHash)regs).aset(sym_text, fallback);
- }
- block = self.callMethod(runtime.getCurrentContext(), "p", regs);
- }
- }
-
- return block;
- }
-
- public void strCatEscaped(IRubyObject self, IRubyObject str, byte[] data, int ts, int te) {
- IRubyObject sourceStr = RubyString.newString(self.getRuntime(), data, ts, te-ts);
- IRubyObject escapedStr = self.callMethod(self.getRuntime().getCurrentContext(), "escape", sourceStr);
- ((RubyString)str).concat(escapedStr);
- }
-
- public void strCatEscapedForPreformatted(IRubyObject self, IRubyObject str, byte[] data, int ts, int te) {
- IRubyObject sourceStr = RubyString.newString(self.getRuntime(), data, ts, te-ts);
- IRubyObject escapedStr = self.callMethod(self.getRuntime().getCurrentContext(), "escape_pre", sourceStr);
- ((RubyString)str).concat(escapedStr);
- }
-
- public void CLEAR(IRubyObject obj) {
- if(block == obj) {
- block = RubyString.newEmptyString(runtime);
- } else if(html == obj) {
- html = RubyString.newEmptyString(runtime);
- } else if(table == obj) {
- table = RubyString.newEmptyString(runtime);
- }
- }
-
- public void ADD_BLOCK() {
- ((RubyString)html).append(red_block(self, regs, block, refs));
- extend = runtime.getNil();
- CLEAR(block);
- CLEAR_REGS();
- }
-
- public void CLEAR_REGS() {
- regs = RubyHash.newHash(runtime);
- }
-
- public void CAT(IRubyObject H) {
- ((RubyString)H).cat(data, ts, te-ts);
- }
-
- public void INLINE(IRubyObject H, String T) {
- ((RubyString)H).append(self.callMethod(runtime.getCurrentContext(), T, regs));
- }
-
- public void DONE(IRubyObject H) {
- ((RubyString)html).append(H);
- CLEAR(H);
- CLEAR_REGS();
- }
-
- public void ADD_EXTENDED_BLOCK() {
- ((RubyString)html).append(red_block(self, regs, block, refs));
- CLEAR(block);
- }
-
- public void ADD_BLOCKCODE() {
- ((RubyString)html).append(red_blockcode(self, regs, block));
- CLEAR(block);
- CLEAR_REGS();
- }
-
- public void ADD_EXTENDED_BLOCKCODE() {
- ((RubyString)html).append(red_blockcode(self, regs, block));
- CLEAR(block);
- }
-
- public void AINC(String T) {
- red_inc(regs, runtime.newSymbol(T));
- }
-
- public void END_EXTENDED() {
- extend = runtime.getNil();
- CLEAR_REGS();
- }
-
- public void ASET(String T, String V) {
- ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.newString(V));
- }
-
- public void STORE(String T) {
- if(p > reg && reg >= ts) {
- IRubyObject str = RubyString.newString(runtime, data, reg, p-reg);
- ((RubyHash)regs).aset(runtime.newSymbol(T), str);
- } else {
- ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.getNil());
- }
- }
-
- public void STORE_B(String T) {
- if(p > bck && bck >= ts) {
- IRubyObject str = RubyString.newString(runtime, data, bck, p-bck);
- ((RubyHash)regs).aset(runtime.newSymbol(T), str);
- } else {
- ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.getNil());
- }
- }
-
- private IRubyObject self;
- private byte[] data;
- private int p, pe;
- private IRubyObject refs;
-
- private Ruby runtime;
- private int orig_p, orig_pe;
- private int cs, act, nest;
- private int ts = -1;
- private int te = -1;
- private int reg = -1;
- private int bck = -1;
- private int eof = -1;
-
- private IRubyObject html;
- private IRubyObject table;
- private IRubyObject block;
- private IRubyObject regs;
-
- private IRubyObject list_layout;
- private String list_type = null;
- private IRubyObject list_index;
- private int list_continue = 0;
- private IRubyObject plain_block;
- private IRubyObject extend;
- private String listm = "";
- private IRubyObject refs_found;
-
public Transformer(IRubyObject self, byte[] data, int p, int pe, IRubyObject refs) {
+// System.err.println("Transformer(data.len: " + data.length + ", p: " + p + ", pe: " + pe + ")");
+ if(p+pe > data.length) {
+ throw new RuntimeException("BLAHAHA");
+ }
this.self = self;
this.data = data;
this.p = p;
- this.pe = pe;
+ this.pe = p+pe;
+ this.eof = p+pe;
this.refs = refs;
-
+
runtime = self.getRuntime();
orig_p = p;
orig_pe = pe;
@@ -633,9 +642,15 @@ public class RedclothScanService implements BasicLibraryService {
%% write init;
%% write exec;
+
+// System.err.println("gah: p: " + p + " pe: " + pe);
if(((RubyString)block).getByteList().realSize > 0) {
-// ADD_BLOCK();
+ ADD_BLOCK();
}
+// System.err.println("gah2: p: " + p + " pe: " + pe);
+// System.err.println(" html: " + html);
+// System.err.println(" table: " + table);
+// System.err.println(" block: " + block);
if(refs.isNil() && !refs_found.callMethod(runtime.getCurrentContext(), "empty?").isTrue()) {
return RedclothScanService.transform(self, data, orig_p, orig_pe, refs_found);
@@ -651,7 +666,7 @@ public class RedclothScanService implements BasicLibraryService {
}
public static IRubyObject inline2(IRubyObject workingCopy, IRubyObject self, IRubyObject refs) {
- return workingCopy.getRuntime().getNil();
+ return RedclothInline.inline2(workingCopy, self, refs);
}
public static IRubyObject transform2(IRubyObject self, IRubyObject str) {
@@ -678,12 +693,137 @@ public class RedclothScanService implements BasicLibraryService {
@JRubyMethod(rest=true)
public static IRubyObject html_esc(IRubyObject self, IRubyObject[] args) {
- return self.getRuntime().getNil();
+ Ruby runtime = self.getRuntime();
+ IRubyObject str = runtime.getNil(),
+ level = runtime.getNil();
+ if(Arity.checkArgumentCount(runtime, args, 1, 2) == 2) {
+ level = args[1];
+ }
+ str = args[0];
+//System.err.println("html_esc called: " + self + ",,, args: " +str + ", " + level);
+
+ IRubyObject new_str = RubyString.newEmptyString(runtime);
+ if(str.isNil()) {
+// System.err.println("isnil1");
+ return new_str;
+ }
+
+ ByteList bl = str.convertToString().getByteList();
+
+ if(bl.realSize == 0) {
+// System.err.println("isnil2");
+ return new_str;
+ }
+
+ byte[] bytes = bl.bytes;
+ int ts = bl.begin;
+ int te = ts + bl.realSize;
+ int t = ts, t2 = ts;
+ String ch = null;
+
+ if(te <= ts) {
+ return new_str;
+ }
+
+ while(t2 < te) {
+ ch = null;
+ // normal + pre
+ switch(bytes[t2]) {
+ case '&': ch = "amp"; break;
+ case '>': ch = "gt"; break;
+ case '<': ch = "lt"; break;
+ }
+
+ // normal (non-pre)
+ if(level != runtime.newSymbol("html_escape_preformatted")) {
+ switch(bytes[t2]) {
+ case '\n': ch = "br"; break;
+ case '"' : ch = "quot"; break;
+ case '\'':
+ ch = (level == runtime.newSymbol("html_escape_attributes")) ? "apos" : "squot";
+ break;
+ }
+ }
+
+ if(ch != null) {
+ if(t2 > t) {
+ ((RubyString)new_str).cat(bytes, t, t2-t);
+ }
+ ((RubyString)new_str).concat(self.callMethod(runtime.getCurrentContext(), ch, RubyHash.newHash(runtime)));
+ t = t2 + 1;
+ }
+
+ t2++;
+ }
+
+
+ if(t2 > t) {
+ ((RubyString)new_str).cat(bytes, t, t2-t);
+ }
+
+// System.err.println(" returning: " + new_str);
+ return new_str;
}
@JRubyMethod
public static IRubyObject latex_esc(IRubyObject self, IRubyObject str) {
- return self.getRuntime().getNil();
+ Ruby runtime = self.getRuntime();
+ IRubyObject new_str = RubyString.newEmptyString(runtime);
+
+ if(str.isNil()) {
+ return new_str;
+ }
+
+ ByteList bl = str.convertToString().getByteList();
+
+ if(bl.realSize == 0) {
+ return new_str;
+ }
+
+ byte[] bytes = bl.bytes;
+ int ts = bl.begin;
+ int te = ts + bl.realSize;
+ int t = ts;
+ int t2 = ts;
+ String ch = null;
+
+ while(t2 < te) {
+ ch = null;
+
+ switch(bytes[t2]) {
+ case '{': ch = "#123"; break;
+ case '}': ch = "#125"; break;
+ case '\\': ch = "#92"; break;
+ case '#': ch = "#35"; break;
+ case '$': ch = "#36"; break;
+ case '%': ch = "#37"; break;
+ case '&': ch = "amp"; break;
+ case '_': ch = "#95"; break;
+ case '^': ch = "circ"; break;
+ case '~': ch = "tilde"; break;
+ case '<': ch = "lt"; break;
+ case '>': ch = "gt"; break;
+ case '\n': ch = "#10"; break;
+ }
+
+ if(ch != null) {
+ if(t2 > t) {
+ ((RubyString)new_str).cat(bytes, t, t2-t);
+ }
+ IRubyObject opts = RubyHash.newHash(runtime);
+ ((RubyHash)opts).aset(runtime.newSymbol("text"), runtime.newString(ch));
+ ((RubyString)new_str).concat(self.callMethod(runtime.getCurrentContext(), "entity", opts));
+ t = t2 + 1;
+ }
+
+ t2++;
+ }
+
+ if(t2 > t) {
+ ((RubyString)new_str).cat(bytes, t, t2-t);
+ }
+
+ return new_str;
}
public boolean basicLoad(final Ruby runtime) throws IOException {