%YAML 1.2
---
name: Markdown
file_extensions:
- md
- mdown
- markdown
- markdn
scope: text.html.markdown
comment: |-
this definition aims to meet CommonMark specifications http://spec.commonmark.org/
with GitHub Formatted Markdown extensions https://github.github.com/gfm/
and has a few extras like Markdown Extra's footnotes https://michelf.ca/projects/php-markdown/extra/#footnotes
the scope suffix should indicate which flavor of Markdown the feature came from, to help make this syntax definition easier to maintain
variables:
thematic_break: |-
(?x:
[ ]{,3} # between 0 to 3 spaces
(?: # followed by one of the following:
[-](?:[ ]{,2}[-]){2,} # - a dash, followed by the following at least twice: between 0 to 2 spaces followed by a dash
| [*](?:[ ]{,2}[*]){2,} # - a star, followed by the following at least twice: between 0 to 2 spaces followed by a star
| [_](?:[ ]{,2}[_]){2,} # - an underscore, followed by the following at least twice: between 0 to 2 spaces followed by an underscore
)
[ \t]*$ # followed by any number of tabs or spaces, followed by the end of the line
)
block_quote: (?:[ ]{,3}>(?:.|$)) atx_heading: (?:[#]{1,6}\s*) indented_code_block: (?:[ ]{4}|\t) list_item: (?:[ ]{,3}(?=\d+\.|[*+-])\d*([*+.-])\s) escape: '\\[-`*_#+.!(){}\[\]\\>|~]'
backticks: |-
(?x:
(`{4})(?![\s`])(?:[^`]+(?=`)|(?!`{4})`+(?!`))+(`{4})(?!`) # 4 backticks, followed by at least one non whitespace, non backtick character, followed by (less than 4 backticks, or at least one non backtick character) at least once, followed by exactly 4 backticks
| (`{3})(?![\s`])(?:[^`]+(?=`)|(?!`{3})`+(?!`))+(`{3})(?!`) # 3 backticks, followed by at least one non whitespace, non backtick character, followed by (less than 3 backticks, or at least one non backtick character) at least once, followed by exactly 3 backticks
| (`{2})(?![\s`])(?:[^`]+(?=`)|(?!`{2})`+(?!`))+(`{2})(?!`) # 2 backticks, followed by at least one non whitespace, non backtick character, followed by (less than 2 backticks, or at least one non backtick character) at least once, followed by exactly 2 backticks
| (`{1})(?![\s`])(?:[^`]+(?=`)|(?!`{1})`+(?!`))+(`{1})(?!`) # 1 backtick, followed by at least one non whitespace, non backtick character, followed by ( at least one non backtick character) at least once, followed by exactly 1 backtick
)
balance_square_brackets: |-
(?x:
(?:
{{escape}}+ # escape characters
| [^\[\]`\\]+(?=[\[\]`\\]|$) # anything that isn't a square bracket or a backtick or the start of an escape character
| {{backticks}} # inline code
| \[(?: # nested square brackets (one level deep)
[^\[\]`]+(?=[\[\]`]) # anything that isn't a square bracket or a backtick
{{backticks}}? # balanced backticks
)*\] # closing square bracket
)+ # at least one character
)
html_entity: '&([a-zA-Z0-9]+|#\d+|#x\h+);'
skip_html_tags: (?:<[^>]+>)
balance_square_brackets_and_emphasis: |-
(?x:
(?:
{{escape}}+ # escape characters
| [^\[\]`\\_*]+(?=[\[\]`\\_*]|$) # anything that isn't a square bracket, a backtick, the start of an escape character, or an emphasis character
| {{backticks}} # inline code
| \[(?: # nested square brackets (one level deep)
[^\[\]`]+(?=[\[\]`]) # anything that isn't a square bracket or a backtick
{{backticks}}? # balanced backticks
)*\] # closing square bracket
)+ # at least one character
)
balance_square_brackets_pipes_and_emphasis: |-
(?x:
(?:
{{escape}}+ # escape characters
| [^\[\]`\\_*|]+(?=[\[\]`\\_*|]|$) # anything that isn't a square bracket, a backtick, the start of an escape character, or an emphasis character
| {{backticks}} # inline code
| \[(?: # nested square brackets (one level deep)
[^\[\]`]+(?=[\[\]`]) # anything that isn't a square bracket or a backtick
{{backticks}}? # balanced backticks
)*\] # closing square bracket
)+ # at least one character
)
balanced_emphasis: |-
(?x:
\* (?!\*){{balance_square_brackets_and_emphasis}}+\* (?!\*)
| \*\* {{balance_square_brackets_and_emphasis}}+\*\*
| _ (?!_) {{balance_square_brackets_and_emphasis}}+_ (?!_)
| __ {{balance_square_brackets_and_emphasis}}+__
)
balanced_table_cell: |- (?x:
(?:
{{balance_square_brackets_pipes_and_emphasis}}
| {{balanced_emphasis}}
)+ # at least one character
)
table_first_row: |-
(?x:
(?:{{balanced_table_cell}}?\|){2} # at least 2 non-escaped pipe chars on the line
| (?!\s+\|){{balanced_table_cell}}\|(?!\s+$) # something other than whitespace followed by a pipe char, followed by something other than whitespace and the end of the line
)
fenced_code_block_start: |-
(?x:
([ \t]*)
(
(`){3,} # 3 or more backticks
(?![^`]*`) # not followed by any more backticks on the same line
| # or
(~){3,} # 3 or more tildas
(?![^~]*~) # not followed by any more tildas on the same line
)
\s* # allow for whitespace between code block start and info string
)
fenced_code_block_trailing_infostring_characters: |-
(?x:
(
\s* # any whitespace, or ..
|
\s[^`]* # any characters (except backticks), separated by whitespace ...
)
$\n? # ... until EOL
)
code_fence_escape: |-
(?x:
^ # the beginning of the line
[ \t]*
(
\2 # the backtick/tilde combination that opened the code fence
(?:\3|\4)* # plus optional additional closing characters
)
\s*$ # any amount of whitespace until EOL
)
html_tag_open_commonmark: |-
(?xi:
<
[a-z] # A tag name consists of an ASCII letter
[a-z0-9-]* # followed by zero or more ASCII letters, digits, or hyphens (-)
(?: # An attribute consists of whitespace, an attribute name, and an optional attribute value specification
\s+
[a-z_:] # An attribute name consists of an ASCII letter, _, or :
[a-z0-9_.:-]* # followed by zero or more ASCII letters, digits, _, ., :, or -
(?: # An attribute value specification consists of optional whitespace, a = character, optional whitespace, and an attribute value
\s*
=
\s*
(?:
[^ @'=<>`]+ # An unquoted attribute value is a nonempty string of characters not including spaces, ", ', =, <, >, or `
| '[^']*' # A single-quoted attribute value consists of ', zero or more characters not including ', and a final '
| "[^"]*" # A double-quoted attribute value consists of ", zero or more characters not including ", and a final "
)
)?
)*
\s*
/?
>
)
html_tag_close_commonmark: |-
(?xi:
</
[a-z] # A tag name consists of an ASCII letter
[a-z0-9-]* # followed by zero or more ASCII letters, digits, or hyphens (-)
\s*
>
)
html_tag_block_end_at_close_tag: |-
(?xi:
(script|style|pre)\b
)
html_tag_block_end_at_blank_line: |-
(?x:
/?
(?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|$|/?>)
)
ascii_space: '\t\n\f '
tag_attribute_name_start: (?=[^{{ascii_space}}=/>}])
tag_attribute_name_break: (?=[{{ascii_space}}=/>}])
tag_unquoted_attribute_start: (?=[^{{ascii_space}}=/>}])
tag_unquoted_attribute_break: (?=[{{ascii_space}}}]|/?>)
contexts:
main:
- match: |-
(?x)^
(?= {{block_quote}}
| {{indented_code_block}}(?!$)
| {{atx_heading}}
| {{thematic_break}}
| {{table_first_row}}
)
comment: |
We could also use an empty end match and set
applyEndPatternLast, but then we must be sure that the begin
pattern will only match stuff matched by the sub-patterns.
push:
- meta_scope: meta.block-level.markdown
- include: ligatures
- include: block-quote
- include: indented-code-block
- include: atx-heading
- include: thematic-break
- include: table
- match: ''
pop: true
- match: '^([ ]{0,3})([*+-])(?=\s)'
captures:
1: markup.list.unnumbered.markdown
2: markup.list.unnumbered.bullet.markdown punctuation.definition.list_item.markdown
push:
- meta_content_scope: markup.list.unnumbered.markdown
- match: ^(?=\S)
pop: true
- include: list-paragraph
- match: '^([ ]{0,3})(\d+(\.))(?=\s)'
captures:
1: markup.list.numbered.markdown
2: markup.list.numbered.bullet.markdown
3: punctuation.definition.list_item.markdown
push:
- meta_content_scope: markup.list.numbered.markdown
- match: ^(?=\S)
pop: true
- include: list-paragraph
- match: '^[ ]{0,3}(?=<((?i:pre))\b)'
comment: Markdown formatting is disabled inside block-level tags.
push: [disabled-markdown-pop-at-eol, disable-markdown-pop-at-tag]
- match: '^[ ]{0,3}(?=<{{html_tag_block_end_at_close_tag}})'
comment: Markdown formatting is disabled inside block-level tags.
push: [disabled-markdown-pop-at-eol, disable-markdown-pop-after-tag]
- match: '^[ ]{0,3}(?=<\?)'
comment: Markdown formatting is disabled inside preprocessor instructions.
push: [disabled-markdown-pop-at-eol, disable-markdown-pop-at-php]
- match: '^[ ]{0,3}(?=<!(?:[A-Z]|--))'
comment: Markdown formatting is disabled inside doctype declarations and comments.
push: [disabled-markdown-pop-at-eol, disable-markdown-pop-after-html-doctype]
- match: '^[ ]{0,3}(?=<!\[CDATA\[)'
comment: Markdown formatting is disabled inside CDATA.
push: [disabled-markdown-pop-at-eol, disable-markdown-pop-after-cdata]
- match: '^[ ]{0,3}(?=(?:{{html_tag_open_commonmark}}|{{html_tag_close_commonmark}})\s*$|<{{html_tag_block_end_at_blank_line}})'
comment: Markdown formatting is disabled inside block level tags and if a complete HTML tag is the only thing on the line.
push: [disabled-markdown-pop-at-eol, disable-markdown-pop-at-blank-line]
- match: |-
(?x:
\s* # Leading whitespace
(\[)(\^[^]]*)(\])(:) # Reference name
[ \t]* # Optional whitespace
)
captures:
1: punctuation.definition.constant.begin.markdown
2: entity.name.reference.link.markdown
3: punctuation.definition.constant.end.markdown
4: punctuation.separator.key-value.markdown
push:
- meta_scope: meta.link.reference.def.footnote.markdown-extra
- match: ^(?![ ]{4}|$)
pop: true
- include: inline-bold-italic
- match: |-
(?x:
\s* # Leading whitespace
(\[)([^]]*)(\])(:) # Reference name
[ \t]* # Optional whitespace
(?:
(<)([^>]+)(>) # The url
| (\S+) # The url
)
)
captures:
1: punctuation.definition.constant.begin.markdown
2: entity.name.reference.link.markdown
3: punctuation.definition.constant.end.markdown
4: punctuation.separator.key-value.markdown
5: punctuation.definition.link.begin.markdown
6: markup.underline.link.markdown
7: punctuation.definition.link.end.markdown
8: markup.underline.link.markdown
push: [link-ref-def, after-link-title, link-title]
- match: '^(?=\S)(?![=-]{3,}\s*$)'
push:
- meta_scope: meta.paragraph.markdown
- match: |-
(?x) # pop out of this context when one of the following conditions are met:
^(?:
\s*$ # the line is blank (or only contains whitespace)
| (?=
{{block_quote}} # a block quote begins the line
| [ ]{,3}[*+-][ ] # an unordered list item begins the line
| [ ]{,3}1[.][ ] # an ordered list item with number "1" begins the line
| \# # an ATX heading begins the line
| [ ]{,3}<( # all types of HTML blocks except type 7 may interrupt a paragraph
{{html_tag_block_end_at_close_tag}} # 1
| !-- # 2
| \? # 3
| ![A-Z] # 4
| !\[CDATA\[ # 5
| {{html_tag_block_end_at_blank_line}} # 6
)
)
)
pop: true
- include: inline-bold-italic-linebreak
- include: scope:text.html.basic
- match: '^(={3,})(?=[ \t]*$)'
scope: markup.heading.1.setext.markdown
captures:
1: punctuation.definition.heading.setext.markdown
pop: true
- match: '^(-{3,})(?=[ \t]*$)'
scope: markup.heading.2.setext.markdown
captures:
1: punctuation.definition.heading.setext.markdown
pop: true
link-ref-def:
- meta_scope: meta.link.reference.def.markdown
- match: ''
pop: true
ampersand:
- match: (?!{{html_entity}})&
comment: |
Markdown will convert this for us. We match it so that the
HTML grammar will not mark it up as invalid.
scope: meta.other.valid-ampersand.markdown
ligatures:
- match: '<=>' - match: '<[-=<]' block-quote:
- match: '[ ]{,3}(>)[ ]?'
comment: |
We terminate the block quote when seeing an empty line, a
separator or a line with leading > characters. The latter is
to “reset” the quote level for quoted lines.
The idea here is to match block level elements first, then once
we have confirmed there are no block level elements left, move to
matching inline markdown. This prevents block level elements being
detected when they shouldn't be.
captures:
1: punctuation.definition.blockquote.markdown
push:
- meta_scope: markup.quote.markdown
- match: |-
(?x)^
(?= \s*$
| {{thematic_break}}
| {{block_quote}}
)
pop: true
- match: |-
(?x)
(?= {{block_quote}}
)
push:
- match: ^
pop: true
- include: block-quote
- match: |-
(?x)
(?= {{indented_code_block}}
| {{atx_heading}}
| {{thematic_break}}
| {{list_item}}
)
push:
- include: indented-code-block
- include: atx-heading
- include: thematic-break
- match: ([ ]{,3})(\d+)(\.)(\s)
captures:
1: markup.list.numbered.markdown
2: markup.list.numbered.bullet.markdown
3: markup.list.numbered.bullet.markdown punctuation.definition.list_item.markdown
4: markup.list.numbered.markdown
push:
- meta_content_scope: markup.list.numbered.markdown meta.paragraph.list.markdown
- include: list-content
- match: ([ ]{,3})([*+-])(\s)
captures:
1: markup.list.unnumbered.markdown
2: markup.list.unnumbered.bullet.markdown punctuation.definition.list_item.markdown
3: markup.list.unnumbered.markdown
push:
- meta_content_scope: markup.list.unnumbered.markdown meta.paragraph.list.markdown
- include: list-content
- match: ^
pop: true
- include: list-paragraph
- match: ''
push:
- match: $|^
pop: true
- include: inline-bold-italic-linebreak
indented-code-block:
- match: '{{indented_code_block}}.*$\n?'
scope: markup.raw.block.markdown
bold:
- include: ligatures
- match: '(\*\*)(\*)(?=\S)(?!\*)'
captures:
1: punctuation.definition.bold.begin.markdown
2: markup.italic.markdown punctuation.definition.italic.begin.markdown
push:
- meta_scope: markup.bold.markdown
- meta_content_scope: markup.italic.markdown
- match: |-
(?x)
[ \t]*\*{4,} # if there are more than 3 its not applicable to be bold or italic
| [ \t]+\*(?!\*) # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation)
| ^\*(?!\*) # emphasis can't be closed at the start of the line
- match: (\*)(\*\*)
captures:
1: markup.italic.markdown punctuation.definition.italic.end.markdown
2: punctuation.definition.bold.end.markdown
pop: true
- match: \*\*
scope: punctuation.definition.bold.end.markdown
set:
- meta_content_scope: markup.italic.markdown
- match: |-
(?x)
[ \t]*\*{3,} # if there are more than 3 its not applicable to be bold or italic
| [ \t]+\*\*+ # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation)
| ^\*\* # emphasis can't be closed at the start of the line
- match: \*
scope: markup.italic.markdown punctuation.definition.italic.end.markdown
pop: true
- include: inline
- include: bold
- include: bold-italic-trailing
- match: \*
scope: punctuation.definition.italic.end.markdown
set:
- meta_content_scope: markup.bold.markdown
- match: |-
(?x)
[ \t]*\*{3,} # if there are more than 3 its not applicable to be bold or italic
| [ \t]+\*\*+ # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation)
| ^\*\* # emphasis can't be closed at the start of the line
- match: \*\*
scope: markup.bold.markdown punctuation.definition.bold.end.markdown
pop: true
- include: inline
- include: italic
- include: bold-italic-trailing
- include: inline
- include: bold-italic-trailing
- match: '\*\*(?=\S)(?!\*\*|\*\s)'
scope: punctuation.definition.bold.begin.markdown
push:
- meta_scope: markup.bold.markdown
- match: |-
(?x)
[ \t]*\*{4,} # if there are more than 3 its not applicable to be bold or italic
| [ \t]+\*\*+ # whitespace followed by 2 or more is also not applicable
| ^\*\* # emphasis can't be closed at the start of the line
- match: (?:_)?(\*\*)
captures:
1: punctuation.definition.bold.end.markdown
pop: true
- include: inline
- match: \b_(?=[^\s_])(?=[^*_]*\*\*)
comment: eat the underscore that has no corresponding underscore before the closing bold punctuation on the same line, as it won't be treated as italic by CommonMark
- include: italic
- include: bold-italic-trailing
- match: '\b(__)(_)(?=\S)(?!_)'
captures:
1: punctuation.definition.bold.begin.markdown
2: markup.italic.markdown punctuation.definition.italic.begin.markdown
push:
- meta_scope: markup.bold.markdown
- meta_content_scope: markup.italic.markdown
- match: |-
(?x)
[ \t]*_{4,} # if there are more than 3 its not applicable to be bold or italic
| [ \t]+_(?!_) # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation)
| ^_(?!_) # emphasis can't be closed at the start of the line
- match: (_)(__)\b
captures:
1: markup.italic.markdown punctuation.definition.italic.end.markdown
2: punctuation.definition.bold.end.markdown
pop: true
- match: _\b
scope: punctuation.definition.italic.end.markdown
set:
- meta_content_scope: markup.bold.markdown
- match: |-
(?x)
[ \t]*_{3,} # if there are more than 3 its not applicable to be bold or italic
| [ \t]+__+ # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation)
| ^__ # emphasis can't be closed at the start of the line
- match: __\b
scope: markup.bold.markdown punctuation.definition.bold.end.markdown
pop: true
- include: inline
- include: italic
- include: bold-italic-trailing
- match: __\b
scope: punctuation.definition.bold.end.markdown
set:
- meta_content_scope: markup.italic.markdown
- match: |-
(?x)
[ \t]*_{3,} # if there are more than 3 its not applicable to be bold or italic
| [ \t]+__+ # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation)
| ^__ # emphasis can't be closed at the start of the line
- match: _\b
scope: markup.italic.markdown punctuation.definition.italic.end.markdown
pop: true
- include: inline
- include: bold
- include: bold-italic-trailing
- include: inline
- include: bold-italic-trailing
- match: '\b__(?=\S)(?!_[_\s])'
scope: punctuation.definition.bold.begin.markdown
push:
- meta_scope: markup.bold.markdown
- match: |-
(?x)
[ \t]*_{4,} # if there are more than 3 its not applicable to be bold or italic
| [ \t]+__+ # whitespace followed by 2 or more is also not applicable
| ^__ # emphasis can't be closed at the start of the line
- match: (?:\*)?(__\b)
captures:
1: punctuation.definition.bold.end.markdown
pop: true
- include: inline
- match: \*(?=[^\s*])(?=[^*_]*__\b)
comment: eat the asterisk that has no corresponding asterisk before the closing bold punctuation on the same line, as it won't be treated as italic by CommonMark
- include: italic
- include: bold-italic-trailing
bracket:
- match: '<(?![A-Za-z/?!$])'
comment: |
Markdown will convert this for us. We match it so that the
HTML grammar will not mark it up as invalid.
scope: meta.other.valid-bracket.markdown
escape:
- match: '{{escape}}'
scope: constant.character.escape.markdown
atx-heading-terminator:
- match: '[ ]*(#*)[ ]*($\n?)' captures:
1: punctuation.definition.heading.end.markdown
2: meta.whitespace.newline.markdown
pop: true
atx-heading:
- match: '(#)(?!#)\s*(?=\S)'
captures:
1: punctuation.definition.heading.begin.markdown
push:
- meta_scope: markup.heading.1.markdown
- meta_content_scope: entity.name.section.markdown
- include: atx-heading-terminator
- include: inline-bold-italic
- match: '(##)(?!#)\s*(?=\S)'
captures:
1: punctuation.definition.heading.begin.markdown
push:
- meta_scope: markup.heading.2.markdown
- meta_content_scope: entity.name.section.markdown
- include: atx-heading-terminator
- include: inline-bold-italic
- match: '(#{3,6})(?!#)\s*(?=\S)'
captures:
1: punctuation.definition.heading.begin.markdown
push:
- meta_scope: markup.heading.markdown
- meta_content_scope: entity.name.section.markdown
- include: atx-heading-terminator
- include: inline-bold-italic
image-inline:
- match: |-
(?x:
(\!\[) # Images start with ![
(?= {{balance_square_brackets}}? # balanced square brackets, backticks, taking into account escapes etc.
\] # Closing square bracket
[ ]? # Space not allowed, but we check for it anyway to mark it as invalid
\( # Open paren
)
)
captures:
1: meta.image.inline.markdown punctuation.definition.image.begin.markdown
push: [image-inline-attr, image-inline-after-text, image-link-text]
image-link-text:
- meta_content_scope: meta.image.inline.description.markdown
- include: link-text
- match: \]
scope: meta.image.inline.markdown punctuation.definition.image.end.markdown
pop: true
image-inline-after-text:
- match: '([ ]*)(\()' captures:
1: invalid.illegal.whitespace.markdown
2: punctuation.definition.metadata.begin.markdown
set:
- meta_scope: meta.image.inline.markdown
- match: \)
scope: punctuation.definition.metadata.end.markdown
pop: true
- match: <(?=[^>)]*>)
scope: punctuation.definition.link.begin.markdown
push:
- meta_content_scope: markup.underline.link.image.markdown
- match: \>
scope: punctuation.definition.link.end.markdown
set: link-title
- match: \s+
scope: invalid.illegal.unexpected-whitespace.markdown
- match: (?=\S)
set:
- meta_scope: meta.image.inline.markdown
- match: '[^\s)]+'
scope: markup.underline.link.image.markdown
- match: \)
scope: punctuation.definition.metadata.end.markdown
pop: true
- match: (?!\n)\s+(?!\s*(?:[)('"]|$))
scope: invalid.illegal.unexpected-whitespace.markdown
- match: (?=\s*(?!\)))
push: link-title
image-inline-attr:
- match: '([ ]*)(\{)(?=[^}]*\})'
captures:
1: invalid.illegal.whitespace.markdown
2: punctuation.definition.attributes.begin.markdown
set:
- meta_scope: meta.image.inline.markdown
- include: tag-attributes
- include: immediately-pop
image-ref:
- match: |-
(?x:
(\!\[) # Images start with ![
(?= {{balance_square_brackets}}? # balanced square brackets, backticks, taking into account escapes etc.
\] # Closing square bracket
[ ]? # Space
\[ # [
[^\]]+ # anything other than ]
\] # ]
)
)
captures:
1: meta.image.reference.markdown punctuation.definition.image.begin.markdown
push: [image-ref-attr, image-ref-after-text, image-ref-text]
image-ref-text:
- meta_content_scope: meta.image.reference.description.markdown
- include: link-text
- match: \]
scope: meta.image.reference.markdown punctuation.definition.image.end.markdown
pop: true
image-ref-after-text:
- match: '[ ]?(\[)([^\]]+)(\])'
captures:
1: punctuation.definition.constant.begin.markdown
2: constant.other.reference.link.markdown
3: punctuation.definition.constant.end.markdown
scope: meta.image.reference.markdown
pop: true
image-ref-attr:
- match: '([ ]*)(\{)(?=[^}]*\})'
captures:
1: invalid.illegal.whitespace.markdown
2: punctuation.definition.attributes.begin.markdown
set:
- meta_scope: meta.image.reference.markdown
- include: tag-attributes
- include: immediately-pop
inline:
- include: escape
- include: ampersand
- include: ligatures
- include: bracket
- include: raw
- include: image-inline
- include: link-inline
- include: autolink-inet
- include: autolink-email
- include: image-ref
- include: link-ref-literal
- include: link-ref
- include: link-ref-footnote
inline-bold-italic:
- include: inline
- include: bold
- include: italic
- include: strikethrough
inline-bold-italic-linebreak:
- include: inline-bold-italic
- include: hard-line-break
italic:
- match: '\*(?=\S)(?!\*)'
scope: punctuation.definition.italic.begin.markdown
push:
- meta_scope: markup.italic.markdown
- match: |-
(?x)
[ \t]*\*{4,} # if there are more than 3 its not applicable to be bold or italic
| [ \t]+\*(?!\*) # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation)
| ^\*(?!\*) # emphasis can't be closed at the start of the line
- match: \*(?!\*[^*])
scope: punctuation.definition.italic.end.markdown
pop: true
- include: inline
- include: bold
- match: '\*+'
- include: bold-italic-trailing
- match: '\b_(?=\S)(?!_)'
scope: punctuation.definition.italic.begin.markdown
push:
- meta_scope: markup.italic.markdown
- match: |-
(?x)
[ \t]*_{4,} # if there are more than 3 its not applicable to be bold or italic
| [ \t]+_(?!_) # whitespace followed by 1 is also not applicable (but whitespace followed by 2 could be bold punctuation)
| ^_(?!_) # emphasis can't be closed at the start of the line
- match: _\b
scope: punctuation.definition.italic.end.markdown
pop: true
- include: inline
- include: bold
- include: bold-italic-trailing
- match: '[*_]+'
strikethrough:
- match: '(~+)(?=\S)(?!~)'
scope: punctuation.definition.strikethrough.begin.markdown
push:
- meta_scope: markup.strikethrough.markdown-gfm
- match: ~+
scope: punctuation.definition.strikethrough.end.markdown
pop: true
- include: inline
- include: bold
- include: italic
- include: bold-italic-trailing
bold-italic-trailing:
- include: scope:text.html.basic
- match: ^\s*$\n?
scope: invalid.illegal.non-terminated.bold-italic.markdown
pop: true
- match: '^(?={{list_item}})'
pop: true
- include: hard-line-break
hard-line-break:
- match: '[ ]{2,}$'
scope: meta.hard-line-break.markdown punctuation.definition.hard-line-break.markdown
- match: '(\\)$\n'
scope: meta.hard-line-break.markdown
captures:
1: constant.character.escape.markdown
autolink-email:
- match: '(<)((?:mailto:)?[-+.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(>)'
scope: meta.link.email.lt-gt.markdown
captures:
1: punctuation.definition.link.begin.markdown
2: markup.underline.link.markdown
4: punctuation.definition.link.end.markdown
- match: '[\w.+-]+@[\w-]+(\.((?![._-][\W])[\w_-])+)+(?![_-])'
scope: markup.underline.link.markdown
autolink-inet:
- match: (<)((?:https?|ftp)://.*?)(>)
scope: meta.link.inet.markdown
captures:
1: punctuation.definition.link.begin.markdown
2: markup.underline.link.markdown
3: punctuation.definition.link.end.markdown
- match: (((https|http|ftp)://)|www\.)[\w-]+(\.[\w-]+)+
scope: markup.underline.link.markdown-gfm
push: - match: (?=[?!.,:*_~]*[\s<]) pop: true
- match: (?={{html_entity}}[?!.,:*_~]*[\s<]) pop: true
- match: \( push:
- meta_scope: markup.underline.link.markdown-gfm
- match: (?=[?!.,:*_~]*[\s<])
pop: true
- match: \)
pop: true
- match: (?=\)[?!.,:*_~]*[\s<])
pop: true
- match: '[^?!.,:*_~\s<&()]+|\S'
scope: markup.underline.link.markdown-gfm
link-inline:
- match: |-
(?x:
(\[)
(?=
{{balance_square_brackets}}?
\]
[ ]?\(
)
)
captures:
1: meta.link.inline.markdown punctuation.definition.link.begin.markdown
push: [link-inline-attr, link-inline-after-text, link-inline-link-text]
link-inline-after-text:
- match: '([ ]*)(\()' captures:
1: invalid.illegal.whitespace.markdown
2: punctuation.definition.metadata.begin.markdown
set:
- meta_scope: meta.link.inline.markdown
- match: \)
scope: punctuation.definition.metadata.end.markdown
pop: true
- match: <(?=[^>)]*>)
scope: punctuation.definition.link.begin.markdown
push:
- match: \>
scope: punctuation.definition.link.end.markdown
set: link-title
- match: \s+
scope: invalid.illegal.unexpected-whitespace.markdown
- match: (?=\S)
set:
- meta_scope: meta.link.inline.markdown
- match: '[^\s)]+'
scope: markup.underline.link.markdown
- match: \)
scope: punctuation.definition.metadata.end.markdown
pop: true
- match: (?!\n)\s+(?!\s*(?:[)('"]|$))
scope: invalid.illegal.unexpected-whitespace.markdown
- match: (?=\s*(?!\)))
push: link-title
link-inline-attr:
- match: '([ ]*)(\{)(?=[^}]*\})'
captures:
1: invalid.illegal.whitespace.markdown
2: punctuation.definition.attributes.begin.markdown
set:
- meta_scope: meta.link.inline.markdown
- include: tag-attributes
- include: immediately-pop
link-inline-link-text:
- meta_content_scope: meta.link.inline.description.markdown
- include: link-text-allow-image
- match: \]
scope: meta.link.inline.markdown punctuation.definition.link.end.markdown
pop: true
link-ref:
- match: |-
(?x:
(\[)
(?= {{balance_square_brackets}}? # balanced square brackets, backticks, taking into account escapes etc.
\] # Closing square bracket
[ ]? # Space
\[ # [
[^\]]+ # anything other than ]
\] # ]
)
)
captures:
1: meta.link.reference.markdown punctuation.definition.link.begin.markdown
push: [link-ref-attr, link-ref-after-text, link-ref-link-text]
link-ref-link-text:
- meta_content_scope: meta.link.reference.description.markdown
- include: link-text-allow-image
- match: \]
scope: meta.link.reference.markdown punctuation.definition.link.end.markdown
pop: true
link-ref-after-text:
- match: '[ ]?(\[)([^\]]+)(\])'
captures:
1: punctuation.definition.constant.begin.markdown
2: constant.other.reference.link.markdown
3: punctuation.definition.constant.end.markdown
scope: meta.link.reference.markdown
pop: true
link-ref-attr:
- match: '([ ]*)(\{)(?=[^}]*\})'
captures:
1: invalid.illegal.whitespace.markdown
2: punctuation.definition.attributes.begin.markdown
set:
- meta_scope: meta.link.reference.markdown
- include: tag-attributes
- include: immediately-pop
link-ref-literal:
- match: |-
(?x:
(\[)
(?=
{{balance_square_brackets}}? # balanced square brackets, backticks, taking into account escapes etc.
\] # Closing square bracket
[ ]? # Space
\[ # [
\] # ]
)
)
captures:
1: meta.link.reference.literal.markdown punctuation.definition.link.begin.markdown
push: [link-ref-literal-attr, link-ref-literal-after-text, link-ref-literal-link-text]
link-ref-literal-link-text:
- meta_content_scope: meta.link.reference.literal.description.markdown
- include: link-text-allow-image
- match: \]
scope: meta.link.reference.literal.markdown punctuation.definition.link.end.markdown
pop: true
link-ref-literal-after-text:
- match: '[ ]?(\[)(\])'
scope: meta.link.reference.literal.markdown
captures:
1: punctuation.definition.constant.begin.markdown
2: punctuation.definition.constant.end.markdown
pop: true
link-ref-literal-attr:
- match: '([ ]*)(\{)(?=[^}]*\})'
captures:
1: invalid.illegal.whitespace.markdown
2: punctuation.definition.attributes.begin.markdown
set:
- meta_scope: meta.link.reference.literal.markdown
- include: tag-attributes
- include: immediately-pop
link-ref-footnote:
- match: |-
(?x:
(\[\^)
([^]]+)
(\])
)
captures:
0: meta.link.reference.footnote.markdown-extra
1: punctuation.definition.link.begin.markdown
2: meta.link.reference.literal.footnote-id.markdown
3: punctuation.definition.link.end.markdown
list-paragraph:
- match: '^(?=(?:[ ]{4}|\t){2,}(?![>+*\s-]))(?={{indented_code_block}})'
push:
- include: indented-code-block
- match: $
pop: true
- match: '^(?=\s+{{block_quote}})'
push:
- include: block-quote
- match: $
pop: true
- match: '^(?={{fenced_code_block_start}})'
push:
- include: fenced-code-block
- match: ''
pop: true
- match: \s+(?=\S)
push:
- match: ^\s*$
pop: true
- match: '([ ]*)([*+-])(?=\s)'
captures:
1: markup.list.unnumbered.markdown
2: markup.list.unnumbered.bullet.markdown punctuation.definition.list_item.markdown
push:
- clear_scopes: 1
- meta_content_scope: markup.list.unnumbered.markdown meta.paragraph.list.markdown
- include: list-content
- match: '([ ]*)(\d+(\.))(?=\s)'
captures:
1: markup.list.numbered.markdown
2: markup.list.numbered.bullet.markdown
3: punctuation.definition.list_item.markdown
push:
- clear_scopes: 1
- meta_content_scope: markup.list.numbered.markdown meta.paragraph.list.markdown
- include: list-content
- match: \s+
scope: meta.paragraph.list.markdown
- match: '(?=\S)'
push: list-content
- match: '(?=\S)'
pop: true
list-content:
- meta_content_scope: meta.paragraph.list.markdown
- match: ^(?={{fenced_code_block_start}})
push:
- match: $
pop: true
- include: fenced-code-block
- match: ^
pop: true
- include: thematic-break
- match: (?=\S)(?!{{list_item}})
push:
- match: (?={{list_item}})
pop: true
- include: inline-bold-italic-linebreak
- include: scope:text.html.basic
- match: $
pop: true
fenced-code-block:
- match: |-
(?x)
{{fenced_code_block_start}}
((?i:xml))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.xml.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.sql.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.python.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.graphviz.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.javascript.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: constant.other.language-name.markdown
embed: scope:source.js
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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.json.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.java.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.csharp.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.rust.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.shell-script.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.php.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.html-php.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.r.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.go.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.ruby.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.objc.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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\+\+))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.objc++.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.c.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.c++.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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))
{{fenced_code_block_trailing_infostring_characters}}
captures:
0: meta.code-fence.definition.begin.regexp.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: 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
.*$\n? # all characters until EOL
captures:
0: meta.code-fence.definition.begin.text.markdown-gfm
2: punctuation.definition.raw.code-fence.begin.markdown
5: constant.other.language-name.markdown
push:
- 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: (`+)(?!`)
scope: punctuation.definition.raw.begin.markdown
push:
- meta_scope: markup.raw.inline.markdown
- match: \1(?!`)
scope: punctuation.definition.raw.end.markdown
pop: true
- match: '`+'
- match: ^\s*$\n?
scope: invalid.illegal.non-terminated.raw.markdown
pop: true
raw:
- match: ^(?={{fenced_code_block_start}})
push:
- match: $
pop: true
- include: fenced-code-block
- include: code-span
thematic-break:
- match: '(?={{thematic_break}})'
push:
- meta_scope: meta.separator.thematic-break.markdown
- match: '[-_*]+'
scope: punctuation.definition.thematic-break.markdown
- match: '$\n?'
pop: true
disable-markdown:
- include: scope:text.html.basic
disable-markdown-pop-at-tag:
- match: (</)(\1)(>)
captures:
1: meta.tag.block.any.html punctuation.definition.tag.begin.html
2: meta.tag.block.any.html entity.name.tag.block.any.html
3: meta.tag.block.any.html punctuation.definition.tag.end.html
pop: true
- include: disable-markdown
disable-markdown-pop-after-tag:
- match: (?!</?(?i:script|style)\b)
pop: true
- include: disable-markdown
disable-markdown-pop-at-blank-line:
- match: ^\s*$
pop: true
- include: disable-markdown
disable-markdown-pop-after-cdata:
- match: (?!<!\[CDATA\[)
pop: true
- include: disable-markdown
disable-markdown-pop-at-php:
- match: \?>
pop: true
- include: disable-markdown
disable-markdown-pop-after-html-doctype:
- match: (?!<!([A-Z]|--))
pop: true
- include: disable-markdown
disabled-markdown-pop-at-eol:
- meta_content_scope: meta.disable-markdown
- match: $\n?
scope: meta.disable-markdown
pop: true
- include: disable-markdown
link-text:
- include: escape
- include: ampersand
- include: raw
- match: \[ push:
- include: link-text
- match: \]
pop: true
- include: bold
- include: italic
- include: hard-line-break
- include: scope:text.html.basic
link-text-allow-image:
- include: link-text
- include: image-inline
- include: image-ref
link-title:
- match: \s*(')
captures:
1: punctuation.definition.string.begin.markdown
set:
- meta_scope: string.other.link.description.title.markdown
- match: \'
scope: punctuation.definition.string.end.markdown
pop: true
- match: ^\s*$\n?
scope: invalid.illegal.non-terminated.link-title.markdown
pop: true
- match: \s*(")
captures:
1: punctuation.definition.string.begin.markdown
set:
- meta_scope: string.other.link.description.title.markdown
- match: \"
scope: punctuation.definition.string.end.markdown
pop: true
- match: ^\s*$\n?
scope: invalid.illegal.non-terminated.link-title.markdown
pop: true
- match: \s*(\()
captures:
1: punctuation.definition.string.begin.markdown
set:
- meta_scope: string.other.link.description.title.markdown
- match: \)
scope: punctuation.definition.string.end.markdown
pop: true
- match: ^\s*$\n?
scope: invalid.illegal.non-terminated.link-title.markdown
pop: true
- match: \s*
pop: true
after-link-title:
- match: '(.*)$\n?'
captures:
1: invalid.illegal.expected-eol.markdown
pop: true
tag-attributes:
- match: \}
scope: punctuation.definition.attributes.end.markdown
pop: true
- match: \,
scope: punctuation.separator.mapping.pair.markdown
- match: '{{tag_attribute_name_start}}'
push: [tag-attr-meta, tag-attr-equals, tag-attr-name]
tag-attr-name:
- meta_scope: entity.other.attribute-name.markdown
- match: '{{tag_attribute_name_break}}'
pop: true
- match: '["''`<]'
scope: invalid.illegal.attribute-name.markdown
tag-attr-meta:
- meta_scope: meta.attribute-with-value.markdown
- include: immediately-pop
tag-attr-equals:
- match: =
scope: punctuation.separator.key-value.markdown
set: tag-attr-value
- include: else-pop
tag-attr-value:
- match: \"
scope: punctuation.definition.string.begin.markdown
set:
- meta_scope: string.quoted.double.markdown
- match: \"
scope: punctuation.definition.string.end.markdown
pop: true
- match: \'
scope: punctuation.definition.string.begin.markdown
set:
- meta_scope: string.quoted.single.markdown
- match: \'
scope: punctuation.definition.string.end.markdown
pop: true
- match: '{{tag_unquoted_attribute_start}}'
set:
- meta_scope: string.unquoted.markdown
- match: '{{tag_unquoted_attribute_break}}'
pop: true
- match: '["''`<]'
scope: invalid.illegal.attribute-value.markdown
- include: else-pop
table:
- match: ^(?={{table_first_row}})
push:
- meta_content_scope: meta.table.header.markdown-gfm
- match: \|
scope: punctuation.separator.table-cell.markdown
- include: inline-bold-italic
- match: $\n?
set:
- match: ^
set:
- meta_content_scope: meta.table.header-separator.markdown-gfm
- match: \|
scope: punctuation.separator.table-cell.markdown
- match: ':'
scope: punctuation.definition.table-cell-alignment.markdown
- match: -+
scope: punctuation.section.table-header.markdown
- match: $\n?
set:
- meta_content_scope: meta.table.markdown-gfm
- match: |- (?x)^
(?= {{block_quote}}
| {{indented_code_block}}(?!$)
| {{atx_heading}}
| {{thematic_break}}
| \s*$
)
pop: true
- match: \|
scope: punctuation.separator.table-cell.markdown
- match: (?={{balanced_emphasis}})
push:
- include: bold
- include: italic
- match: ''
pop: true
- match: |-
(?x)
(?!{{backticks}})
`+
scope: invalid.deprecated.unescaped-backticks.markdown
- include: inline
- include: scope:text.html.basic
else-pop:
- match: (?=\S)
pop: true
immediately-pop:
- match: ''
pop: true