Skip to content

Commit

Permalink
Fix image URLs and image titles so they can contain parentheses. [#71
Browse files Browse the repository at this point in the history
…state:resolved]
  • Loading branch information
jgarber committed Feb 13, 2009
1 parent 66edc78 commit f6306a1
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 60 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
@@ -1,5 +1,7 @@
=== Edge

* Image URLs and image titles can now contain parentheses. #71

* Handle caps properly in link titles. #77

* Remove extra preformatted line breaks after extended block code. #79
Expand Down
1 change: 1 addition & 0 deletions ext/redcloth_scan/redcloth.h
Expand Up @@ -44,6 +44,7 @@ VALUE red_pass_code(VALUE, VALUE, VALUE, ID);
#define PASS(H, A, T) rb_str_append(H, red_pass(self, regs, ID2SYM(rb_intern(A)), rb_intern(T), refs))
#define PARSE_ATTR(A) red_parse_attr(self, regs, ID2SYM(rb_intern(A)))
#define PARSE_LINK_ATTR(A) red_parse_link_attr(self, regs, ID2SYM(rb_intern(A)))
#define PARSE_IMAGE_ATTR(A) red_parse_image_attr(self, regs, ID2SYM(rb_intern(A)))
#define PASS_CODE(H, A, T, O) rb_str_append(H, red_pass_code(self, regs, ID2SYM(rb_intern(A)), rb_intern(T)))
#define ADD_BLOCK() \
rb_str_append(html, red_block(self, regs, block, refs)); \
Expand Down
27 changes: 1 addition & 26 deletions ext/redcloth_scan/redcloth_attributes.c.rl
Expand Up @@ -51,30 +51,5 @@ redcloth_link_attributes(self, str)
{
StringValue(str);
int cs = redcloth_attributes_en_link_says;
VALUE regs = redcloth_attribute_parser(cs, self, RSTRING_PTR(str), RSTRING_PTR(str) + RSTRING_LEN(str) + 1);

// Store title/alt
VALUE name = rb_hash_aref(regs, ID2SYM(rb_intern("name")));
if ( name != Qnil ) {
char *p = RSTRING_PTR(name) + RSTRING_LEN(name);
if (*(p - 1) == ')') {
char level = -1;
p--;
while (p > RSTRING_PTR(name) && level < 0) {
switch(*(p - 1)) {
case '(': ++level; break;
case ')': --level; break;
}
--p;
}
VALUE title = rb_str_new(p + 1, RSTRING_PTR(name) + RSTRING_LEN(name) - 2 - p );
if (p > RSTRING_PTR(name) && *(p - 1) == ' ') --p;
if (p != RSTRING_PTR(name)) {
rb_hash_aset(regs, ID2SYM(rb_intern("name")), rb_str_new(RSTRING_PTR(name), p - RSTRING_PTR(name) ));
rb_hash_aset(regs, ID2SYM(rb_intern("title")), title);
}
}
}

return regs;
return redcloth_attribute_parser(cs, self, RSTRING_PTR(str), RSTRING_PTR(str) + RSTRING_LEN(str) + 1);
}
28 changes: 1 addition & 27 deletions ext/redcloth_scan/redcloth_attributes.java.rl
Expand Up @@ -90,32 +90,6 @@ public class RedclothAttributes extends RedclothScanService.Base {

ByteList bl = str.convertToString().getByteList();
int cs = redcloth_attributes_en_link_says;
IRubyObject regs = new RedclothAttributes(cs, self, bl.bytes, bl.begin, bl.realSize).parse();

// Store title/alt
IRubyObject name = ((RubyHash)regs).aref(runtime.newSymbol("name"));
if ( !name.isNil() ) {
String s = name.convertToString().toString();
int p = s.length();
if (s.charAt(p - 1) == ')') {
int level = -1;
p--;
while (p > 0 && level < 0) {
switch(s.charAt(p - 1)) {
case '(': ++level; break;
case ')': --level; break;
}
--p;
}
IRubyObject title = runtime.newString(s.substring(p + 1, s.length() - 1));
if(p > 0 && s.charAt(p - 1) == ' ') --p;
if(p != 0) {
((RubyHash)regs).aset(runtime.newSymbol("name"), runtime.newString(s.substring(0, p)));
((RubyHash)regs).aset(runtime.newSymbol("title"), title);
}
}
}

return regs;
return new RedclothAttributes(cs, self, bl.bytes, bl.begin, bl.realSize).parse();
}
}
38 changes: 37 additions & 1 deletion ext/redcloth_scan/redcloth_inline.c.rl
Expand Up @@ -36,10 +36,46 @@ VALUE
red_parse_link_attr(VALUE self, VALUE regs, VALUE ref)
{
VALUE txt = rb_hash_aref(regs, ref);
VALUE new_regs = redcloth_link_attributes(self, txt);
VALUE new_regs = red_parse_title(redcloth_link_attributes(self, txt), ref);

return rb_funcall(regs, rb_intern("update"), 1, new_regs);
}

VALUE
red_parse_image_attr(VALUE self, VALUE regs, VALUE ref)
{

return red_parse_title(regs, ref);
}

