the-way 0.12.1

A code snippets manager for your terminal
Documentation
%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
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}>(?:.|$))         # between 0 and 3 spaces, followed by a greater than sign, followed by any character or the end of the line
    atx_heading: (?:[#]{1,6}\s*)             # between 1 and 6 hashes, followed by any amount of whitespace
    indented_code_block: (?:[ ]{4}|\t)       # 4 spaces or a tab
    list_item: (?:[ ]{,3}(?=\d+\.|[*+-])\d*([*+.-])\s) # between 0 and 3 spaces, followed by either: at least one integer and a full stop, or (a star, plus or dash), followed by whitespace
    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: |- # Pipes inside other inline spans (such as emphasis, code, etc.) will not break a cell, emphasis in table cells can't span multiple lines
      (?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}}}]|/?>)
    # 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: |-
        (?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?)' # \n is optional so ## is matched as end punctuation in new document (at eof)
      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: '([ ]*)(\()' # spaces not allowed before the open paren, but we check for it anyway to mark it as invalid
      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: # After a valid domain, zero or more non-space non-< characters may follow
        - match: (?=[?!.,:*_~]*[\s<]) # Trailing punctuation (specifically, ?, !, ., ,, :, *, _, and ~) will not be considered part of the autolink, though they may be included in the interior of the link
          pop: true
        - match: (?={{html_entity}}[?!.,:*_~]*[\s<]) # If an autolink ends in a semicolon (;), we check to see if it appears to resemble an entity reference; if the preceding text is & followed by one or more alphanumeric characters. If so, it is excluded from the autolink
          pop: true
        - match: \( # When an autolink ends in ), we scan the entire autolink for the total number of parentheses. If there is a greater number of closing parentheses than opening ones, we don’t consider the last character part of the autolink, in order to facilitate including an autolink inside a parenthesis
          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: '([ ]*)(\()' # spaces not allowed before the open paren, but we check for it anyway to mark it as invalid
      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: \[ # nested square brackets are allowed
      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

###[ LINK/IMAGE/REFERENCE ATTRIBUTES ]########################################

  tag-attributes:
    # https://kramdown.gettalong.org/syntax.html#span-ials
    # https://michelf.ca/projects/php-markdown/extra/
    # https://pandoc.org/MANUAL.html#extension-link_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 ]##################################################################

  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: |- # The table is broken at the first empty line, or beginning of another block-level structure
                          (?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

###[ PROTOTYPES ]#############################################################

  else-pop:
    - match: (?=\S)
      pop: true

  immediately-pop:
    - match: ''
      pop: true