babel / babel-sublime

Syntax definitions for ES6 JavaScript with React JSX extensions.
https://babeljs.io/
MIT License
3.26k stars 170 forks source link

Question on how to short-circuit on ``` for fenced code blocks in Markdown #415

Closed simov closed 3 years ago

simov commented 3 years ago

Not really an issue with this package, but what would be the best way to short-circuit the syntax highlighting on having triple backticks on a new line?

The reason I'm asking is because in certain extended syntaxes for Markdown that support syntax highlighting inside fenced code blocks in some cases the JavaScript syntax fails to exit properly and continues to highlight the following Markdown content instead.

I checked that the default syntax highlighting for JavaScript that ships with ST4 have that issue as well.

Essentially triple backticks shouldn't be considered a valid syntax since you need a function identifier in front of double backtick in order for this to be actually a valid syntax. What happens now both in the default syntax highlighting and this one is that the syntax definition waits for a string literal after the third backtick, but again that won't work in JavaScript anyway.

Thom1729 commented 3 years ago

Can you provide an example of broken Markdown highlighting?

simov commented 3 years ago

md-js

Seems like identifiers, parentheses, comments and probably others. Note that I've been using this highlighter for years in that markdown syntax and I've never seen so many leaks outside of the fenced code blocks. In fact I can't remember seeing any.

Nothing changed on my end other than using the latest stable syntax from this package and that I switched over to ST4. My only assumption so far is that this have something to do with the Babel syntax itself because it is being included inside the markdown fenced code blocks and leaks out.

Thom1729 commented 3 years ago

I can't reproduce.

Are you using a third-party Markdown syntax? If so, it looks like a bug in that syntax. The correct way to embed a language in a code block is via embed/escape; this ensures that the host language can handle the closing backticks before the embedded language even sees them. (It also uses a lot less memory than with_prototype and avoids some other problems as well).

If it is a bug with a third-party Markdown syntax, I don't think it would make sense to fix it here.

simov commented 3 years ago

I use this one https://github.com/jonschlinkert/sublime-markdown-extended and it looks like this:

- match: '(```|~~~|{%\s*highlight)\s*(javascript|js)\s*((?:linenos\s*)?%})?$'
  captures:
    1: punctuation.definition.fenced.markdown
    2: variable.language.fenced.markdown
    3: punctuation.definition.fenced.markdown
  push:
    - meta_scope: markup.raw.block.markdown markup.raw.block.fenced.markdown
    - meta_content_scope: source.js
    - match: '(```|~~~|{%\s*endhighlight\s*%})\n'
      captures:
        1: punctuation.definition.fenced.markdown
        2: variable.language.fenced.markdown
        3: punctuation.definition.fenced.markdown
      pop: true
    - include: scope:source.js

I've seen the constructs you are talking about in Sublime's docs, but this syntax is pretty old and probably those constructs were not available at that time. In any case if that's not an issue with this syntax then feel free to close this issue. Thanks.

Thom1729 commented 3 years ago

Yeah, that's going to run into problems in a wide variety of situations, and I don't think this syntax could accommodate them all even if it were a good idea. I would open an issue on the tracker, but the project looks abandoned.

If you want Markdown with more languages, you can extend the core syntax, e.g.:

%YAML 1.2
---
name: Customized Markdown
scope: text.html.markdown
extends: Packages/Markdown/Markdown.sublime-syntax
contexts:
  fenced-code-block:
     - meta_prepend: true
     - match: |-
          (?x)
           {{fenced_code_block_start}}
           ((?i:vue))
           {{fenced_code_block_trailing_infostring_characters}}
       captures:
         0: meta.code-fence.definition.begin.vue.markdown-gfm
         2: punctuation.definition.raw.code-fence.begin.markdown
         5: constant.other.language-name.markdown
       embed: scope:text.html.vue
       embed_scope: markup.raw.code-fence.vue.markdown-gfm
       escape: '{{code_fence_escape}}'
       escape_captures:
         0: meta.code-fence.definition.end.vue.markdown-gfm
         1: punctuation.definition.raw.code-fence.end.markdown

Save the above in your User directory as “Customized Markdown.sublime-syntax” and it will highlight Vue code blocks (if you have the Vue package installed). Customize/extend as needed for other languages.