1" Vim syntax file
2" Language:     Markdown
3" Maintainer:   Tim Pope <vimNOSPAM@tpope.org>
4" Filenames:    *.markdown
5" Last Change:  2020 Jan 14
6
7if exists("b:current_syntax")
8  finish
9endif
10
11if !exists('main_syntax')
12  let main_syntax = 'markdown'
13endif
14
15runtime! syntax/html.vim
16unlet! b:current_syntax
17
18if !exists('g:markdown_fenced_languages')
19  let g:markdown_fenced_languages = []
20endif
21let s:done_include = {}
22for s:type in map(copy(g:markdown_fenced_languages),'matchstr(v:val,"[^=]*$")')
23  if has_key(s:done_include, matchstr(s:type,'[^.]*'))
24    continue
25  endif
26  if s:type =~ '\.'
27    let b:{matchstr(s:type,'[^.]*')}_subtype = matchstr(s:type,'\.\zs.*')
28  endif
29  exe 'syn include @markdownHighlight'.substitute(s:type,'\.','','g').' syntax/'.matchstr(s:type,'[^.]*').'.vim'
30  unlet! b:current_syntax
31  let s:done_include[matchstr(s:type,'[^.]*')] = 1
32endfor
33unlet! s:type
34unlet! s:done_include
35
36if !exists('g:markdown_minlines')
37  let g:markdown_minlines = 50
38endif
39execute 'syn sync minlines=' . g:markdown_minlines
40syn case ignore
41
42syn match markdownValid '[<>]\c[a-z/$!]\@!' transparent contains=NONE
43syn match markdownValid '&\%(#\=\w*;\)\@!' transparent contains=NONE
44
45syn match markdownLineStart "^[<@]\@!" nextgroup=@markdownBlock,htmlSpecialChar
46
47syn cluster markdownBlock contains=markdownH1,markdownH2,markdownH3,markdownH4,markdownH5,markdownH6,markdownBlockquote,markdownListMarker,markdownOrderedListMarker,markdownCodeBlock,markdownRule
48syn cluster markdownInline contains=markdownLineBreak,markdownLinkText,markdownItalic,markdownBold,markdownCode,markdownEscape,@htmlTop,markdownError,markdownValid
49
50syn match markdownH1 "^.\+\n=\+$" contained contains=@markdownInline,markdownHeadingRule,markdownAutomaticLink
51syn match markdownH2 "^.\+\n-\+$" contained contains=@markdownInline,markdownHeadingRule,markdownAutomaticLink
52
53syn match markdownHeadingRule "^[=-]\+$" contained
54
55syn region markdownH1 matchgroup=markdownH1Delimiter start="##\@!"      end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained
56syn region markdownH2 matchgroup=markdownH2Delimiter start="###\@!"     end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained
57syn region markdownH3 matchgroup=markdownH3Delimiter start="####\@!"    end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained
58syn region markdownH4 matchgroup=markdownH4Delimiter start="#####\@!"   end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained
59syn region markdownH5 matchgroup=markdownH5Delimiter start="######\@!"  end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained
60syn region markdownH6 matchgroup=markdownH6Delimiter start="#######\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained
61
62syn match markdownBlockquote ">\%(\s\|$\)" contained nextgroup=@markdownBlock
63
64syn region markdownCodeBlock start="    \|\t" end="$" contained
65
66" TODO: real nesting
67syn match markdownListMarker "\%(\t\| \{0,4\}\)[-*+]\%(\s\+\S\)\@=" contained
68syn match markdownOrderedListMarker "\%(\t\| \{0,4}\)\<\d\+\.\%(\s\+\S\)\@=" contained
69
70syn match markdownRule "\* *\* *\*[ *]*$" contained
71syn match markdownRule "- *- *-[ -]*$" contained
72
73syn match markdownLineBreak " \{2,\}$"
74
75syn region markdownIdDeclaration matchgroup=markdownLinkDelimiter start="^ \{0,3\}!\=\[" end="\]:" oneline keepend nextgroup=markdownUrl skipwhite
76syn match markdownUrl "\S\+" nextgroup=markdownUrlTitle skipwhite contained
77syn region markdownUrl matchgroup=markdownUrlDelimiter start="<" end=">" oneline keepend nextgroup=markdownUrlTitle skipwhite contained
78syn region markdownUrlTitle matchgroup=markdownUrlTitleDelimiter start=+"+ end=+"+ keepend contained
79syn region markdownUrlTitle matchgroup=markdownUrlTitleDelimiter start=+'+ end=+'+ keepend contained
80syn region markdownUrlTitle matchgroup=markdownUrlTitleDelimiter start=+(+ end=+)+ keepend contained
81
82syn region markdownLinkText matchgroup=markdownLinkTextDelimiter start="!\=\[\%(\%(\_[^][]\|\[\_[^][]*\]\)*]\%( \=[[(]\)\)\@=" end="\]\%( \=[[(]\)\@=" nextgroup=markdownLink,markdownId skipwhite contains=@markdownInline,markdownLineStart
83syn region markdownLink matchgroup=markdownLinkDelimiter start="(" end=")" contains=markdownUrl keepend contained
84syn region markdownId matchgroup=markdownIdDelimiter start="\[" end="\]" keepend contained
85syn region markdownAutomaticLink matchgroup=markdownUrlDelimiter start="<\%(\w\+:\|[[:alnum:]_+-]\+@\)\@=" end=">" keepend oneline
86
87let s:concealends = ''
88if has('conceal') && get(g:, 'markdown_syntax_conceal', 1) == 1
89  let s:concealends = ' concealends'
90endif
91exe 'syn region markdownItalic matchgroup=markdownItalicDelimiter start="\S\@<=\*\|\*\S\@=" end="\S\@<=\*\|\*\S\@=" skip="\\\*" contains=markdownLineStart,@Spell' . s:concealends
92exe 'syn region markdownItalic matchgroup=markdownItalicDelimiter start="\w\@<!_\S\@=" end="\S\@<=_\w\@!" skip="\\_" contains=markdownLineStart,@Spell' . s:concealends
93exe 'syn region markdownBold matchgroup=markdownBoldDelimiter start="\S\@<=\*\*\|\*\*\S\@=" end="\S\@<=\*\*\|\*\*\S\@=" skip="\\\*" contains=markdownLineStart,markdownItalic,@Spell' . s:concealends
94exe 'syn region markdownBold matchgroup=markdownBoldDelimiter start="\w\@<!__\S\@=" end="\S\@<=__\w\@!" skip="\\_" contains=markdownLineStart,markdownItalic,@Spell' . s:concealends
95exe 'syn region markdownBoldItalic matchgroup=markdownBoldItalicDelimiter start="\S\@<=\*\*\*\|\*\*\*\S\@=" end="\S\@<=\*\*\*\|\*\*\*\S\@=" skip="\\\*" contains=markdownLineStart,@Spell' . s:concealends
96exe 'syn region markdownBoldItalic matchgroup=markdownBoldItalicDelimiter start="\w\@<!___\S\@=" end="\S\@<=___\w\@!" skip="\\_" contains=markdownLineStart,@Spell' . s:concealends
97
98syn region markdownCode matchgroup=markdownCodeDelimiter start="`" end="`" keepend contains=markdownLineStart
99syn region markdownCode matchgroup=markdownCodeDelimiter start="`` \=" end=" \=``" keepend contains=markdownLineStart
100syn region markdownCode matchgroup=markdownCodeDelimiter start="^\s*````*.*$" end="^\s*````*\ze\s*$" keepend
101
102syn match markdownFootnote "\[^[^\]]\+\]"
103syn match markdownFootnoteDefinition "^\[^[^\]]\+\]:"
104
105if main_syntax ==# 'markdown'
106  let s:done_include = {}
107  for s:type in g:markdown_fenced_languages
108    if has_key(s:done_include, matchstr(s:type,'[^.]*'))
109      continue
110    endif
111    exe 'syn region markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\..*','','').' matchgroup=markdownCodeDelimiter start="^\s*````*\s*\%({.\{-}\.\)\='.matchstr(s:type,'[^=]*').'}\=\S\@!.*$" end="^\s*````*\ze\s*$" keepend contains=@markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\.','','g') . s:concealends
112    let s:done_include[matchstr(s:type,'[^.]*')] = 1
113  endfor
114  unlet! s:type
115  unlet! s:done_include
116endif
117
118syn match markdownEscape "\\[][\\`*_{}()<>#+.!-]"
119syn match markdownError "\w\@<=_\w\@="
120
121hi def link markdownH1                    htmlH1
122hi def link markdownH2                    htmlH2
123hi def link markdownH3                    htmlH3
124hi def link markdownH4                    htmlH4
125hi def link markdownH5                    htmlH5
126hi def link markdownH6                    htmlH6
127hi def link markdownHeadingRule           markdownRule
128hi def link markdownH1Delimiter           markdownHeadingDelimiter
129hi def link markdownH2Delimiter           markdownHeadingDelimiter
130hi def link markdownH3Delimiter           markdownHeadingDelimiter
131hi def link markdownH4Delimiter           markdownHeadingDelimiter
132hi def link markdownH5Delimiter           markdownHeadingDelimiter
133hi def link markdownH6Delimiter           markdownHeadingDelimiter
134hi def link markdownHeadingDelimiter      Delimiter
135hi def link markdownOrderedListMarker     markdownListMarker
136hi def link markdownListMarker            htmlTagName
137hi def link markdownBlockquote            Comment
138hi def link markdownRule                  PreProc
139
140hi def link markdownFootnote              Typedef
141hi def link markdownFootnoteDefinition    Typedef
142
143hi def link markdownLinkText              htmlLink
144hi def link markdownIdDeclaration         Typedef
145hi def link markdownId                    Type
146hi def link markdownAutomaticLink         markdownUrl
147hi def link markdownUrl                   Float
148hi def link markdownUrlTitle              String
149hi def link markdownIdDelimiter           markdownLinkDelimiter
150hi def link markdownUrlDelimiter          htmlTag
151hi def link markdownUrlTitleDelimiter     Delimiter
152
153hi def link markdownItalic                htmlItalic
154hi def link markdownItalicDelimiter       markdownItalic
155hi def link markdownBold                  htmlBold
156hi def link markdownBoldDelimiter         markdownBold
157hi def link markdownBoldItalic            htmlBoldItalic
158hi def link markdownBoldItalicDelimiter   markdownBoldItalic
159hi def link markdownCodeDelimiter         Delimiter
160
161hi def link markdownEscape                Special
162hi def link markdownError                 Error
163
164let b:current_syntax = "markdown"
165if main_syntax ==# 'markdown'
166  unlet main_syntax
167endif
168
169" vim:set sw=2:
170