diff --git a/CHANGELOG b/CHANGELOG index 155b5912..69af5b10 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ === Edge +* Separated attributes out to have their own mark/store variable and regs. This way, they won't conflict with captured text or backtracked text. [Jason Garber] + * Added a RedCloth::EXTENSION_LANGUAGE constant so you can tell what version of the parser you are using. [Jason Garber] * Added a NotCompiledError to give a friendlier message when people just unpack RedCloth into their projects. [Jason Garber] diff --git a/Rakefile b/Rakefile index 018af256..3cdcfbfa 100644 --- a/Rakefile +++ b/Rakefile @@ -121,10 +121,12 @@ def ragel(target_file, source_file) preferred_code_style = case host_language when "R" "F1" - else + when "C" "T0" + else + nil end - code_style = " -" + (@code_style || preferred_code_style) + code_style = preferred_code_style ? " -" + (@code_style || preferred_code_style) : "" ensure_ragel_version(target_file) do sh %{ragel #{source_file} -#{host_language}#{code_style} -o #{target_file}} end @@ -216,11 +218,12 @@ end require 'rubygems' require 'spec/rake/spectask' Rake::Task[:default].prerequisites.clear -Spec::Rake::SpecTask.new(:default) do |t| - t.spec_opts = ["--color", "--require=spec/differs/inline.rb", "--diff=RedClothDiffers::Inline"] +Spec::Rake::SpecTask.new do |t| + t.spec_opts = ["--options #{File.dirname(__FILE__) + '/spec/spec.opts'}"] t.spec_files = FileList['spec/**/*_spec.rb'] end +task :default => :spec task :spec => [:compile] task :remove_other_platforms do diff --git a/ext/redcloth_scan/redcloth.h b/ext/redcloth_scan/redcloth.h index 7a6e75ae..67f5396e 100644 --- a/ext/redcloth_scan/redcloth.h +++ b/ext/redcloth_scan/redcloth.h @@ -49,10 +49,11 @@ VALUE red_pass(VALUE, VALUE, VALUE, ID, VALUE); VALUE red_pass_code(VALUE, VALUE, VALUE, ID); /* parser macros */ -#define CLEAR_REGS() regs = rb_hash_new(); +#define CLEAR_REGS() regs = rb_hash_new(); attr_regs = rb_hash_new(); #define RESET_REG() reg = NULL #define MARK() reg = p; #define MARK_B() bck = p; +#define MARK_ATTR() attr_reg = p; #define CAT(H) rb_str_cat(H, ts, te-ts) #define CLEAR(H) H = STR_NEW2("") #define RSTRIP_BANG(H) rb_funcall(H, rb_intern("rstrip!"), 0) @@ -75,13 +76,16 @@ VALUE red_pass_code(VALUE, VALUE, VALUE, ID); #define ADD_BLOCKCODE() rb_str_append(html, red_blockcode(self, regs, block)); CLEAR(block); CLEAR_REGS() #define ADD_EXTENDED_BLOCKCODE() rb_str_append(html, red_blockcode(self, regs, block)); CLEAR(block); #define ASET(T, V) rb_hash_aset(regs, ID2SYM(rb_intern(T)), STR_NEW2(V)); -#define AINC(T) red_inc(regs, ID2SYM(rb_intern(T))); +#define ATTR_SET(T, V) rb_hash_aset(attr_regs, ID2SYM(rb_intern(T)), STR_NEW2(V)); +#define ATTR_INC(T) red_inc(attr_regs, ID2SYM(rb_intern(T))); #define INC(N) N++; #define SET_ATTRIBUTES() \ SET_ATTRIBUTE("class_buf", "class"); \ SET_ATTRIBUTE("id_buf", "id"); \ SET_ATTRIBUTE("lang_buf", "lang"); \ - SET_ATTRIBUTE("style_buf", "style"); + SET_ATTRIBUTE("style_buf", "style"); \ + rb_funcall(regs, rb_intern("merge!"), 1, attr_regs); \ + attr_regs = rb_hash_new(); #define SET_ATTRIBUTE(B, A) \ if (rb_hash_aref(regs, ID2SYM(rb_intern(B))) != Qnil) rb_hash_aset(regs, ID2SYM(rb_intern(A)), rb_hash_aref(regs, ID2SYM(rb_intern(B)))); #define TRANSFORM(T) \ @@ -108,6 +112,15 @@ VALUE red_pass_code(VALUE, VALUE, VALUE, ID); } else { \ rb_hash_aset(regs, ID2SYM(rb_intern(T)), Qnil); \ } +#define STORE_ATTR(T) \ + if (p > attr_reg && attr_reg >= ts) { \ + VALUE str = STR_NEW(attr_reg, p-attr_reg); \ + rb_hash_aset(attr_regs, ID2SYM(rb_intern(T)), str); \ + /*printf("STORE_B(" T ") '%s' (p:'%s' reg:'%s')\n", RSTRING_PTR(str), p, reg);*/ \ + } else { \ + rb_hash_aset(attr_regs, ID2SYM(rb_intern(T)), Qnil); \ + } + #define STORE_URL(T) \ if (p > reg && reg >= ts) { \ char punct = 1; \ diff --git a/ext/redcloth_scan/redcloth_attributes.c.rl b/ext/redcloth_scan/redcloth_attributes.c.rl index 23dcf820..2bbc1b1c 100644 --- a/ext/redcloth_scan/redcloth_attributes.c.rl +++ b/ext/redcloth_scan/redcloth_attributes.c.rl @@ -24,8 +24,9 @@ redcloth_attribute_parser(machine, self, p, pe) char *p, *pe; { int cs, act; - char *ts = 0, *te = 0, *reg = 0, *bck = NULL, *eof = NULL; + char *ts = 0, *te = 0, *reg = 0, *bck = NULL, *attr_reg = NULL, *eof = NULL; VALUE regs = rb_hash_new(); + VALUE attr_regs = rb_hash_new(); %% write init; diff --git a/ext/redcloth_scan/redcloth_attributes.java.rl b/ext/redcloth_scan/redcloth_attributes.java.rl index ca47c896..16ee83a0 100644 --- a/ext/redcloth_scan/redcloth_attributes.java.rl +++ b/ext/redcloth_scan/redcloth_attributes.java.rl @@ -35,19 +35,6 @@ public class RedclothAttributes extends RedclothScanService.Base { %% 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) { - if(!((RubyHash)regs).aref(runtime.newSymbol(B)).isNil()) { - ((RubyHash)regs).aset(runtime.newSymbol(A), ((RubyHash)regs).aref(runtime.newSymbol(B))); - } - } - private int machine; public RedclothAttributes(int machine, IRubyObject self, byte[] data, int p, int pe) { @@ -66,6 +53,7 @@ public class RedclothAttributes extends RedclothScanService.Base { this.orig_pe = this.pe; this.regs = RubyHash.newHash(runtime); + this.attr_regs = RubyHash.newHash(runtime); this.machine = machine; } diff --git a/ext/redcloth_scan/redcloth_attributes.rb.rl b/ext/redcloth_scan/redcloth_attributes.rb.rl index 311fba13..eb17ddfe 100644 --- a/ext/redcloth_scan/redcloth_attributes.rb.rl +++ b/ext/redcloth_scan/redcloth_attributes.rb.rl @@ -25,6 +25,7 @@ module RedCloth def redcloth_attribute_parser(cs, data) @data = data + "\0" @regs = {} + @attr_regs = {} @p = 0 @pe = @data.length diff --git a/ext/redcloth_scan/redcloth_attributes.rl b/ext/redcloth_scan/redcloth_attributes.rl index b99e7f77..8bb8a960 100644 --- a/ext/redcloth_scan/redcloth_attributes.rl +++ b/ext/redcloth_scan/redcloth_attributes.rl @@ -7,10 +7,7 @@ machine redcloth_attributes; - 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 )+ ; + C2 = ( C_CLAS | C_STYL | C_LNGE )+ ; mtext_with_attributes = ( C2 mtext >A %T ) >X ; diff --git a/ext/redcloth_scan/redcloth_common.rl b/ext/redcloth_scan/redcloth_common.rl index 9232a1bf..1d61d7e3 100644 --- a/ext/redcloth_scan/redcloth_common.rl +++ b/ext/redcloth_scan/redcloth_common.rl @@ -4,6 +4,8 @@ action A { MARK(); } action B { MARK_B(); } + action ATTR { MARK_ATTR(); } + action SET_ATTR { SET_ATTRIBUTES(); } action T { STORE("text"); } action X { CLEAR_REGS(); RESET_REG(); } action cat { CAT(block); } @@ -13,29 +15,29 @@ default = ^0 ; EOF = 0 ; - # textile modifiers - A_LEFT = "<" %{ ASET("align", "left"); } ; - A_RIGHT = ">" %{ ASET("align", "right"); } ; - A_JUSTIFIED = "<>" %{ ASET("align", "justify"); } ; - A_CENTER = "=" %{ ASET("align", "center"); } ; - A_PADLEFT = "(" >A %{ AINC("padding-left"); } ; - A_PADRIGHT = ")" >A %{ AINC("padding-right"); } ; + # textile element attributes + A_LEFT = "<" %{ ATTR_SET("align", "left"); } ; + A_RIGHT = ">" %{ ATTR_SET("align", "right"); } ; + A_JUSTIFIED = "<>" %{ ATTR_SET("align", "justify"); } ; + A_CENTER = "=" %{ ATTR_SET("align", "center"); } ; + A_PADLEFT = "(" %{ ATTR_INC("padding-left"); } ; + A_PADRIGHT = ")" %{ ATTR_INC("padding-right"); } ; A_HLGN = ( A_LEFT | A_RIGHT | A_JUSTIFIED | A_CENTER | A_PADLEFT | A_PADRIGHT ) ; A_LIMIT = ( A_LEFT | A_CENTER | A_RIGHT ) ; - A_VLGN = ( "-" %{ ASET("vertical-align", "middle"); } | "^" %{ ASET("vertical-align", "top"); } | "~" %{ ASET("vertical-align", "bottom"); } ) ; - C_CLAS = ( "(" ( [^)#]+ >A %{ STORE("class"); } )? ("#" [^)]+ >A %{STORE("id");} )? ")" ) ; - C_LNGE = ( "[" [^\]]+ >A %{ STORE("lang"); } "]" ) ; - C_STYL = ( "{" [^}]+ >A %{ STORE("style"); } "}" ) ; - S_CSPN = ( "\\" [0-9]+ >A %{ STORE("colspan"); } ) ; - S_RSPN = ( "/" [0-9]+ >A %{ STORE("rowspan"); } ) ; - D_HEADER = "_" %{ ASET("th", "true"); } ; + A_VLGN = ( "-" %{ ATTR_SET("vertical-align", "middle"); } | "^" %{ ATTR_SET("vertical-align", "top"); } | "~" %{ ATTR_SET("vertical-align", "bottom"); } ) ; + C_CLAS = ( "(" ( [^)#]+ >ATTR %{ STORE_ATTR("class"); } )? ("#" [^)]+ >ATTR %{STORE_ATTR("id");} )? ")" ) ; + C_LNGE = ( "[" [^\]]+ >ATTR %{ STORE_ATTR("lang"); } "]" ) ; + C_STYL = ( "{" [^}]+ >ATTR %{ STORE_ATTR("style"); } "}" ) ; + S_CSPN = ( "\\" [0-9]+ >ATTR %{ STORE_ATTR("colspan"); } ) ; + S_RSPN = ( "/" [0-9]+ >ATTR %{ STORE_ATTR("rowspan"); } ) ; + D_HEADER = "_" %{ ATTR_SET("th", "true"); } ; A = ( ( A_HLGN | A_VLGN )* ) ; A2 = ( A_LIMIT? ) ; S = ( S_CSPN | S_RSPN )* ; C = ( C_CLAS | C_STYL | C_LNGE )* ; D = ( D_HEADER ) ; - N_CONT = "_" %{ ASET("list_continue", "true"); }; - N_NUM = digit+ >A %{ STORE("start"); }; + N_CONT = "_" %{ ATTR_SET("list_continue", "true"); }; + N_NUM = digit+ >ATTR %{ STORE_ATTR("start"); }; N = ( N_CONT | N_NUM )? ; PUNCT = ( "!" | '"' | "#" | "$" | "%" | "&" | "'" | "," | "-" | "." | "/" | ":" | ";" | "=" | "?" | "\\" | "^" | "`" | "|" | "~" | "[" | "]" | "(" | ")" | "<" ) ; dotspace = ("." " "*) ; @@ -106,7 +108,7 @@ uri = (target | absolute_uri | absolute_path | rel_path) ; # common - title = ( '(' default+ >A %{ STORE("title"); } :> ')' ) ; + title = ( '(' default+ >ATTR %{ STORE_ATTR("title"); } :> ')' ) ; word = ( alnum | safe | " " ) ; mspace = ( ( " " | "\t" | LF )+ ) -- LF{2} ; mtext = ( chars (mspace chars)* ) ; diff --git a/ext/redcloth_scan/redcloth_inline.c.rl b/ext/redcloth_scan/redcloth_inline.c.rl index a1a043c5..9750bc95 100644 --- a/ext/redcloth_scan/redcloth_inline.c.rl +++ b/ext/redcloth_scan/redcloth_inline.c.rl @@ -96,6 +96,7 @@ red_block(VALUE self, VALUE regs, VALUE block, VALUE refs) VALUE sym_text = ID2SYM(rb_intern("text")); VALUE btype = rb_hash_aref(regs, ID2SYM(rb_intern("type"))); block = rb_funcall(block, rb_intern("strip"), 0); + VALUE attr_regs = rb_hash_new(); if ((!NIL_P(block)) && !NIL_P(btype)) { method = rb_str_intern(btype); @@ -147,10 +148,11 @@ redcloth_inline(self, p, pe, refs) VALUE refs; { int cs, act; - char *ts = NULL, *te = NULL, *reg = NULL, *eof = NULL; + char *ts = NULL, *te = NULL, *reg = NULL, *attr_reg = NULL, *eof = NULL; char *orig_p = p; VALUE block = STR_NEW2(""); VALUE regs = Qnil; + VALUE attr_regs = Qnil; %% write init; diff --git a/ext/redcloth_scan/redcloth_inline.java.rl b/ext/redcloth_scan/redcloth_inline.java.rl index f0e3d936..44ee32bf 100644 --- a/ext/redcloth_scan/redcloth_inline.java.rl +++ b/ext/redcloth_scan/redcloth_inline.java.rl @@ -87,7 +87,7 @@ public class RedclothInline extends RedclothScanService.Base { return regs; } - public void PASS_CODE(IRubyObject H, String A, String T, int O) { + public void PASS_CODE(IRubyObject H, String A, String T) { ((RubyString)H).append(red_pass_code(self, regs, runtime.newSymbol(A), T)); } @@ -122,6 +122,7 @@ public class RedclothInline extends RedclothScanService.Base { this.refs = refs; this.block = RubyString.newEmptyString(runtime); this.regs = runtime.getNil(); + this.attr_regs = runtime.getNil(); this.opts = 0; } diff --git a/ext/redcloth_scan/redcloth_inline.rl b/ext/redcloth_scan/redcloth_inline.rl index 27ae2eb1..4b8f8230 100644 --- a/ext/redcloth_scan/redcloth_inline.rl +++ b/ext/redcloth_scan/redcloth_inline.rl @@ -35,8 +35,8 @@ image_title = ( '(' mtext ')' ) ; image_is = ( A2 C ". "? (uri image_title?) >A %{ STORE("src"); } ) ; image_link = ( ":" uri >A %{ STORE_URL("href"); } ) ; - image = ( "!" image_is "!" %A image_link? ) >X ; - bracketed_image = ( "[!" image_is "!" %A image_link? "]" ) >X ; + image = ( "!" image_is "!" %A image_link? ) >X %SET_ATTR ; + bracketed_image = ( "[!" image_is "!" %A image_link? "]" ) >X %SET_ATTR ; # footnotes footno = "[" >X %A digit+ %T "]" ; diff --git a/ext/redcloth_scan/redcloth_scan.c.rl b/ext/redcloth_scan/redcloth_scan.c.rl index cc084037..4727e432 100644 --- a/ext/redcloth_scan/redcloth_scan.c.rl +++ b/ext/redcloth_scan/redcloth_scan.c.rl @@ -32,11 +32,11 @@ redcloth_transform(self, p, pe, refs) { char *orig_p = p, *orig_pe = pe; int cs, act, nest = 0; - char *ts = NULL, *te = NULL, *reg = NULL, *bck = NULL, *eof = NULL; + char *ts = NULL, *te = NULL, *reg = NULL, *bck = NULL, *attr_reg = NULL, *eof = NULL; VALUE html = STR_NEW2(""); VALUE table = STR_NEW2(""); VALUE block = STR_NEW2(""); - VALUE regs; CLEAR_REGS() + VALUE regs, attr_regs; CLEAR_REGS() VALUE list_layout = Qnil; diff --git a/ext/redcloth_scan/redcloth_scan.java.rl b/ext/redcloth_scan/redcloth_scan.java.rl index 821bd9cf..b54c13d1 100644 --- a/ext/redcloth_scan/redcloth_scan.java.rl +++ b/ext/redcloth_scan/redcloth_scan.java.rl @@ -26,7 +26,22 @@ import org.jruby.util.ByteList; public class RedclothScanService implements BasicLibraryService { public static class Base { - + + public void SET_ATTRIBUTES() { + SET_ATTRIBUTE("class_buf", "class"); + SET_ATTRIBUTE("id_buf", "id"); + SET_ATTRIBUTE("lang_buf", "lang"); + SET_ATTRIBUTE("style_buf", "style"); + regs.callMethod(runtime.getCurrentContext(), "merge!", attr_regs); + attr_regs = RubyHash.newHash(runtime); + } + + public void SET_ATTRIBUTE(String B, String A) { + if(!((RubyHash)regs).aref(runtime.newSymbol(B)).isNil()) { + ((RubyHash)regs).aset(runtime.newSymbol(A), ((RubyHash)regs).aref(runtime.newSymbol(B))); + } + } + public void CLEAR_LIST() { list_layout = runtime.newArray(); } @@ -232,6 +247,7 @@ public class RedclothScanService implements BasicLibraryService { public void CLEAR_REGS() { regs = RubyHash.newHash(runtime); + attr_regs = RubyHash.newHash(runtime); } public void RESET_REG() { @@ -246,6 +262,10 @@ public class RedclothScanService implements BasicLibraryService { bck = p; } + public void MARK_ATTR() { + attr_reg = p; + } + public void CAT(IRubyObject H) { ((RubyString)H).cat(data, ts, te-ts); } @@ -288,8 +308,9 @@ public class RedclothScanService implements BasicLibraryService { CLEAR(block); } - public void AINC(String T) { - red_inc(regs, runtime.newSymbol(T)); + + public void ATTR_INC(String T) { + red_inc(attr_regs, runtime.newSymbol(T)); } public void INC(int N) { @@ -305,6 +326,10 @@ public class RedclothScanService implements BasicLibraryService { ((RubyHash)regs).aset(runtime.newSymbol(T), runtime.newString(V)); } + public void ATTR_SET(String T, String V) { + ((RubyHash)attr_regs).aset(runtime.newSymbol(T), runtime.newString(V)); + } + public void STORE(String T) { if(p > reg && reg >= ts) { @@ -324,6 +349,15 @@ public class RedclothScanService implements BasicLibraryService { } } + public void STORE_ATTR(String T) { + if(p > attr_reg && attr_reg >= ts) { + IRubyObject str = RubyString.newString(runtime, data, attr_reg, p-attr_reg); + ((RubyHash)attr_regs).aset(runtime.newSymbol(T), str); + } else { + ((RubyHash)attr_regs).aset(runtime.newSymbol(T), runtime.getNil()); + } + } + public IRubyObject self; public byte[] data; public int p, pe; @@ -336,12 +370,14 @@ public class RedclothScanService implements BasicLibraryService { public int te = -1; public int reg = -1; public int bck = -1; + public int attr_reg = -1; public int eof = -1; public IRubyObject html; public IRubyObject table; public IRubyObject block; public IRubyObject regs; + public IRubyObject attr_regs; public IRubyObject list_layout; public String list_type = null; diff --git a/ext/redcloth_scan/redcloth_scan.rb.rl b/ext/redcloth_scan/redcloth_scan.rb.rl index 4b2695b2..8ddafc6b 100644 --- a/ext/redcloth_scan/redcloth_scan.rb.rl +++ b/ext/redcloth_scan/redcloth_scan.rb.rl @@ -85,7 +85,7 @@ module RedCloth attr_accessor :p, :pe, :refs attr_reader :data attr_accessor :orig_data, :cs, :act, :ts, :te, :reg, :bck, :eof, - :html, :table, :block, :regs + :html, :table, :block, :regs, :attr_regs attr_accessor :list_layout, :list_type, :list_index, :list_continue, :listm, :refs_found, :plain_block @@ -98,8 +98,12 @@ module RedCloth def MARK_B() @bck = @p end + def MARK_ATTR() + @attr_reg = @p + end def CLEAR_REGS() @regs = {} + @attr_regs = {} end def RESET_REG() @reg = nil @@ -168,14 +172,18 @@ module RedCloth def ASET(t, v) @regs[t.to_sym] = v end - def AINC(t) - red_inc(@regs, t.to_sym) + def ATTR_SET(t, v) + @attr_regs[t.to_sym] = v + end + def ATTR_INC(t) + red_inc(@attr_regs, t.to_sym) end def SET_ATTRIBUTES() SET_ATTRIBUTE("class_buf", "class") SET_ATTRIBUTE("id_buf", "id") SET_ATTRIBUTE("lang_buf", "lang") SET_ATTRIBUTE("style_buf", "style") + @regs.merge!(@attr_regs) end def SET_ATTRIBUTE(b, a) @regs[a.to_sym] = @regs[b.to_sym] unless @regs[b.to_sym].nil? @@ -207,6 +215,15 @@ module RedCloth @regs[t.to_sym] = nil end end + def STORE_ATTR(t) + if (@attr_reg && @p > @attr_reg && @attr_reg >= @ts) + str = @data[@attr_reg, @p - @attr_reg] + @attr_regs[t.to_sym] = str + # /*printf("STORE_B(" T ") '%s' (p:'%s' reg:'%s')\n", RSTRING_PTR(str), p, reg);*/ \ + else + @attr_regs[t.to_sym] = nil + end + end def STORE_URL(t) if (@reg && @p > @reg && @reg >= @ts) punct = true diff --git a/ext/redcloth_scan/redcloth_scan.rl b/ext/redcloth_scan/redcloth_scan.rl index 823c92e4..e6aaba30 100644 --- a/ext/redcloth_scan/redcloth_scan.rl +++ b/ext/redcloth_scan/redcloth_scan.rl @@ -10,25 +10,25 @@ # blocks notextile_tag = notextile (LF | EOF) ; noparagraph_line_start = " "+ ; - notextile_block_start = ( "notextile" >A %{ STORE("type"); } A C :> "." ( "." %extend | "" ) " "+ ) ; + notextile_block_start = ( "notextile" >A %{ STORE("type"); } A C :> "." ( "." %extend | "" ) " "+ ) %SET_ATTR ; pre_tag_start = "]* ">" (space* code_tag_start)? ; pre_tag_end = (code_tag_end space*)? "" LF? ; - pre_block_start = ( "pre" >A %{ STORE("type"); } A C :> "." ( "." %extend | "" ) " "+ ) ; - bc_start = ( "bc" >A %{ STORE("type"); } A C :> "." ( "." %extend | "" ) " "+ ) ; - bq_start = ( "bq" >A %{ STORE("type"); } A C :> "." ( "." %extend | "" ) ( ":" %A uri %{ STORE("cite"); } )? " "+ ) ; + pre_block_start = ( "pre" >A %{ STORE("type"); } A C :> "." ( "." %extend | "" ) " "+ ) %SET_ATTR ; + bc_start = ( "bc" >A %{ STORE("type"); } A C :> "." ( "." %extend | "" ) " "+ ) %SET_ATTR ; + bq_start = ( "bq" >A %{ STORE("type"); } A C :> "." ( "." %extend | "" ) ( ":" %A uri %{ STORE("cite"); } )? " "+ ) %SET_ATTR ; non_ac_btype = ( "bq" | "bc" | "pre" | "notextile" | "table" ); btype = (alpha alnum*) -- (non_ac_btype | "fn" digit+); - block_start = ( btype >A %{ STORE("type"); } A C :> "." ( "." %extend | "" ) " "+ ) >B %{ STORE_B("fallback"); }; + block_start = ( btype >A %{ STORE("type"); } A C :> "." ( "." %extend | "" ) " "+ ) >B %{ STORE_B("fallback"); } %SET_ATTR ; all_btypes = btype | non_ac_btype; next_block_start = ( all_btypes A_noactions C_noactions :> "."+ " " ) >A @{ fexec(reg); } ; double_return = LF [ \t]* LF ; block_end = ( double_return | EOF ); ftype = ( "fn" >A %{ STORE("type"); } digit+ >A %{ STORE("id"); } ) ; - footnote_start = ( ftype A C :> dotspace ) ; + footnote_start = ( ftype A C :> dotspace ) %SET_ATTR ; ul = "*" %{NEST(); SET_LIST_TYPE("ul");}; ol = "#" %{NEST(); SET_LIST_TYPE("ol");}; - ul_start = ( ul | ol )* ul A C :> " "+ ; - ol_start = ( ul | ol )* ol N A C :> " "+ ; + ul_start = ( ul | ol )* ul A C :> " "+ %SET_ATTR; + ol_start = ( ul | ol )* ol N A C :> " "+ %SET_ATTR ; list_start = " "* ( ul_start | ol_start ) >{RESET_NEST();} ; dt_start = "-" . " "+ ; dd_start = ":=" ; @@ -56,12 +56,12 @@ # tables para = ( default+ ) -- LF ; btext = para ( LF{2} )? ; - tddef = ( D? S A C :> dotspace ) ; + tddef = ( D? S A C :> dotspace ) %SET_ATTR ; td = ( tddef? btext >A %T :> "|" >{PASS(table, "text", "td");} ) >X ; - trdef = ( A C :> dotspace ) ; + trdef = ( A C :> dotspace ) %SET_ATTR ; tr = ( trdef? "|" %{INLINE(table, "tr_open");} td+ ) >X %{INLINE(table, "tr_close");} ; trows = ( tr (LF >X tr)* ) ; - tdef = ( "table" >X A C :> dotspace LF ) ; + tdef = ( "table" >X A C :> dotspace LF ) %SET_ATTR ; table = ( tdef? trows >{CLEAR(table); INLINE(table, "table_open"); RESET_REG();} ) ; # info diff --git a/spec/differs/inline.rb b/spec/differs/inline.rb index deefafbd..caab1552 100644 --- a/spec/differs/inline.rb +++ b/spec/differs/inline.rb @@ -16,7 +16,7 @@ def initialize(options) } def diff_as_string(data_new, data_old) - output = "" + output = "\e[0m" last_action = nil sdiff = Diff::LCS.sdiff(data_old, data_new) sdiff.each do |change| diff --git a/spec/fixtures/table.yml b/spec/fixtures/table.yml index 1336c06e..54440478 100644 --- a/spec/fixtures/table.yml +++ b/spec/fixtures/table.yml @@ -346,3 +346,25 @@ html: |- 3 +--- +name: with cell attributes +in: |[en]. lang-ok|{color:red;}. style-ok|(myclass). class-ok| +html: |- + + + + + + +
lang-okstyle-okclass-ok
+--- +name: with improper cell attributes +in: |[en]lang-bad|{color:red;}style-bad|(myclass)class-bad| +html: |- + + + + + + +
[en]lang-bad{color:red;}style-bad(myclass)class-bad
diff --git a/spec/spec.opts b/spec/spec.opts new file mode 100644 index 00000000..b921ac63 --- /dev/null +++ b/spec/spec.opts @@ -0,0 +1,3 @@ +--color +--require=spec/differs/inline.rb +--diff=RedClothDiffers::Inline \ No newline at end of file