bminer / node-blade

Blade - HTML Template Compiler, inspired by Jade & Haml
Other
320 stars 28 forks source link

variable interpolation broken #120

Closed punund closed 11 years ago

punund commented 11 years ago

I don't know when this happened between alpha1 and beta3, but this gives error now:

:javascript
  a = #{b}   // unexpected character "#"
  a = "#{b}" // OK
bminer commented 11 years ago

Yeah... I figured someone would run into this at some point.

Since you are using a "javascript" filter, Blade will try to parse your code using UglifyJs2. Because of this, the JavaScript code in your filter must be valid JavaScript. The unexpected character message is actually UglifyJS complaining. Once your code has been Uglified (at compile time), it is passed to the interpolation routine, which adds some magic code to allow you to substitute your value "b" at run time. Finally, at run time when "b" is available, the value "b" is basically concatenated with the rest of your JavaScript code.

Does that make sense?

bminer commented 11 years ago

Closing this issue for now.

punund commented 11 years ago

In other words, this functionality is gone, and in order to init our client side variables, we have to stick with 3.0.0alpha?

bminer commented 11 years ago

@punund - no, the functionality is still there. Just wrap everything in double quotes like you suggested. Or, are you trying to pass in arbitrary JavaScript code? What's the use case, so I can try to figure out if I need to make any changes before Blade 3.0 stable release. Thanks!

punund commented 11 years ago

The use case is the ability to use any values, not just strings. My code was passing around objects, now I have to either downgrade, or to wrap everything in JSON.stringify()/JSON.parse().

bminer commented 11 years ago

For now, just downgrade as you suggested. I will think of something to fix this and will keep you posted.

bminer commented 11 years ago

@punund - Now you got me thinking... how did you pass in Objects and other values before?

Like this?

- var obj = JSON.stringify({"foo":"bar"});
:javascript
    var obj = #{obj};
    alert(obj.foo);

At any rate, could you shoot over a sample Blade template? I don't even think your JSON.stringify() / JSON.parse() workaround will work in this situation.

punund commented 11 years ago

Before my original example worked. Say, the server passes b, which was assigned an object, and s, which was a string. Template has

:js
  bb = #{b}
  ss = "#{s}"

Earlier both notations worked, now just the last one. Probably there is somewhere JSON.stringify() in your code. Now I'd have to pass {b: JSON.stringify(b)} to the template and use either

:js
  bb = JSON.parse("#{b}")

inline, or invoke JSON.parse() later in the client scripts.

To sum up, I would like to continue being able to pass values of any type, not just strings.

bminer commented 11 years ago

@punund - no problem. This will be fixed in the next version.

bminer commented 11 years ago

Note: support for escaped and unescaped interpolation will be added in the next release. Use !{foobar} in your :javascript filter to get unescaped strings. #{foobar} will escape the contents (i.e. convert double quotes to ", etc.) of foobar at runtime.

punund commented 11 years ago

I think there is a misunderstanding here. If I have an Object in foo, neither notation works:

:js
  a = #{ foo }
  a = !{ foo }
bminer commented 11 years ago

Correct. You have to use JSON.stringify on foo first. Like this....

- var foo = {"foo":"bar"}
:js
        a = !{JSON.stringify(foo)};

Does that make sense?