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
+