summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Stankiewicz <sheerun@sher.pl>2019-12-12 16:43:09 +0100
committerAdam Stankiewicz <sheerun@sher.pl>2019-12-12 16:43:09 +0100
commitcea0d08a062478503814e51aa21c6486a0dd1b21 (patch)
tree085f856a71019a5f9046501b9f45116286726d51
parent43085dc02f34d7d54208e6e20989d4779bffe71c (diff)
downloadvim-polyglot-4.1.4.tar.gz
vim-polyglot-4.1.4.zip
Replace markdown plugin for faster onev4.1.4
-rw-r--r--README.md2
-rw-r--r--after/ftplugin/markdown.vim205
-rw-r--r--autoload/markdown.vim532
-rwxr-xr-xbuild2
-rw-r--r--config.vim12
-rw-r--r--ftdetect/polyglot.vim23
-rw-r--r--ftplugin/markdown.vim903
-rw-r--r--indent/markdown.vim79
-rw-r--r--syntax/markdown.vim1085
-rw-r--r--syntax/markdown_jekyll.vim34
10 files changed, 1671 insertions, 1206 deletions
diff --git a/README.md b/README.md
index 52e2776b..e41ef2ad 100644
--- a/README.md
+++ b/README.md
@@ -119,7 +119,7 @@ If you need full functionality of any plugin, please use it directly with your p
- [log](https://github.com/MTDL9/vim-log-highlighting) (syntax)
- [lua](https://github.com/tbastos/vim-lua) (syntax, indent)
- [mako](https://github.com/sophacles/vim-bundle-mako) (syntax, indent, ftplugin)
-- [markdown](https://github.com/plasticboy/vim-markdown) (syntax, indent, ftplugin)
+- [markdown](https://github.com/gabrielelana/vim-markdown) (syntax, autoload, ftplugin)
- [mathematica](https://github.com/voldikss/vim-mma) (syntax, ftplugin)
- [mdx](https://github.com/jxnblk/vim-mdx-js) (syntax)
- [meson](https://github.com/mesonbuild/meson) (syntax, indent, ftplugin)
diff --git a/after/ftplugin/markdown.vim b/after/ftplugin/markdown.vim
deleted file mode 100644
index 1d1e410c..00000000
--- a/after/ftplugin/markdown.vim
+++ /dev/null
@@ -1,205 +0,0 @@
-if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1
-
-" vim: ts=4 sw=4:
-" folding for Markdown headers, both styles (atx- and setex-)
-" http://daringfireball.net/projects/markdown/syntax#header
-"
-" this code can be placed in file
-" $HOME/.vim/after/ftplugin/markdown.vim
-"
-" original version from Steve Losh's gist: https://gist.github.com/1038710
-
-function! s:is_mkdCode(lnum)
- let name = synIDattr(synID(a:lnum, 1, 0), 'name')
- return (name =~ '^mkd\%(Code$\|Snippet\)' || name != '' && name !~ '^\%(mkd\|html\)')
-endfunction
-
-if get(g:, "vim_markdown_folding_style_pythonic", 0)
- function! Foldexpr_markdown(lnum)
- let l1 = getline(a:lnum)
- "~~~~~ keep track of fenced code blocks ~~~~~
- "If we hit a code block fence
- if l1 =~ '````*' || l1 =~ '\~\~\~\~*'
- " toggle the variable that says if we're in a code block
- if b:fenced_block == 0
- let b:fenced_block = 1
- elseif b:fenced_block == 1
- let b:fenced_block = 0
- endif
- " else, if we're caring about front matter
- elseif g:vim_markdown_frontmatter == 1
- " if we're in front matter and not on line 1
- if b:front_matter == 1 && a:lnum > 2
- let l0 = getline(a:lnum-1)
- " if the previous line fenced front matter
- if l0 == '---'
- " we must not be in front matter
- let b:front_matter = 0
- endif
- " else, if we're on line one
- elseif a:lnum == 1
- " if we hit a front matter fence
- if l1 == '---'
- " we're in the front matter
- let b:front_matter = 1
- endif
- endif
- endif
-
- " if we're in a code block or front matter
- if b:fenced_block == 1 || b:front_matter == 1
- if a:lnum == 1
- " fold any 'preamble'
- return '>1'
- else
- " keep previous foldlevel
- return '='
- endif
- endif
-
- let l2 = getline(a:lnum+1)
- " if the next line starts with two or more '='
- " and is not code
- if l2 =~ '^==\+\s*' && !s:is_mkdCode(a:lnum+1)
- " next line is underlined (level 1)
- return '>0'
- " else, if the nex line starts with two or more '-'
- " and is not code
- elseif l2 =~ '^--\+\s*' && !s:is_mkdCode(a:lnum+1)
- " next line is underlined (level 2)
- return '>1'
- endif
-
- "if we're on a non-code line starting with a pound sign
- if l1 =~ '^#' && !s:is_mkdCode(a:lnum)
- " set the fold level to the number of hashes -1
- " return '>'.(matchend(l1, '^#\+') - 1)
- " set the fold level to the number of hashes
- return '>'.(matchend(l1, '^#\+'))
- " else, if we're on line 1
- elseif a:lnum == 1
- " fold any 'preamble'
- return '>1'
- else
- " keep previous foldlevel
- return '='
- endif
- endfunction
-
- function! Foldtext_markdown()
- let line = getline(v:foldstart)
- let has_numbers = &number || &relativenumber
- let nucolwidth = &fdc + has_numbers * &numberwidth
- let windowwidth = winwidth(0) - nucolwidth - 6
- let foldedlinecount = v:foldend - v:foldstart
- let line = strpart(line, 0, windowwidth - 2 -len(foldedlinecount))
- let line = substitute(line, '\%("""\|''''''\)', '', '')
- let fillcharcount = windowwidth - len(line) - len(foldedlinecount) + 1
- return line . ' ' . repeat("-", fillcharcount) . ' ' . foldedlinecount
- endfunction
-else " vim_markdown_folding_style_pythonic == 0
- function! Foldexpr_markdown(lnum)
- if (a:lnum == 1)
- let l0 = ''
- else
- let l0 = getline(a:lnum-1)
- endif
-
- " keep track of fenced code blocks
- if l0 =~ '````*' || l0 =~ '\~\~\~\~*'
- if b:fenced_block == 0
- let b:fenced_block = 1
- elseif b:fenced_block == 1
- let b:fenced_block = 0
- endif
- elseif g:vim_markdown_frontmatter == 1
- if b:front_matter == 1
- if l0 == '---'
- let b:front_matter = 0
- endif
- elseif a:lnum == 2
- if l0 == '---'
- let b:front_matter = 1
- endif
- endif
- endif
-
- if b:fenced_block == 1 || b:front_matter == 1
- " keep previous foldlevel
- return '='
- endif
-
- let l2 = getline(a:lnum+1)
- if l2 =~ '^==\+\s*' && !s:is_mkdCode(a:lnum+1)
- " next line is underlined (level 1)
- return '>1'
- elseif l2 =~ '^--\+\s*' && !s:is_mkdCode(a:lnum+1)
- " next line is underlined (level 2)
- if s:vim_markdown_folding_level >= 2
- return '>1'
- else
- return '>2'
- endif
- endif
-
- let l1 = getline(a:lnum)
- if l1 =~ '^#' && !s:is_mkdCode(a:lnum)
- " fold level according to option
- if s:vim_markdown_folding_level == 1 || matchend(l1, '^#\+') > s:vim_markdown_folding_level
- if a:lnum == line('$')
- return matchend(l1, '^#\+') - 1
- else
- return -1
- endif
- else
- " headers are not folded
- return 0
- endif
- endif
-
- if l0 =~ '^#' && !s:is_mkdCode(a:lnum-1)
- " previous line starts with hashes
- return '>'.matchend(l0, '^#\+')
- else
- " keep previous foldlevel
- return '='
- endif
- endfunction
-endif
-
-
-let b:fenced_block = 0
-let b:front_matter = 0
-let s:vim_markdown_folding_level = get(g:, "vim_markdown_folding_level", 1)
-
-function! s:MarkdownSetupFolding()
- if !get(g:, "vim_markdown_folding_disabled", 0)
- if get(g:, "vim_markdown_folding_style_pythonic", 0)
- if get(g:, "vim_markdown_override_foldtext", 1)
- setlocal foldtext=Foldtext_markdown()
- endif
- endif
- setlocal foldexpr=Foldexpr_markdown(v:lnum)
- setlocal foldmethod=expr
- endif
-endfunction
-
-function! s:MarkdownSetupFoldLevel()
- if get(g:, "vim_markdown_folding_style_pythonic", 0)
- " set default foldlevel
- execute "setlocal foldlevel=".s:vim_markdown_folding_level
- endif
-endfunction
-
-call s:MarkdownSetupFoldLevel()
-call s:MarkdownSetupFolding()
-
-augroup Mkd
- " These autocmds need to be kept in sync with the autocmds calling
- " s:MarkdownRefreshSyntax in ftplugin/markdown.vim.
- autocmd BufWinEnter,BufWritePost <buffer> call s:MarkdownSetupFolding()
- autocmd InsertEnter,InsertLeave <buffer> call s:MarkdownSetupFolding()
- autocmd CursorHold,CursorHoldI <buffer> call s:MarkdownSetupFolding()
-augroup END
-
-endif
diff --git a/autoload/markdown.vim b/autoload/markdown.vim
new file mode 100644
index 00000000..3db667e1
--- /dev/null
+++ b/autoload/markdown.vim
@@ -0,0 +1,532 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1
+
+
+" {{{ FOLDING
+
+function! markdown#FoldLevelOfLine(lnum)
+ let currentline = getline(a:lnum)
+ let nextline = getline(a:lnum + 1)
+
+ " an empty line is not going to change the indentation level
+ if match(currentline, '^\s*$') >= 0
+ return '='
+ endif
+
+ " folding lists
+ if s:SyntaxGroupOfLineIs(a:lnum, '^markdownListItem')
+ if s:SyntaxGroupOfLineIs(a:lnum - 1, '^markdownListItem')
+ return 'a1'
+ endif
+ if s:SyntaxGroupOfLineIs(a:lnum + 1, '^markdownListItem')
+ return 's1'
+ endif
+ return '='
+ endif
+
+ " we are not going to fold things inside list items, too hairy
+ let is_inside_a_list_item = s:SyntaxGroupOfLineIs(a:lnum, '^markdownListItem')
+ if is_inside_a_list_item
+ return '='
+ endif
+
+ " folding atx headers
+ if match(currentline, '^#\{1,6}\s') >= 0
+ let header_level = strlen(substitute(currentline, '^\(#\{1,6}\).*', '\1', ''))
+ return '>' . header_level
+ endif
+
+ " folding fenced code blocks
+ let next_line_syntax_group = synIDattr(synID(a:lnum + 1, 1, 1), 'name')
+ if match(currentline, '^\s*```') >= 0
+ if next_line_syntax_group ==# 'markdownFencedCodeBlock'
+ return 'a1'
+ endif
+ return 's1'
+ endif
+
+ " folding code blocks
+ let current_line_syntax_group = synIDattr(synID(a:lnum, 1, 1), 'name')
+ let prev_line_syntax_group = synIDattr(synID(a:lnum - 1, 1, 1), 'name')
+ if match(currentline, '^\s\{4,}') >= 0
+ if current_line_syntax_group ==# 'markdownCodeBlock'
+ if prev_line_syntax_group !=# 'markdownCodeBlock'
+ return 'a1'
+ endif
+ if next_line_syntax_group !=# 'markdownCodeBlock'
+ return 's1'
+ endif
+ endif
+ return '='
+ endif
+
+ " folding setex headers
+ if (match(currentline, '^.*$') >= 0)
+ if (match(nextline, '^=\+$') >= 0)
+ return '>1'
+ endif
+ if (match(nextline, '^-\+$') >= 0)
+ return '>2'
+ endif
+ endif
+
+ return '='
+endfunction
+
+function! s:SyntaxGroupOfLineIs(lnum, pattern)
+ let stack = synstack(a:lnum, a:cnum)
+ if len(stack) > 0
+ return synIDattr(stack[0], 'name') =~# a:pattern
+ endif
+ return 0
+endfunction
+
+" }}}
+
+" {{{ EDIT
+
+function! markdown#EditBlock() range abort
+ if exists('b:markdown_temporary_buffer') && b:markdown_temporary_buffer
+ echo 'Sorry, you cannot edit a code block inside a temporary buffer'
+ return
+ endif
+ " Github fenced code blocks like ```ruby
+ let code_block = s:LocateFencedCodeBlock(a:firstline,
+ \ '^\s*`\{3,}\(\w\+\)\%(\s.*$\|$\)',
+ \ '^\s*`\{3,}\s*$'
+ \ )
+ if code_block['from'] == 0 || code_block['to'] == 0
+ " Github fenced code blocks with metadata like ```{ruby, <WHATEVER>}
+ let code_block = s:LocateFencedCodeBlock(a:firstline,
+ \ '^\s*`\{3,}{\(\w\+\),[^}]\+}\%(\s.*$\|$\)',
+ \ '^\s*`\{3,}\s*$'
+ \ )
+ endif
+ if code_block['from'] == 0 || code_block['to'] == 0
+ " Github fenced code blocks alternate style like ~~~ruby
+ let code_block = s:LocateFencedCodeBlock(a:firstline,
+ \ '^\s*\~\{3,}\(\w\+\)\%(\s.*$\|$\)',
+ \ '^\s*\~\{3,}\s*$'
+ \ )
+ endif
+ if code_block['from'] == 0 || code_block['to'] == 0
+ " Liquid fenced code blocks {% highlight ruby %}
+ " (since we support some liquid/jekyll tags, why not?)
+ let code_block = s:LocateFencedCodeBlock(a:firstline,
+ \ '^\s*{%\s*highlight\s\+\(\w\+\)\s*%}\%(\s.*$\|$\)',
+ \ '^\s*{%\s*endhighlight\s*%}\%(\s.*$\|$\)'
+ \ )
+ endif
+ if code_block['from'] == 0 || code_block['to'] == 0
+ let code_block = s:LocateRangeBlock(a:firstline, a:lastline)
+ endif
+ if code_block['from'] == 0 || code_block['to'] == 0
+ echo 'Sorry, I did not find any suitable code block to edit or create'
+ return
+ endif
+
+ let code_block['file_extension'] = '.' . code_block['language']
+ if has_key(s:known_file_extensions, code_block['language'])
+ let code_block['file_extension'] = s:known_file_extensions[code_block['language']]
+ endif
+ let code_block['file_path'] = tempname() . code_block['file_extension']
+ let code_block['content'] = getline(code_block['from'], code_block['to'])
+ let code_block['content'] = s:UnindentBlock(code_block['content'], code_block['indentation'])
+
+ call writefile(code_block['content'], code_block['file_path'])
+ augroup MarkdownReplaceEditedBlock
+ autocmd BufEnter <buffer> call s:ReplaceEditedBlock()
+ augroup END
+
+ let b:code_block = code_block
+ execute 'split ' . code_block['file_path']
+ let b:markdown_temporary_buffer = 1
+ autocmd BufLeave <buffer> wq
+endfunction
+
+function! s:ReplaceEditedBlock()
+ augroup MarkdownReplaceEditedBlock
+ autocmd!
+ augroup END
+ augroup! MarkdownReplaceEditedBlock
+
+ if b:code_block['to'] - b:code_block['from'] >= 0
+ execute b:code_block['from'] . ',' b:code_block['to'] . ' delete _'
+ endif
+ let content = readfile(b:code_block['file_path'])
+ let content = s:IndentBlock(l:content, b:code_block['indentation'])
+ let content = s:SurroundWithFencedCodeBlock(l:content, b:code_block)
+ call append(b:code_block['from']-1, content)
+ call setpos('.', b:code_block['back_to_position'])
+
+ execute 'silent bwipeout! ' . b:code_block['file_path']
+ call delete(b:code_block['file_path'])
+ unlet! b:code_block
+endfunction
+
+function! s:UnindentBlock(content, indentation)
+ return map(a:content, 'substitute(v:val, ''^' . a:indentation . ''', '''', ''g'')')
+endfunction
+
+function! s:IndentBlock(content, indentation)
+ return map(a:content, 'substitute(v:val, ''^'', ''' . a:indentation . ''', ''g'')')
+endfunction
+
+function! s:SurroundWithFencedCodeBlock(code, editing)
+ if !a:editing['surround'] | return a:code | endif
+ if a:editing['language'] =~# 'markdown' | return a:code | endif
+ let before =
+ \ (a:editing['make_room_before'] ? [''] : []) +
+ \ [a:editing['indentation'] . '```' . a:editing['language']]
+ let after =
+ \ [a:editing['indentation'] . '```'] +
+ \ (a:editing['make_room_after'] ? [''] : [])
+ return l:before + a:code + l:after
+endfunction
+
+function! s:LocateRangeBlock(from, to)
+ " TODO: extract initialize_code_block
+ let code_block = {'from': 0, 'to': 0, 'language': 'txt', 'indentation': '', 'surround': 0}
+ if a:to >= a:from
+ let code_block['from'] = a:from
+ let code_block['to'] = a:to
+ let code_block['back_to_position'] = getpos('.')
+ let code_block['language'] = 'markdown'
+
+ if a:from == a:to && getline(a:from) =~ '^\s*$'
+ let code_block['surround'] = 1
+ let code_block['make_room_before'] = getline(a:from - 1) !~ '^\s*$'
+ let code_block['make_room_after'] = getline(a:to + 1) !~ '^\s*$'
+ let code_block['language'] = input('filetype? (default: markdown) ', '', 'filetype')
+ if code_block['language'] =~ '^\s*$'
+ let code_block['language'] = 'markdown'
+ endif
+ endif
+ endif
+ return code_block
+endfunction
+
+function! s:LocateFencedCodeBlock(starting_from, upper_delimiter, lower_delimiter)
+ " TODO: extract initialize_code_block
+ let code_block = {'from': 0, 'to': 0, 'language': 'txt', 'indentation': '', 'surround': 0}
+ let initial_position = getpos('.')
+ let search_position = copy(initial_position)
+ let search_position[1] = a:starting_from
+ let search_position[2] = 0
+ cal setpos('.', search_position)
+
+ let start_code_block_backward = search(a:upper_delimiter, 'cbnW')
+ let end_code_block_backward = search(a:lower_delimiter, 'cbnW')
+ let end_code_block_forward = search(a:lower_delimiter, 'cnW')
+
+ let found_code_block =
+ \ start_code_block_backward > 0 &&
+ \ end_code_block_forward > 0
+ let between_two_code_blocks =
+ \ start_code_block_backward < end_code_block_backward &&
+ \ end_code_block_backward <= a:starting_from
+ let starting_inside_code_block =
+ \ found_code_block &&
+ \ !between_two_code_blocks &&
+ \ start_code_block_backward <= a:starting_from &&
+ \ end_code_block_forward >= a:starting_from
+
+ if starting_inside_code_block
+ let code_block['language'] = s:ExtractLanguage(start_code_block_backward, a:upper_delimiter)
+ let code_block['indentation'] = s:ExtractIndentation(start_code_block_backward)
+ let code_block['back_to_position'] = initial_position
+ let code_block['back_to_position'][1] = start_code_block_backward
+ let code_block['back_to_position'][2] = 0
+ let code_block['from'] = start_code_block_backward + 1
+ let code_block['to'] = end_code_block_forward - 1
+ endif
+ return code_block
+endfunction
+
+function! s:ExtractLanguage(start_at, upper_delimiter)
+ return substitute(getline(a:start_at), a:upper_delimiter, '\1', '')
+endfunction
+
+function! s:ExtractIndentation(start_at)
+ return substitute(getline(a:start_at), '\(^\s*\).\+$', '\1', '')
+endfunction
+
+let s:known_file_extensions = {
+ \ 'abap': '.abap',
+ \ 'antlr': '.g4',
+ \ 'asp': '.asp',
+ \ 'ats': '.dats',
+ \ 'actionscript': '.as',
+ \ 'ada': '.adb',
+ \ 'agda': '.agda',
+ \ 'apacheconf': '.apacheconf',
+ \ 'apex': '.cls',
+ \ 'applescript': '.applescript',
+ \ 'arc': '.arc',
+ \ 'arduino': '.ino',
+ \ 'asciidoc': '.asciidoc',
+ \ 'assembly': '.asm',
+ \ 'augeas': '.aug',
+ \ 'autohotkey': '.ahk',
+ \ 'autoit': '.au3',
+ \ 'awk': '.awk',
+ \ 'batchfile': '.bat',
+ \ 'befunge': '.befunge',
+ \ 'blitzbasic': '.bb',
+ \ 'blitzmax': '.bmx',
+ \ 'bluespec': '.bsv',
+ \ 'boo': '.boo',
+ \ 'brainfuck': '.b',
+ \ 'brightscript': '.brs',
+ \ 'bro': '.bro',
+ \ 'c': '.c',
+ \ 'c++': '.cpp',
+ \ 'cpp': '.cpp',
+ \ 'clips': '.clp',
+ \ 'cmake': '.cmake',
+ \ 'cobol': '.cob',
+ \ 'css': '.css',
+ \ 'ceylon': '.ceylon',
+ \ 'chuck': '.ck',
+ \ 'cirru': '.cirru',
+ \ 'clean': '.icl',
+ \ 'clojure': '.clj',
+ \ 'coffeescript': '.coffee',
+ \ 'coldfusion': '.cfm',
+ \ 'coq': '.coq',
+ \ 'creole': '.creole',
+ \ 'crystal': '.cr',
+ \ 'cucumber': '.feature',
+ \ 'cuda': '.cu',
+ \ 'cython': '.pyx',
+ \ 'd': '.d',
+ \ 'dm': '.dm',
+ \ 'dot': '.dot',
+ \ 'dart': '.dart',
+ \ 'diff': '.diff',
+ \ 'dylan': '.dylan',
+ \ 'ecl': '.ecl',
+ \ 'eiffel': '.e',
+ \ 'elixir': '.ex',
+ \ 'elm': '.elm',
+ \ 'erlang': '.erl',
+ \ 'flux': '.fx',
+ \ 'fortran': '.f90',
+ \ 'factor': '.factor',
+ \ 'fancy': '.fy',
+ \ 'fantom': '.fan',
+ \ 'forth': '.fth',
+ \ 'gas': '.s',
+ \ 'glsl': '.glsl',
+ \ 'genshi': '.kid',
+ \ 'glyph': '.glf',
+ \ 'go': '.go',
+ \ 'gosu': '.gs',
+ \ 'groff': '.man',
+ \ 'groovy': '.groovy',
+ \ 'html': '.html',
+ \ 'http': '.http',
+ \ 'haml': '.haml',
+ \ 'handlebars': '.handlebars',
+ \ 'harbour': '.hb',
+ \ 'haskell': '.hs',
+ \ 'haxe': '.hx',
+ \ 'hy': '.hy',
+ \ 'idl': '.pro',
+ \ 'ini': '.ini',
+ \ 'idris': '.idr',
+ \ 'io': '.io',
+ \ 'ioke': '.ik',
+ \ 'j': '.ijs',
+ \ 'json': '.json',
+ \ 'json5': '.json5',
+ \ 'jsonld': '.jsonld',
+ \ 'jade': '.jade',
+ \ 'java': '.java',
+ \ 'javascript': '.js',
+ \ 'julia': '.jl',
+ \ 'krl': '.krl',
+ \ 'kotlin': '.kt',
+ \ 'lfe': '.lfe',
+ \ 'llvm': '.ll',
+ \ 'lasso': '.lasso',
+ \ 'less': '.less',
+ \ 'lilypond': '.ly',
+ \ 'livescript': '.ls',
+ \ 'logos': '.xm',
+ \ 'logtalk': '.lgt',
+ \ 'lua': '.lua',
+ \ 'm': '.mumps',
+ \ 'makefile': '.mak',
+ \ 'mako': '.mako',
+ \ 'markdown': '.md',
+ \ 'mask': '.mask',
+ \ 'matlab': '.matlab',
+ \ 'max': '.maxpat',
+ \ 'mediawiki': '.mediawiki',
+ \ 'mirah': '.druby',
+ \ 'monkey': '.monkey',
+ \ 'moocode': '.moo',
+ \ 'moonscript': '.moon',
+ \ 'myghty': '.myt',
+ \ 'nsis': '.nsi',
+ \ 'nemerle': '.n',
+ \ 'netlogo': '.nlogo',
+ \ 'nginx': '.nginxconf',
+ \ 'nimrod': '.nim',
+ \ 'nu': '.nu',
+ \ 'numpy': '.numpy',
+ \ 'ocaml': '.ml',
+ \ 'objdump': '.objdump',
+ \ 'omgrofl': '.omgrofl',
+ \ 'opa': '.opa',
+ \ 'opencl': '.cl',
+ \ 'org': '.org',
+ \ 'oxygene': '.oxygene',
+ \ 'pawn': '.pwn',
+ \ 'php': '.php',
+ \ 'parrot': '.parrot',
+ \ 'pascal': '.pas',
+ \ 'perl': '.pl',
+ \ 'perl6': '.p6',
+ \ 'pike': '.pike',
+ \ 'pod': '.pod',
+ \ 'pogoscript': '.pogo',
+ \ 'postscript': '.ps',
+ \ 'powershell': '.ps1',
+ \ 'processing': '.pde',
+ \ 'prolog': '.prolog',
+ \ 'puppet': '.pp',
+ \ 'python': '.py',
+ \ 'qml': '.qml',
+ \ 'r': '.r',
+ \ 'rdoc': '.rdoc',
+ \ 'realbasic': '.rbbas',
+ \ 'rhtml': '.rhtml',
+ \ 'rmarkdown': '.rmd',
+ \ 'racket': '.rkt',
+ \ 'rebol': '.rebol',
+ \ 'redcode': '.cw',
+ \ 'robotframework': '.robot',
+ \ 'rouge': '.rg',
+ \ 'ruby': '.rb',
+ \ 'rust': '.rs',
+ \ 'scss': '.scss',
+ \ 'sql': '.sql',
+ \ 'sage': '.sage',
+ \ 'sass': '.sass',
+ \ 'scala': '.scala',
+ \ 'scaml': '.scaml',
+ \ 'scheme': '.scm',
+ \ 'scilab': '.sci',
+ \ 'self': '.self',
+ \ 'shell': '.sh',
+ \ 'shen': '.shen',
+ \ 'slash': '.sl',
+ \ 'smalltalk': '.st',
+ \ 'smarty': '.tpl',
+ \ 'squirrel': '.nut',
+ \ 'stylus': '.styl',
+ \ 'supercollider': '.scd',
+ \ 'toml': '.toml',
+ \ 'txl': '.txl',
+ \ 'tcl': '.tcl',
+ \ 'tcsh': '.tcsh',
+ \ 'tex': '.tex',
+ \ 'tea': '.tea',
+ \ 'textile': '.textile',
+ \ 'turing': '.t',
+ \ 'twig': '.twig',
+ \ 'typescript': '.ts',
+ \ 'unrealscript': '.uc',
+ \ 'vhdl': '.vhdl',
+ \ 'vala': '.vala',
+ \ 'verilog': '.v',
+ \ 'viml': '.vim',
+ \ 'volt': '.volt',
+ \ 'xc': '.xc',
+ \ 'xml': '.xml',
+ \ 'xproc': '.xpl',
+ \ 'xquery': '.xquery',
+ \ 'xs': '.xs',
+ \ 'xslt': '.xslt',
+ \ 'xtend': '.xtend',
+ \ 'yaml': '.yml',
+ \ 'ec': '.ec',
+ \ 'edn': '.edn',
+ \ 'fish': '.fish',
+ \ 'mupad': '.mu',
+ \ 'nesc': '.nc',
+ \ 'ooc': '.ooc',
+ \ 'restructuredtext': '.rst',
+ \ 'wisp': '.wisp',
+ \ 'xbase': '.prg',
+\ }
+
+" }}}
+
+" {{{ FORMAT
+function! markdown#FormatTable()
+ let p = '^\s*|\s.*\s|\s*$'
+ if exists(':Tabularize') && getline('.') =~# '^\s*|' && (getline(line('.')-1) =~# p || getline(line('.')+1) =~# p)
+ let column = strlen(substitute(getline('.')[0:col('.')],'[^|]','','g'))
+ let position = strlen(matchstr(getline('.')[0:col('.')],'.*|\s*\zs.*'))
+ let separator_line_number = search('^\s*|\s*-\{3,}', 'cbnW')
+
+ call s:ShrinkTableHeaderSeparator(separator_line_number)
+ Tabularize/|/l1
+ call s:ExpandTableHeaderSeparator(separator_line_number)
+ normal! 0
+
+ call search(repeat('[^|]*|',column).'\s\{-\}'.repeat('.',position),'ce',line('.'))
+ endif
+endfunction
+
+function! s:ShrinkTableHeaderSeparator(separator_line_number)
+ if a:separator_line_number > 0
+ let separator_line = getline(a:separator_line_number)
+ let separator_line = substitute(separator_line, '-\+', '---', 'g')
+ call setline(a:separator_line_number, separator_line)
+ endif
+endfunction
+
+function! s:ExpandTableHeaderSeparator(separator_line_number)
+ if a:separator_line_number > 0
+ let separator_line = getline(a:separator_line_number)
+ let separator_line = substitute(
+ \ separator_line,
+ \ '|\([^|]*\)',
+ \ '\="| " . repeat("-", strlen(submatch(1)) - 2) . " "',
+ \ 'g')
+ let separator_line = substitute(separator_line, '\s*$', '', '')
+ call setline(a:separator_line_number, separator_line)
+ endif
+endfunction
+" }}}
+
+" {{{ SWITCH STATUS
+function! markdown#SwitchStatus()
+ let current_line = getline('.')
+ if match(current_line, '^\s*[*\-+] \[ \]') >= 0
+ call setline('.', substitute(current_line, '^\(\s*[*\-+]\) \[ \]', '\1 [x]', ''))
+ return
+ endif
+ if match(current_line, '^\s*[*\-+] \[x\]') >= 0
+ call setline('.', substitute(current_line, '^\(\s*[*\-+]\) \[x\]', '\1', ''))
+ return
+ endif
+ if match(current_line, '^\s*[*\-+] \(\[[x ]\]\)\@!') >= 0
+ call setline('.', substitute(current_line, '^\(\s*[*\-+]\)', '\1 [ ]', ''))
+ return
+ endif
+ if match(current_line, '^\s*#\{1,5}\s') >= 0
+ call setline('.', substitute(current_line, '^\(\s*#\{1,5}\) \(.*$\)', '\1# \2', ''))
+ return
+ endif
+ if match(current_line, '^\s*#\{6}\s') >= 0
+ call setline('.', substitute(current_line, '^\(\s*\)#\{6} \(.*$\)', '\1# \2', ''))
+ return
+ endif
+endfunction
+" }}}
+
+endif
diff --git a/build b/build
index 7e4b5221..67ad3c50 100755
--- a/build
+++ b/build
@@ -233,7 +233,7 @@ PACKS="
log:MTDL9/vim-log-highlighting
lua:tbastos/vim-lua
mako:sophacles/vim-bundle-mako
- markdown:plasticboy/vim-markdown
+ markdown:gabrielelana/vim-markdown
mathematica:voldikss/vim-mma
mdx:jxnblk/vim-mdx-js
meson:mesonbuild/meson:_ALL:/data/syntax-highlighting/vim/
diff --git a/config.vim b/config.vim
index 1565a7ec..86db52a9 100644
--- a/config.vim
+++ b/config.vim
@@ -1,3 +1,15 @@
+if !exists('g:markdown_enable_spell_checking')
+ let g:markdown_enable_spell_checking = 0
+end
+
+if !exists('g:markdown_enable_input_abbreviations')
+ let g:markdown_enable_input_abbreviations = 0
+end
+
+if !exists('g:markdown_enable_mappings')
+ let g:markdown_enable_mappings = 0
+end
+
" Enable jsx syntax by default
if !exists('g:jsx_ext_required')
let g:jsx_ext_required = 0
diff --git a/ftdetect/polyglot.vim b/ftdetect/polyglot.vim
index 5ab23e80..480ea023 100644
--- a/ftdetect/polyglot.vim
+++ b/ftdetect/polyglot.vim
@@ -1,3 +1,15 @@
+if !exists('g:markdown_enable_spell_checking')
+ let g:markdown_enable_spell_checking = 0
+end
+
+if !exists('g:markdown_enable_input_abbreviations')
+ let g:markdown_enable_input_abbreviations = 0
+end
+
+if !exists('g:markdown_enable_mappings')
+ let g:markdown_enable_mappings = 0
+end
+
" Enable jsx syntax by default
if !exists('g:jsx_ext_required')
let g:jsx_ext_required = 0
@@ -781,15 +793,8 @@ endif
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1
augroup filetypedetect
- " markdown, from markdown.vim in plasticboy/vim-markdown
-if !has('patch-7.4.480')
- " Before this patch, vim used modula2 for .md.
- au! filetypedetect BufRead,BufNewFile *.md
-endif
-
-" markdown filetype file
-au BufRead,BufNewFile *.{md,mdown,mkd,mkdn,markdown,mdwn} setfiletype markdown
-au BufRead,BufNewFile *.{md,mdown,mkd,mkdn,markdown,mdwn}.{des3,des,bf,bfa,aes,idea,cast,rc2,rc4,rc5,desx} setfiletype markdown
+ " markdown, from markdown.vim in gabrielelana/vim-markdown
+au BufRead,BufNewFile *.{md,mdown,mkd,mkdn,markdown,mdwn} set filetype=markdown
augroup end
endif
diff --git a/ftplugin/markdown.vim b/ftplugin/markdown.vim
index 43c9773a..8d327f61 100644
--- a/ftplugin/markdown.vim
+++ b/ftplugin/markdown.vim
@@ -1,795 +1,202 @@
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1
-"TODO print messages when on visual mode. I only see VISUAL, not the messages.
-
-" Function interface phylosophy:
-"
-" - functions take arbitrary line numbers as parameters.
-" Current cursor line is only a suitable default parameter.
-"
-" - only functions that bind directly to user actions:
-"
-" - print error messages.
-" All intermediate functions limit themselves return `0` to indicate an error.
-"
-" - move the cursor. All other functions do not move the cursor.
-"
-" This is how you should view headers for the header mappings:
-"
-" |BUFFER
-" |
-" |Outside any header
-" |
-" a-+# a
-" |
-" |Inside a
-" |
-" a-+
-" b-+## b
-" |
-" |inside b
-" |
-" b-+
-" c-+### c
-" |
-" |Inside c
-" |
-" c-+
-" d-|# d
-" |
-" |Inside d
-" |
-" d-+
-" e-|e
-" |====
-" |
-" |Inside e
-" |
-" e-+
-
-" For each level, contains the regexp that matches at that level only.
-"
-let s:levelRegexpDict = {
- \ 1: '\v^(#[^#]@=|.+\n\=+$)',
- \ 2: '\v^(##[^#]@=|.+\n-+$)',
- \ 3: '\v^###[^#]@=',
- \ 4: '\v^####[^#]@=',
- \ 5: '\v^#####[^#]@=',
- \ 6: '\v^######[^#]@='
-\ }
-
-" Maches any header level of any type.
-"
-" This could be deduced from `s:levelRegexpDict`, but it is more
-" efficient to have a single regexp for this.
-"
-let s:headersRegexp = '\v^(#|.+\n(\=+|-+)$)'
-
-" Returns the line number of the first header before `line`, called the
-" current header.
-"
-" If there is no current header, return `0`.
-"
-" @param a:1 The line to look the header of. Default value: `getpos('.')`.
-"
-function! s:GetHeaderLineNum(...)
- if a:0 == 0
- let l:l = line('.')
- else
- let l:l = a:1
- endif
- while(l:l > 0)
- if join(getline(l:l, l:l + 1), "\n") =~ s:headersRegexp
- return l:l
- endif
- let l:l -= 1
- endwhile
- return 0
-endfunction
+if exists('b:did_ftplugin') | finish | endif
-" - if inside a header goes to it.
-" Return its line number.
-"
-" - if on top level outside any headers,
-" print a warning
-" Return `0`.
-"
-function! s:MoveToCurHeader()
- let l:lineNum = s:GetHeaderLineNum()
- if l:lineNum != 0
- call cursor(l:lineNum, 1)
- else
- echo 'outside any header'
- "normal! gg
- endif
- return l:lineNum
-endfunction
+" {{{ CONFIGURATION
-" Move cursor to next header of any level.
-"
-" If there are no more headers, print a warning.
-"
-function! s:MoveToNextHeader()
- if search(s:headersRegexp, 'W') == 0
- "normal! G
- echo 'no next header'
- endif
-endfunction
+if !exists('g:markdown_flavor')
+ let g:markdown_flavor = 'github'
+endif
-" Move cursor to previous header (before current) of any level.
-"
-" If it does not exist, print a warning.
-"
-function! s:MoveToPreviousHeader()
- let l:curHeaderLineNumber = s:GetHeaderLineNum()
- let l:noPreviousHeader = 0
- if l:curHeaderLineNumber <= 1
- let l:noPreviousHeader = 1
- else
- let l:previousHeaderLineNumber = s:GetHeaderLineNum(l:curHeaderLineNumber - 1)
- if l:previousHeaderLineNumber == 0
- let l:noPreviousHeader = 1
- else
- call cursor(l:previousHeaderLineNumber, 1)
- endif
- endif
- if l:noPreviousHeader
- echo 'no previous header'
- endif
-endfunction
+if !exists('g:markdown_enable_folding')
+ let g:markdown_enable_folding = 0
+endif
-" - if line is inside a header, return the header level (h1 -> 1, h2 -> 2, etc.).
-"
-" - if line is at top level outside any headers, return `0`.
-"
-function! s:GetHeaderLevel(...)
- if a:0 == 0
- let l:line = line('.')
- else
- let l:line = a:1
- endif
- let l:linenum = s:GetHeaderLineNum(l:line)
- if l:linenum != 0
- return s:GetLevelOfHeaderAtLine(l:linenum)
- else
- return 0
- endif
-endfunction
+if !exists('g:markdown_enable_mappings')
+ " make it compatible with previous configuration value
+ if exists('g:markdown_include_default_mappings')
+ let g:markdown_enable_mappings = g:markdown_include_default_mappings
+ else
+ let g:markdown_enable_mappings = 1
+ endif
+endif
-" Returns the level of the header at the given line.
-"
-" If there is no header at the given line, returns `0`.
-"
-function! s:GetLevelOfHeaderAtLine(linenum)
- let l:lines = join(getline(a:linenum, a:linenum + 1), "\n")
- for l:key in keys(s:levelRegexpDict)
- if l:lines =~ get(s:levelRegexpDict, l:key)
- return l:key
- endif
- endfor
- return 0
-endfunction
+if !exists('g:markdown_enable_insert_mode_mappings')
+ " make it compatible with previous configuration value
+ if exists('g:markdown_include_insert_mode_default_mappings')
+ let g:markdown_enable_insert_mode_mappings = g:markdown_include_insert_mode_default_mappings
+ else
+ let g:markdown_enable_insert_mode_mappings = 1
+ endif
+endif
-" Move cursor to parent header of the current header.
-"
-" If it does not exit, print a warning and do nothing.
-"
-function! s:MoveToParentHeader()
- let l:linenum = s:GetParentHeaderLineNumber()
- if l:linenum != 0
- call cursor(l:linenum, 1)
- else
- echo 'no parent header'
- endif
-endfunction
+if !exists('g:markdown_enable_insert_mode_leader_mappings')
+ let g:markdown_enable_insert_mode_leader_mappings = 0
+endif
-" Return the line number of the parent header of line `line`.
-"
-" If it has no parent, return `0`.
-"
-function! s:GetParentHeaderLineNumber(...)
- if a:0 == 0
- let l:line = line('.')
- else
- let l:line = a:1
- endif
- let l:level = s:GetHeaderLevel(l:line)
- if l:level > 1
- let l:linenum = s:GetPreviousHeaderLineNumberAtLevel(l:level - 1, l:line)
- return l:linenum
- endif
- return 0
-endfunction
+if !exists('g:markdown_drop_empty_blockquotes')
+ let g:markdown_drop_empty_blockquotes = 0
+endif
-" Return the line number of the previous header of given level.
-" in relation to line `a:1`. If not given, `a:1 = getline()`
-"
-" `a:1` line is included, and this may return the current header.
-"
-" If none return 0.
-"
-function! s:GetNextHeaderLineNumberAtLevel(level, ...)
- if a:0 < 1
- let l:line = line('.')
- else
- let l:line = a:1
- endif
- let l:l = l:line
- while(l:l <= line('$'))
- if join(getline(l:l, l:l + 1), "\n") =~ get(s:levelRegexpDict, a:level)
- return l:l
- endif
- let l:l += 1
- endwhile
- return 0
-endfunction
+if !exists('g:markdown_mapping_switch_status')
+ let g:markdown_mapping_switch_status = '<space>'
+endif
-" Return the line number of the previous header of given level.
-" in relation to line `a:1`. If not given, `a:1 = getline()`
-"
-" `a:1` line is included, and this may return the current header.
-"
-" If none return 0.
-"
-function! s:GetPreviousHeaderLineNumberAtLevel(level, ...)
- if a:0 == 0
- let l:line = line('.')
- else
- let l:line = a:1
- endif
- let l:l = l:line
- while(l:l > 0)
- if join(getline(l:l, l:l + 1), "\n") =~ get(s:levelRegexpDict, a:level)
- return l:l
- endif
- let l:l -= 1
- endwhile
- return 0
-endfunction
+if !exists('g:markdown_enable_spell_checking')
+ let g:markdown_enable_spell_checking = 1
+endif
-" Move cursor to next sibling header.
-"
-" If there is no next siblings, print a warning and don't move.
-"
-function! s:MoveToNextSiblingHeader()
- let l:curHeaderLineNumber = s:GetHeaderLineNum()
- let l:curHeaderLevel = s:GetLevelOfHeaderAtLine(l:curHeaderLineNumber)
- let l:curHeaderParentLineNumber = s:GetParentHeaderLineNumber()
- let l:nextHeaderSameLevelLineNumber = s:GetNextHeaderLineNumberAtLevel(l:curHeaderLevel, l:curHeaderLineNumber + 1)
- let l:noNextSibling = 0
- if l:nextHeaderSameLevelLineNumber == 0
- let l:noNextSibling = 1
- else
- let l:nextHeaderSameLevelParentLineNumber = s:GetParentHeaderLineNumber(l:nextHeaderSameLevelLineNumber)
- if l:curHeaderParentLineNumber == l:nextHeaderSameLevelParentLineNumber
- call cursor(l:nextHeaderSameLevelLineNumber, 1)
- else
- let l:noNextSibling = 1
- endif
- endif
- if l:noNextSibling
- echo 'no next sibling header'
- endif
-endfunction
+if !exists('g:markdown_enable_input_abbreviations')
+ let g:markdown_enable_input_abbreviations = 1
+endif
-" Move cursor to previous sibling header.
-"
-" If there is no previous siblings, print a warning and do nothing.
-"
-function! s:MoveToPreviousSiblingHeader()
- let l:curHeaderLineNumber = s:GetHeaderLineNum()
- let l:curHeaderLevel = s:GetLevelOfHeaderAtLine(l:curHeaderLineNumber)
- let l:curHeaderParentLineNumber = s:GetParentHeaderLineNumber()
- let l:previousHeaderSameLevelLineNumber = s:GetPreviousHeaderLineNumberAtLevel(l:curHeaderLevel, l:curHeaderLineNumber - 1)
- let l:noPreviousSibling = 0
- if l:previousHeaderSameLevelLineNumber == 0
- let l:noPreviousSibling = 1
- else
- let l:previousHeaderSameLevelParentLineNumber = s:GetParentHeaderLineNumber(l:previousHeaderSameLevelLineNumber)
- if l:curHeaderParentLineNumber == l:previousHeaderSameLevelParentLineNumber
- call cursor(l:previousHeaderSameLevelLineNumber, 1)
- else
- let l:noPreviousSibling = 1
- endif
- endif
- if l:noPreviousSibling
- echo 'no previous sibling header'
- endif
-endfunction
+" }}}
-function! s:Toc(...)
- if a:0 > 0
- let l:window_type = a:1
- else
- let l:window_type = 'vertical'
- endif
+" {{{ OPTIONS
- let l:bufnr = bufnr('%')
- let l:cursor_line = line('.')
- let l:cursor_header = 0
- let l:fenced_block = 0
- let l:front_matter = 0
- let l:header_list = []
- let l:header_max_len = 0
- let l:vim_markdown_toc_autofit = get(g:, "vim_markdown_toc_autofit", 0)
- let l:vim_markdown_frontmatter = get(g:, "vim_markdown_frontmatter", 0)
- for i in range(1, line('$'))
- let l:lineraw = getline(i)
- let l:l1 = getline(i+1)
- let l:line = substitute(l:lineraw, "#", "\\\#", "g")
- if l:line =~ '````*' || l:line =~ '\~\~\~\~*'
- if l:fenced_block == 0
- let l:fenced_block = 1
- elseif l:fenced_block == 1
- let l:fenced_block = 0
- endif
- elseif l:vim_markdown_frontmatter == 1
- if l:front_matter == 1
- if l:line == '---'
- let l:front_matter = 0
- endif
- elseif i == 1
- if l:line == '---'
- let l:front_matter = 1
- endif
- endif
- endif
- if l:line =~ '^#\+' || (l:l1 =~ '^=\+\s*$' || l:l1 =~ '^-\+\s*$') && l:line =~ '^\S'
- let l:is_header = 1
- else
- let l:is_header = 0
- endif
- if l:is_header == 1 && l:fenced_block == 0 && l:front_matter == 0
- " append line to location list
- let l:item = {'lnum': i, 'text': l:line, 'valid': 1, 'bufnr': l:bufnr, 'col': 1}
- let l:header_list = l:header_list + [l:item]
- " set header number of the cursor position
- if l:cursor_header == 0
- if i == l:cursor_line
- let l:cursor_header = len(l:header_list)
- elseif i > l:cursor_line
- let l:cursor_header = len(l:header_list) - 1
- endif
- endif
- " keep track of the longest header size (heading level + title)
- let l:total_len = stridx(l:line, ' ') + strdisplaywidth(l:line)
- if l:total_len > l:header_max_len
- let l:header_max_len = l:total_len
- endif
- endif
- endfor
- call setloclist(0, l:header_list)
- if len(l:header_list) == 0
- echom "Toc: No headers."
- return
- endif
+setlocal textwidth=0
+setlocal ts=2 sw=2 expandtab smarttab
+setlocal comments=b:*,b:-,b:+,n:>,se:``` commentstring=>\ %s
+setlocal formatoptions=tron
+setlocal formatlistpat=^\\s*\\d\\+\\.\\s\\+\\\\|^\\s*[+-\\*]\\s\\+
+setlocal nolisp
+setlocal autoindent
+
+" Enable spelling and completion based on dictionary words
+if &spelllang !~# '^\s*$' && g:markdown_enable_spell_checking
+ setlocal spell
+endif
+
+" Custom dictionary for emoji
+execute 'setlocal dictionary+=' . shellescape(expand('<sfile>:p:h:h')) . '/dict/emoticons.dict'
+setlocal iskeyword+=:,+,-
+setlocal complete+=k
+
+if g:markdown_enable_input_abbreviations
+ " Replace common ascii emoticons with supported emoji
+ iabbrev <buffer> :-) :smile:
+ iabbrev <buffer> :-D :laughing:
+ iabbrev <buffer> :-( :disappointed:
+
+ " Replace common punctuation
+ iabbrev <buffer> ... …
+ iabbrev <buffer> << «
+ iabbrev <buffer> >> »
+endif
+
+" Folding
+if g:markdown_enable_folding
+ setlocal foldmethod=expr
+ setlocal foldexpr=markdown#FoldLevelOfLine(v:lnum)
+endif
+
+" }}}
- if l:window_type ==# 'horizontal'
- lopen
- elseif l:window_type ==# 'vertical'
- vertical lopen
- " auto-fit toc window when possible to shrink it
- if (&columns/2) > l:header_max_len && l:vim_markdown_toc_autofit == 1
- execute 'vertical resize ' . (l:header_max_len + 1)
- else
- execute 'vertical resize ' . (&columns/2)
- endif
- elseif l:window_type ==# 'tab'
- tab lopen
- else
- lopen
- endif
- setlocal modifiable
- for i in range(1, line('$'))
- " this is the location-list data for the current item
- let d = getloclist(0)[i-1]
- " atx headers
- if match(d.text, "^#") > -1
- let l:level = len(matchstr(d.text, '#*', 'g'))-1
- let d.text = substitute(d.text, '\v^#*[ ]*', '', '')
- let d.text = substitute(d.text, '\v[ ]*#*$', '', '')
- " setex headers
- else
- let l:next_line = getbufline(d.bufnr, d.lnum+1)
- if match(l:next_line, "=") > -1
- let l:level = 0
- elseif match(l:next_line, "-") > -1
- let l:level = 1
- endif
- endif
- call setline(i, repeat(' ', l:level). d.text)
- endfor
- setlocal nomodified
- setlocal nomodifiable
- execute 'normal! ' . l:cursor_header . 'G'
-endfunction
-" Convert Setex headers in range `line1 .. line2` to Atx.
-"
-" Return the number of conversions.
-"
-function! s:SetexToAtx(line1, line2)
- let l:originalNumLines = line('$')
- execute 'silent! ' . a:line1 . ',' . a:line2 . 'substitute/\v(.*\S.*)\n\=+$/# \1/'
- execute 'silent! ' . a:line1 . ',' . a:line2 . 'substitute/\v(.*\S.*)\n-+$/## \1/'
- return l:originalNumLines - line('$')
+" {{{ FUNCTIONS
+
+function! s:JumpToHeader(forward, visual)
+ let cnt = v:count1
+ let save = @/
+ let pattern = '\v^#{1,6}.*$|^.+\n%(\-+|\=+)$'
+ if a:visual
+ normal! gv
+ endif
+ if a:forward
+ let motion = '/' . pattern
+ else
+ let motion = '?' . pattern
+ endif
+ while cnt > 0
+ silent! execute motion
+ let cnt = cnt - 1
+ endwhile
+ call histdel('/', -1)
+ let @/ = save
endfunction
-" If `a:1` is 0, decrease the level of all headers in range `line1 .. line2`.
-"
-" Otherwise, increase the level. `a:1` defaults to `0`.
-"
-function! s:HeaderDecrease(line1, line2, ...)
- if a:0 > 0
- let l:increase = a:1
+function! s:Indent(indent)
+ if getline('.') =~ '\v^\s*%([-*+]|\d\.)\s*$'
+ if a:indent
+ normal >>
else
- let l:increase = 0
+ normal <<
endif
- if l:increase
- let l:forbiddenLevel = 6
- let l:replaceLevels = [5, 1]
- let l:levelDelta = 1
+ call setline('.', substitute(getline('.'), '\([-*+]\|\d\.\)\s*$', '\1 ', ''))
+ normal $
+ elseif getline('.') =~ '\v^\s*(\s?\>)+\s*$'
+ if a:indent
+ call setline('.', substitute(getline('.'), '>\s*$', '>> ', ''))
else
- let l:forbiddenLevel = 1
- let l:replaceLevels = [2, 6]
- let l:levelDelta = -1
+ call setline('.', substitute(getline('.'), '\s*>\s*$', ' ', ''))
+ call setline('.', substitute(getline('.'), '^\s\+$', '', ''))
endif
- for l:line in range(a:line1, a:line2)
- if join(getline(l:line, l:line + 1), "\n") =~ s:levelRegexpDict[l:forbiddenLevel]
- echomsg 'There is an h' . l:forbiddenLevel . ' at line ' . l:line . '. Aborting.'
- return
- endif
- endfor
- let l:numSubstitutions = s:SetexToAtx(a:line1, a:line2)
- let l:flags = (&gdefault ? '' : 'g')
- for l:level in range(replaceLevels[0], replaceLevels[1], -l:levelDelta)
- execute 'silent! ' . a:line1 . ',' . (a:line2 - l:numSubstitutions) . 'substitute/' . s:levelRegexpDict[l:level] . '/' . repeat('#', l:level + l:levelDelta) . '/' . l:flags
- endfor
-endfunction
-
-" Format table under cursor.
-"
-" Depends on Tabularize.
-"
-function! s:TableFormat()
- let l:pos = getpos('.')
- normal! {
- " Search instead of `normal! j` because of the table at beginning of file edge case.
- call search('|')
- normal! j
- " Remove everything that is not a pipe, colon or hyphen next to a colon othewise
- " well formated tables would grow because of addition of 2 spaces on the separator
- " line by Tabularize /|.
- let l:flags = (&gdefault ? '' : 'g')
- execute 's/\(:\@<!-:\@!\|[^|:-]\)//e' . l:flags
- execute 's/--/-/e' . l:flags
- Tabularize /|
- " Move colons for alignment to left or right side of the cell.
- execute 's/:\( \+\)|/\1:|/e' . l:flags
- execute 's/|\( \+\):/|:\1/e' . l:flags
- execute 's/ /-/' . l:flags
- call setpos('.', l:pos)
+ normal $
+ endif
endfunction
-" Wrapper to do move commands in visual mode.
-"
-function! s:VisMove(f)
- norm! gv
- call function(a:f)()
+function! s:IsAnEmptyListItem()
+ return getline('.') =~ '\v^\s*%([-*+]|\d\.)\s*$'
endfunction
-" Map in both normal and visual modes.
-"
-function! s:MapNormVis(rhs,lhs)
- execute 'nn <buffer><silent> ' . a:rhs . ' :call ' . a:lhs . '()<cr>'
- execute 'vn <buffer><silent> ' . a:rhs . ' <esc>:call <sid>VisMove(''' . a:lhs . ''')<cr>'
+function! s:IsAnEmptyQuote()
+ return getline('.') =~ '\v^\s*(\s?\>)+\s*$'
endfunction
-" Parameters:
-"
-" - step +1 for right, -1 for left
-"
-" TODO: multiple lines.
-"
-function! s:FindCornerOfSyntax(lnum, col, step)
- let l:col = a:col
- let l:syn = synIDattr(synID(a:lnum, l:col, 1), 'name')
- while synIDattr(synID(a:lnum, l:col, 1), 'name') ==# l:syn
- let l:col += a:step
- endwhile
- return l:col - a:step
-endfunction
-
-" Return the next position of the given syntax name,
-" inclusive on the given position.
-"
-" TODO: multiple lines
-"
-function! s:FindNextSyntax(lnum, col, name)
- let l:col = a:col
- let l:step = 1
- while synIDattr(synID(a:lnum, l:col, 1), 'name') !=# a:name
- let l:col += l:step
- endwhile
- return [a:lnum, l:col]
-endfunction
+" }}}
-function! s:FindCornersOfSyntax(lnum, col)
- return [<sid>FindLeftOfSyntax(a:lnum, a:col), <sid>FindRightOfSyntax(a:lnum, a:col)]
-endfunction
-function! s:FindRightOfSyntax(lnum, col)
- return <sid>FindCornerOfSyntax(a:lnum, a:col, 1)
-endfunction
+" {{{ MAPPINGS
-function! s:FindLeftOfSyntax(lnum, col)
- return <sid>FindCornerOfSyntax(a:lnum, a:col, -1)
-endfunction
+" Commands
+command! -nargs=0 -range MarkdownEditBlock :<line1>,<line2>call markdown#EditBlock()
-" Returns:
-"
-" - a string with the the URL for the link under the cursor
-" - an empty string if the cursor is not on a link
-"
-" TODO
-"
-" - multiline support
-" - give an error if the separator does is not on a link
-"
-function! s:Markdown_GetUrlForPosition(lnum, col)
- let l:lnum = a:lnum
- let l:col = a:col
- let l:syn = synIDattr(synID(l:lnum, l:col, 1), 'name')
-
- if l:syn ==# 'mkdInlineURL' || l:syn ==# 'mkdURL' || l:syn ==# 'mkdLinkDefTarget'
- " Do nothing.
- elseif l:syn ==# 'mkdLink'
- let [l:lnum, l:col] = <sid>FindNextSyntax(l:lnum, l:col, 'mkdURL')
- let l:syn = 'mkdURL'
- elseif l:syn ==# 'mkdDelimiter'
- let l:line = getline(l:lnum)
- let l:char = l:line[col - 1]
- if l:char ==# '<'
- let l:col += 1
- elseif l:char ==# '>' || l:char ==# ')'
- let l:col -= 1
- elseif l:char ==# '[' || l:char ==# ']' || l:char ==# '('
- let [l:lnum, l:col] = <sid>FindNextSyntax(l:lnum, l:col, 'mkdURL')
- else
- return ''
- endif
- else
- return ''
- endif
+if g:markdown_enable_mappings
+ " Jumping around
+ noremap <silent> <buffer> <script> ]] :<C-u>call <SID>JumpToHeader(1, 0)<CR>
+ noremap <silent> <buffer> <script> [[ :<C-u>call <SID>JumpToHeader(0, 0)<CR>
+ vnoremap <silent> <buffer> <script> ]] :<C-u>call <SID>JumpToHeader(1, 1)<CR>
+ vnoremap <silent> <buffer> <script> [[ :<C-u>call <SID>JumpToHeader(0, 1)<CR>
+ noremap <silent> <buffer> <script> ][ <nop>
+ noremap <silent> <buffer> <script> [] <nop>
- let [l:left, l:right] = <sid>FindCornersOfSyntax(l:lnum, l:col)
- return getline(l:lnum)[l:left - 1 : l:right - 1]
-endfunction
+ if g:markdown_enable_insert_mode_mappings
+ " Indenting things
+ inoremap <silent> <buffer> <script> <expr> <Tab>
+ \ <SID>IsAnEmptyListItem() \|\| <SID>IsAnEmptyQuote() ? '<C-O>:call <SID>Indent(1)<CR>' : '<Tab>'
+ inoremap <silent> <buffer> <script> <expr> <S-Tab>
+ \ <SID>IsAnEmptyListItem() \|\| <SID>IsAnEmptyQuote() ? '<C-O>:call <SID>Indent(0)<CR>' : '<Tab>'
-" Front end for GetUrlForPosition.
-"
-function! s:OpenUrlUnderCursor()
- let l:url = s:Markdown_GetUrlForPosition(line('.'), col('.'))
- if l:url != ''
- call s:VersionAwareNetrwBrowseX(l:url)
+ if g:markdown_drop_empty_blockquotes
+ " Remove empty quote and list items when press <CR>
+ inoremap <silent> <buffer> <script> <expr> <CR> <SID>IsAnEmptyQuote() \|\| <SID>IsAnEmptyListItem() ? '<C-O>:normal 0D<CR>' : '<CR>'
else
- echomsg 'The cursor is not on a link.'
+ " Remove only empty list items when press <CR>
+ inoremap <silent> <buffer> <script> <expr> <CR> <SID>IsAnEmptyListItem() ? '<C-O>:normal 0D<CR>' : '<CR>'
endif
-endfunction
-
-" We need a definition guard because we invoke 'edit' which will reload this
-" script while this function is running. We must not replace it.
-if !exists('*s:EditUrlUnderCursor')
- function s:EditUrlUnderCursor()
- let l:url = s:Markdown_GetUrlForPosition(line('.'), col('.'))
- if l:url != ''
- if get(g:, 'vim_markdown_autowrite', 0)
- write
- endif
- let l:anchor = ''
- if get(g:, 'vim_markdown_follow_anchor', 0)
- let l:parts = split(l:url, '#', 1)
- if len(l:parts) == 2
- let [l:url, l:anchor] = parts
- let l:anchorexpr = get(g:, 'vim_markdown_anchorexpr', '')
- if l:anchorexpr != ''
- let l:anchor = eval(substitute(
- \ l:anchorexpr, 'v:anchor',
- \ escape('"'.l:anchor.'"', '"'), ''))
- endif
- endif
- endif
- if l:url != ''
- let l:ext = ''
- if get(g:, 'vim_markdown_no_extensions_in_markdown', 0)
- " use another file extension if preferred
- if exists('g:vim_markdown_auto_extension_ext')
- let l:ext = '.'.g:vim_markdown_auto_extension_ext
- else
- let l:ext = '.md'
- endif
- endif
- let l:url = fnameescape(fnamemodify(expand('%:h').'/'.l:url.l:ext, ':.'))
- let l:editmethod = ''
- " determine how to open the linked file (split, tab, etc)
- if exists('g:vim_markdown_edit_url_in')
- if g:vim_markdown_edit_url_in == 'tab'
- let l:editmethod = 'tabnew'
- elseif g:vim_markdown_edit_url_in == 'vsplit'
- let l:editmethod = 'vsp'
- elseif g:vim_markdown_edit_url_in == 'hsplit'
- let l:editmethod = 'sp'
- else
- let l:editmethod = 'edit'
- endif
- else
- " default to current buffer
- let l:editmethod = 'edit'
- endif
- execute l:editmethod l:url
- endif
- if l:anchor != ''
- silent! execute '/'.l:anchor
- endif
- else
- echomsg 'The cursor is not on a link.'
- endif
- endfunction
-endif
-function! s:VersionAwareNetrwBrowseX(url)
- if has('patch-7.4.567')
- call netrw#BrowseX(a:url, 0)
- else
- call netrw#NetrwBrowseX(a:url, 0)
- endif
-endf
+ " Format tables
+ inoremap <silent> <buffer> <Bar> <Bar><Esc>:call markdown#FormatTable()<CR>a
+ endif
-function! s:MapNotHasmapto(lhs, rhs)
- if !hasmapto('<Plug>' . a:rhs)
- execute 'nmap <buffer>' . a:lhs . ' <Plug>' . a:rhs
- execute 'vmap <buffer>' . a:lhs . ' <Plug>' . a:rhs
- endif
-endfunction
+ " Switch status of things
+ execute 'nnoremap <silent> <buffer> ' . g:markdown_mapping_switch_status . ' :call markdown#SwitchStatus()<CR>'
-call <sid>MapNormVis('<Plug>Markdown_MoveToNextHeader', '<sid>MoveToNextHeader')
-call <sid>MapNormVis('<Plug>Markdown_MoveToPreviousHeader', '<sid>MoveToPreviousHeader')
-call <sid>MapNormVis('<Plug>Markdown_MoveToNextSiblingHeader', '<sid>MoveToNextSiblingHeader')
-call <sid>MapNormVis('<Plug>Markdown_MoveToPreviousSiblingHeader', '<sid>MoveToPreviousSiblingHeader')
-call <sid>MapNormVis('<Plug>Markdown_MoveToParentHeader', '<sid>MoveToParentHeader')
-call <sid>MapNormVis('<Plug>Markdown_MoveToCurHeader', '<sid>MoveToCurHeader')
-nnoremap <Plug>Markdown_OpenUrlUnderCursor :call <sid>OpenUrlUnderCursor()<cr>
-nnoremap <Plug>Markdown_EditUrlUnderCursor :call <sid>EditUrlUnderCursor()<cr>
-
-if !get(g:, 'vim_markdown_no_default_key_mappings', 0)
- call <sid>MapNotHasmapto(']]', 'Markdown_MoveToNextHeader')
- call <sid>MapNotHasmapto('[[', 'Markdown_MoveToPreviousHeader')
- call <sid>MapNotHasmapto('][', 'Markdown_MoveToNextSiblingHeader')
- call <sid>MapNotHasmapto('[]', 'Markdown_MoveToPreviousSiblingHeader')
- call <sid>MapNotHasmapto(']u', 'Markdown_MoveToParentHeader')
- call <sid>MapNotHasmapto(']c', 'Markdown_MoveToCurHeader')
- call <sid>MapNotHasmapto('gx', 'Markdown_OpenUrlUnderCursor')
- call <sid>MapNotHasmapto('ge', 'Markdown_EditUrlUnderCursor')
-endif
+ " Leader mappings
+ nnoremap <buffer> <Leader>e :MarkdownEditBlock<CR>
+ vnoremap <buffer> <Leader>e :MarkdownEditBlock<CR>
+ nnoremap <silent> <buffer> <Leader>ft :call markdown#FormatTable()<CR>
-command! -buffer -range=% HeaderDecrease call s:HeaderDecrease(<line1>, <line2>)
-command! -buffer -range=% HeaderIncrease call s:HeaderDecrease(<line1>, <line2>, 1)
-command! -buffer -range=% SetexToAtx call s:SetexToAtx(<line1>, <line2>)
-command! -buffer TableFormat call s:TableFormat()
-command! -buffer Toc call s:Toc()
-command! -buffer Toch call s:Toc('horizontal')
-command! -buffer Tocv call s:Toc('vertical')
-command! -buffer Toct call s:Toc('tab')
-
-" Heavily based on vim-notes - http://peterodding.com/code/vim/notes/
-if exists('g:vim_markdown_fenced_languages')
- let s:filetype_dict = {}
- for s:filetype in g:vim_markdown_fenced_languages
- let key = matchstr(s:filetype, "[^=]*")
- let val = matchstr(s:filetype, "[^=]*$")
- let s:filetype_dict[key] = val
- endfor
-else
- let s:filetype_dict = {
- \ 'c++': 'cpp',
- \ 'viml': 'vim',
- \ 'bash': 'sh',
- \ 'ini': 'dosini'
- \ }
+ " Insert Mode mappings
+ if g:markdown_enable_insert_mode_leader_mappings
+ inoremap <buffer> <Leader>e <Esc>:MarkdownEditBlock<CR>
+ inoremap <silent> <buffer> <Leader>ft <Esc>:call markdown#FormatTable()<CR>a
+ endif
endif
-function! s:MarkdownHighlightSources(force)
- " Syntax highlight source code embedded in notes.
- " Look for code blocks in the current file
- let filetypes = {}
- for line in getline(1, '$')
- let ft = matchstr(line, '```\s*\zs[0-9A-Za-z_+-]*')
- if !empty(ft) && ft !~ '^\d*$' | let filetypes[ft] = 1 | endif
- endfor
- if !exists('b:mkd_known_filetypes')
- let b:mkd_known_filetypes = {}
- endif
- if !exists('b:mkd_included_filetypes')
- " set syntax file name included
- let b:mkd_included_filetypes = {}
- endif
- if !a:force && (b:mkd_known_filetypes == filetypes || empty(filetypes))
- return
- endif
-
- " Now we're ready to actually highlight the code blocks.
- let startgroup = 'mkdCodeStart'
- let endgroup = 'mkdCodeEnd'
- for ft in keys(filetypes)
- if a:force || !has_key(b:mkd_known_filetypes, ft)
- if has_key(s:filetype_dict, ft)
- let filetype = s:filetype_dict[ft]
- else
- let filetype = ft
- endif
- let group = 'mkdSnippet' . toupper(substitute(filetype, "[+-]", "_", "g"))
- if !has_key(b:mkd_included_filetypes, filetype)
- let include = s:SyntaxInclude(filetype)
- let b:mkd_included_filetypes[filetype] = 1
- else
- let include = '@' . toupper(filetype)
- endif
- let command = 'syntax region %s matchgroup=%s start="^\s*```\s*%s$" matchgroup=%s end="\s*```$" keepend contains=%s%s'
- execute printf(command, group, startgroup, ft, endgroup, include, has('conceal') && get(g:, 'vim_markdown_conceal', 1) && get(g:, 'vim_markdown_conceal_code_blocks', 1) ? ' concealends' : '')
- execute printf('syntax cluster mkdNonListItem add=%s', group)
-
- let b:mkd_known_filetypes[ft] = 1
- endif
- endfor
-endfunction
-
-function! s:SyntaxInclude(filetype)
- " Include the syntax highlighting of another {filetype}.
- let grouplistname = '@' . toupper(a:filetype)
- " Unset the name of the current syntax while including the other syntax
- " because some syntax scripts do nothing when "b:current_syntax" is set
- if exists('b:current_syntax')
- let syntax_save = b:current_syntax
- unlet b:current_syntax
- endif
- try
- execute 'syntax include' grouplistname 'syntax/' . a:filetype . '.vim'
- execute 'syntax include' grouplistname 'after/syntax/' . a:filetype . '.vim'
- catch /E484/
- " Ignore missing scripts
- endtry
- " Restore the name of the current syntax
- if exists('syntax_save')
- let b:current_syntax = syntax_save
- elseif exists('b:current_syntax')
- unlet b:current_syntax
- endif
- return grouplistname
-endfunction
-
-
-function! s:MarkdownRefreshSyntax(force)
- if &filetype =~ 'markdown' && line('$') > 1
- call s:MarkdownHighlightSources(a:force)
- endif
-endfunction
-
-function! s:MarkdownClearSyntaxVariables()
- if &filetype =~ 'markdown'
- unlet! b:mkd_included_filetypes
- endif
-endfunction
+" }}}
-augroup Mkd
- " These autocmd calling s:MarkdownRefreshSyntax need to be kept in sync with
- " the autocmds calling s:MarkdownSetupFolding in after/ftplugin/markdown.vim.
- autocmd! * <buffer>
- autocmd BufWinEnter <buffer> call s:MarkdownRefreshSyntax(1)
- autocmd BufUnload <buffer> call s:MarkdownClearSyntaxVariables()
- autocmd BufWritePost <buffer> call s:MarkdownRefreshSyntax(0)
- autocmd InsertEnter,InsertLeave <buffer> call s:MarkdownRefreshSyntax(0)
- autocmd CursorHold,CursorHoldI <buffer> call s:MarkdownRefreshSyntax(0)
-augroup END
+let b:did_ftplugin = 1
endif
diff --git a/indent/markdown.vim b/indent/markdown.vim
deleted file mode 100644
index fa797312..00000000
--- a/indent/markdown.vim
+++ /dev/null
@@ -1,79 +0,0 @@
-if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1
-
-if exists("b:did_indent") | finish | endif
-let b:did_indent = 1
-
-setlocal indentexpr=GetMarkdownIndent()
-setlocal nolisp
-setlocal autoindent
-
-" Automatically continue blockquote on line break
-setlocal formatoptions+=r
-setlocal comments=b:>
-if get(g:, "vim_markdown_auto_insert_bullets", 1)
- " Do not automatically insert bullets when auto-wrapping with text-width
- setlocal formatoptions-=c
- " Accept various markers as bullets
- setlocal comments+=b:*,b:+,b:-
-endif
-
-" Only define the function once
-if exists("*GetMarkdownIndent") | finish | endif
-
-function! s:IsMkdCode(lnum)
- let name = synIDattr(synID(a:lnum, 1, 0), 'name')
- return (name =~ '^mkd\%(Code$\|Snippet\)' || name != '' && name !~ '^\%(mkd\|html\)')
-endfunction
-
-function! s:IsLiStart(line)
- return a:line !~ '^ *\([*-]\)\%( *\1\)\{2}\%( \|\1\)*$' &&
- \ a:line =~ '^\s*[*+-] \+'
-endfunction
-
-function! s:IsHeaderLine(line)
- return a:line =~ '^\s*#'
-endfunction
-
-function! s:IsBlankLine(line)
- return a:line =~ '^$'
-endfunction
-
-function! s:PrevNonBlank(lnum)
- let i = a:lnum
- while i > 1 && s:IsBlankLine(getline(i))
- let i -= 1
- endwhile
- return i
-endfunction
-
-function GetMarkdownIndent()
- if v:lnum > 2 && s:IsBlankLine(getline(v:lnum - 1)) && s:IsBlankLine(getline(v:lnum - 2))
- return 0
- endif
- let list_ind = get(g:, "vim_markdown_new_list_item_indent", 4)
- " Find a non-blank line above the current line.
- let lnum = s:PrevNonBlank(v:lnum - 1)
- " At the start of the file use zero indent.
- if lnum == 0 | return 0 | endif
- let ind = indent(lnum)
- let line = getline(lnum) " Last line
- let cline = getline(v:lnum) " Current line
- if s:IsLiStart(cline)
- " Current line is the first line of a list item, do not change indent
- return indent(v:lnum)
- elseif s:IsHeaderLine(cline) && !s:IsMkdCode(v:lnum)
- " Current line is the header, do not indent
- return 0
- elseif s:IsLiStart(line)
- if s:IsMkdCode(lnum)
- return ind
- else
- " Last line is the first line of a list item, increase indent
- return ind + list_ind
- end
- else
- return ind
- endif
-endfunction
-
-endif
diff --git a/syntax/markdown.vim b/syntax/markdown.vim
index 063ba10d..8c5e10ba 100644
--- a/syntax/markdown.vim
+++ b/syntax/markdown.vim
@@ -1,188 +1,947 @@
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1
" Vim syntax file
-" Language: Markdown
-" Maintainer: Ben Williams <benw@plasticboy.com>
-" URL: http://plasticboy.com/markdown-vim-mode/
-" Remark: Uses HTML syntax file
-" TODO: Handle stuff contained within stuff (e.g. headings within blockquotes)
+" Language: Markdown
+" Maintainer: Gabriele Lana <gabriele.lana@gmail.com>
+" Filenames: *.md
+if exists("b:current_syntax")
+ finish
+endif
-" Read the HTML syntax to start with
-if version < 600
- so <sfile>:p:h/html.vim
-else
- runtime! syntax/html.vim
-
- if exists('b:current_syntax')
- unlet b:current_syntax
- endif
+if !exists('main_syntax')
+ let main_syntax = 'markdown'
endif
-if version < 600
- syntax clear
-elseif exists("b:current_syntax")
- finish
+if !exists('g:markdown_flavor')
+ let g:markdown_flavor = 'github'
endif
-" don't use standard HiLink, it will not work with included syntax files
-if version < 508
- command! -nargs=+ HtmlHiLink hi link <args>
+if exists('g:markdown_enable_conceal') && g:markdown_enable_conceal
+ let b:markdown_concealends = 'concealends'
+ let b:markdown_conceal = 'conceal'
+ set conceallevel=2
+ set concealcursor=
else
- command! -nargs=+ HtmlHiLink hi def link <args>
+ let b:markdown_concealends = ''
+ let b:markdown_conceal = ''
endif
syn spell toplevel
+syn sync fromstart
syn case ignore
-syn sync linebreaks=1
-
-let s:conceal = ''
-let s:concealends = ''
-let s:concealcode = ''
-if has('conceal') && get(g:, 'vim_markdown_conceal', 1)
- let s:conceal = ' conceal'
- let s:concealends = ' concealends'
-endif
-if has('conceal') && get(g:, 'vim_markdown_conceal_code_blocks', 1)
- let s:concealcode = ' concealends'
-endif
-" additions to HTML groups
-if get(g:, 'vim_markdown_emphasis_multiline', 1)
- let s:oneline = ''
-else
- let s:oneline = ' oneline'
-endif
-syn region mkdItalic matchgroup=mkdItalic start="\%(\*\|_\)" end="\%(\*\|_\)"
-syn region mkdBold matchgroup=mkdBold start="\%(\*\*\|__\)" end="\%(\*\*\|__\)"
-syn region mkdBoldItalic matchgroup=mkdBoldItalic start="\%(\*\*\*\|___\)" end="\%(\*\*\*\|___\)"
-execute 'syn region htmlItalic matchgroup=mkdItalic start="\%(^\|\s\)\zs\*\ze[^\\\*\t ]\%(\%([^*]\|\\\*\|\n\)*[^\\\*\t ]\)\?\*\_W" end="[^\\\*\t ]\zs\*\ze\_W" keepend contains=@Spell' . s:oneline . s:concealends
-execute 'syn region htmlItalic matchgroup=mkdItalic start="\%(^\|\s\)\zs_\ze[^\\_\t ]" end="[^\\_\t ]\zs_\ze\_W" keepend contains=@Spell' . s:oneline . s:concealends
-execute 'syn region htmlBold matchgroup=mkdBold start="\%(^\|\s\)\zs\*\*\ze\S" end="\S\zs\*\*" keepend contains=@Spell' . s:oneline . s:concealends
-execute 'syn region htmlBold matchgroup=mkdBold start="\%(^\|\s\)\zs__\ze\S" end="\S\zs__" keepend contains=@Spell' . s:oneline . s:concealends
-execute 'syn region htmlBoldItalic matchgroup=mkdBoldItalic start="\%(^\|\s\)\zs\*\*\*\ze\S" end="\S\zs\*\*\*" keepend contains=@Spell' . s:oneline . s:concealends
-execute 'syn region htmlBoldItalic matchgroup=mkdBoldItalic start="\%(^\|\s\)\zs___\ze\S" end="\S\zs___" keepend contains=@Spell' . s:oneline . s:concealends
-
-" [link](URL) | [link][id] | [link][] | ![image](URL)
-syn region mkdFootnotes matchgroup=mkdDelimiter start="\[^" end="\]"
-execute 'syn region mkdID matchgroup=mkdDelimiter start="\[" end="\]" contained oneline' . s:conceal
-execute 'syn region mkdURL matchgroup=mkdDelimiter start="(" end=")" contained oneline' . s:conceal
-execute 'syn region mkdLink matchgroup=mkdDelimiter start="\\\@<!!\?\[\ze[^]\n]*\n\?[^]\n]*\][[(]" end="\]" contains=@mkdNonListItem,@Spell nextgroup=mkdURL,mkdID skipwhite' . s:concealends
-
-" Autolink without angle brackets.
-" mkd inline links: protocol optional user:pass@ sub/domain .com, .co.uk, etc optional port path/querystring/hash fragment
-" ------------ _____________________ ----------------------------- _________________________ ----------------- __
-syn match mkdInlineURL /https\?:\/\/\(\w\+\(:\w\+\)\?@\)\?\([A-Za-z0-9][-_0-9A-Za-z]*\.\)\{1,}\(\w\{2,}\.\?\)\{1,}\(:[0-9]\{1,5}\)\?\S*/
-
-" Autolink with parenthesis.
-syn region mkdInlineURL matchgroup=mkdDelimiter start="(\(https\?:\/\/\(\w\+\(:\w\+\)\?@\)\?\([A-Za-z0-9][-_0-9A-Za-z]*\.\)\{1,}\(\w\{2,}\.\?\)\{1,}\(:[0-9]\{1,5}\)\?\S*)\)\@=" end=")"
-
-" Autolink with angle brackets.
-syn region mkdInlineURL matchgroup=mkdDelimiter start="\\\@<!<\ze[a-z][a-z0-9,.-]\{1,22}:\/\/[^> ]*>" end=">"
-
-" Link definitions: [id]: URL (Optional Title)
-syn region mkdLinkDef matchgroup=mkdDelimiter start="^ \{,3}\zs\[\^\@!" end="]:" oneline nextgroup=mkdLinkDefTarget skipwhite
-syn region mkdLinkDefTarget start="<\?\zs\S" excludenl end="\ze[>[:space:]\n]" contained nextgroup=mkdLinkTitle,mkdLinkDef skipwhite skipnl oneline
-syn region mkdLinkTitle matchgroup=mkdDelimiter start=+"+ end=+"+ contained
-syn region mkdLinkTitle matchgroup=mkdDelimiter start=+'+ end=+'+ contained
-syn region mkdLinkTitle matchgroup=mkdDelimiter start=+(+ end=+)+ contained
-
-"HTML headings
-syn region htmlH1 matchgroup=mkdHeading start="^\s*#" end="$" contains=mkdLink,mkdInlineURL,@Spell
-syn region htmlH2 matchgroup=mkdHeading start="^\s*##" end="$" contains=mkdLink,mkdInlineURL,@Spell
-syn region htmlH3 matchgroup=mkdHeading start="^\s*###" end="$" contains=mkdLink,mkdInlineURL,@Spell
-syn region htmlH4 matchgroup=mkdHeading start="^\s*####" end="$" contains=mkdLink,mkdInlineURL,@Spell
-syn region htmlH5 matchgroup=mkdHeading start="^\s*#####" end="$" contains=mkdLink,mkdInlineURL,@Spell
-syn region htmlH6 matchgroup=mkdHeading start="^\s*######" end="$" contains=mkdLink,mkdInlineURL,@Spell
-syn match htmlH1 /^.\+\n=\+$/ contains=mkdLink,mkdInlineURL,@Spell
-syn match htmlH2 /^.\+\n-\+$/ contains=mkdLink,mkdInlineURL,@Spell
-
-"define Markdown groups
-syn match mkdLineBreak / \+$/
-syn region mkdBlockquote start=/^\s*>/ end=/$/ contains=mkdLink,mkdInlineURL,mkdLineBreak,@Spell
-execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/\(\([^\\]\|^\)\\\)\@<!`/ end=/`/' . s:concealcode
-execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/\(\([^\\]\|^\)\\\)\@<!``/ skip=/[^`]`[^`]/ end=/``/' . s:concealcode
-execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/^\s*\z(`\{3,}\)[^`]*$/ end=/^\s*\z1`*\s*$/' . s:concealcode
-execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/\(\([^\\]\|^\)\\\)\@<!\~\~/ end=/\(\([^\\]\|^\)\\\)\@<!\~\~/' . s:concealcode
-execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start=/^\s*\z(\~\{3,}\)\s*[0-9A-Za-z_+-]*\s*$/ end=/^\s*\z1\~*\s*$/' . s:concealcode
-execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start="<pre[^>]*\\\@<!>" end="</pre>"' . s:concealcode
-execute 'syn region mkdCode matchgroup=mkdCodeDelimiter start="<code[^>]*\\\@<!>" end="</code>"' . s:concealcode
-syn region mkdFootnote start="\[^" end="\]"
-syn match mkdCode /^\s*\n\(\(\s\{8,}[^ ]\|\t\t\+[^\t]\).*\n\)\+/
-syn match mkdCode /\%^\(\(\s\{4,}[^ ]\|\t\+[^\t]\).*\n\)\+/
-syn match mkdCode /^\s*\n\(\(\s\{4,}[^ ]\|\t\+[^\t]\).*\n\)\+/ contained
-syn match mkdListItem /^\s*\%([-*+]\|\d\+\.\)\ze\s\+/ contained
-syn region mkdListItemLine start="^\s*\%([-*+]\|\d\+\.\)\s\+" end="$" oneline contains=@mkdNonListItem,mkdListItem,@Spell
-syn region mkdNonListItemBlock start="\(\%^\(\s*\([-*+]\|\d\+\.\)\s\+\)\@!\|\n\(\_^\_$\|\s\{4,}[^ ]\|\t+[^\t]\)\@!\)" end="^\(\s*\([-*+]\|\d\+\.\)\s\+\)\@=" contains=@mkdNonListItem,@Spell
-syn match mkdRule /^\s*\*\s\{0,1}\*\s\{0,1}\*\(\*\|\s\)*$/
-syn match mkdRule /^\s*-\s\{0,1}-\s\{0,1}-\(-\|\s\)*$/
-syn match mkdRule /^\s*_\s\{0,1}_\s\{0,1}_\(_\|\s\)*$/
-
-" YAML frontmatter
-if get(g:, 'vim_markdown_frontmatter', 0)
- syn include @yamlTop syntax/yaml.vim
- syn region Comment matchgroup=mkdDelimiter start="\%^---$" end="^\(---\|\.\.\.\)$" contains=@yamlTop keepend
- unlet! b:current_syntax
-endif
-if get(g:, 'vim_markdown_toml_frontmatter', 0)
- try
- syn include @tomlTop syntax/toml.vim
- syn region Comment matchgroup=mkdDelimiter start="\%^+++$" end="^+++$" transparent contains=@tomlTop keepend
- unlet! b:current_syntax
- catch /E484/
- syn region Comment matchgroup=mkdDelimiter start="\%^+++$" end="^+++$"
- endtry
-endif
+" {{{ INLINE ELEMENTS
+
+syn cluster markdownInline contains=
+ \ markdownItalic,markdownBold,markdownBoldItalic,markdownStrike,markdownInlineCode,
+ \ markdownPullRequestLinkInText,markdownUrlLinkInText,markdownUserLinkInText,
+ \ markdownEmailLinkInText,markdownLinkContainer,markdownXmlComment,
+ \ markdownXmlElement,markdownXmlEmptyElement,markdownXmlEntities
+
+execute 'syn region markdownItalic matchgroup=markdownInlineDelimiter '
+ \ . 'start="\%(\s\|_\|^\)\@<=\*\%(\s\|\*\|$\)\@!" end="\%(\s\|\*\)\@<!\*" '
+ \ . 'contains=@markdownInline '
+ \ . b:markdown_concealends
+execute 'syn region markdownItalic matchgroup=markdownInlineDelimiter '
+ \ . 'start="\%(\s\|\*\|^\)\@<=_\%(\s\|_\|$\)\@!" end="\%(\s\|_\)\@<!_" '
+ \ . 'contains=@markdownInline '
+ \ . b:markdown_concealends
+
+execute 'syn region markdownBold matchgroup=markdownInlineDelimiter '
+ \ . 'start="\%(\s\|__\|^\)\@<=\*\*\%(\s\|\*\|$\)\@!" end="\%(\s\|\*\*\)\@<!\*\*" '
+ \ . 'contains=@markdownInline '
+ \ . b:markdown_concealends
+execute 'syn region markdownBold matchgroup=markdownInlineDelimiter '
+ \ . 'start="\%(\s\|\*\*\|^\)\@<=__\%(\s\|_\|$\)\@!" end="\%(\s\|__\)\@<!__" '
+ \ . 'contains=@markdownInline '
+ \ . b:markdown_concealends
+
+execute 'syn region markdownBoldItalic matchgroup=markdownInlineDelimiter '
+ \ . 'start="\%(\s\|_\|^\)\@<=\*\*\*\%(\s\|\*\|$\)\@!" end="\%(\s\|\*\)\@<!\*\*\*" '
+ \ . 'contains=@markdownInline '
+ \ . b:markdown_concealends
+execute 'syn region markdownBoldItalic matchgroup=markdownInlineDelimiter '
+ \ . 'start="\%(\s\|\*\|^\)\@<=___\%(\s\|_\|$\)\@!" end="\%(\s\|_\)\@<!___" '
+ \ . 'contains=@markdownInline '
+ \ . b:markdown_concealends
+execute 'syn region markdownBoldItalic matchgroup=markdownInlineDelimiter '
+ \ . 'start="\%(\s\|_\|^\)\@<=\*\*_\%(\s\|_\|$\)\@!" end="\%(\s\|_\)\@<!_\*\*" '
+ \ . 'contains=@markdownInline '
+ \ . b:markdown_concealends
+execute 'syn region markdownBoldItalic matchgroup=markdownInlineDelimiter '
+ \ . 'start="\%(\s\|\*\|^\)\@<=__\*\%(\s\|\*\|$\)\@!" end="\%(\s\|\*\)\@<!\*__" '
+ \ . 'contains=@markdownInline '
+ \ . b:markdown_concealends
+
+syn match markdownStrike /\%(\\\)\@<!\~\~\%(\S\)\@=\_.\{-}\%(\S\)\@<=\~\~/ contains=markdownStrikeDelimiter,@markdownInline
+syn match markdownStrikeDelimiter /\~\~/ contained
+
+" Fenced code blocks in list items must be preceded by an empty line This is
+" made this way so that the second rule could eat up something that is not a
+" fenced code block like
+"
+" * This is a list item
+" ```ruby
+" # this is not a fenced code block but it's a code block
+" def ruby;
+" ```
+execute 'syn region markdownInlineCode matchgroup=markdownCodeDelimiter start=/\%(`\)\@<!`/ end=/`/ keepend contains=@NoSpell ' . b:markdown_concealends
+execute 'syn region markdownInlineCode matchgroup=markdownCodeDelimiter start=/\%(`\)\@<!`\z(`\+\)/ end=/`\z1/ keepend contains=@NoSpell ' . b:markdown_concealends
+
+" case insensitive
+" preceded by something that is not a word
+" could be surrounded by angle brackets
+" could begin with / or // (path) or the url protocol
+" inside the url pairs of balanced parentheses are allowed
+" inside the url html entities are allowed
+" the end block is different because ?!:,. are not included in the url if they
+" appear at the end of the url
+let b:markdown_syntax_url =
+ \ '\c'
+ \ . '\%(\W\)\@<='
+ \ . '<\?'
+ \ . '\%('
+ \ . '\%(\<\%(https\?\|ftp\|file\):\/\/\|www\.\|ftp\.\)'
+ \ . '\|'
+ \ . '\/\/\?'
+ \ . '\)'
+ \ . '\%('
+ \ . '&#\?[0-9A-Za-z]\{1,8};'
+ \ . '\|'
+ \ . '\\'
+ \ . '\|'
+ \ . '([-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?)'
+ \ . '\|'
+ \ . '\[[-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?\]'
+ \ . '\|'
+ \ . '{[-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?}'
+ \ . '\|'
+ \ . '[-A-Z0-9+&@#/%=~_|$?!:,.]'
+ \ . '\)*'
+ \ . '\%('
+ \ . '&#\?[0-9A-Za-z]\{1,8};'
+ \ . '\|'
+ \ . '\\'
+ \ . '\|'
+ \ . '([-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?)'
+ \ . '\|'
+ \ . '\[[-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?\]'
+ \ . '\|'
+ \ . '{[-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?}'
+ \ . '\|'
+ \ . '[-A-Z0-9+&@#/%=~_|$]\+'
+ \ . '\)'
+ \ . '>\?'
+execute 'syn match markdownUrlLinkInText /' . b:markdown_syntax_url . '/ contains=@NoSpell display'
+
+syn match markdownPullRequestLinkInText /\%(\w\)\@<!#\d\+/ display
+syn match markdownUserLinkInText /\%(\w\)\@<!@[[:alnum:]._\/-]\+/ contains=@NoSpell display
+syn match markdownEmailLinkInText /[[:alnum:]._%+-]\+@[[:alnum:].-]\+\.\w\{2,4}/ contains=@NoSpell display
-if get(g:, 'vim_markdown_json_frontmatter', 0)
- try
- syn include @jsonTop syntax/json.vim
- syn region Comment matchgroup=mkdDelimiter start="\%^{$" end="^}$" contains=@jsonTop keepend
- unlet! b:current_syntax
- catch /E484/
- syn region Comment matchgroup=mkdDelimiter start="\%^{$" end="^}$"
- endtry
+" something encosed in square brackets
+" could not be preceded by a backslash
+" could contain pairs of square brackets
+" could contain no more than two consecutive newlines
+" could contain single square brackets (open or closed) escaped
+" could not contain unbalanced square brackets like 'a [ b \] c'
+" could not contain nested square brackets
+let b:markdown_syntax_allowed_characters_in_square_brackets = '\%([^\[\]]\|\\\[\|\\\]\)*'
+let b:markdown_syntax_square_brackets_block = ''
+ \ . '\%(\\\)\@<!\['
+ \ . '\%('
+ \ . b:markdown_syntax_allowed_characters_in_square_brackets
+ \ . '\|'
+ \ . b:markdown_syntax_allowed_characters_in_square_brackets
+ \ . '\['
+ \ . b:markdown_syntax_allowed_characters_in_square_brackets
+ \ . '\]'
+ \ . b:markdown_syntax_allowed_characters_in_square_brackets
+ \ . '\)'
+ \ . '\%('
+ \ . '\n\%(\n\)\@!'
+ \ . '\%('
+ \ . b:markdown_syntax_allowed_characters_in_square_brackets
+ \ . '\|'
+ \ . b:markdown_syntax_allowed_characters_in_square_brackets
+ \ . '\['
+ \ . b:markdown_syntax_allowed_characters_in_square_brackets
+ \ . '\]'
+ \ . b:markdown_syntax_allowed_characters_in_square_brackets
+ \ . '\)'
+ \ . '\)*'
+ \ . '\]'
+
+" something encosed in round brackets
+" could not be preceded by a backslash
+" could contain pairs of round brackets
+" could contain no more than two consecutive newlines
+" could contain single round brackets (open or closed) escaped
+" could not contain unbalanced round brackets like 'a ( b \) c'
+" could not contain nested round brackets
+let b:markdown_syntax_allowed_characters_in_round_brackets = '[^()]*'
+let b:markdown_syntax_round_brackets_block = ''
+ \ . '\%(\\\)\@<!('
+ \ . '\%('
+ \ . b:markdown_syntax_allowed_characters_in_round_brackets
+ \ . '\|'
+ \ . b:markdown_syntax_allowed_characters_in_round_brackets
+ \ . '('
+ \ . b:markdown_syntax_allowed_characters_in_round_brackets
+ \ . ')'
+ \ . b:markdown_syntax_allowed_characters_in_round_brackets
+ \ . '\)'
+ \ . '\%('
+ \ . '\n\%(\n\)\@!'
+ \ . '\%('
+ \ . b:markdown_syntax_allowed_characters_in_round_brackets
+ \ . '\|'
+ \ . b:markdown_syntax_allowed_characters_in_round_brackets
+ \ . '('
+ \ . b:markdown_syntax_allowed_characters_in_round_brackets
+ \ . ')'
+ \ . b:markdown_syntax_allowed_characters_in_round_brackets
+ \ . '\)'
+ \ . '\)*'
+ \ . ')'
+
+execute 'syn match markdownLinkContainer '
+ \ . 'contains=markdownLinkTextContainer,markdownLinkUrlContainer transparent '
+ \ . '/'
+ \ . '!\?'
+ \ . b:markdown_syntax_square_brackets_block
+ \ . '\%(\s*\|\n\%\(\n\)\@!\)'
+ \ . '\%('
+ \ . b:markdown_syntax_round_brackets_block
+ \ . '\|'
+ \ . b:markdown_syntax_square_brackets_block
+ \ . '\)'
+ \ . '/'
+
+execute 'syn match markdownLinkTextContainer contained '
+ \ . 'contains=markdownLinkText '
+ \ . '/'
+ \ . '!\?'
+ \ . b:markdown_syntax_square_brackets_block
+ \ . '/'
+
+execute 'syn match markdownLinkText contained '
+ \ . 'contains=@markdownInline,@NoSpell '
+ \ . '/'
+ \ . '!\?'
+ \ . b:markdown_syntax_square_brackets_block
+ \ . '/'
+ \ . 'hs=s+1,he=e-1'
+
+execute 'syn match markdownLinkUrlContainer contained '
+ \ . 'contains=markdownLinkUrl,markdownLinkTitleSingleQuoted,markdownLinkTitleDoubleQuoted '
+ \ . '/'
+ \ . b:markdown_syntax_round_brackets_block
+ \ . '/ '
+ \ . b:markdown_conceal
+
+execute 'syn match markdownLinkUrl contained '
+ \ . 'contains=@NoSpell '
+ \ . '/'
+ \ . '\%((\)\@<='
+ \ . '\%('
+ \ . '&#\?[0-9A-Za-z]\{1,8};'
+ \ . '\|'
+ \ . '\\'
+ \ . '\|'
+ \ . '([-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?)'
+ \ . '\|'
+ \ . '\[[-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?\]'
+ \ . '\|'
+ \ . '{[-A-Z0-9+&@#/%=~_|$?!:,.]*\\\?}'
+ \ . '\|'
+ \ . '[-A-Z0-9+&@#/%=~_|$?!:,.]'
+ \ . '\|'
+ \ . '\s'
+ \ . '\)\+'
+ \ . '\%(\s\+["'']\|)\|\n\)\@='
+ \ . '/'
+
+execute 'syn region markdownLinkTitleSingleQuoted start=/\s*''/ skip=/\\''/ end=/''\_s*/ display '
+ \ . 'keepend contained contains=@markdownInline '
+ \ . b:markdown_conceal
+
+execute 'syn region markdownLinkTitleDoubleQuoted start=/\s*"/ skip=/\\"/ end=/"\_s*/ display '
+ \ . 'keepend contained contains=@markdownInline '
+ \ . b:markdown_conceal
+
+syn match markdownXmlComment /\c<\!--\_.\{-}-->/ contains=@NoSpell
+syn match markdownXmlElement /\c<\([-A-Z0-9_$?!:,.]\+\)[^>]\{-}>\_.\{-}<\/\1>/ contains=@NoSpell
+syn match markdownXmlEmptyElement /\c<\([-A-Z0-9_$?!:,.]\+\)\%(\s\+[^>]\{-}\/>\|\s*\/>\)/ contains=@NoSpell
+syn match markdownXmlEntities /&#\?[0-9A-Za-z]\{1,8};/ contains=@NoSpell
+
+" }}}
+
+
+" {{{ ANCHORED BLOCKS
+
+syn match markdownRule /^\s*\*\s*\*\s*\*[[:space:]*]*$/ display
+syn match markdownRule /^\s*-\s*-\s*-[[:space:]-]*$/ display
+syn match markdownRule /^\s*_\s*_\s*_[[:space:]_]*$/ display
+
+if g:markdown_flavor ==? 'github'
+ syn region markdownH1 matchgroup=markdownHeadingDelimiter start=/^#\%(\s\+\)\@=/ end=/#*\s*$/ display oneline contains=@markdownInline
+ syn region markdownH2 matchgroup=markdownHeadingDelimiter start=/^##\%(\s\+\)\@=/ end=/#*\s*$/ display oneline contains=@markdownInline
+ syn region markdownH3 matchgroup=markdownHeadingDelimiter start=/^###\%(\s\+\)\@=/ end=/#*\s*$/ display oneline contains=@markdownInline
+ syn region markdownH4 matchgroup=markdownHeadingDelimiter start=/^####\%(\s\+\)\@=/ end=/#*\s*$/ display oneline contains=@markdownInline
+ syn region markdownH5 matchgroup=markdownHeadingDelimiter start=/^#####\%(\s\+\)\@=/ end=/#*\s*$/ display oneline contains=@markdownInline
+ syn region markdownH6 matchgroup=markdownHeadingDelimiter start=/^######\%(\s\+\)\@=/ end=/#*\s*$/ display oneline contains=@markdownInline
+
+ syn match markdownH1 /^.\+\n=\+$/ display contains=@markdownInline,markdownHeadingUnderline
+ syn match markdownH2 /^.\+\n-\+$/ display contains=@markdownInline,markdownHeadingUnderline
+ syn match markdownHeadingUnderline /^[=-]\+$/ display contained
endif
-if get(g:, 'vim_markdown_math', 0)
- syn include @tex syntax/tex.vim
- syn region mkdMath start="\\\@<!\$" end="\$" skip="\\\$" contains=@tex keepend
- syn region mkdMath start="\\\@<!\$\$" end="\$\$" skip="\\\$" contains=@tex keepend
+if g:markdown_flavor ==? 'kramdown'
+ syn match markdownHeaderContainer /^#\{1,6}.\+$/ display transparent
+ \ contains=@markdownInline,markdownHeader,markdownHeaderId,markdownHeadingDelimiter
+ syn match markdownHeader /\%(^#\+\)\@<=\%([^#]\+\%(#\+\s*\%($\|{\)\)\@=\|[^{]\{-}\%({\)\@=\|#$\)/
+
+ syn match markdownHeader /^.\+\n=\+$/ display contains=@markdownInline,markdownHeadingUnderline,markdownHeaderId
+ syn match markdownHeader /^.\+\n-\+$/ display contains=@markdownInline,markdownHeadingUnderline,markdownHeaderId
+ syn match markdownHeadingUnderline /^[=-]\+$/ display contained
+
+ syn match markdownHeaderId /{[^}]\+}\s*$/ display contained
+ syn match markdownHeadingDelimiter /#\+\%(.\+\)\@=/ display contained
endif
-" Strike through
-if get(g:, 'vim_markdown_strikethrough', 0)
- execute 'syn region mkdStrike matchgroup=htmlStrike start="\%(\~\~\)" end="\%(\~\~\)"' . s:concealends
- HtmlHiLink mkdStrike htmlStrike
+execute 'syn match markdownLinkReference '
+ \ . 'contains=@NoSpell '
+ \ . 'display '
+ \ . '/'
+ \ . '^\s\{,3}'
+ \ . b:markdown_syntax_square_brackets_block
+ \ . ':.*'
+ \ . '\%(\n\%\(\n\)\@!.*$\)*'
+ \ . '/'
+
+syn region markdownBlockquote start=/^\s*\%(>\s\?\)\+\%(.\)\@=/ end=/\n\n/ contains=markdownBlockquoteDelimiter,@NoSpell
+syn match markdownBlockquoteDelimiter /^\s*\%(>\s\?\)\+/ contained
+
+syn region markdownFencedCodeBlock matchgroup=markdownCodeDelimiter start=/^\s\{,3}```\%(`*\).*$/ end=/^\s\{,3}```\%(`*\)\s*$/ contains=@NoSpell
+syn region markdownFencedCodeBlock matchgroup=markdownCodeDelimiter start=/^\s\{,3}\~\~\~\%(\~*\).*$/ end=/^\s\{,3}\~\~\~\%(\~*\)\s*$/ contains=@NoSpell
+
+syn match markdownCodeBlock /\%(^\n\)\@<=\%(\%(\s\{4,}\|\t\+\).*\n\)\+$/ contains=@NoSpell
+
+let s:markdown_table_header_rows_separator = ''
+ \ . '\%('
+ \ . '\s*|\?\%(\s*[-:]-\{1,}[-:]\s*|\)\+\s*[-:]-\{1,}[-:]\s*|\?\s*'
+ \ . '\|'
+ \ . '\s*|\s*[-:]-\{1,}[-:]\s*|\s*'
+ \ . '\|'
+ \ . '\s*|\s*[-:]-\{1,}[-:]\s*'
+ \ . '\|'
+ \ . '\s*[-:]-\{1,}[-:]\s*|\s*'
+ \ . '\)'
+execute 'syn match markdownTable '
+ \ . 'transparent contains=markdownTableHeader,markdownTableDelimiter,@markdownInline '
+ \ . '/'
+ \ . '^\s*\n'
+ \ . '\s*|\?\%([^|]\+|\)*[^|]\+|\?\s*\n'
+ \ . s:markdown_table_header_rows_separator . '\n'
+ \ . '\%('
+ \ . '\s*|\?\%([^|]\+|\)*[^|]\+|\?\s*\n'
+ \ . '\)*'
+ \ . '$'
+ \ . '/'
+syn match markdownTableDelimiter /|/ contained
+execute 'syn match markdownTableDelimiter contained '
+ \ . '/' . s:markdown_table_header_rows_separator . '/'
+execute 'syn match markdownTableHeader contained contains=@markdownInline '
+ \ . '/\%(|\?\s*\)\@<=[^|]\+\%(.*\n' . s:markdown_table_header_rows_separator . '\)\@=/'
+
+" }}}
+
+
+" {{{ NESTED BLOCKS
+
+for s:level in range(1, 16)
+ let s:indented_as_content = '\%( \{' . (2*s:level) . '}\|\t\{' . (s:level) . '}\)'
+ let s:indented_as_container = '\%( \{' . (2*(s:level-1)) . '}\|\t\{' . (s:level-1) . '}\)'
+ let s:preceded_by_separator = '^\s*\n'
+
+ execute 'syn region markdownListItemAtLevel' . (s:level) . ' '
+ \ . 'matchgroup=markdownItemDelimiter '
+ \ . (s:level > 1 ? 'contained ' : '')
+ \ . 'keepend '
+ \ . 'contains='
+ \ . 'markdownTableInListItemAtLevel' . (s:level) . ','
+ \ . 'markdownCodeBlockInListItemAtLevel' . (s:level) . ','
+ \ . 'markdownFencedCodeBlockInListItemAtLevel' . (s:level) . ','
+ \ . 'markdownH1InListItemAtLevel' . (s:level) . ','
+ \ . 'markdownH2InListItemAtLevel' . (s:level) . ','
+ \ . 'markdownH3InListItemAtLevel' . (s:level) . ','
+ \ . 'markdownH4InListItemAtLevel' . (s:level) . ','
+ \ . 'markdownH5InListItemAtLevel' . (s:level) . ','
+ \ . 'markdownH6InListItemAtLevel' . (s:level) . ','
+ \ . 'markdownRuleInListItemAtLevel' . (s:level) . ','
+ \ . 'markdownBlockquoteInListItemAtLevel' . (s:level) . ','
+ \ . 'markdownListItemAtLevel' . (s:level+1) . ','
+ \ . '@markdownInline '
+ \ . 'start=/^' . (s:indented_as_container) . '\%([-*+]\|\d\+\.\)\%(\s\+\[[ x]\]\)\?\s\+/ '
+ \ . 'end='
+ \ . '/'
+ \ . '\n\%(\n\n\)\@='
+ \ . '\|'
+ \ . '\n\%(' . (s:indented_as_container) . '\%([-*+]\|\d\+\.\)\s\+\)\@='
+ \ . '\|'
+ \ . '\n\%(\n' . (s:indented_as_container) . '\S\)\@='
+ \ . '/'
+
+ " fenced code blocks could have leading spaces after the base level indentation
+ " so at least it must be indented as content but could be indented more
+ " there's no upper limit to the indentation because the following rule on
+ " code blocks is going to take care of that
+ " TL;DR: don't swap markdownFencedCodeBlockInListItemAtLevel* with
+ " markdownCodeBlockInListItemAtLevel* :-)
+ execute 'syn region markdownFencedCodeBlockInListItemAtLevel' . (s:level) . ' '
+ \ . 'contained contains=@NoSpell '
+ \ . 'matchgroup=markdownFencedCodeBlockInItemDelimiter '
+ \ . 'start='
+ \ . '/'
+ \ . (s:preceded_by_separator)
+ \ . '\z( \{' . (2*s:level) . ',}\|\t\{' . (s:level) . ',}\)*```\%(`*\).*$'
+ \ . '/ '
+ \ . 'end=/^\z1```\%(`*\)\s*$/'
+ execute 'syn region markdownFencedCodeBlockInListItemAtLevel' . (s:level) . ' '
+ \ . 'contained contains=@NoSpell '
+ \ . 'matchgroup=markdownFencedCodeBlockInItemDelimiter '
+ \ . 'start='
+ \ . '/'
+ \ . (s:preceded_by_separator)
+ \ . '\z( \{' . (2*s:level) . ',}\|\t\{' . (s:level) . ',}\)*\~\~\~\%(\~*\).*$'
+ \ . '/ '
+ \ . 'end=/^\z1\~\~\~\%(\~*\)\s*$/'
+ execute 'hi def link markdownFencedCodeBlockInListItemAtLevel' . (s:level) . ' String'
+
+ execute 'syn match markdownCodeBlockInListItemAtLevel' . (s:level) . ' '
+ \ . 'contained contains=@NoSpell '
+ \ . '/' . (s:preceded_by_separator) . '\%(\%( \{' . (6+2*s:level) . ',}\|\t\{' . (1+s:level) . ',}\).*\n\?\)\+$/'
+ execute 'hi def link markdownCodeBlockInListItemAtLevel' . (s:level) . ' String'
+
+ execute 'syn region markdownH1InListItemAtLevel' . (s:level) . ' '
+ \ . 'contained display oneline '
+ \ . 'matchgroup=markdownHeadingDelimiter '
+ \ . 'contains=@markdownInline '
+ \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '#\%(\s\+\)\@=/ '
+ \ . 'end=/#*\s*$/'
+ execute 'syn region markdownH2InListItemAtLevel' . (s:level) . ' '
+ \ . 'contained display oneline '
+ \ . 'matchgroup=markdownHeadingDelimiter '
+ \ . 'contains=@markdownInline '
+ \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '##\%(\s\+\)\@=/ '
+ \ . 'end=/#*\s*$/'
+ execute 'syn region markdownH3InListItemAtLevel' . (s:level) . ' '
+ \ . 'contained display oneline '
+ \ . 'matchgroup=markdownHeadingDelimiter '
+ \ . 'contains=@markdownInline '
+ \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '###\%(\s\+\)\@=/ '
+ \ . 'end=/#*\s*$/'
+ execute 'syn region markdownH4InListItemAtLevel' . (s:level) . ' '
+ \ . 'contained display oneline '
+ \ . 'matchgroup=markdownHeadingDelimiter '
+ \ . 'contains=@markdownInline '
+ \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '####\%(\s\+\)\@=/ '
+ \ . 'end=/#*\s*$/'
+ execute 'syn region markdownH5InListItemAtLevel' . (s:level) . ' '
+ \ . 'contained display oneline '
+ \ . 'matchgroup=markdownHeadingDelimiter '
+ \ . 'contains=@markdownInline '
+ \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '#####\%(\s\+\)\@=/ '
+ \ . 'end=/#*\s*$/'
+ execute 'syn region markdownH6InListItemAtLevel' . (s:level) . ' '
+ \ . 'contained display oneline '
+ \ . 'matchgroup=markdownHeadingDelimiter '
+ \ . 'contains=@markdownInline '
+ \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '######\%(\s\+\)\@=/ '
+ \ . 'end=/#*\s*$/'
+ execute 'hi def link markdownH1InListItemAtLevel' . (s:level) . ' Title'
+ execute 'hi def link markdownH2InListItemAtLevel' . (s:level) . ' Title'
+ execute 'hi def link markdownH3InListItemAtLevel' . (s:level) . ' Title'
+ execute 'hi def link markdownH4InListItemAtLevel' . (s:level) . ' Title'
+ execute 'hi def link markdownH5InListItemAtLevel' . (s:level) . ' Title'
+ execute 'hi def link markdownH6InListItemAtLevel' . (s:level) . ' Title'
+
+ execute 'syn match markdownH1InListItemAtLevel' . (s:level) . ' '
+ \ . 'display contained contains=@markdownInline,markdownHeadingDelimiterInListItemAtLevel'. (s:level) . ' '
+ \ . '/' . (s:preceded_by_separator) . (s:indented_as_content) . '.\+\n' . (s:indented_as_content) . '=\+$/'
+ execute 'syn match markdownH1InListItemAtLevel' . (s:level) . ' '
+ \ . 'display contained contains=@markdownInline,markdownHeadingDelimiterInListItemAtLevel'. (s:level) . ' '
+ \ . '/' . (s:preceded_by_separator) . (s:indented_as_content) . '.\+\n' . (s:indented_as_content) . '-\+$/'
+ execute 'syn match markdownHeadingDelimiterInListItemAtLevel' . (s:level) . ' '
+ \ . 'display contained '
+ \ . '/^' . (s:indented_as_content) . '\%(-\+\|=\+\)$/'
+ execute 'hi def link markdownH1InListItemAtLevel' . (s:level) . ' Title'
+ execute 'hi def link markdownH2InListItemAtLevel' . (s:level) . ' Title'
+ execute 'hi def link markdownHeadingDelimiterInListItemAtLevel' . (s:level) . ' Special'
+
+ execute 'syn match markdownRuleInListItemAtLevel' . (s:level) . ' '
+ \ . '/' . (s:preceded_by_separator) . (s:indented_as_content) . '*\*\s*\*\s*\*[[:space:]*]*$/ display'
+ execute 'syn match markdownRuleInListItemAtLevel' . (s:level) . ' '
+ \ . '/' . (s:preceded_by_separator) . (s:indented_as_content) . '-\s*-\s*-[[:space:]-]*$/ display'
+ execute 'syn match markdownRuleInListItemAtLevel' . (s:level) . ' '
+ \ . '/' . (s:preceded_by_separator) . (s:indented_as_content) . '_\s*_\s*_[[:space:]_]*$/ display'
+ execute 'hi def link markdownRuleInListItemAtLevel' . (s:level) . ' Identifier'
+
+ execute 'syn region markdownBlockquoteInListItemAtLevel' . (s:level) . ' '
+ \ . 'contained '
+ \ . 'contains=markdownBlockquoteDelimiterInListItemAtLevel' . (s:level) . ',@NoSpell '
+ \ . 'start=/' . (s:preceded_by_separator) . (s:indented_as_content) . '\%(>\s\?\)\+\%(.\)\@=/ '
+ \ . 'end=/\n\n/'
+ execute 'syn match markdownBlockquoteDelimiterInListItemAtLevel' . (s:level) . ' '
+ \ . 'contained '
+ \ . '/^' . (s:indented_as_content) . '\%(>\s\?\)\+/'
+ execute 'hi def link markdownBlockquoteInListItemAtLevel' . (s:level) . ' Comment'
+ execute 'hi def link markdownBlockquoteDelimiterInListItemAtLevel' . (s:level) . ' Delimiter'
+
+ " " the only constraint here is that the table begins at least at the same
+ " " level as the list item's content, se we could reuse the previous syntactic
+ " " elements, we could do that because tables could have arbitrary indentation
+ execute 'syn match markdownTableInListItemAtLevel' . (s:level) . ' '
+ \ . 'transparent contained contains=markdownTableHeader,markdownTableDelimiter,@markdownInline '
+ \ . '/'
+ \ . '^\s*\n'
+ \ . (s:indented_as_content) . '\s*|\?\%([^|]\+|\)*[^|]\+|\?\s*\n'
+ \ . s:markdown_table_header_rows_separator . '\n'
+ \ . '\%('
+ \ . '\s*|\?\%([^|]\+|\)*[^|]\+|\?\s*\n'
+ \ . '\)*'
+ \ . '$'
+ \ . '/'
+endfor
+hi def link markdownItemDelimiter Special
+hi def link markdownFencedCodeBlockInItemDelimiter Special
+
+" }}}
+
+
+" {{{ EMOTICONS
+
+syn keyword markdownEmoticonKeyword :bowtie: :smile: :laughing: :blush: :smiley:
+syn keyword markdownEmoticonKeyword :bowtie: :smile: :laughing: :blush: :smiley:
+syn keyword markdownEmoticonKeyword :relaxed: :smirk: :heart_eyes: :kissing_heart: :kissing_closed_eyes:
+syn keyword markdownEmoticonKeyword :flushed: :relieved: :satisfied: :grin: :wink:
+syn keyword markdownEmoticonKeyword :stuck_out_tongue_winking_eye: :stuck_out_tongue_closed_eyes: :grinning: :kissing: :kissing_smiling_eyes:
+syn keyword markdownEmoticonKeyword :stuck_out_tongue: :sleeping: :worried: :frowning: :anguished:
+syn keyword markdownEmoticonKeyword :open_mouth: :grimacing: :confused: :hushed: :expressionless:
+syn keyword markdownEmoticonKeyword :unamused: :sweat_smile: :sweat: :disappointed_relieved: :weary:
+syn keyword markdownEmoticonKeyword :pensive: :disappointed: :confounded: :fearful: :cold_sweat:
+syn keyword markdownEmoticonKeyword :persevere: :cry: :sob: :joy: :astonished:
+syn keyword markdownEmoticonKeyword :scream: :neckbeard: :tired_face: :angry: :rage:
+syn keyword markdownEmoticonKeyword :triumph: :sleepy: :yum: :mask: :sunglasses:
+syn keyword markdownEmoticonKeyword :dizzy_face: :imp: :smiling_imp: :neutral_face: :no_mouth:
+syn keyword markdownEmoticonKeyword :innocent: :alien: :yellow_heart: :blue_heart: :purple_heart:
+syn keyword markdownEmoticonKeyword :heart: :green_heart: :broken_heart: :heartbeat: :heartpulse:
+syn keyword markdownEmoticonKeyword :two_hearts: :revolving_hearts: :cupid: :sparkling_heart: :sparkles:
+syn keyword markdownEmoticonKeyword :star: :star2: :dizzy: :boom: :collision:
+syn keyword markdownEmoticonKeyword :anger: :exclamation: :question: :grey_exclamation: :grey_question:
+syn keyword markdownEmoticonKeyword :zzz: :dash: :sweat_drops: :notes: :musical_note:
+syn keyword markdownEmoticonKeyword :fire: :hankey: :poop: :shit: :+1:
+syn keyword markdownEmoticonKeyword :thumbsup: :-1: :thumbsdown: :ok_hand: :punch:
+syn keyword markdownEmoticonKeyword :facepunch: :fist: :v: :wave: :hand:
+syn keyword markdownEmoticonKeyword :raised_hand: :open_hands: :point_up: :point_down: :point_left:
+syn keyword markdownEmoticonKeyword :point_right: :raised_hands: :pray: :point_up_2: :clap:
+syn keyword markdownEmoticonKeyword :muscle: :metal: :fu: :walking: :runner:
+syn keyword markdownEmoticonKeyword :running: :couple: :family: :two_men_holding_hands: :two_women_holding_hands:
+syn keyword markdownEmoticonKeyword :dancer: :dancers: :ok_woman: :no_good: :information_desk_person:
+syn keyword markdownEmoticonKeyword :raising_hand: :bride_with_veil: :person_with_pouting_face: :person_frowning: :bow:
+syn keyword markdownEmoticonKeyword :couplekiss: :couple_with_heart: :massage: :haircut: :nail_care:
+syn keyword markdownEmoticonKeyword :boy: :girl: :woman: :man: :baby:
+syn keyword markdownEmoticonKeyword :older_woman: :older_man: :person_with_blond_hair: :man_with_gua_pi_mao: :man_with_turban:
+syn keyword markdownEmoticonKeyword :construction_worker: :cop: :angel: :princess: :smiley_cat:
+syn keyword markdownEmoticonKeyword :smile_cat: :heart_eyes_cat: :kissing_cat: :smirk_cat: :scream_cat:
+syn keyword markdownEmoticonKeyword :crying_cat_face: :joy_cat: :pouting_cat: :japanese_ogre: :japanese_goblin:
+syn keyword markdownEmoticonKeyword :see_no_evil: :hear_no_evil: :speak_no_evil: :guardsman: :skull:
+syn keyword markdownEmoticonKeyword :feet: :lips: :kiss: :droplet: :ear:
+syn keyword markdownEmoticonKeyword :eyes: :nose: :tongue: :love_letter: :bust_in_silhouette:
+syn keyword markdownEmoticonKeyword :busts_in_silhouette: :speech_balloon: :thought_balloon: :feelsgood: :finnadie:
+syn keyword markdownEmoticonKeyword :goberserk: :godmode: :hurtrealbad: :rage1: :rage2:
+syn keyword markdownEmoticonKeyword :rage3: :rage4: :suspect: :trollface: :sunny:
+syn keyword markdownEmoticonKeyword :umbrella: :cloud: :snowflake: :snowman: :zap:
+syn keyword markdownEmoticonKeyword :cyclone: :foggy: :ocean: :cat: :dog:
+syn keyword markdownEmoticonKeyword :mouse: :hamster: :rabbit: :wolf: :frog:
+syn keyword markdownEmoticonKeyword :tiger: :koala: :bear: :pig: :pig_nose:
+syn keyword markdownEmoticonKeyword :cow: :boar: :monkey_face: :monkey: :horse:
+syn keyword markdownEmoticonKeyword :racehorse: :camel: :sheep: :elephant: :panda_face:
+syn keyword markdownEmoticonKeyword :snake: :bird: :baby_chick: :hatched_chick: :hatching_chick:
+syn keyword markdownEmoticonKeyword :chicken: :penguin: :turtle: :bug: :honeybee:
+syn keyword markdownEmoticonKeyword :ant: :beetle: :snail: :octopus: :tropical_fish:
+syn keyword markdownEmoticonKeyword :fish: :whale: :whale2: :dolphin: :cow2:
+syn keyword markdownEmoticonKeyword :ram: :rat: :water_buffalo: :tiger2: :rabbit2:
+syn keyword markdownEmoticonKeyword :dragon: :goat: :rooster: :dog2: :pig2:
+syn keyword markdownEmoticonKeyword :mouse2: :ox: :dragon_face: :blowfish: :crocodile:
+syn keyword markdownEmoticonKeyword :dromedary_camel: :leopard: :cat2: :poodle: :paw_prints:
+syn keyword markdownEmoticonKeyword :bouquet: :cherry_blossom: :tulip: :four_leaf_clover: :rose:
+syn keyword markdownEmoticonKeyword :sunflower: :hibiscus: :maple_leaf: :leaves: :fallen_leaf:
+syn keyword markdownEmoticonKeyword :herb: :mushroom: :cactus: :palm_tree: :evergreen_tree:
+syn keyword markdownEmoticonKeyword :deciduous_tree: :chestnut: :seedling: :blossom: :ear_of_rice:
+syn keyword markdownEmoticonKeyword :shell: :globe_with_meridians: :sun_with_face: :full_moon_with_face: :new_moon_with_face:
+syn keyword markdownEmoticonKeyword :new_moon: :waxing_crescent_moon: :first_quarter_moon: :waxing_gibbous_moon: :full_moon:
+syn keyword markdownEmoticonKeyword :waning_gibbous_moon: :last_quarter_moon: :waning_crescent_moon: :last_quarter_moon_with_face: :first_quarter_moon_with_face:
+syn keyword markdownEmoticonKeyword :moon: :earth_africa: :earth_americas: :earth_asia: :volcano:
+syn keyword markdownEmoticonKeyword :milky_way: :partly_sunny: :octocat: :squirrel: :bamboo:
+syn keyword markdownEmoticonKeyword :gift_heart: :dolls: :school_satchel: :mortar_board: :flags:
+syn keyword markdownEmoticonKeyword :fireworks: :sparkler: :wind_chime: :rice_scene: :jack_o_lantern:
+syn keyword markdownEmoticonKeyword :ghost: :santa: :christmas_tree: :gift: :bell:
+syn keyword markdownEmoticonKeyword :no_bell: :tanabata_tree: :tada: :confetti_ball: :balloon:
+syn keyword markdownEmoticonKeyword :crystal_ball: :cd: :dvd: :floppy_disk: :camera:
+syn keyword markdownEmoticonKeyword :video_camera: :movie_camera: :computer: :tv: :iphone:
+syn keyword markdownEmoticonKeyword :phone: :telephone: :telephone_receiver: :pager: :fax:
+syn keyword markdownEmoticonKeyword :minidisc: :vhs: :sound: :speaker: :mute:
+syn keyword markdownEmoticonKeyword :loudspeaker: :mega: :hourglass: :hourglass_flowing_sand: :alarm_clock:
+syn keyword markdownEmoticonKeyword :watch: :radio: :satellite: :loop: :mag:
+syn keyword markdownEmoticonKeyword :mag_right: :unlock: :lock: :lock_with_ink_pen: :closed_lock_with_key:
+syn keyword markdownEmoticonKeyword :key: :bulb: :flashlight: :high_brightness: :low_brightness:
+syn keyword markdownEmoticonKeyword :electric_plug: :battery: :calling: :email: :mailbox:
+syn keyword markdownEmoticonKeyword :postbox: :bath: :bathtub: :shower: :toilet:
+syn keyword markdownEmoticonKeyword :wrench: :nut_and_bolt: :hammer: :seat: :moneybag:
+syn keyword markdownEmoticonKeyword :yen: :dollar: :pound: :euro: :credit_card:
+syn keyword markdownEmoticonKeyword :money_with_wings: :e-mail: :inbox_tray: :outbox_tray: :envelope:
+syn keyword markdownEmoticonKeyword :incoming_envelope: :postal_horn: :mailbox_closed: :mailbox_with_mail: :mailbox_with_no_mail:
+syn keyword markdownEmoticonKeyword :door: :smoking: :bomb: :gun: :hocho:
+syn keyword markdownEmoticonKeyword :pill: :syringe: :page_facing_up: :page_with_curl: :bookmark_tabs:
+syn keyword markdownEmoticonKeyword :bar_chart: :chart_with_upwards_trend: :chart_with_downwards_trend: :scroll: :clipboard:
+syn keyword markdownEmoticonKeyword :calendar: :date: :card_index: :file_folder: :open_file_folder:
+syn keyword markdownEmoticonKeyword :scissors: :pushpin: :paperclip: :black_nib: :pencil2:
+syn keyword markdownEmoticonKeyword :straight_ruler: :triangular_ruler: :closed_book: :green_book: :blue_book:
+syn keyword markdownEmoticonKeyword :orange_book: :notebook: :notebook_with_decorative_cover: :ledger: :books:
+syn keyword markdownEmoticonKeyword :bookmark: :name_badge: :microscope: :telescope: :newspaper:
+syn keyword markdownEmoticonKeyword :football: :basketball: :soccer: :baseball: :tennis:
+syn keyword markdownEmoticonKeyword :8ball: :rugby_football: :bowling: :golf: :mountain_bicyclist:
+syn keyword markdownEmoticonKeyword :bicyclist: :horse_racing: :snowboarder: :swimmer: :surfer:
+syn keyword markdownEmoticonKeyword :ski: :spades: :hearts: :clubs: :diamonds:
+syn keyword markdownEmoticonKeyword :gem: :ring: :trophy: :musical_score: :musical_keyboard:
+syn keyword markdownEmoticonKeyword :violin: :space_invader: :video_game: :black_joker: :flower_playing_cards:
+syn keyword markdownEmoticonKeyword :game_die: :dart: :mahjong: :clapper: :memo:
+syn keyword markdownEmoticonKeyword :pencil: :book: :art: :microphone: :headphones:
+syn keyword markdownEmoticonKeyword :trumpet: :saxophone: :guitar: :shoe: :sandal:
+syn keyword markdownEmoticonKeyword :high_heel: :lipstick: :boot: :shirt: :tshirt:
+syn keyword markdownEmoticonKeyword :necktie: :womans_clothes: :dress: :running_shirt_with_sash: :jeans:
+syn keyword markdownEmoticonKeyword :kimono: :bikini: :ribbon: :tophat: :crown:
+syn keyword markdownEmoticonKeyword :womans_hat: :mans_shoe: :closed_umbrella: :briefcase: :handbag:
+syn keyword markdownEmoticonKeyword :pouch: :purse: :eyeglasses: :fishing_pole_and_fish: :coffee:
+syn keyword markdownEmoticonKeyword :tea: :sake: :baby_bottle: :beer: :beers:
+syn keyword markdownEmoticonKeyword :cocktail: :tropical_drink: :wine_glass: :fork_and_knife: :pizza:
+syn keyword markdownEmoticonKeyword :hamburger: :fries: :poultry_leg: :meat_on_bone: :spaghetti:
+syn keyword markdownEmoticonKeyword :curry: :fried_shrimp: :bento: :sushi: :fish_cake:
+syn keyword markdownEmoticonKeyword :rice_ball: :rice_cracker: :rice: :ramen: :stew:
+syn keyword markdownEmoticonKeyword :oden: :dango: :egg: :bread: :doughnut:
+syn keyword markdownEmoticonKeyword :custard: :icecream: :ice_cream: :shaved_ice: :birthday:
+syn keyword markdownEmoticonKeyword :cake: :cookie: :chocolate_bar: :candy: :lollipop:
+syn keyword markdownEmoticonKeyword :honey_pot: :apple: :green_apple: :tangerine: :lemon:
+syn keyword markdownEmoticonKeyword :cherries: :grapes: :watermelon: :strawberry: :peach:
+syn keyword markdownEmoticonKeyword :melon: :banana: :pear: :pineapple: :sweet_potato:
+syn keyword markdownEmoticonKeyword :eggplant: :tomato: :corn: :house: :house_with_garden:
+syn keyword markdownEmoticonKeyword :school: :office: :post_office: :hospital: :bank:
+syn keyword markdownEmoticonKeyword :convenience_store: :love_hotel: :hotel: :wedding: :church:
+syn keyword markdownEmoticonKeyword :department_store: :european_post_office: :city_sunrise: :city_sunset: :japanese_castle:
+syn keyword markdownEmoticonKeyword :european_castle: :tent: :factory: :tokyo_tower: :japan:
+syn keyword markdownEmoticonKeyword :mount_fuji: :sunrise_over_mountains: :sunrise: :stars: :statue_of_liberty:
+syn keyword markdownEmoticonKeyword :bridge_at_night: :carousel_horse: :rainbow: :ferris_wheel: :fountain:
+syn keyword markdownEmoticonKeyword :roller_coaster: :ship: :speedboat: :boat: :sailboat:
+syn keyword markdownEmoticonKeyword :rowboat: :anchor: :rocket: :airplane: :helicopter:
+syn keyword markdownEmoticonKeyword :steam_locomotive: :tram: :mountain_railway: :bike: :aerial_tramway:
+syn keyword markdownEmoticonKeyword :suspension_railway: :mountain_cableway: :tractor: :blue_car: :oncoming_automobile:
+syn keyword markdownEmoticonKeyword :car: :red_car: :taxi: :oncoming_taxi: :articulated_lorry:
+syn keyword markdownEmoticonKeyword :bus: :oncoming_bus: :rotating_light: :police_car: :oncoming_police_car:
+syn keyword markdownEmoticonKeyword :fire_engine: :ambulance: :minibus: :truck: :train:
+syn keyword markdownEmoticonKeyword :station: :train2: :bullettrain_front: :bullettrain_side: :light_rail:
+syn keyword markdownEmoticonKeyword :monorail: :railway_car: :trolleybus: :ticket: :fuelpump:
+syn keyword markdownEmoticonKeyword :vertical_traffic_light: :traffic_light: :warning: :construction: :beginner:
+syn keyword markdownEmoticonKeyword :atm: :slot_machine: :busstop: :barber: :hotsprings:
+syn keyword markdownEmoticonKeyword :checkered_flag: :crossed_flags: :izakaya_lantern: :moyai: :circus_tent:
+syn keyword markdownEmoticonKeyword :performing_arts: :round_pushpin: :triangular_flag_on_post: :jp: :kr:
+syn keyword markdownEmoticonKeyword :cn: :us: :fr: :es: :it:
+syn keyword markdownEmoticonKeyword :ru: :gb: :uk: :de: :one:
+syn keyword markdownEmoticonKeyword :two: :three: :four: :five: :six:
+syn keyword markdownEmoticonKeyword :seven: :eight: :nine: :keycap_ten: :1234:
+syn keyword markdownEmoticonKeyword :zero: :hash: :symbols: :arrow_backward: :arrow_down:
+syn keyword markdownEmoticonKeyword :arrow_forward: :arrow_left: :capital_abcd: :abcd: :abc:
+syn keyword markdownEmoticonKeyword :arrow_lower_left: :arrow_lower_right: :arrow_right: :arrow_up: :arrow_upper_left:
+syn keyword markdownEmoticonKeyword :arrow_upper_right: :arrow_double_down: :arrow_double_up: :arrow_down_small: :arrow_heading_down:
+syn keyword markdownEmoticonKeyword :arrow_heading_up: :leftwards_arrow_with_hook: :arrow_right_hook: :left_right_arrow: :arrow_up_down:
+syn keyword markdownEmoticonKeyword :arrow_up_small: :arrows_clockwise: :arrows_counterclockwise: :rewind: :fast_forward:
+syn keyword markdownEmoticonKeyword :information_source: :ok: :twisted_rightwards_arrows: :repeat: :repeat_one:
+syn keyword markdownEmoticonKeyword :new: :top: :up: :cool: :free:
+syn keyword markdownEmoticonKeyword :ng: :cinema: :koko: :signal_strength: :u5272:
+syn keyword markdownEmoticonKeyword :u5408: :u55b6: :u6307: :u6708: :u6709:
+syn keyword markdownEmoticonKeyword :u6e80: :u7121: :u7533: :u7a7a: :u7981:
+syn keyword markdownEmoticonKeyword :sa: :restroom: :mens: :womens: :baby_symbol:
+syn keyword markdownEmoticonKeyword :no_smoking: :parking: :wheelchair: :metro: :baggage_claim:
+syn keyword markdownEmoticonKeyword :accept: :wc: :potable_water: :put_litter_in_its_place: :secret:
+syn keyword markdownEmoticonKeyword :congratulations: :m: :passport_control: :left_luggage: :customs:
+syn keyword markdownEmoticonKeyword :ideograph_advantage: :cl: :sos: :id: :no_entry_sign:
+syn keyword markdownEmoticonKeyword :underage: :no_mobile_phones: :do_not_litter: :non-potable_water: :no_bicycles:
+syn keyword markdownEmoticonKeyword :no_pedestrians: :children_crossing: :no_entry: :eight_spoked_asterisk: :eight_pointed_black_star:
+syn keyword markdownEmoticonKeyword :heart_decoration: :vs: :vibration_mode: :mobile_phone_off: :chart:
+syn keyword markdownEmoticonKeyword :currency_exchange: :aries: :taurus: :gemini: :cancer:
+syn keyword markdownEmoticonKeyword :leo: :virgo: :libra: :scorpius: :sagittarius:
+syn keyword markdownEmoticonKeyword :capricorn: :aquarius: :pisces: :ophiuchus: :six_pointed_star:
+syn keyword markdownEmoticonKeyword :negative_squared_cross_mark: :a: :b: :ab: :o2:
+syn keyword markdownEmoticonKeyword :diamond_shape_with_a_dot_inside: :recycle: :end: :on: :soon:
+syn keyword markdownEmoticonKeyword :clock1: :clock130: :clock10: :clock1030: :clock11:
+syn keyword markdownEmoticonKeyword :clock1130: :clock12: :clock1230: :clock2: :clock230:
+syn keyword markdownEmoticonKeyword :clock3: :clock330: :clock4: :clock430: :clock5:
+syn keyword markdownEmoticonKeyword :clock530: :clock6: :clock630: :clock7: :clock730:
+syn keyword markdownEmoticonKeyword :clock8: :clock830: :clock9: :clock930: :heavy_dollar_sign:
+syn keyword markdownEmoticonKeyword :copyright: :registered: :tm: :x: :heavy_exclamation_mark:
+syn keyword markdownEmoticonKeyword :bangbang: :interrobang: :o: :heavy_multiplication_x: :heavy_plus_sign:
+syn keyword markdownEmoticonKeyword :heavy_minus_sign: :heavy_division_sign: :white_flower: :100: :heavy_check_mark:
+syn keyword markdownEmoticonKeyword :ballot_box_with_check: :radio_button: :link: :curly_loop: :wavy_dash:
+syn keyword markdownEmoticonKeyword :part_alternation_mark: :trident: :black_square: :white_square: :white_check_mark:
+syn keyword markdownEmoticonKeyword :black_square_button: :white_square_button: :black_circle: :white_circle: :red_circle:
+syn keyword markdownEmoticonKeyword :large_blue_circle: :large_blue_diamond: :large_orange_diamond: :small_blue_diamond: :small_orange_diamond:
+syn keyword markdownEmoticonKeyword :small_red_triangle: :small_red_triangle_down: :shipit: :relaxed: :smirk:
+syn keyword markdownEmoticonKeyword :heart_eyes: :kissing_heart: :kissing_closed_eyes: :flushed: :relieved:
+syn keyword markdownEmoticonKeyword :satisfied: :grin: :wink: :stuck_out_tongue_winking_eye: :stuck_out_tongue_closed_eyes:
+syn keyword markdownEmoticonKeyword :grinning: :kissing: :kissing_smiling_eyes: :stuck_out_tongue: :sleeping:
+syn keyword markdownEmoticonKeyword :worried: :frowning: :anguished: :open_mouth: :grimacing:
+syn keyword markdownEmoticonKeyword :confused: :hushed: :expressionless: :unamused: :sweat_smile:
+syn keyword markdownEmoticonKeyword :sweat: :disappointed_relieved: :weary: :pensive: :disappointed:
+syn keyword markdownEmoticonKeyword :confounded: :fearful: :cold_sweat: :persevere: :cry:
+syn keyword markdownEmoticonKeyword :sob: :joy: :astonished: :scream: :neckbeard:
+syn keyword markdownEmoticonKeyword :tired_face: :angry: :rage: :triumph: :sleepy:
+syn keyword markdownEmoticonKeyword :yum: :mask: :sunglasses: :dizzy_face: :imp:
+syn keyword markdownEmoticonKeyword :smiling_imp: :neutral_face: :no_mouth: :innocent: :alien:
+syn keyword markdownEmoticonKeyword :yellow_heart: :blue_heart: :purple_heart: :heart: :green_heart:
+syn keyword markdownEmoticonKeyword :broken_heart: :heartbeat: :heartpulse: :two_hearts: :revolving_hearts:
+syn keyword markdownEmoticonKeyword :cupid: :sparkling_heart: :sparkles: :star: :star2:
+syn keyword markdownEmoticonKeyword :dizzy: :boom: :collision: :anger: :exclamation:
+syn keyword markdownEmoticonKeyword :question: :grey_exclamation: :grey_question: :zzz: :dash:
+syn keyword markdownEmoticonKeyword :sweat_drops: :notes: :musical_note: :fire: :hankey:
+syn keyword markdownEmoticonKeyword :poop: :shit: :+1: :thumbsup: :-1:
+syn keyword markdownEmoticonKeyword :thumbsdown: :ok_hand: :punch: :facepunch: :fist:
+syn keyword markdownEmoticonKeyword :v: :wave: :hand: :raised_hand: :open_hands:
+syn keyword markdownEmoticonKeyword :point_up: :point_down: :point_left: :point_right: :raised_hands:
+syn keyword markdownEmoticonKeyword :pray: :point_up_2: :clap: :muscle: :metal:
+syn keyword markdownEmoticonKeyword :fu: :walking: :runner: :running: :couple:
+syn keyword markdownEmoticonKeyword :family: :two_men_holding_hands: :two_women_holding_hands: :dancer: :dancers:
+syn keyword markdownEmoticonKeyword :ok_woman: :no_good: :information_desk_person: :raising_hand: :bride_with_veil:
+syn keyword markdownEmoticonKeyword :person_with_pouting_face: :person_frowning: :bow: :couplekiss: :couple_with_heart:
+syn keyword markdownEmoticonKeyword :massage: :haircut: :nail_care: :boy: :girl:
+syn keyword markdownEmoticonKeyword :woman: :man: :baby: :older_woman: :older_man:
+syn keyword markdownEmoticonKeyword :person_with_blond_hair: :man_with_gua_pi_mao: :man_with_turban: :construction_worker: :cop:
+syn keyword markdownEmoticonKeyword :angel: :princess: :smiley_cat: :smile_cat: :heart_eyes_cat:
+syn keyword markdownEmoticonKeyword :kissing_cat: :smirk_cat: :scream_cat: :crying_cat_face: :joy_cat:
+syn keyword markdownEmoticonKeyword :pouting_cat: :japanese_ogre: :japanese_goblin: :see_no_evil: :hear_no_evil:
+syn keyword markdownEmoticonKeyword :speak_no_evil: :guardsman: :skull: :feet: :lips:
+syn keyword markdownEmoticonKeyword :kiss: :droplet: :ear: :eyes: :nose:
+syn keyword markdownEmoticonKeyword :tongue: :love_letter: :bust_in_silhouette: :busts_in_silhouette: :speech_balloon:
+syn keyword markdownEmoticonKeyword :thought_balloon: :feelsgood: :finnadie: :goberserk: :godmode:
+syn keyword markdownEmoticonKeyword :hurtrealbad: :rage1: :rage2: :rage3: :rage4:
+syn keyword markdownEmoticonKeyword :suspect: :trollface: :sunny: :umbrella: :cloud:
+syn keyword markdownEmoticonKeyword :snowflake: :snowman: :zap: :cyclone: :foggy:
+syn keyword markdownEmoticonKeyword :ocean: :cat: :dog: :mouse: :hamster:
+syn keyword markdownEmoticonKeyword :rabbit: :wolf: :frog: :tiger: :koala:
+syn keyword markdownEmoticonKeyword :bear: :pig: :pig_nose: :cow: :boar:
+syn keyword markdownEmoticonKeyword :monkey_face: :monkey: :horse: :racehorse: :camel:
+syn keyword markdownEmoticonKeyword :sheep: :elephant: :panda_face: :snake: :bird:
+syn keyword markdownEmoticonKeyword :baby_chick: :hatched_chick: :hatching_chick: :chicken: :penguin:
+syn keyword markdownEmoticonKeyword :turtle: :bug: :honeybee: :ant: :beetle:
+syn keyword markdownEmoticonKeyword :snail: :octopus: :tropical_fish: :fish: :whale:
+syn keyword markdownEmoticonKeyword :whale2: :dolphin: :cow2: :ram: :rat:
+syn keyword markdownEmoticonKeyword :water_buffalo: :tiger2: :rabbit2: :dragon: :goat:
+syn keyword markdownEmoticonKeyword :rooster: :dog2: :pig2: :mouse2: :ox:
+syn keyword markdownEmoticonKeyword :dragon_face: :blowfish: :crocodile: :dromedary_camel: :leopard:
+syn keyword markdownEmoticonKeyword :cat2: :poodle: :paw_prints: :bouquet: :cherry_blossom:
+syn keyword markdownEmoticonKeyword :tulip: :four_leaf_clover: :rose: :sunflower: :hibiscus:
+syn keyword markdownEmoticonKeyword :maple_leaf: :leaves: :fallen_leaf: :herb: :mushroom:
+syn keyword markdownEmoticonKeyword :cactus: :palm_tree: :evergreen_tree: :deciduous_tree: :chestnut:
+syn keyword markdownEmoticonKeyword :seedling: :blossom: :ear_of_rice: :shell: :globe_with_meridians:
+syn keyword markdownEmoticonKeyword :sun_with_face: :full_moon_with_face: :new_moon_with_face: :new_moon: :waxing_crescent_moon:
+syn keyword markdownEmoticonKeyword :first_quarter_moon: :waxing_gibbous_moon: :full_moon: :waning_gibbous_moon: :last_quarter_moon:
+syn keyword markdownEmoticonKeyword :waning_crescent_moon: :last_quarter_moon_with_face: :first_quarter_moon_with_face: :moon: :earth_africa:
+syn keyword markdownEmoticonKeyword :earth_americas: :earth_asia: :volcano: :milky_way: :partly_sunny:
+syn keyword markdownEmoticonKeyword :octocat: :squirrel: :bamboo: :gift_heart: :dolls:
+syn keyword markdownEmoticonKeyword :school_satchel: :mortar_board: :flags: :fireworks: :sparkler:
+syn keyword markdownEmoticonKeyword :wind_chime: :rice_scene: :jack_o_lantern: :ghost: :santa:
+syn keyword markdownEmoticonKeyword :christmas_tree: :gift: :bell: :no_bell: :tanabata_tree:
+syn keyword markdownEmoticonKeyword :tada: :confetti_ball: :balloon: :crystal_ball: :cd:
+syn keyword markdownEmoticonKeyword :dvd: :floppy_disk: :camera: :video_camera: :movie_camera:
+syn keyword markdownEmoticonKeyword :computer: :tv: :iphone: :phone: :telephone:
+syn keyword markdownEmoticonKeyword :telephone_receiver: :pager: :fax: :minidisc: :vhs:
+syn keyword markdownEmoticonKeyword :sound: :speaker: :mute: :loudspeaker: :mega:
+syn keyword markdownEmoticonKeyword :hourglass: :hourglass_flowing_sand: :alarm_clock: :watch: :radio:
+syn keyword markdownEmoticonKeyword :satellite: :loop: :mag: :mag_right: :unlock:
+syn keyword markdownEmoticonKeyword :lock: :lock_with_ink_pen: :closed_lock_with_key: :key: :bulb:
+syn keyword markdownEmoticonKeyword :flashlight: :high_brightness: :low_brightness: :electric_plug: :battery:
+syn keyword markdownEmoticonKeyword :calling: :email: :mailbox: :postbox: :bath:
+syn keyword markdownEmoticonKeyword :bathtub: :shower: :toilet: :wrench: :nut_and_bolt:
+syn keyword markdownEmoticonKeyword :hammer: :seat: :moneybag: :yen: :dollar:
+syn keyword markdownEmoticonKeyword :pound: :euro: :credit_card: :money_with_wings: :e-mail:
+syn keyword markdownEmoticonKeyword :inbox_tray: :outbox_tray: :envelope: :incoming_envelope: :postal_horn:
+syn keyword markdownEmoticonKeyword :mailbox_closed: :mailbox_with_mail: :mailbox_with_no_mail: :door: :smoking:
+syn keyword markdownEmoticonKeyword :bomb: :gun: :hocho: :pill: :syringe:
+syn keyword markdownEmoticonKeyword :page_facing_up: :page_with_curl: :bookmark_tabs: :bar_chart: :chart_with_upwards_trend:
+syn keyword markdownEmoticonKeyword :chart_with_downwards_trend: :scroll: :clipboard: :calendar: :date:
+syn keyword markdownEmoticonKeyword :card_index: :file_folder: :open_file_folder: :scissors: :pushpin:
+syn keyword markdownEmoticonKeyword :paperclip: :black_nib: :pencil2: :straight_ruler: :triangular_ruler:
+syn keyword markdownEmoticonKeyword :closed_book: :green_book: :blue_book: :orange_book: :notebook:
+syn keyword markdownEmoticonKeyword :notebook_with_decorative_cover: :ledger: :books: :bookmark: :name_badge:
+syn keyword markdownEmoticonKeyword :microscope: :telescope: :newspaper: :football: :basketball:
+syn keyword markdownEmoticonKeyword :soccer: :baseball: :tennis: :8ball: :rugby_football:
+syn keyword markdownEmoticonKeyword :bowling: :golf: :mountain_bicyclist: :bicyclist: :horse_racing:
+syn keyword markdownEmoticonKeyword :snowboarder: :swimmer: :surfer: :ski: :spades:
+syn keyword markdownEmoticonKeyword :hearts: :clubs: :diamonds: :gem: :ring:
+syn keyword markdownEmoticonKeyword :trophy: :musical_score: :musical_keyboard: :violin: :space_invader:
+syn keyword markdownEmoticonKeyword :video_game: :black_joker: :flower_playing_cards: :game_die: :dart:
+syn keyword markdownEmoticonKeyword :mahjong: :clapper: :memo: :pencil: :book:
+syn keyword markdownEmoticonKeyword :art: :microphone: :headphones: :trumpet: :saxophone:
+syn keyword markdownEmoticonKeyword :guitar: :shoe: :sandal: :high_heel: :lipstick:
+syn keyword markdownEmoticonKeyword :boot: :shirt: :tshirt: :necktie: :womans_clothes:
+syn keyword markdownEmoticonKeyword :dress: :running_shirt_with_sash: :jeans: :kimono: :bikini:
+syn keyword markdownEmoticonKeyword :ribbon: :tophat: :crown: :womans_hat: :mans_shoe:
+syn keyword markdownEmoticonKeyword :closed_umbrella: :briefcase: :handbag: :pouch: :purse:
+syn keyword markdownEmoticonKeyword :eyeglasses: :fishing_pole_and_fish: :coffee: :tea: :sake:
+syn keyword markdownEmoticonKeyword :baby_bottle: :beer: :beers: :cocktail: :tropical_drink:
+syn keyword markdownEmoticonKeyword :wine_glass: :fork_and_knife: :pizza: :hamburger: :fries:
+syn keyword markdownEmoticonKeyword :poultry_leg: :meat_on_bone: :spaghetti: :curry: :fried_shrimp:
+syn keyword markdownEmoticonKeyword :bento: :sushi: :fish_cake: :rice_ball: :rice_cracker:
+syn keyword markdownEmoticonKeyword :rice: :ramen: :stew: :oden: :dango:
+syn keyword markdownEmoticonKeyword :egg: :bread: :doughnut: :custard: :icecream:
+syn keyword markdownEmoticonKeyword :ice_cream: :shaved_ice: :birthday: :cake: :cookie:
+syn keyword markdownEmoticonKeyword :chocolate_bar: :candy: :lollipop: :honey_pot: :apple:
+syn keyword markdownEmoticonKeyword :green_apple: :tangerine: :lemon: :cherries: :grapes:
+syn keyword markdownEmoticonKeyword :watermelon: :strawberry: :peach: :melon: :banana:
+syn keyword markdownEmoticonKeyword :pear: :pineapple: :sweet_potato: :eggplant: :tomato:
+syn keyword markdownEmoticonKeyword :corn: :house: :house_with_garden: :school: :office:
+syn keyword markdownEmoticonKeyword :post_office: :hospital: :bank: :convenience_store: :love_hotel:
+syn keyword markdownEmoticonKeyword :hotel: :wedding: :church: :department_store: :european_post_office:
+syn keyword markdownEmoticonKeyword :city_sunrise: :city_sunset: :japanese_castle: :european_castle: :tent:
+syn keyword markdownEmoticonKeyword :factory: :tokyo_tower: :japan: :mount_fuji: :sunrise_over_mountains:
+syn keyword markdownEmoticonKeyword :sunrise: :stars: :statue_of_liberty: :bridge_at_night: :carousel_horse:
+syn keyword markdownEmoticonKeyword :rainbow: :ferris_wheel: :fountain: :roller_coaster: :ship:
+syn keyword markdownEmoticonKeyword :speedboat: :boat: :sailboat: :rowboat: :anchor:
+syn keyword markdownEmoticonKeyword :rocket: :airplane: :helicopter: :steam_locomotive: :tram:
+syn keyword markdownEmoticonKeyword :mountain_railway: :bike: :aerial_tramway: :suspension_railway: :mountain_cableway:
+syn keyword markdownEmoticonKeyword :tractor: :blue_car: :oncoming_automobile: :car: :red_car:
+syn keyword markdownEmoticonKeyword :taxi: :oncoming_taxi: :articulated_lorry: :bus: :oncoming_bus:
+syn keyword markdownEmoticonKeyword :rotating_light: :police_car: :oncoming_police_car: :fire_engine: :ambulance:
+syn keyword markdownEmoticonKeyword :minibus: :truck: :train: :station: :train2:
+syn keyword markdownEmoticonKeyword :bullettrain_front: :bullettrain_side: :light_rail: :monorail: :railway_car:
+syn keyword markdownEmoticonKeyword :trolleybus: :ticket: :fuelpump: :vertical_traffic_light: :traffic_light:
+syn keyword markdownEmoticonKeyword :warning: :construction: :beginner: :atm: :slot_machine:
+syn keyword markdownEmoticonKeyword :busstop: :barber: :hotsprings: :checkered_flag: :crossed_flags:
+syn keyword markdownEmoticonKeyword :izakaya_lantern: :moyai: :circus_tent: :performing_arts: :round_pushpin:
+syn keyword markdownEmoticonKeyword :triangular_flag_on_post: :jp: :kr: :cn: :us:
+syn keyword markdownEmoticonKeyword :fr: :es: :it: :ru: :gb:
+syn keyword markdownEmoticonKeyword :uk: :de: :one: :two: :three:
+syn keyword markdownEmoticonKeyword :four: :five: :six: :seven: :eight:
+syn keyword markdownEmoticonKeyword :nine: :keycap_ten: :1234: :zero: :hash:
+syn keyword markdownEmoticonKeyword :symbols: :arrow_backward: :arrow_down: :arrow_forward: :arrow_left:
+syn keyword markdownEmoticonKeyword :capital_abcd: :abcd: :abc: :arrow_lower_left: :arrow_lower_right:
+syn keyword markdownEmoticonKeyword :arrow_right: :arrow_up: :arrow_upper_left: :arrow_upper_right: :arrow_double_down:
+syn keyword markdownEmoticonKeyword :arrow_double_up: :arrow_down_small: :arrow_heading_down: :arrow_heading_up: :leftwards_arrow_with_hook:
+syn keyword markdownEmoticonKeyword :arrow_right_hook: :left_right_arrow: :arrow_up_down: :arrow_up_small: :arrows_clockwise:
+syn keyword markdownEmoticonKeyword :arrows_counterclockwise: :rewind: :fast_forward: :information_source: :ok:
+syn keyword markdownEmoticonKeyword :twisted_rightwards_arrows: :repeat: :repeat_one: :new: :top:
+syn keyword markdownEmoticonKeyword :up: :cool: :free: :ng: :cinema:
+syn keyword markdownEmoticonKeyword :koko: :signal_strength: :u5272: :u5408: :u55b6:
+syn keyword markdownEmoticonKeyword :u6307: :u6708: :u6709: :u6e80: :u7121:
+syn keyword markdownEmoticonKeyword :u7533: :u7a7a: :u7981: :sa: :restroom:
+syn keyword markdownEmoticonKeyword :mens: :womens: :baby_symbol: :no_smoking: :parking:
+syn keyword markdownEmoticonKeyword :wheelchair: :metro: :baggage_claim: :accept: :wc:
+syn keyword markdownEmoticonKeyword :potable_water: :put_litter_in_its_place: :secret: :congratulations: :m:
+syn keyword markdownEmoticonKeyword :passport_control: :left_luggage: :customs: :ideograph_advantage: :cl:
+syn keyword markdownEmoticonKeyword :sos: :id: :no_entry_sign: :underage: :no_mobile_phones:
+syn keyword markdownEmoticonKeyword :do_not_litter: :non-potable_water: :no_bicycles: :no_pedestrians: :children_crossing:
+syn keyword markdownEmoticonKeyword :no_entry: :eight_spoked_asterisk: :eight_pointed_black_star: :heart_decoration: :vs:
+syn keyword markdownEmoticonKeyword :vibration_mode: :mobile_phone_off: :chart: :currency_exchange: :aries:
+syn keyword markdownEmoticonKeyword :taurus: :gemini: :cancer: :leo: :virgo:
+syn keyword markdownEmoticonKeyword :libra: :scorpius: :sagittarius: :capricorn: :aquarius:
+syn keyword markdownEmoticonKeyword :pisces: :ophiuchus: :six_pointed_star: :negative_squared_cross_mark: :a:
+syn keyword markdownEmoticonKeyword :b: :ab: :o2: :diamond_shape_with_a_dot_inside: :recycle:
+syn keyword markdownEmoticonKeyword :end: :on: :soon: :clock1: :clock130:
+syn keyword markdownEmoticonKeyword :clock10: :clock1030: :clock11: :clock1130: :clock12:
+syn keyword markdownEmoticonKeyword :clock1230: :clock2: :clock230: :clock3: :clock330:
+syn keyword markdownEmoticonKeyword :clock4: :clock430: :clock5: :clock530: :clock6:
+syn keyword markdownEmoticonKeyword :clock630: :clock7: :clock730: :clock8: :clock830:
+syn keyword markdownEmoticonKeyword :clock9: :clock930: :heavy_dollar_sign: :copyright: :registered:
+syn keyword markdownEmoticonKeyword :tm: :x: :heavy_exclamation_mark: :bangbang: :interrobang:
+syn keyword markdownEmoticonKeyword :o: :heavy_multiplication_x: :heavy_plus_sign: :heavy_minus_sign: :heavy_division_sign:
+syn keyword markdownEmoticonKeyword :white_flower: :100: :heavy_check_mark: :ballot_box_with_check: :radio_button:
+syn keyword markdownEmoticonKeyword :link: :curly_loop: :wavy_dash: :part_alternation_mark: :trident:
+syn keyword markdownEmoticonKeyword :black_square: :white_square: :white_check_mark: :black_square_button: :white_square_button:
+syn keyword markdownEmoticonKeyword :black_circle: :white_circle: :red_circle: :large_blue_circle: :large_blue_diamond:
+syn keyword markdownEmoticonKeyword :large_orange_diamond: :small_blue_diamond: :small_orange_diamond: :small_red_triangle: :small_red_triangle_down:
+syn keyword markdownEmoticonKeyword :shipit:
+
+" }}}
+
+
+" {{{ HIGHLIGHT DEFINITION
+
+hi def Italic term=italic cterm=italic gui=italic
+hi def Bold term=bold cterm=bold gui=bold
+hi def BoldItalic term=bold,italic cterm=bold,italic gui=bold,italic
+
+hi def link markdownItalic Italic
+hi def link markdownBold Bold
+hi def link markdownBoldItalic BoldItalic
+
+hi def link markdownPullRequestLinkInText Underlined
+hi def link markdownUserLinkInText Underlined
+hi def link markdownUrlLinkInText Underlined
+hi def link markdownEmailLinkInText Underlined
+
+hi def link markdownLinkText Underlined
+hi def link markdownLinkUrl Underlined
+hi def link markdownLinkTitleSingleQuoted Bold
+hi def link markdownLinkTitleDoubleQuoted Bold
+hi def link markdownLinkUrlContainer Delimiter
+hi def link markdownLinkTextContainer Delimiter
+hi def link markdownLinkReference NonText
+
+hi def link markdownCodeDelimiter Delimiter
+hi def link markdownInlineCode String
+hi def link markdownFencedCodeBlock String
+hi def link markdownCodeBlock String
+
+hi def link markdownTableDelimiter Delimiter
+hi def link markdownTableHeader Bold
+
+hi def link markdownStrike NonText
+hi def link markdownStrikeDelimiter Delimiter
+hi def link markdownBlockquote Comment
+hi def link markdownBlockquoteDelimiter Delimiter
+hi def link markdownInlineDelimiter Delimiter
+hi def link markdownListDelimiter Delimiter
+
+hi def link markdownHeaderId Delimiter
+hi def link markdownHeadingDelimiter Delimiter
+hi def link markdownHeadingUnderline Delimiter
+hi def link markdownHeader Title
+hi def link markdownH1 Title
+hi def link markdownH2 Title
+hi def link markdownH3 Title
+hi def link markdownH4 Title
+hi def link markdownH5 Title
+hi def link markdownH6 Title
+
+hi def link markdownEmoticonKeyword Statement
+hi def link markdownRule Identifier
+
+hi def link markdownXmlComment NonText
+hi def link markdownXmlElement NonText
+hi def link markdownXmlEmptyElement NonText
+hi def link markdownXmlEntities Special
+
+" }}}
+
+
+if !exists('g:markdown_include_jekyll_support') || g:markdown_include_jekyll_support
+ execute 'runtime! syntax/markdown_jekyll.vim'
endif
-syn cluster mkdNonListItem contains=@htmlTop,htmlItalic,htmlBold,htmlBoldItalic,mkdFootnotes,mkdInlineURL,mkdLink,mkdLinkDef,mkdLineBreak,mkdBlockquote,mkdCode,mkdRule,htmlH1,htmlH2,htmlH3,htmlH4,htmlH5,htmlH6,mkdMath,mkdStrike
-
-"highlighting for Markdown groups
-HtmlHiLink mkdString String
-HtmlHiLink mkdCode String
-HtmlHiLink mkdCodeDelimiter String
-HtmlHiLink mkdCodeStart String
-HtmlHiLink mkdCodeEnd String
-HtmlHiLink mkdFootnote Comment
-HtmlHiLink mkdBlockquote Comment
-HtmlHiLink mkdListItem Identifier
-HtmlHiLink mkdRule Identifier
-HtmlHiLink mkdLineBreak Visual
-HtmlHiLink mkdFootnotes htmlLink
-HtmlHiLink mkdLink htmlLink
-HtmlHiLink mkdURL htmlString
-HtmlHiLink mkdInlineURL htmlLink
-HtmlHiLink mkdID Identifier
-HtmlHiLink mkdLinkDef mkdID
-HtmlHiLink mkdLinkDefTarget mkdURL
-HtmlHiLink mkdLinkTitle htmlString
-HtmlHiLink mkdDelimiter Delimiter
-
-let b:current_syntax = "mkd"
-
-delcommand HtmlHiLink
-" vim: ts=8
+let b:current_syntax = "markdown"
+if main_syntax ==# 'markdown'
+ unlet main_syntax
+endif
endif
diff --git a/syntax/markdown_jekyll.vim b/syntax/markdown_jekyll.vim
new file mode 100644
index 00000000..68bf549b
--- /dev/null
+++ b/syntax/markdown_jekyll.vim
@@ -0,0 +1,34 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'markdown') == -1
+
+let b:markdown_in_jekyll=0
+
+if getline(1) =~ '^---\s*$'
+ let b:markdown_in_jekyll=1
+
+ syn region markdownJekyllFrontMatter matchgroup=markdownJekyllDelimiter contains=@NoSpell
+ \ start="\%^---" end="^---$"
+
+ syn region markdownJekyllLiquidTag matchgroup=markdownJekyllDelimiter contains=@NoSpell oneline
+ \ start="{%" end="%}"
+
+ syn region markdownJekyllLiquidOutputTag matchgroup=markdownJekyllDelimiter contains=@NoSpell oneline
+ \ start="{{" skip=/"}}"/ end="}}"
+
+ syn region markdownJekyllLiquidBlockTag matchgroup=markdownJekyllDelimiter contains=@NoSpell
+ \ start="{%\s*\z(comment\|raw\|highlight\)[^%]*%}" end="{%\s*\%(no\|end\)\z1\s*%}"
+
+ silent spell! nocomment
+ silent spell! endcomment
+ silent spell! nohighlight
+ silent spell! endhighlight
+ silent spell! noraw
+ silent spell! endraw
+
+ hi def link markdownJekyllFrontMatter NonText
+ hi def link markdownJekyllLiquidTag NonText
+ hi def link markdownJekyllLiquidOutputTag NonText
+ hi def link markdownJekyllLiquidBlockTag NonText
+ hi def link markdownJekyllDelimiter Delimiter
+endif
+
+endif