tildeio / htmlbars

A variant of Handlebars that emits DOM and allows you to write helpers that manipulate live DOM nodes
MIT License
1.61k stars 193 forks source link

Character Entities do not render in attributes #467

Open justinaray opened 8 years ago

justinaray commented 8 years ago

May have been previously reported or may just not be supported, however, Character Entities do not appear to be rendered correctly in attributes.

No combination of SafeString, {{, or {{{ seems to work in attributes.

https://ember-twiddle.com/ea4439dcf4e7cce49e09f198aa01550c?openFiles=templates.application.hbs%2C

mmun commented 8 years ago

Thanks for reporting the issue. It's probably a problem at the tokenizer stage, i.e. in https://github.com/tildeio/simple-html-tokenizer. Would you be able to make a failing test there (or take a stab at fixing it?)

rwjblue commented 8 years ago

I'm not so sure here. The example from the twiddle is:

<button title="{{testNoSs}}"></button>

SHT is likely not involved here since it is only used for entities found while parsing at build time like this:

<button title="One &amp; Two"></button>

At runtime we are generally setting properties on the element (falling back to setting attributes when required). I suspect that something like the following does not parse the HTML char ref:

var el = document.createElement('button');
el.title = "One &amp; Two";
mmun commented 8 years ago

ah, I misunderstood the issue. Rob is right. I didn't realize it was concerning dynamic attributes.

justinaray commented 8 years ago

Updated the twiddle to add a js-based dynamic set.

Not sure if it exercises it in the exact way you are thinking about @rwjblue as it is simply updating existing buttons. In the update case at least, seems to support both raw ampersand and html char ref.

https://ember-twiddle.com/ea4439dcf4e7cce49e09f198aa01550c?openFiles=templates.application.hbs%2Ctemplates.components.js-entity-attr.hbs

rwjblue commented 8 years ago

As you can see from the updated twiddle, when you do:

    buttons[1].innerHTML = 'Entity: one &amp; two';
    buttons[1].title = 'Entity: one &amp; two';

The HTML char ref in buttons[1].title is not parsed:

screenshot

justinaray commented 8 years ago

d'oh! Can't even use my own twiddle correctly. :facepalm: You're right of course @rwjblue.

In researching this yesterday, I saw an approach utilizing a second node to set the innerHTML and then scraping that for use in the title attr. Probably more trouble/hacky than it's worth, no?

Also learned that & is technically valid in HTML5 as long as it's not ambiguous.

Guess the workaround is to just use raw & when possible?

rwjblue commented 8 years ago

Yes, the simpler fix that you could use in your app is to do something like this:

// app/helpers/translate-html-entities.js
import Ember from 'ember';

let fakeNode;
export default Ember.Helper.helper(function([string]) {
  if (!fakeNode) {
    fakeNode = document.createElement('div');
  }

  let sanitizedString = Ember.Handlebars.Utils.escapeExpression(string);
  fakeNode.innerHTML = sanitizedString;

  return fakeNode.textContent;  
});

Demo: https://ember-twiddle.com/03d0d2a034c4184c2deca6d389c8176a?fileTreeShown=false&openFiles=helpers.translate-html-entities.js%2Ctemplates.components.js-entity-attr.hbs

Note: I did include some rudimentary escaping in that helper, but you should review more closely to ensure it properly handles unsafe content.

justinaray commented 8 years ago

That's great! Above and beyond as usual @rwjblue ! I'll look into the sanitization for use in our app.

Since there's no context of the general mustache output, probably difficult to add this support natively, right? Glimmer might have more context? 👈 just for future consideration

Thanks for all the help!

justinaray commented 8 years ago

For the sake of me future searchers, I have updated the twiddle with solution, examples, link to this issue, etc.

https://ember-twiddle.com/ea4439dcf4e7cce49e09f198aa01550c?openFiles=helpers.translate-html-entities.js%2Ctemplates.components.js-entity-attr.hbs