Search code examples
google-apps-scriptweb-applicationstemplate-engine

Line breaks in templated HTML scriptlets


If I have an HTML file test.html:

<p><?= str ?></p>

And a script function:

var t = HtmlService.createTemplateFromFile("test.html");
t.str = "test\nstring";
var content = t.evaluate().setSandboxMode(...).getContent();
Logger.log(content);

Is there any way to safely replace the newline with an HTML line break? I can use String.prototype.replace() to replace \n with <br/>, but then I'd have to use <?!= to disable the HTML templating engine's contextual escaping. I'm dealing with untrusted input and so I need both escaping and smart handling of line breaks. Having it contextually would be nice. As things stand, I wrote my own escaper, but it is only good for one context.


Solution

  • I see two options for your scenario, the simple one is to forget the substitution entirely and use a <pre> tag, which will render your line breaks (and other formatting chars)

    <pre> <?= str ?> </pre>

    The second is to perform the substitution and sanitize your input with a custom function, so that you can safely use the force print scriptlet.

    In your html:

    <?!= sanitize(str); ?>

    and in your .gs:

    function sanitize(val){
      var vals = val.split('\n'); //split string into an array on newlines
      for(var i in vals){
        vals[i] = Encoder.htmlEncode(vals[i]);  //sanitize each element in the array
      }
      return vals.join('<br />'); //join the elements as a string, with <br /> as glue.
    }
    

    Note, in my example I'm using the library located here to sanitize the strings: http://www.strictly-software.com/scripts/downloads/encoder.js