Bug: coffee code as html attribute value #26

Closed
bogdan opened this Issue May 8, 2012 · 6 comments

Comments

Projects
None yet
2 participants
@bogdan

bogdan commented May 8, 2012

Template code

%a{href: [1,2].join()} OMG
@netzpirat

This comment has been minimized.

Show comment
Hide comment
@netzpirat

netzpirat May 8, 2012

Owner

The problem here is that attributes are separated by a comma and the attribute regexp sees your attribute value as [1, which obviously fails to compile.

I have spent almost two days for these 8 lines of code (most time used to read Mastering Regular Expressions) and I'm unable to provide a solution for this. If you are a regexp expert, feel free to send a pull request.

You can work around this by simply using string interpolation:

%a{ href: "#{ [1,2].join() }" } OMG

I know this is not that elegant, but there is currently no other way to do it within the attribute itself. You could also define a function and call it within the attribute.

I'll update the docs to be more specific on this.

Owner

netzpirat commented May 8, 2012

The problem here is that attributes are separated by a comma and the attribute regexp sees your attribute value as [1, which obviously fails to compile.

I have spent almost two days for these 8 lines of code (most time used to read Mastering Regular Expressions) and I'm unable to provide a solution for this. If you are a regexp expert, feel free to send a pull request.

You can work around this by simply using string interpolation:

%a{ href: "#{ [1,2].join() }" } OMG

I know this is not that elegant, but there is currently no other way to do it within the attribute itself. You could also define a function and call it within the attribute.

I'll update the docs to be more specific on this.

@bogdan

This comment has been minimized.

Show comment
Hide comment
@bogdan

bogdan May 8, 2012

Why do you parse the content of {} when it's a valid peace of coffee-script code that could be just evaluated and only than be converted into html attributes?

coffee> {href: [1,2].join()}
{ href: '1,2' }

I know that there might be overhead with different styles of attributes representation you support. But this might be the way out for current case.

bogdan commented May 8, 2012

Why do you parse the content of {} when it's a valid peace of coffee-script code that could be just evaluated and only than be converted into html attributes?

coffee> {href: [1,2].join()}
{ href: '1,2' }

I know that there might be overhead with different styles of attributes representation you support. But this might be the way out for current case.

@netzpirat

This comment has been minimized.

Show comment
Hide comment
@netzpirat

netzpirat May 8, 2012

Owner

Depending on the compiler setting, the attributes are further processed:

  • Escaping the output
  • Cleaning the output
  • Process boolean values
  • Detect data attributes shortcut notation
Owner

netzpirat commented May 8, 2012

Depending on the compiler setting, the attributes are further processed:

  • Escaping the output
  • Cleaning the output
  • Process boolean values
  • Detect data attributes shortcut notation
@bogdan

This comment has been minimized.

Show comment
Hide comment
@bogdan

bogdan May 8, 2012

Yes, I understand that, but unfortunately there is no way to make it work in all cases with regexp parser.
I can assume that the following won't work as well:

%div{ class: "#{ [@one, @two].join(" ") }" } OMG

And these edge cases may last forever, because programming code is recursive grammar and it can not be parsed with regexp.

Several ways I see now to fix the problem:

  • make all the processing you mentioned after compilation that would require to have some helper method on client side or something like this.
  • Reuse some code from coffee-script parser - don't imagine how exactly this gonna work. But this seems possible.
  • Build algorithm that will find , that are attribute separators - this might require a kind of iterator that will have a brackets counting within and iterate over chars. It needs to determine of , is not wrapped with some brackets pair.

Take a look at https://github.com/visionmedia/jade - it's client side templating pretty similar to haml-coffee. They solved this problem somehow. Probably it can help.

bogdan commented May 8, 2012

Yes, I understand that, but unfortunately there is no way to make it work in all cases with regexp parser.
I can assume that the following won't work as well:

%div{ class: "#{ [@one, @two].join(" ") }" } OMG

And these edge cases may last forever, because programming code is recursive grammar and it can not be parsed with regexp.

Several ways I see now to fix the problem:

  • make all the processing you mentioned after compilation that would require to have some helper method on client side or something like this.
  • Reuse some code from coffee-script parser - don't imagine how exactly this gonna work. But this seems possible.
  • Build algorithm that will find , that are attribute separators - this might require a kind of iterator that will have a brackets counting within and iterate over chars. It needs to determine of , is not wrapped with some brackets pair.

Take a look at https://github.com/visionmedia/jade - it's client side templating pretty similar to haml-coffee. They solved this problem somehow. Probably it can help.

@netzpirat

This comment has been minimized.

Show comment
Hide comment
@netzpirat

netzpirat May 8, 2012

Owner

Even when your example can be re-written as

%div{ class: "#{ [@one, @two].join(' ') }" } OMG

, you're completely right: the pure regexp key value parsing will never be that robust. You made good points, however

  • moving more logic to the render time is something I try to avoid, because I believe general performance is more important than having the possibility to move more logic to the attributes.
  • the CoffeeScript approach is not possible, because there's currently no way to get back the CoffeeScript code from a CoffeeScript parser node (only generation to JavaScript is possible, which I know from my work on Codo). And the template is internally buffered as CoffeeScript and not JavaScript.
  • I don't know Jade, but I guess it's possible because the syntax is valid JavaScript.

In the end I simply moved some logic from the regexp to the code, as your third option :P

Owner

netzpirat commented May 8, 2012

Even when your example can be re-written as

%div{ class: "#{ [@one, @two].join(' ') }" } OMG

, you're completely right: the pure regexp key value parsing will never be that robust. You made good points, however

  • moving more logic to the render time is something I try to avoid, because I believe general performance is more important than having the possibility to move more logic to the attributes.
  • the CoffeeScript approach is not possible, because there's currently no way to get back the CoffeeScript code from a CoffeeScript parser node (only generation to JavaScript is possible, which I know from my work on Codo). And the template is internally buffered as CoffeeScript and not JavaScript.
  • I don't know Jade, but I guess it's possible because the syntax is valid JavaScript.

In the end I simply moved some logic from the regexp to the code, as your third option :P

@netzpirat netzpirat closed this in fa150b4 May 8, 2012

@bogdan

This comment has been minimized.

Show comment
Hide comment
@bogdan

bogdan May 10, 2012

Great job, thanks.

bogdan commented May 10, 2012

Great job, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment