Skip to content

Bug: coffee code as html attribute value #26

bogdan opened this Issue May 8, 2012 · 6 comments

2 participants

bogdan commented May 8, 2012

Template code

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

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 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.


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 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 - it's client side templating pretty similar to haml-coffee. They solved this problem somehow. Probably it can help.


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 added a commit that closed this issue May 8, 2012
@netzpirat Rewrite attribute parsing to be more robust. (Closes #26)
This rewrites the HAML attribute tag parsing to move some parse logic
from the regexp to the code, which allows more robust parsing when it
comes to inline CoffeeScript detection.

Previously the attributes key and value are purely parsed with a regexp,
expect the data attributes.

The rewrite combines the data attribute parsing and the regexp based
attribute parsing by simply splitting the attributes by the chosen key
format and further process the key and values.

This allows more complex CoffeeScript in the attributes like

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

which was not possible before.
@netzpirat netzpirat closed this in fa150b4 May 8, 2012
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
Something went wrong with that request. Please try again.