4

Do you ever escape single quotes in template toolkit for necessary javascript handlers? If so, how do you do it.

[% SET s = "A'B'C" %]

<a href="/abc.html" onclick="popup('[% s | html_entity %]')">ABC</a>

html_entity obviously doesn't work because it only handles the double quote. So how do you do it?

simbabque
  • 53,749
  • 8
  • 73
  • 136
Zach
  • 157
  • 3
  • 7

5 Answers5

8

I don't use the inlined event handlers -- for the same reason I refuse to use the style attribute for css. Jquery just makes it to easy to do class="foo" on the html and $('.foo').click( function () {} ), in an external .js file.

But, for the purpose of doing my best to answer this question, check out these docs on Template::Filter for the ones in core.

It seems as if you could do [% s | replace( "'", "\\'" ) %], to escape single quotes. Or you could probably write a more complex sanitizing javascript parser that permits only function calls, and make your own Template::Filter

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
  • 3
    Although I agree with your advice, I've just realized the real solution has another backslash: [% s | replace( "'", "\\'" ) %] – Zach Aug 12 '10 at 15:30
  • Confirmed; the single backslash is a no-op, replacing the apostrophe with another apostrophe. For anyone else who finds this answer, use the double backslash. Otherwise, your code may lead to an emergency response team being formed to investigate why the Javascript on the production site suddenly stopped working and push an emergency changeset. Ahem. – BlairHippo Nov 08 '21 at 18:03
5

2018 update for reference:

TT has a method for this called squote for escaping single quotes and dquote for double quotes.

[% tim = "Tim O'Reilly" %]
[% tim.squote %]          # Tim O\'Reilly

Questioned link would be something like:

<a href="/abc.html" onclick="popup('[% s.squote %]')">ABC</a>

http://www.template-toolkit.org/docs/manual/VMethods.html#section_squote

pizzamonster
  • 1,141
  • 10
  • 9
1

Perl isn't my strongest language... But!

Easiest way I've found is to use the JSON module. In a module called JS.pm or something:

use JSON;

sub encode () {
   my $self = shift;
   my $string = shift;

   $json = JSON->new->allow_nonref;

   return $json->encode( $string );
}

More here: http://search.cpan.org/~makamaka/JSON-2.90/lib/JSON.pm

Then in your template:

[% use JS; %]

<script>
  var escaped_string = [% JS.encode( some_template_variable ) %];
</script>
KeatsKelleher
  • 10,015
  • 4
  • 45
  • 52
  • 1
    The OP doesn't say this is the underlying issue, but it could be an X-Y problem, of course. You're reinventing the wheel here though, there's already a mature plugin for TT called Template::Plugin::JSON – RET Nov 20 '14 at 22:27
1

You can try: popup('[% s | html %]').

Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438
Ky6uk
  • 1,067
  • 3
  • 16
  • 26
0

Remember to double-escape the slash in the replacement, otherwise it will be interpreted as escaping the apostrophe.

[% string.replace( "'", "\\'" ) %]
HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133