diff --git a/Markdown/Markdown.sublime-syntax b/Markdown/Markdown.sublime-syntax index 0b2b9aa047..f2b1008835 100644 --- a/Markdown/Markdown.sublime-syntax +++ b/Markdown/Markdown.sublime-syntax @@ -95,7 +95,8 @@ variables: ) fenced_code_block_start: |- (?x: - [ ]{0,3} # up to 3 spaces + [ ]* + ([ ]{0,3}) # up to 3 spaces ( `{3,} # 3 or more backticks (?![^`]*`) # not followed by any more backticks on the same line @@ -104,6 +105,15 @@ variables: (?![^~]*~) # not followed by any more tildas on the same line ) ) + code_fence_escape: |- + (?x: + ^ # the beginning of the line + #\1 # whitespace previously captured + #[ ]{0,3} # up to 3 spaces - doesn't have to be the same as the opening fence, but within 3 spaces + [ ]* + (\2) # the backtick/tilde combination that opened the code fence + \s*$ # any amount of whitespace until EOL + ) html_tag_open_commonmark: |- (?xi: < @@ -146,6 +156,13 @@ variables: (?i:address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul) (?:\s|$|/?>) ) + # code_fence_escape: |- + # (?x: + # ^ # the beginning of the line + # [ ]{0,3} # up to 3 spaces + # (\1) # the backtick/tilde combination that opened the code fence + # \s*$ # any amount of whitespace until EOL + # ) contexts: main: - match: |- @@ -853,7 +870,7 @@ contexts: - include: block-quote - match: $ pop: true - - match: '^(?=\s+{{fenced_code_block_start}})' + - match: '^(?={{fenced_code_block_start}})' push: - include: fenced-code-block - match: '' @@ -887,7 +904,7 @@ contexts: pop: true list-content: - meta_content_scope: meta.paragraph.list.markdown - - match: ^\s*(?={{fenced_code_block_start}}) + - match: ^(?={{fenced_code_block_start}}) push: - match: $ pop: true @@ -904,18 +921,321 @@ contexts: - match: $ pop: true fenced-code-block: + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:xml)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.xml.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:text.xml + embed_scope: markup.raw.code-fence.xml.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.xml.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:sql)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.sql.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.sql + embed_scope: markup.raw.code-fence.sql.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.sql.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:python|py)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.python.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.python + embed_scope: markup.raw.code-fence.python.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.python.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:graphviz)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.graphviz.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.dot + embed_scope: markup.raw.code-fence.graphviz.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.graphviz.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:javascript|js)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.javascript.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.javascript + embed_scope: markup.raw.code-fence.javascript.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.javascript.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:json)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.json.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.json + embed_scope: markup.raw.code-fence.json.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.json.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:java)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.java.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.java + embed_scope: markup.raw.code-fence.java.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.java.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:csharp|c\#|cs)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.csharp.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.cs + embed_scope: markup.raw.code-fence.csharp.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.csharp.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:rust)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.rust.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.rust + embed_scope: markup.raw.code-fence.rust.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.rust.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:shell-script|sh|bash|zsh)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.shell-script.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.shell.bash + embed_scope: markup.raw.code-fence.shell-script.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.shell-script.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:php|inc)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.php.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.php + embed_scope: markup.raw.code-fence.php.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.php.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:html\+php)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.html-php.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:embedding.php + embed_scope: markup.raw.code-fence.html-php.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.html-php.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:rscript|r|splus)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.r.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.r + embed_scope: markup.raw.code-fence.r.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.r.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:golang)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.go.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.go + embed_scope: markup.raw.code-fence.go.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.go.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:ruby|rb|rbx)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.ruby.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.ruby + embed_scope: markup.raw.code-fence.ruby.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.ruby.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:objc|obj-c|objectivec|objective-c)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.objc.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.objc + embed_scope: markup.raw.code-fence.objc.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.objc.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:objc\+\+|obj-c\+\+|objectivec\+\+|objective-c\+\+)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.objc++.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.objc++ + embed_scope: markup.raw.code-fence.objc++.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.objc++.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:c)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.c.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.c + embed_scope: markup.raw.code-fence.c.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.c.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:c\+\+|cpp)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.c++.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.c++ + embed_scope: markup.raw.code-fence.c++.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.c++.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) + {{fenced_code_block_start}} + ((?i:regexp|regex)) + \s*$\n? # any whitespace until EOL + captures: + 0: meta.code-fence.definition.begin.regexp.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown + embed: scope:source.regexp + embed_scope: markup.raw.code-fence.regexp.markdown-gfm + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.regexp.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown - match: |- (?x) {{fenced_code_block_start}} ([\w-]*) # any number of word characters or dashes - .*$ # all characters until eol + .*$\n? # all characters until EOL captures: - 1: punctuation.definition.raw.code-fence.begin.markdown - 2: constant.other.language-name.markdown + 0: meta.code-fence.definition.begin.text.markdown-gfm + 2: punctuation.definition.raw.code-fence.begin.markdown + 3: constant.other.language-name.markdown push: - - meta_scope: markup.raw.code-fence.markdown-gfm - - match: '[ ]{,3}\1\s*$' - scope: punctuation.definition.raw.code-fence.end.markdown + - meta_content_scope: markup.raw.code-fence.markdown-gfm + - match: '{{code_fence_escape}}' + captures: + 0: meta.code-fence.definition.end.text.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown pop: true code-span: - match: (`+)(?!`) diff --git a/Markdown/syntax_test_markdown.md b/Markdown/syntax_test_markdown.md index 604dc37e42..49f4a1255f 100644 --- a/Markdown/syntax_test_markdown.md +++ b/Markdown/syntax_test_markdown.md @@ -1232,7 +1232,7 @@ http://spec.commonmark.org/0.28/#example-318 | ^^^^ punctuation.definition.raw.code-fence.begin | ^^^^ constant.other.language-name ~~~~~~ -| ^^^^^ punctuation.definition.raw.code-fence.end +| ^^^^ punctuation.definition.raw.code-fence.end ```test | ^^^^ constant.other.language-name @@ -1634,7 +1634,7 @@ paragraph |^^^^^^^^^^^^^^^ meta.paragraph.list | ^^^ punctuation.definition.raw.code-fence.begin | ^^^^^^^^ constant.other.language-name -| ^^^^^^^^^^^ markup.raw.code-fence +| ^^^^^^^^^^^ meta.code-fence |^^^^ meta.paragraph.list markup.raw.code-fence ``` @@ -1853,7 +1853,7 @@ okay 1. Test ```python -| ^^^ markup.list.numbered markup.raw.code-fence punctuation.definition.raw.code-fence.begin +| ^^^ markup.list.numbered meta.code-fence punctuation.definition.raw.code-fence.begin Test | <- - invalid @@ -1863,3 +1863,76 @@ okay 1. Test 2 |^ markup.list.numbered.bullet punctuation.definition.list_item + +```xml +|^^^^^ meta.code-fence.definition.begin.xml +| ^^^ constant.other.language-name + +|^^^^^^^^^^^^^^^^^^^^^^ markup.raw.code-fence.xml +| ^^^^^^^ meta.tag.preprocessor.xml entity.other.attribute-name.localname.xml + + + +``` +|^^ punctuation.definition.raw.code-fence.end + +```sql +|^^^^^ meta.code-fence.definition.begin.sql +| ^^^ constant.other.language-name +SELECT TOP 10 * +|^^^^^^^^^^^^^^^ markup.raw.code-fence.sql +|^^^^^^^^^ keyword.other.DML.sql +FROM TableName +``` +|^^ meta.code-fence.definition.end.sql punctuation.definition.raw.code-fence.end - markup + +```python +|^^ punctuation.definition.raw.code-fence.begin +|^^^^^^^^^ meta.code-fence.definition.begin.python - markup +| ^^^^^^ constant.other.language-name +def function(): + pass +| ^^^^ keyword.control.flow.python +unclosed_paren = ( +| ^ meta.group.python punctuation.section.group.begin.python +``` +|^^ meta.code-fence.definition.end.python punctuation.definition.raw.code-fence.end + +```Graphviz +graph n {} +| ^^^ storage.type.dot +``` + +| <- - markup.raw + +```php +var_dump(expression); +| ^^^^^^ support.function.var.php +``` + +```html+php +
+|^^^ entity.name.tag.block.any.html +