VALUE
red_parse_title(VALUE regs, VALUE ref)
{
// Store title/alt
VALUE txt = rb_hash_aref(regs, ref);
if ( txt != Qnil ) {
char *p = RSTRING_PTR(txt) + RSTRING_LEN(txt);
if (*(p - 1) == ')') {
char level = -1;
p--;
while (p > RSTRING_PTR(txt) && level < 0) {
switch(*(p - 1)) {
case '(': ++level; break;
case ')': --level; break;
}
--p;
}
VALUE title = rb_str_new(p + 1, RSTRING_PTR(txt) + RSTRING_LEN(txt) - 2 - p );
if (p > RSTRING_PTR(txt) && *(p - 1) == ' ') --p;
if (p != RSTRING_PTR(txt)) {
rb_hash_aset(regs, ref, rb_str_new(RSTRING_PTR(txt), p - RSTRING_PTR(txt) ));
rb_hash_aset(regs, ID2SYM(rb_intern("title")), title);
}
}
}
return regs;
}

VALUE
red_pass_code(VALUE self, VALUE regs, VALUE ref, ID meth)
{
Expand Down
36 changes: 35 additions & 1 deletion ext/redcloth_scan/redcloth_inline.java.rl
Expand Up @@ -53,10 +53,40 @@ public class RedclothInline extends RedclothScanService.Base {

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);
IRubyObject new_regs = red_parse_title(RedclothAttributes.link_attributes(self, txt), ref);
return regs.callMethod(runtime.getCurrentContext(), "update", new_regs);
}

public IRubyObject red_parse_image_attr(IRubyObject self, IRubyObject regs, IRubyObject ref) {
return red_parse_title(regs, ref);
}

public IRubyObject red_parse_title(IRubyObject regs, IRubyObject ref) {
IRubyObject name = ((RubyHash)regs).aref(ref);
if ( !name.isNil() ) {
String s = name.convertToString().toString();
int p = s.length();
if (s.charAt(p - 1) == ')') {
int level = -1;
p--;
while (p > 0 && level < 0) {
switch(s.charAt(p - 1)) {
case '(': ++level; break;
case ')': --level; break;
}
--p;
}
IRubyObject title = runtime.newString(s.substring(p + 1, s.length() - 1));
if(p > 0 && s.charAt(p - 1) == ' ') --p;
if(p != 0) {
((RubyHash)regs).aset(ref, runtime.newString(s.substring(0, p)));
((RubyHash)regs).aset(runtime.newSymbol("title"), title);
}
}
}
return 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));
}
Expand All @@ -69,6 +99,10 @@ public class RedclothInline extends RedclothScanService.Base {
red_parse_link_attr(self, regs, runtime.newSymbol(A));
}

public void PARSE_IMAGE_ATTR(String A) {
red_parse_image_attr(self, regs, runtime.newSymbol(A));
}

private int opts;

public RedclothInline(IRubyObject self, byte[] data, int p, int pe, IRubyObject refs) {
Expand Down
8 changes: 4 additions & 4 deletions ext/redcloth_scan/redcloth_inline.rl
Expand Up @@ -18,8 +18,8 @@
bracketed_link = ( '["' link_says '":' %A uri %{ STORE("href"); } :> "]" ) >X ;

# images
image_src = ( uri ) >A %{ STORE("src"); } ;
image_is = ( A2 C ". "? image_src :> title? ) ;
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 ;
Expand Down Expand Up @@ -95,8 +95,8 @@

main := |*

image { INLINE(block, "image"); };
bracketed_image { INLINE(block, "image"); };
image { PARSE_IMAGE_ATTR("src"); INLINE(block, "image"); };
bracketed_image { PARSE_IMAGE_ATTR("src"); INLINE(block, "image"); };

link { PARSE_LINK_ATTR("name"); PASS(block, "name", "link"); };
bracketed_link { PARSE_LINK_ATTR("name"); PASS(block, "name", "link"); };
Expand Down
17 changes: 16 additions & 1 deletion test/images.yml
Expand Up @@ -251,4 +251,19 @@ html: <p>This is an <img src="image.jpg" alt="" /> you see.</p>
---
name: with link in square brackets
in: This is an [!image.jpg!:http://example.com/] you see.
html: <p>This is an <a href="http://example.com/"><img src="image.jpg" alt="" /></a> you see.</p>
html: <p>This is an <a href="http://example.com/"><img src="image.jpg" alt="" /></a> you see.</p>
---
name: url containing parentheses
in: "!http://commons.wikimedia.org/wiki/File:Rubis_sur_calcite_2(Vietnam).jpg!"
html: |-
<p><img src="http://commons.wikimedia.org/wiki/File:Rubis_sur_calcite_2(Vietnam).jpg" alt="" /></p>
---
name: with alt and url containing parentheses
in: "!http://commons.wikimedia.org/wiki/File:Rubis_sur_calcite_2(Vietnam).jpg(a big rock)!"
html: |-
<p><img src="http://commons.wikimedia.org/wiki/File:Rubis_sur_calcite_2(Vietnam).jpg" title="a big rock" alt="a big rock" /></p>
---
name: with link that contains parentheses
in: "!image.jpg(Alt text with (parentheses).)!"
html: |-
<p><img src="image.jpg" title="Alt text with (parentheses)." alt="Alt text with (parentheses)." /></p>

0 comments on commit f6306a1

Please sign in to comment.