highlightjs / highlight.js

JavaScript syntax highlighter with language auto-detection and zero dependencies.
https://highlightjs.org/
BSD 3-Clause "New" or "Revised" License
23.38k stars 3.56k forks source link

(javscript/typescript) improve JSX comment highlighting #1625

Open brigand opened 6 years ago

brigand commented 6 years ago

Live example on the npm website.

react-ck5 readme on npmjs.com

  state = { editorState: null }
  render() {
    return (
      <div>
        <ClassicBasic
          value={/* ... */}
          onChange={/* ... */}
          editorState={this.state.editorState}
          onStateChange={editorState => this.setState({ editorState })}
        />
        <button
          // prevent editor losing focus
          onMouseDown={e => e.preventDefault()}
          onClick={() => {
            this.setState(s => update(s, 'editorState.bold.value', value => !value));
          }}
        >
          Toggle bold
        </button>
      </div>
    );
  }

Expected behavior

Comments in jsx attribute positions should look like comments. The spec isn't explicit about it, but babel, acorn, typescript, and flow all support the syntax.


Thanks!

original issue

nickmccurdy commented 6 years ago

I'm pretty sure this is illegal JSX syntax, the spec doesn't mention using // comments and this might be typo or something specific to your JSX transpiler, but I don't think it's standard.

Edit: Apparently it is legal but only between <>, not between ><.

joshgoebel commented 4 years ago

Edit: Apparently it is legal but only between <>, not between ><.

So in that case it acts like a Javascript style comment... that probably also pours a little rainstorm on the idea of trying to use "html/xml" as the internal parser for these blocks though.

Seeming more and more like we need a dedicated jsx grammar.

joshgoebel commented 3 years ago

Screen Shot 2020-10-01 at 2 25 57 AM

What I have working so far built on top of the new consolidated JS/TS stuff... wasn't that hard either.

joshgoebel commented 3 years ago

@allejo @egor-rogov

There is a weirdness here though... we're inside "tag" (which has it's own styling) and when we hit a {} pair then we have embedded JS... which should go back to the default "unhighlighted" color... not the tag color... so to do this we really need a new css class... reset or default or something that is pinned to whatever .hljs is... to allow content inside of a tag to do a "reset" to get back to the "parent" style...

Any thoughts on this or naming?

joshgoebel commented 3 years ago

Some dark magic:

            contains: [
              HTML_TAG,
              XML_ENTITIES,
              {
                begin: /[^<]+/, // eat everything up until the next <
                end: /./, // to avoid 0-width match error
                // always return, this rule is not intended to consume
                // anything, just bookend the JSX/HTML segment
                returnEnd: true,
                returnBegin: true,
                endsParent:true, // when we've paired all HTML tags, we endParent
                "on:begin": (_, resp) => {
                  if (nestedTagCount !== 0) resp.ignoreMatch();
                }
              }
            ]

It's likely we just need a response.endsParent() that could be called from HTML_TAG's on:end rule (to allow modes to conditionally end the parent)... but still it's cool this seems to work great. :-)

allejo commented 3 years ago

@allejo @egor-rogov

There is a weirdness here though... we're inside "tag" (which has it's own styling) and when we hit a {} pair then we have embedded JS... which should go back to the default "unhighlighted" color... not the tag color... so to do this we really need a new css class... reset or default or something that is pinned to whatever .hljs is... to allow content inside of a tag to do a "reset" to get back to the "parent" style...

Any thoughts on this or naming?

What about hljs-unset following CSS's unset keyword?