Skip to content

Document parsing of (X)HTML entities, or drop it even? #4

Closed

Description

@syranide

We should probably document how (X)HTML entities are parsed.

However, I can imagine dropping HTML entities instead and adopt the escaping used by JS-strings, i.e. bla \< \{ \u1234 bla. To me it would make sense in many ways:

  1. JSX is the JavaScript-equivalent of HTML (it's not HTML), using JavaScript syntax seems preferable.
  2. JSX explicitly disallows inline HTML in-favor of just JSXElements and JSXText, HTML entities seem a bit malplaced in that context.
  3. It's currently <a href="&amp;\" /> vs <a href={'&\\'} /> which is kind of awkward.

The downside of dropping HTML entities is obviously that you wouldn't be able to copy-paste HTML and it could be a mental disconnect for a lot of users. But I think it makes a lot of sense from a technical perspective.

I think it makes even more sense if you look beyond HTML. Why would you be using HTML entities for non-HTML frontends? Like iOS, QT, etc.

Activity

  1. gajus commented on Sep 2, 2015

    @gajus

    The downside of dropping HTML entities is obviously that you wouldn't be able to copy-paste HTML and it could be a mental disconnect for a lot of users. But I think it makes a lot of sense from a technical perspective.

    React has already chose to deviate from HTML. react/react#2781

    and

    Third, our thinking is that JSX's primary advantage is the symmetry of matching closing tags which make code easier to read, not the direct resemblance to HTML or XML. It's convenient to copy/paste HTML directly, but other minor differences (in self-closing tags, for example) make this a losing battle and we have a HTML to JSX converter to help you anyway. Finally, to translate HTML to idiomatic React code, a fair amount of work is usually involved in breaking up the markup into components that make sense, so changing class to className is only a small part of that anyway.

    from @spicyj answer https://www.quora.com/Why-do-I-have-to-use-className-instead-of-class-in-ReactJs-components-done-in-JSX/answer/Ben-Alpert

    Therefore, I am in favour of dropping HTML entity support.

  2. RReverser commented on Sep 2, 2015

    @RReverser
    Contributor

    React has already chose to deviate from HTML.

    @gajus From HTML - yes, from XML - not so much (apart from JS injections).

  3. gajus commented on Sep 2, 2015

    @gajus

    Well, I am biased. I want JSX to allow template strings in JSXAttributeValue. The fate of that issue depends on whether HTML entity support is dropped or not. This is another consideration to have when deciding on this.

  4. RReverser commented on Sep 2, 2015

    @RReverser
    Contributor

    Do those two braces around really mean that much to you to change two behaviors? 😄

  5. gajus commented on Sep 2, 2015

    @gajus

    One is HTML entities. Whats the second?

  6. RReverser commented on Sep 2, 2015

    @RReverser
    Contributor

    Template strings without braces on their own.

  7. gajus commented on Sep 2, 2015

    @gajus

    I think that since JSX is present in JS and that it is in essence a syntactic sugar for createElement, then it should behave in the same way, i.e.,

    React.createElement(`div`, {className: `foo-${foo}`}, `bar-${bar}`);

    should not be different from

    <div className=`foo-${foo}`>`bar-${bar}`</div>
  8. RReverser commented on Sep 2, 2015

    @RReverser
    Contributor

    Then we return to questions like numeric literals, object and array literals and so.

  9. gajus commented on Sep 2, 2015

    @gajus

    @RReverser Explain?

    If I understand correctly, then yes, objects, strings, null and numbers (thats all there is) should be valid attribute values.

    <div foo=null />
    <div foo=123 />
    <div foo=() => {} />
    <div foo=({}) />

    Does this clash with anything in the spec?

  10. RReverser commented on Sep 2, 2015

    @RReverser
    Contributor

    It doesn't clash, but increases complexity for purely aesthetic reason.

  11. gajus commented on Sep 2, 2015

    @gajus

    That is true. But consistency/conventions lower bug count (sorry, no reference for this stats). Assuming that is true, then if the rest of the code base is using convention X (template string in this case), it would make sense if JSX supported that too.

  12. RReverser commented on Sep 3, 2015

    @RReverser
    Contributor

    That arguments has two sides - on one hand, you're increasing consistency for those who work with JS for developing logic, an on another you at the same time decrease consistency and familiarity for those who develop views (HTML/XML coders).

  13. sebmarkbage commented on Sep 3, 2015

    @sebmarkbage
    Contributor

    I think that it probably only makes sense to do this if we also drop it from JSXText or drop JSXText completely, as described in #8 and #35 .

  14. syranide commented on Sep 3, 2015

    @syranide
    ContributorAuthor

    @sebmarkbage I'd say #28 is a candidate for otherwise keeping JSX as it is and being able to drop XHTML entities.

    That arguments has two sides - on one hand, you're increasing consistency for those who work with JS for developing logic, an on another you at the same time decrease consistency and familiarity for those who develop views (HTML/XML coders).

    IMHO the problem is that it is inconsistent, it would be fine if <a href="&nbsp;" /> was the same as <a href={"&nbsp;"} />, which it isn't... to be honest I'm quite sure that many don't even realize this difference exists.

  15. 16 remaining items

  16. sebmarkbage commented on Sep 25, 2015

    @sebmarkbage
    Contributor

    Or backslashes...

  17. sebmck commented on Sep 25, 2015

    @sebmck

    Oh right. I've actually broken backslashes in JSX attributes before in Babel and it took over 7 days for someone to notice and file an issue: babel/babel#2114.

  18. NekR commented on Sep 25, 2015

    @NekR

    I believe that entities (or other specific things) should be handled by the renderer which transforms JSX-output to HTML DOM/HTML string, but not by the transformer which transforms JSX to JSX-output.

  19. syranide commented on Sep 25, 2015

    @syranide
    ContributorAuthor

    @NekR It would then apply to all strings equally so even user input would be subject to HTML entity decoding (aside from it being a runtime cost too), you definitely do not want that.

  20. NekR commented on Sep 25, 2015

    @NekR

    @syranide what is user input in JSX? I did not say everything in runtime should be parsed with entities.

    class EntitiesString {
      constructor(str) {
        this.str = myLibraryDoesHTMLEntytiesParsingHere(str);
      }
    
      toString() {
        return str;
      }
    }
    
    <div>{ new EntitiesString('&nbsp;') }</div>
  21. syranide commented on Sep 25, 2015

    @syranide
    ContributorAuthor

    ...by the renderer which transforms JSX-output to HTML DOM/HTML string...

    @NekR I interpreted that differently. IMHO what you are proposing is runtime decoding (which is for everyone to decide on their own) and outside this discussion about entities/escape codes in JSX source code. EDIT: That is to say, JSX needs to support escaping to some extent (like { and <), regardless of whether or not JSX will drop support for HTML entities.

  22. NekR commented on Sep 25, 2015

    @NekR

    @NekR I interpreted that differently.

    Yes, I meanе that renderers are responsible for parsing entities. One could support EntitiesString, other don't.

    . IMHO what you are proposing is runtime decoding (which is for everyone to decide on their own) and outside this discussion about entities/escape codes in JSX source code.

    Of course I do not propose such decoding method here for JSX, it's implementation detail of JSX consumers. What I am saying is that entities parsing on a transpilation stage is not needed (because of runtime possibilities) and hence it's in scope of this discussion, right?

    EDIT: That is to say, JSX needs to support escaping to some extent (like { and <), regardless of whether or not JSX will drop support for HTML entities.

    Hmm.. <div>{ '{test}' } { '<div>' }</div> seems like it's escaped?

  23. syranide commented on Sep 25, 2015

    @syranide
    ContributorAuthor

    What I am saying is that entities parsing on a transpilation stage is not needed (because of runtime possibilities) and hence it's in scope of this discussion, right?

    IMHO no, entity parsing during transpilation and runtime decoding of entities are "complementary". Runtime decoding of static source code strings in this context is inefficient and cumbersome.

    Hmm.. <div>{ '{test}' } { '<div>' }</div> seems like it's escaped?

    Produces React.createElement('div', null, '{test}', '<div>') and yeah it will visually render the same as it would if you had {'{test}<div>'}, but it's not the same. So yes, you can work around the problem that way (but you're inserting a JS string, not escaping in JSX). However, this all-or-nothing if you don't want to affect runtime behavior is really inconvenient, especially considering <div>{'&nbsp;'}</div> is very different from <div>&nbsp;</div> at current.

  24. NekR commented on Sep 25, 2015

    @NekR

    IMHO no, entity parsing during transpilation and runtime decoding of entities are "complementary". Runtime decoding of static source code strings in this context is inefficient and cumbersome.

    Sorry, but topic is "Document parsing of (X)HTML entities, or drop it even?" and I am saying: Drop it. How it's not related? Runtime parsing was suggested as a solution. Some one who do not want runtime solution could write plugin which will pre-parse entities to JS escapes or something like that. But you are not even listening to me. What I am saying is that it makes sense to have JSXText to equal to simple JS string (sugar). Like these two should be equivalent: <div>&nbsp;</div> and <div>{'&nbsp;'}</div>.

    Runtime decoding of static source code strings in this context is inefficient and cumbersome.

    This is only problem of React since it's doing re-render on every move. I use JSX in a different way and it's perfectly fine for me.

    So yes, you can work around the problem that way (but you're inserting a JS string, not escaping in JSX). However, this all-or-nothing if you don't want to affect runtime behavior is really inconvenient, especially considering <div>{'&nbsp;'}</div> is very different from <div>&nbsp;</div> at current.

    Why we need to do work arounds or escape JSX? Just have JS string everywhere. I do not see any difference here except that transpiration entities parsing is benefit for React.

    P.S. Interesting that you made this repository public and asked for feedback from non-React implementations and when people came here with their opinions, you say: "This is not related". Just make it private repository and then no problem with "not related".

  25. syranide commented on Sep 25, 2015

    @syranide
    ContributorAuthor

    P.S. Interesting that you made this repository public and asked for feedback from non-React implementations and when people came here with their opinions, you say: "This is not related". Just make it private repository and then no problem with "not related".

    @NekR I'm only one collaborator of many, these are my opinions. Feel free to refute them, but there are many things to consider. If I didn't care about your opinion I wouldn't have responded.

    Sorry, but topic is "Document parsing of (X)HTML entities, or drop it even?" and I am saying: Drop it. How it's not related? Runtime parsing was suggested as a solution.

    Decoding at compile-time (source code and static strings) and run-time (dynamic strings) can both co-exist and make sense. In the context of language design, run-time decoding being possible is not an argument against a syntax feature, nor vice versa. They are solutions to different problems.

    Yes, we both agree that HTML entities should be dropped, that's not what I objected to. I undoubtedly think that is the way forward, but the holes left behind by dropping HTML entities still needs to be considered, runtime decoding is not it.

  26. NekR commented on Sep 25, 2015

    @NekR

    In the context of language design, run-time decoding being possible is not an argument against a syntax feature, nor vice versa.

    I saw many such arguments and decisions in TC-39, but okay, you do not accepts this as argument then nevermind.

    runtime decoding is not it.

    Why? Where is a big performance problem with it except of React contact re-render?

  27. dantman commented on Jan 5, 2016

    @dantman

    Personally I don't think the DX argument is valid. And that is not through an expectation of everyone using character maps, etc...

    JSX is JavaScript and it doesn't really make sense that the solution when writing JS+JSX to "I can't type © with my keyboard" is "You can use &copy; in JSX strings but you're SOL in every other part of the JS". Which of course leads to a mess like:

    <Foo
        label="I can &copy; here"
        legal={__('This site \u00A9 2016 Acme Media Inc.')} />

    Same code. But you can use &copy; in one part of the JSX and you can't in the other because you have something – which doesn't have to be i18n, it can be collection processing or anything else – that requires that one of the strings be part of JS space and not JSX space.

    If this is a problem, it is a problem universal to JS and not one that should have a JSX-only fix.

    Rather I think the solution is to embrace the fact we're writing JS and fix this with JS. Specifically, given #25 I think the solution to "I can't type © with my keyboard and don't want to use a character map, C&P, or use some other tooling" is this.

    var ent = require('character-entities');
    
    <Foo
        label=`I can ${ent.copy} here`
        legal={_(`This site ${ent.copy} 2016 Acme Media Inc.`)} />
  28. added a commit that references this issue on Mar 1, 2022
    ccf19c5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Impl RealityReality that the spec does not capture

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions