foundation / panini

A super simple flat file generator.
Other
592 stars 104 forks source link

[Workaround Provided] Helper escaping issue - text from data escaped, text from context not escaped #87

Closed chrisbloom7 closed 7 years ago

chrisbloom7 commented 7 years ago

I have the following files:

# pages/test.html

---
test: <p>This is b <b>test</b></p>

---
{{#html-test-a}}<p>This is a <b>test</b></p>{{/html-test-a}}
{{html-test-b}}
# helpers/html-test-a.js
module.exports = function(content) {
  return content.fn(this);
}
# helpers/html-test-b.js
module.exports = function(context) {
  return context.data.root.test;
}

The result is that the output of html-test-a is not escaped, but the output from html-test-b is. Why is that the case? This happens regardless of where the data is defined (data file or Front Matter), and regardless of if the data is concatenated onto another string or not. Console logging of the data from inside the helper method shows the HTML is unescaped (<p>This is b <b>test</b></p>). Why and how does the helper care where the input originates from?

Output

kevmul commented 7 years ago

Hello chrisbloom7, I just figured this out on my issue Non-escaped string #86.

All you need to do is:

{{{ html-test-b }}}

Note that there are three brackets. This works on all strings it seems, and returns the correct html.

chrisbloom7 commented 7 years ago

@kevmul I need it to go through a helper because it's part of our i18n process and we do some processing on the output.

chrisbloom7 commented 7 years ago

@kevmul Nevermind, I think I misunderstood. I'll give that a try

chrisbloom7 commented 7 years ago

@kevmul Confirmed, thanks for that

To Panini admins - that's a bit confusing, especially since the first form doesn't escape output. Would be helpful to explain that in the README, but better to make it uniform IMO.

marvinhuebner commented 7 years ago

You can use the Handlebars Method SafeString. This marks the return as already escaped.

Here is an example:

helpers/sprite.js

const Handlebars = require('handlebars');

module.exports = function(symbol) {

    let html = `
        <span class="sprite sprite--${symbol}">
            <svg viewBox="0 0 1 1"><use xlink:href='assets/sprite/sprite.svg#${symbol}'></use></svg>
        </span>
    `;

    return new Handlebars.SafeString(html);
};

And use it like this in your template:

index.html

{{sprite '500px'}}
gakimball commented 7 years ago

Thanks for the example @marvinhuebner, this is how Handlebars works so it's not something Panini is going to change. For more info: