diff --git a/autoload/SpaceVim/layers/lang/markdown.vim b/autoload/SpaceVim/layers/lang/markdown.vim index 41ee0b00f..284c3c674 100644 --- a/autoload/SpaceVim/layers/lang/markdown.vim +++ b/autoload/SpaceVim/layers/lang/markdown.vim @@ -70,7 +70,7 @@ function! SpaceVim#layers#lang#markdown#plugins() abort let plugins = [] call add(plugins, ['SpaceVim/vim-markdown',{ 'on_ft' : 'markdown'}]) call add(plugins, ['joker1007/vim-markdown-quote-syntax',{ 'on_ft' : 'markdown'}]) - call add(plugins, ['mzlogin/vim-markdown-toc',{ 'on_ft' : 'markdown'}]) + call add(plugins, [g:_spacevim_root_dir . 'bundle/vim-markdown-toc', {'merged' : 0}]) call add(plugins, ['iamcco/mathjax-support-for-mkdp',{ 'on_ft' : 'markdown'}]) call add(plugins, ['lvht/tagbar-markdown',{'merged' : 0}]) " check node package managers to ensure building of 2 plugins below diff --git a/bundle/vim-markdown-toc/.github/FUNDING.yml b/bundle/vim-markdown-toc/.github/FUNDING.yml new file mode 100644 index 000000000..8625cb831 --- /dev/null +++ b/bundle/vim-markdown-toc/.github/FUNDING.yml @@ -0,0 +1,13 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +custom: https://mazhuang.org/donate/ diff --git a/bundle/vim-markdown-toc/.gitignore b/bundle/vim-markdown-toc/.gitignore new file mode 100644 index 000000000..aac6530ba --- /dev/null +++ b/bundle/vim-markdown-toc/.gitignore @@ -0,0 +1,3 @@ +*.swp +.DS_Store +tags diff --git a/bundle/vim-markdown-toc/LICENSE b/bundle/vim-markdown-toc/LICENSE new file mode 100644 index 000000000..b62b600a9 --- /dev/null +++ b/bundle/vim-markdown-toc/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Zhuang Ma + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/bundle/vim-markdown-toc/README.md b/bundle/vim-markdown-toc/README.md new file mode 100644 index 000000000..d7d959ed0 --- /dev/null +++ b/bundle/vim-markdown-toc/README.md @@ -0,0 +1,227 @@ +# vim-markdown-toc + +A vim 7.4+ plugin to generate table of contents for Markdown files. + +[中文版使用指南][7] + +## Table of Contents + + + +* [Features](#features) +* [Installation](#installation) + * [vim-plug](#vim-plug) + * [Vundle](#vundle) +* [Usage](#usage) + * [Generate table of contents](#generate-table-of-contents) + * [Update existing table of contents](#update-existing-table-of-contents) + * [Remove table of contents](#remove-table-of-contents) +* [Options](#options) +* [Screenshots](#screenshots) +* [References](#references) + + + +## Features + +* Generate table of contents for Markdown files. + + Supported Markdown parsers: + + - [x] GFM (GitHub Flavored Markdown) + - [x] GitLab + - [x] Redcarpet + +* Update existing table of contents. + +* Auto update existing table of contents on save. + +## Installation + +Suggest to manage your vim plugins via [vim-plug][8] or [Vundle][4], so you can install it simply three steps: + +### vim-plug + +1. add the following line to your vimrc file + + ``` + Plug 'mzlogin/vim-markdown-toc' + ``` + +2. `:so $MYVIMRC` + +3. `:PlugInstall` + +### Vundle + +1. add the following line to your vimrc file + + ``` + Plugin 'mzlogin/vim-markdown-toc' + ``` + +2. `:so $MYVIMRC` + +3. `:PluginInstall` + +## Usage + +### Generate table of contents + +Move the cursor to the line you want to append table of contents, then type a command below suit you. The command will generate **headings after the cursor** into table of contents. + +1. `:GenTocGFM` + + Generate table of contents in [GFM][2] link style. + + This command is suitable for Markdown files in GitHub repositories, like `README.md`, and Markdown files for GitBook. + +2. `:GenTocRedcarpet` + + Generate table of contents in [Redcarpet][3] link style. + + This command is suitable for Jekyll or anywhere else use Redcarpet as its Markdown parser. + +3. `:GenTocGitLab` + + Generate table of contents in [GitLab][9] link style. + + This command is suitable for GitLab repository and wiki. + +4. `:GenTocMarked` + + Generate table of contents for [iamcco/markdown-preview.vim][10] which use [Marked][11] markdown parser. + +You can view [here][1] to know differences between *GFM* and *Redcarpet* style toc links. + +### Update existing table of contents + +Generally you don't need to do this manually, existing table of contents will auto update on save by default. + +The `:UpdateToc` command, which is designed to update toc manually, can only work when `g:vmt_auto_update_on_save` turned off, and keep insert fence. + +### Remove table of contents + +`:RemoveToc` command will do this for you, just remember keep insert fence option by default. + +## Options + +1. `g:vmt_auto_update_on_save` + + default: 1 + + This plugin will update existing table of contents on save automatic. + + You can close this feature by add the following line to your vimrc file: + + ```viml + let g:vmt_auto_update_on_save = 0 + ``` + +2. `g:vmt_dont_insert_fence` + + default: 0 + + By default, the `:GenTocXXX` commands will add `` fence to the table of contents, it is designed for feature of auto update table of contents on save and `:UpdateToc` command, it won't effect what your Markdown file looks like after parse. + + If you don't like this, you can remove the fence by add the following line to your vimrc file: + + ```viml + let g:vmt_dont_insert_fence = 1 + ``` + + But then you will lose the convenience of auto update tables of contents on save and `:UpdateToc` command. When you want to update toc, you need to remove existing toc manually and rerun `:GenTocXXX` commands. + +3. `g:vmt_fence_text` + + default: `vim-markdown-toc` + + Inner text of the fence marker for the table of contents, see `g:vmt_dont_insert_fence`. + +4. `g:vmt_fence_closing_text` + + default: `g:vmt_fence_text` + + Inner text of the closing fence marker. E.g., you could `let g:vmt_fence_text = 'TOC'` and `let g:vmt_fence_closing_text = '/TOC'` to get + + ``` + + [TOC] + + ``` + +5. `g:vmt_fence_hidden_markdown_style` + + default: `''` + + By default, _vim-markdown-toc_ will add the markdown style into the fence of the text for the table of contents. You can avoid this and set a default markdown style with `g:vmt_fence_hidden_markdown_style` that is applied if a fence is found containing the `g:vmt_fence_text` without any markdown style. Obviously, `g:vmt_fence_hidden_markdown_style` has to be supported, i.e. currently one of `['GFM', 'Redcarpet', 'GitLab', 'Marked']`. + +6. `g:vmt_cycle_list_item_markers` + + default: 0 + + By default, `*` is used to denote every level of a list: + + ``` + * [Level 1](#level-1) + * [Level 1-1](#level-1-1) + * [Level 1-2](#level-1-2) + * [Level 1-2-1](#level-1-2-1) + * [Level 2](level-2) + ``` + + If you set: + + ```viml + let g:vmt_cycle_list_item_markers = 1 + ``` + + every level will instead cycle between the valid list item markers `*`, `-` and `+`: + + ``` + * [Level 1](#level-1) + - [Level 1-1](#level-1-1) + - [Level 1-2](#level-1-2) + + [Level 1-2-1](#level-1-2-1) + * [Level 2](level-2) + ``` + + This renders the same according to Markdown rules, but might appeal to those who care about readability of the source. + +7. `g:vmt_list_item_char` + + default: `*` + + The list item marker, it can be `*`, `-` or `+`. + +8. `g:vmt_include_headings_before` + + default: `0` + + Include headings before the position you are inserting Table of Contents. + +## Screenshots + +* [online demo in English][5] + +![](./screenshots/english.gif) + +* [online demo in Chinese][6] + +![](./screenshots/chinese.gif) + +## References + +* + +[1]: http://mazhuang.org/2015/12/05/diff-between-gfm-and-redcarpet/ +[2]: https://github.github.com/gfm/ +[3]: https://github.com/vmg/redcarpet +[4]: http://github.com/VundleVim/Vundle.Vim +[5]: https://github.com/mzlogin/chinese-copywriting-guidelines/blob/Simplified/README.en.md +[6]: https://github.com/mzlogin/awesome-adb +[7]: http://mazhuang.org/2015/12/19/vim-markdown-toc/ +[8]: https://github.com/junegunn/vim-plug +[9]: https://docs.gitlab.com/ee/user/markdown.html +[10]:https://github.com/iamcco/markdown-preview.vim +[11]:https://github.com/markedjs/marked diff --git a/bundle/vim-markdown-toc/ftdetect/markdown.vim b/bundle/vim-markdown-toc/ftdetect/markdown.vim new file mode 100644 index 000000000..2b698727c --- /dev/null +++ b/bundle/vim-markdown-toc/ftdetect/markdown.vim @@ -0,0 +1 @@ +au BufRead,BufNewFile *.{md,mdown,mkd,mkdn,markdown,mdwn,mdx} set filetype=markdown diff --git a/bundle/vim-markdown-toc/ftplugin/markdown.vim b/bundle/vim-markdown-toc/ftplugin/markdown.vim new file mode 100644 index 000000000..48c957ecf --- /dev/null +++ b/bundle/vim-markdown-toc/ftplugin/markdown.vim @@ -0,0 +1,492 @@ +if exists("g:loaded_MarkdownTocPlugin") + finish +elseif v:version < 704 + finish +endif + +let g:loaded_MarkdownTocPlugin = 1 + +if !exists("g:vmt_auto_update_on_save") + let g:vmt_auto_update_on_save = 1 +endif + +if !exists("g:vmt_dont_insert_fence") + let g:vmt_dont_insert_fence = 0 +endif + +if !exists("g:vmt_fence_text") + let g:vmt_fence_text = 'vim-markdown-toc' +endif + +if !exists("g:vmt_fence_closing_text") + let g:vmt_fence_closing_text = g:vmt_fence_text +endif + +if !exists("g:vmt_fence_hidden_markdown_style") + let g:vmt_fence_hidden_markdown_style = '' +endif + +if !exists("g:vmt_list_item_char") + let g:vmt_list_item_char = '*' +endif + +if !exists("g:vmt_list_indent_text") + let g:vmt_list_indent_text = '' +endif + +if !exists("g:vmt_cycle_list_item_markers") + let g:vmt_cycle_list_item_markers = 0 +endif + +if !exists("g:vmt_include_headings_before") + let g:vmt_include_headings_before = 0 +endif + +if !exists("g:vmt_link") + let g:vmt_link = 1 +endif + +if !exists("g:vmt_min_level") + let g:vmt_min_level = 1 +endif + +if !exists("g:vmt_max_level") + let g:vmt_max_level = 6 +endif + +let g:GFMHeadingIds = {} + +let s:supportMarkdownStyles = ['GFM', 'Redcarpet', 'GitLab', 'Marked'] + +let s:GFM_STYLE_INDEX = 0 +let s:REDCARPET_STYLE_INDEX = 1 +let s:GITLAB_STYLE_INDEX = 2 +let s:MARKED_STYLE_INDEX = 3 + +function! s:HeadingLineRegex() + return '\v(^.+$\n^\=+$|^.+$\n^\-+$|^#{1,6})' +endfunction + +function! s:GetSections(beginRegex, endRegex) + let l:winview = winsaveview() + let l:sections = {} + + keepjumps normal! gg0 + let l:flags = "Wc" + let l:beginLine = 0 + let l:regex = a:beginRegex + while search(l:regex, l:flags) + let l:lineNum = line(".") + if l:beginLine == 0 + let l:beginLine = l:lineNum + let l:regex = a:endRegex + else + let l:sections[l:beginLine] = l:lineNum + let l:beginLine = 0 + let l:regex = a:beginRegex + endif + let l:flags = "W" + endwhile + + call winrestview(l:winview) + + return l:sections +endfunction + +function! s:GetCodeSections() + let l:codeSections = {} + + call extend(l:codeSections, GetSections("^```", "^```")) + call extend(l:codeSections, GetSections("^\\~\\~\\~", "^\\~\\~\\~")) + call extend(l:codeSections, GetSections("^{% highlight", "^{% endhighlight")) + + return l:codeSections +endfunction + +function! s:IsLineInCodeSections(codeSections, lineNum) + for beginLine in keys(a:codeSections) + if a:lineNum >= str2nr(beginLine) + if a:lineNum <= a:codeSections[beginLine] + return 1 + endif + endif + endfor + + return 0 +endfunction + +function! s:GetHeadingLines() + let l:winview = winsaveview() + let l:headingLines = [] + let l:codeSections = GetCodeSections() + + let l:flags = "W" + if g:vmt_include_headings_before == 1 + keepjumps normal! gg0 + let l:flags = "Wc" + endif + + let l:headingLineRegex = HeadingLineRegex() + + while search(l:headingLineRegex, l:flags) != 0 + let l:line = getline(".") + let l:lineNum = line(".") + if IsLineInCodeSections(l:codeSections, l:lineNum) == 0 + " === compatible with Setext Style headings + let l:nextLine = getline(l:lineNum + 1) + if matchstr(l:nextLine, '\v^\=+$') != "" + let l:line = "# " . l:line + elseif matchstr(l:nextLine, '\v^\-+$') != "" + let l:line = "## " . l:line + endif + " === + + call add(l:headingLines, l:line) + endif + let l:flags = "W" + endwhile + + call winrestview(l:winview) + + return l:headingLines +endfunction + +function! s:GetHeadingLevel(headingLine) + return match(a:headingLine, '[^#]') +endfunction + +function! s:GetHeadingLinkGFM(headingName) + let l:headingLink = tr(a:headingName, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz") + + " \_^ : start of line + " _\+ : one of more underscore _ + " \| : OR + " _\+ : one of more underscore _ + " \_$ : end of line + let l:headingLink = substitute(l:headingLink, "\\_^_\\+\\|_\\+\\_$", "", "g") + " Characters that are not alphanumeric, latin1 extended (for accents) and + " chinese/korean chars are removed. + " \\%#=0: allow this pattern to use the regexp engine he wants. Having + " `set re=1` in the vimrc could break this behavior. cf. issue #19 + let l:headingLink = substitute(l:headingLink, "\\%#=0[^[:alnum:]\u00C0-\u00FF\u0400-\u04ff\u4e00-\u9fbf\u3040-\u309F\u30A0-\u30FF\uAC00-\uD7AF _-]", "", "g") + let l:headingLink = substitute(l:headingLink, " ", "-", "g") + + if l:headingLink ==# "" + let l:nullKey = "" + if has_key(g:GFMHeadingIds, l:nullKey) + let g:GFMHeadingIds[l:nullKey] += 1 + let l:headingLink = l:headingLink . "-" . g:GFMHeadingIds[l:nullKey] + else + let g:GFMHeadingIds[l:nullKey] = 0 + endif + elseif has_key(g:GFMHeadingIds, l:headingLink) + let g:GFMHeadingIds[l:headingLink] += 1 + let l:headingLink = l:headingLink . "-" . g:GFMHeadingIds[l:headingLink] + else + let g:GFMHeadingIds[l:headingLink] = 0 + endif + + return l:headingLink +endfunction + +" suppport for GitLab, fork of GetHeadingLinkGFM +" it's dirty to copy & paste code but more clear for maintain +function! s:GetHeadingLinkGitLab(headingName) + let l:headingLink = tolower(a:headingName) + + let l:headingLink = substitute(l:headingLink, "\\_^_\\+\\|_\\+\\_$", "", "g") + let l:headingLink = substitute(l:headingLink, "\\%#=0[^[:alnum:]\u00C0-\u00FF\u0400-\u04ff\u4e00-\u9fbf _-]", "", "g") + let l:headingLink = substitute(l:headingLink, " ", "-", "g") + let l:headingLink = substitute(l:headingLink, "-\\{2,}", "-", "g") + + if l:headingLink ==# "" + let l:nullKey = "" + if has_key(g:GFMHeadingIds, l:nullKey) + let g:GFMHeadingIds[l:nullKey] += 1 + let l:headingLink = l:headingLink . "-" . g:GFMHeadingIds[l:nullKey] + else + let g:GFMHeadingIds[l:nullKey] = 0 + endif + elseif has_key(g:GFMHeadingIds, l:headingLink) + let g:GFMHeadingIds[l:headingLink] += 1 + let l:headingLink = l:headingLink . "-" . g:GFMHeadingIds[l:headingLink] + else + let g:GFMHeadingIds[l:headingLink] = 0 + endif + + return l:headingLink +endfunction + +function! s:GetHeadingLinkRedcarpet(headingName) + let l:headingLink = tolower(a:headingName) + + let l:headingLink = substitute(l:headingLink, "<[^>]\\+>", "", "g") + let l:headingLink = substitute(l:headingLink, "&", "&", "g") + let l:headingLink = substitute(l:headingLink, "\"", """, "g") + let l:headingLink = substitute(l:headingLink, "'", "'", "g") + + let l:headingLink = substitute(l:headingLink, "[ \\-&+\\$,/:;=?@\"#{}|\\^\\~\\[\\]`\\*()%.!']\\+", "-", "g") + let l:headingLink = substitute(l:headingLink, "-\\{2,}", "-", "g") + let l:headingLink = substitute(l:headingLink, "\\%^[\\-_]\\+\\|[\\-_]\\+\\%$", "", "g") + + return l:headingLink +endfunction + +function! s:GetHeadingLinkMarked(headingName) + let l:headingLink = tolower(a:headingName) + + let l:headingLink = substitute(l:headingLink, "[ ]\\+", "-", "g") + + return l:headingLink +endfunction + +function! s:GetHeadingName(headingLine) + let l:headingName = substitute(a:headingLine, '^#*\s*', "", "") + let l:headingName = substitute(l:headingName, '\s*#*$', "", "") + + let l:headingName = substitute(l:headingName, '\[\([^\[\]]*\)\]([^()]*)', '\1', "g") + let l:headingName = substitute(l:headingName, '\[\([^\[\]]*\)\]\[[^\[\]]*\]', '\1', "g") + + return l:headingName +endfunction + +function! s:GetHeadingLink(headingName, markdownStyle) + if a:markdownStyle ==# s:supportMarkdownStyles[s:GFM_STYLE_INDEX] + return GetHeadingLinkGFM(a:headingName) + elseif a:markdownStyle ==# s:supportMarkdownStyles[s:REDCARPET_STYLE_INDEX] + return GetHeadingLinkRedcarpet(a:headingName) + elseif a:markdownStyle ==# s:supportMarkdownStyles[s:GITLAB_STYLE_INDEX] + return GetHeadingLinkGitLab(a:headingName) + elseif a:markdownStyle ==# s:supportMarkdownStyles[s:MARKED_STYLE_INDEX] + return GetHeadingLinkMarked(a:headingName) + endif +endfunction + +function! GetHeadingLinkTest(headingLine, markdownStyle) + let l:headingName = GetHeadingName(a:headingLine) + return GetHeadingLink(l:headingName, a:markdownStyle) +endfunction + +function! s:GenToc(markdownStyle) + call GenTocInner(a:markdownStyle, 0) +endfunction + +function! s:GenTocInner(markdownStyle, isModeline) + if index(s:supportMarkdownStyles, a:markdownStyle) == -1 + echom "Unsupport markdown style: " . a:markdownStyle + return + endif + + let l:headingLines = GetHeadingLines() + let l:levels = [] + let l:listItemChars = [g:vmt_list_item_char] + + let g:GFMHeadingIds = {} + + for headingLine in l:headingLines + call add(l:levels, GetHeadingLevel(headingLine)) + endfor + + let l:minLevel = max([min(l:levels),g:vmt_min_level]) + + if g:vmt_dont_insert_fence == 0 + silent put =GetBeginFence(a:markdownStyle, a:isModeline) + endif + + if g:vmt_cycle_list_item_markers == 1 + let l:listItemChars = ['*', '-', '+'] + endif + + let l:i = 0 + " a black line before toc + if !empty(l:headingLines) + silent put ='' + endif + + for headingLine in l:headingLines + let l:headingName = GetHeadingName(headingLine) + " only add line if less than max level and greater than min level + if l:levels[i] <= g:vmt_max_level && l:levels[i] >= g:vmt_min_level + let l:headingIndents = l:levels[i] - l:minLevel + let l:listItemChar = l:listItemChars[(l:levels[i] + 1) % len(l:listItemChars)] + " make link if desired, otherwise just bullets + if g:vmt_link + let l:headingLink = GetHeadingLink(l:headingName, a:markdownStyle) + let l:heading = repeat(s:GetIndentText(), l:headingIndents) + let l:heading = l:heading . l:listItemChar + let l:heading = l:heading . " [" . l:headingName . "]" + let l:heading = l:heading . "(#" . l:headingLink . ")" + else + let l:heading = repeat(s:GetIndentText(), l:headingIndents) + let l:heading = l:heading . l:listItemChar + let l:heading = l:heading . " " . l:headingName + endif + silent put =l:heading + endif + let l:i += 1 + endfor + + " a blank line after toc to avoid effect typo of content below + silent put ='' + + if g:vmt_dont_insert_fence == 0 + silent put =GetEndFence() + endif +endfunction + +function! s:GetIndentText() + if !empty(g:vmt_list_indent_text) + return g:vmt_list_indent_text + endif + if &expandtab + return repeat(" ", &shiftwidth) + else + return "\t" + endif +endfunction + +function! s:GetBeginFence(markdownStyle, isModeline) + if a:isModeline != 0 + return "" + else + return "" + endif +endfunction + +function! s:GetEndFence() + return "" +endfunction + +function! s:GetBeginFencePattern(isModeline) + if a:isModeline != 0 + return "" + else + return "" + endif +endfunction + +function! s:GetEndFencePattern() + return "" +endfunction + +function! s:GetMarkdownStyleInModeline() + let l:myFileType = &filetype + let l:lst = split(l:myFileType, "\\.") + if len(l:lst) == 2 && l:lst[1] ==# "markdown" + return l:lst[0] + else + return "Unknown" + endif +endfunction + +function! s:UpdateToc() + let l:winview = winsaveview() + + let l:totalLineNum = line("$") + + let [l:markdownStyle, l:beginLineNumber, l:endLineNumber, l:isModeline] = DeleteExistingToc() + + if l:markdownStyle ==# "" + echom "Cannot find existing toc" + elseif l:markdownStyle ==# "Unknown" + echom "Find unsupported style toc" + else + let l:isFirstLine = (l:beginLineNumber == 1) + if l:beginLineNumber > 1 + let l:beginLineNumber -= 1 + endif + + if l:isFirstLine != 0 + call cursor(l:beginLineNumber, 1) + put! ='' + endif + + call cursor(l:beginLineNumber, 1) + call GenTocInner(l:markdownStyle, l:isModeline) + + if l:isFirstLine != 0 + call cursor(l:beginLineNumber, 1) + delete _ + endif + + " fix line number to avoid shake + if l:winview['lnum'] > l:endLineNumber + let l:diff = line("$") - l:totalLineNum + let l:winview['lnum'] += l:diff + let l:winview['topline'] += l:diff + endif + endif + + call winrestview(l:winview) +endfunction + +function! s:DeleteExistingToc() + let l:winview = winsaveview() + + keepjumps normal! gg0 + + let l:markdownStyle = GetMarkdownStyleInModeline() + + let l:isModeline = 0 + + if index(s:supportMarkdownStyles, l:markdownStyle) != -1 + let l:isModeline = 1 + endif + + let l:tocBeginPattern = GetBeginFencePattern(l:isModeline) + let l:tocEndPattern = GetEndFencePattern() + + let l:beginLineNumber = -1 + let l:endLineNumber= -1 + + if search(l:tocBeginPattern, "Wc") != 0 + let l:beginLine = getline(".") + let l:beginLineNumber = line(".") + + if search(l:tocEndPattern, "W") != 0 + if l:isModeline == 0 + let l:markdownStyle = matchlist(l:beginLine, l:tocBeginPattern)[1] + endif + + let l:doDelete = 0 + if index(s:supportMarkdownStyles, l:markdownStyle) == -1 + if l:markdownStyle ==# "" && index(s:supportMarkdownStyles, g:vmt_fence_hidden_markdown_style) != -1 + let l:markdownStyle = g:vmt_fence_hidden_markdown_style + let l:isModeline = 1 + let l:doDelete = 1 + else + let l:markdownStyle = "Unknown" + endif + else + let l:doDelete = 1 + endif + + if l:doDelete == 1 + let l:endLineNumber = line(".") + silent execute l:beginLineNumber. "," . l:endLineNumber. "delete_" + end + else + let l:markdownStyle = "" + echom "Cannot find toc end fence" + endif + else + let l:markdownStyle = "" + echom "Cannot find toc begin fence" + endif + + call winrestview(l:winview) + + return [l:markdownStyle, l:beginLineNumber, l:endLineNumber, l:isModeline] + endfunction + + command! GenTocGFM :call GenToc(s:supportMarkdownStyles[s:GFM_STYLE_INDEX]) + command! GenTocGitLab :call GenToc(s:supportMarkdownStyles[s:GITLAB_STYLE_INDEX]) + command! GenTocRedcarpet :call GenToc(s:supportMarkdownStyles[s:REDCARPET_STYLE_INDEX]) + command! GenTocMarked :call GenToc(s:supportMarkdownStyles[s:MARKED_STYLE_INDEX]) + command! GenTocModeline :call GenTocInner(GetMarkdownStyleInModeline(), 1) + command! UpdateToc :call UpdateToc() + command! RemoveToc :call DeleteExistingToc() + + if g:vmt_auto_update_on_save == 1 + autocmd BufWritePre *.{md,mdown,mkd,mkdn,markdown,mdwn} if !&diff | exe 'silent! UpdateToc' | endif + endif diff --git a/bundle/vim-markdown-toc/test/GFM.md b/bundle/vim-markdown-toc/test/GFM.md new file mode 100644 index 000000000..2398cc34b --- /dev/null +++ b/bundle/vim-markdown-toc/test/GFM.md @@ -0,0 +1,56 @@ + + + +* [heading1](#heading1) + * [heading2](#heading2) +* [chapter 1](#chapter-1) +* [chapter two](#chapter-------two) +* [第三章!](#第三章) + * [heading without space behind hashes](#heading-without-space-behind-hashes) + * [heading with trailing hashes](#heading-with-trailing-hashes) + * [heading with trailing hashes nested with spaces #](#heading-with-trailing-hashes-nested-with-spaces-) + * [heading with trailing hashes nested with spaces # #](#heading-with-trailing-hashes-nested-with-spaces--) + * [1.1 heading with dot 2.1](#11-heading-with-dot-21) + * [1.1](#11) + * [heading with some "special" (yes, special) chars: les caractères unicodes](#heading-with-some-special-yes-special-chars-les-caractères-unicodes) + * [heading with Cyrillic Б б](#heading-with-cyrillic-Б-б) + + + +heading1 +=== + +not heading1 +===ha + +heading2 +-- + +not heading2 +---ha + +=== + +--- + +# chapter 1 + +# chapter two + +# 第三章! + +##heading without space behind hashes + +## heading with trailing hashes ## + +## heading with trailing hashes nested with spaces # # + +## heading with trailing hashes nested with spaces # # + +## 1.1 heading with dot 2.1 + +## 1.1 + +### heading with some "special" (yes, special) chars: les caractères unicodes + +## heading with Cyrillic Б б diff --git a/bundle/vim-markdown-toc/test/Marked.md b/bundle/vim-markdown-toc/test/Marked.md new file mode 100644 index 000000000..25a383dab --- /dev/null +++ b/bundle/vim-markdown-toc/test/Marked.md @@ -0,0 +1,173 @@ +# Hi There ~ + + + +* [Chapter One Basics ~](#chapter-one-basics-~) + * [Section 1.1 Introduction](#section-1.1-introduction) +* [Chapter Two Test More](#chapter-two-test-more) + * [Section 2.1 Don't Do This!](#section-2.1-don't-do-this!) + * [Section 2.2 If you meet problem please contact bardongong@163.com](#section-2.2-if-you-meet-problem-please-contact-bardongong@163.com) + * [Section 2.3 Do you know `Vim`?](#section-2.3-do-you-know-`vim`?) + * [Section 2.4 Carefully Use 'Symbol $' & "Symbol %"](#section-2.4-carefully-use-'symbol-$'-&-"symbol-%") + * [Section 2.5 When you write < means small, > means big](#section-2.5-when-you-write-<-means-small,->-means-big) +* [Chapter Three End of Tests](#chapter-three-end-of-tests) + * [Section 3.1 Can I use /? || \?](#section-3.1-can-i-use-/?-||-\?) + * [Section 3.2 Test @ and -](#section-3.2-test-@-and--) + * [Section 3.3 Done. Cheer Up~](#section-3.3-done.-cheer-up~) + + + +> Actually, Marked.js replace all none "\w" characters to "-", however, +> iamcco/markdown-preview.vim replace only "\s" characters "-", make it +> clear, the rule here is for the later one. + +Let's fill some lines here ~~~ + +Let's fill some lines here ~~~ + +Let's fill some lines here ~~~ + +Let's fill some lines here ~~~ + +Let's fill some lines here ~~~ + +Let's fill some lines here ~~~ + +Let's fill some lines here ~~~ + +Let's fill some lines here ~~~ + +Let's fill some lines here ~~~ + +Let's fill some lines here ~~~ + +Let's fill some lines here ~~~ + +## Chapter One Basics ~ + +Let's fill some lines here for Basics ~~~ + +Let's fill some lines here for Basics ~~~ + +Let's fill some lines here for Basics ~~~ + +Let's fill some lines here for Basics ~~~ + +### Section 1.1 Introduction + +Let's fill some lines here for Basics ~~~ + +Let's fill some lines here for Basics ~~~ + +Let's fill some lines here for Basics ~~~ + +Let's fill some lines here for Basics ~~~ + +Let's fill some lines here for Basics ~~~ + +Let's fill some lines here for Basics ~~~ + +Let's fill some lines here for Basics ~~~ + +## Chapter Two Test More + +Let's fill some lines here for more tests ~~~ + +Let's fill some lines here for more tests ~~~ + +### Section 2.1 Don't Do This! + +Let's fill some lines here for more tests ~~~ + +Let's fill some lines here for more tests ~~~ + +Let's fill some lines here for more tests ~~~ + +### Section 2.2 If you meet problem please contact bardongong@163.com + +Let's fill some lines here for more tests ~~~ + +Let's fill some lines here for more tests ~~~ + +Let's fill some lines here for more tests ~~~ + +### Section 2.3 Do you know `Vim`? + +Let's fill some lines here for more tests ~~~ + +### Section 2.4 Carefully Use 'Symbol $' & "Symbol %" + +Let's fill some lines here for more tests ~~~ + +### Section 2.5 When you write < means small, > means big + +Let's fill some lines here for more tests ~~~ + +## Chapter Three End of Tests + +Let's fill some lines here for end of tests ~~~ + +Let's fill some lines here for end of tests ~~~ + +### Section 3.1 Can I use /? || \? + +Let's fill some lines here for end of tests ~~~ + +Let's fill some lines here for end of tests ~~~ + +Let's fill some lines here for end of tests ~~~ + +Let's fill some lines here for end of tests ~~~ + +Let's fill some lines here for end of tests ~~~ + +Let's fill some lines here for end of tests ~~~ + +Let's fill some lines here for end of tests ~~~ + +Let's fill some lines here for end of tests ~~~ + +Let's fill some lines here for end of tests ~~~ + +Let's fill some lines here for end of tests ~~~ + +Let's fill some lines here for end of tests ~~~ + +### Section 3.2 Test @ and - + +That's all thx. + + +That's all thx. + + +That's all thx. + + +That's all thx. + + +That's all thx. + + +That's all thx. + + +That's all thx. + + +That's all thx. + + +That's all thx. + + +That's all thx. + + +That's all thx. + +### Section 3.3 Done. Cheer Up~ + +YES! YOU CAN DO ALL OF ThOSE THINGS! + diff --git a/bundle/vim-markdown-toc/test/test.vim b/bundle/vim-markdown-toc/test/test.vim new file mode 100644 index 000000000..5817c183a --- /dev/null +++ b/bundle/vim-markdown-toc/test/test.vim @@ -0,0 +1,109 @@ +exec "silent! source " . "../ftplugin/markdown.vim" + +let g:caseCount = 0 +let g:passCaseCount = 0 +let g:errorCaseCount = 0 + +function! ASSERT(var) + let g:caseCount += 1 + if a:var != 0 + let g:passCaseCount += 1 + echo "case " . g:caseCount . " pass" + else + let g:errorCaseCount += 1 + echoe "case " . g:caseCount . " error" + endif +endfunction + +" GFM Test Cases {{{ +let g:GFMHeadingIds = {} + +call ASSERT(GetHeadingLinkTest("# 你好!", "GFM") ==# "你好") +call ASSERT(GetHeadingLinkTest("## Hello World", "GFM") ==# "hello-world") +call ASSERT(GetHeadingLinkTest("### Hello World", "GFM") ==# "hello-world-1") +call ASSERT(GetHeadingLinkTest("#### `Hello World`", "GFM") ==# "hello-world-2") +call ASSERT(GetHeadingLinkTest("##### _Hello_World_", "GFM") ==# "hello_world") +call ASSERT(GetHeadingLinkTest("###### ,", "GFM") ==# "") +call ASSERT(GetHeadingLinkTest("# ,", "GFM") ==# "-1") +call ASSERT(GetHeadingLinkTest("## No additional spaces before / after punctuation in fullwidth form", "GFM") ==# "no-additional-spaces-before--after-punctuation-in-fullwidth-form") +call ASSERT(GetHeadingLinkTest("### No additional spaces before/after punctuation in fullwidth form", "GFM") ==# "no-additional-spaces-beforeafter-punctuation-in-fullwidth-form") +call ASSERT(GetHeadingLinkTest("#### Hello Markdown ", "GFM") ==# "hello----markdown") +call ASSERT(GetHeadingLinkTest("####Heading without a space after the hashes", "GFM") ==# "heading-without-a-space-after-the-hashes") +call ASSERT(GetHeadingLinkTest("### heading with trailing hashes ###", "GFM") ==# "heading-with-trailing-hashes") +call ASSERT(GetHeadingLinkTest("### heading with trailing hashes###", "GFM") ==# "heading-with-trailing-hashes-1") +call ASSERT(GetHeadingLinkTest("### heading with trailing hashes ends with spaces ### ", "GFM") ==# "heading-with-trailing-hashes-ends-with-spaces-") +call ASSERT(GetHeadingLinkTest("### heading with trailing hashes nested with spaces # # # ", "GFM") ==# "heading-with-trailing-hashes-nested-with-spaces----") +call ASSERT(GetHeadingLinkTest("### [vim-markdown-toc](https://github.com/mzlogin/vim-markdown-toc)", "GFM") ==# "vim-markdown-toc") +call ASSERT(GetHeadingLinkTest("### [vim-markdown-toc-again][1]", "GFM") ==# "vim-markdown-toc-again") +call ASSERT(GetHeadingLinkTest("### ![vim-markdown-toc-img](/path/to/a/png)", "GFM") ==# "vim-markdown-toc-img") +call ASSERT(GetHeadingLinkTest("### ![](/path/to/a/png)", "GFM") ==# "-2") +call ASSERT(GetHeadingLinkTest("### 1.1", "GFM") ==# "11") +call ASSERT(GetHeadingLinkTest("### heading with some \"special\" \(yes, special\) chars: les caractères unicodes", "GFM") ==# "heading-with-some-special-yes-special-chars-les-caractères-unicodes") +call ASSERT(GetHeadingLinkTest("## 初音ミクV3について", "GFM") ==# "初音ミクv3について") +call ASSERT(GetHeadingLinkTest("# 안녕", "GFM") ==# "안녕") +" }}} + +" GitLab Test Cases {{{ +let g:GFMHeadingIds = {} + +call ASSERT(GetHeadingLinkTest("# 你好!", "GitLab") ==# "你好") +call ASSERT(GetHeadingLinkTest("## Hello World", "GitLab") ==# "hello-world") +call ASSERT(GetHeadingLinkTest("### Hello World", "GitLab") ==# "hello-world-1") +call ASSERT(GetHeadingLinkTest("#### `Hello World`", "GitLab") ==# "hello-world-2") +call ASSERT(GetHeadingLinkTest("##### _Hello_World_", "GitLab") ==# "hello_world") +call ASSERT(GetHeadingLinkTest("###### ,", "GitLab") ==# "") +call ASSERT(GetHeadingLinkTest("# ,", "GitLab") ==# "-1") +call ASSERT(GetHeadingLinkTest("## No additional spaces before / after punctuation in fullwidth form", "GitLab") ==# "no-additional-spaces-before-after-punctuation-in-fullwidth-form") +call ASSERT(GetHeadingLinkTest("### No additional spaces before/after punctuation in fullwidth form", "GitLab") ==# "no-additional-spaces-beforeafter-punctuation-in-fullwidth-form") +call ASSERT(GetHeadingLinkTest("#### Hello Markdown ", "GitLab") ==# "hello-markdown") +call ASSERT(GetHeadingLinkTest("####Heading without a space after the hashes", "GitLab") ==# "heading-without-a-space-after-the-hashes") +call ASSERT(GetHeadingLinkTest("### heading with trailing hashes ###", "GitLab") ==# "heading-with-trailing-hashes") +call ASSERT(GetHeadingLinkTest("### heading with trailing hashes###", "GitLab") ==# "heading-with-trailing-hashes-1") +call ASSERT(GetHeadingLinkTest("### heading with trailing hashes ends with spaces ### ", "GitLab") ==# "heading-with-trailing-hashes-ends-with-spaces-") +call ASSERT(GetHeadingLinkTest("### heading with trailing hashes nested with spaces # # # ", "GitLab") ==# "heading-with-trailing-hashes-nested-with-spaces-") +call ASSERT(GetHeadingLinkTest("### [vim-markdown-toc](https://github.com/mzlogin/vim-markdown-toc)", "GitLab") ==# "vim-markdown-toc") +call ASSERT(GetHeadingLinkTest("### [vim-markdown-toc-again][1]", "GitLab") ==# "vim-markdown-toc-again") +call ASSERT(GetHeadingLinkTest("### ![vim-markdown-toc-img](/path/to/a/png)", "GitLab") ==# "vim-markdown-toc-img") +call ASSERT(GetHeadingLinkTest("### ![](/path/to/a/png)", "GitLab") ==# "-2") +call ASSERT(GetHeadingLinkTest("### 1.1", "GitLab") ==# "11") +call ASSERT(GetHeadingLinkTest("### heading with some \"special\" \(yes, special\) chars: les caractères unicodes", "GitLab") ==# "heading-with-some-special-yes-special-chars-les-caractères-unicodes") +call ASSERT(GetHeadingLinkTest("## heading with Cyrillic Б б", "GitLab") ==# "heading-with-cyrillic-б-б") +call ASSERT(GetHeadingLinkTest("## Ю heading starts with Cyrillic", "GitLab") ==# "ю-heading-starts-with-cyrillic") +" }}} + +" Redcarpet Test Cases {{{ +call ASSERT(GetHeadingLinkTest("# -Hello-World-", "Redcarpet") ==# "hello-world") +call ASSERT(GetHeadingLinkTest("## _Hello_World_", "Redcarpet") ==# "hello_world") +call ASSERT(GetHeadingLinkTest("### (Hello()World)", "Redcarpet") ==# "hello-world") +call ASSERT(GetHeadingLinkTest("#### 让 Discuz! 局域网内可访问", "Redcarpet") ==# "让-discuz-局域网内可访问") +call ASSERT(GetHeadingLinkTest('##### "你好"世界"', "Redcarpet") ==# "quot-你好-quot-世界-quot") +call ASSERT(GetHeadingLinkTest("###### '你好'世界'", "Redcarpet") ==# "39-你好-39-世界-39") +call ASSERT(GetHeadingLinkTest("# &你好&世界&", "Redcarpet") ==# "amp-你好-amp-世界-amp") +call ASSERT(GetHeadingLinkTest("## `-ms-text-autospace` to the rescue?", "Redcarpet") ==# "ms-text-autospace-to-the-rescue") +" }}} + +" Marked Test Cases {{{ +call ASSERT(GetHeadingLinkTest("# 你好!", "Marked") ==# "你好!") +call ASSERT(GetHeadingLinkTest("## Hello World", "Marked") ==# "hello-world") +call ASSERT(GetHeadingLinkTest("### Hello World", "Marked") ==# "hello-world") +call ASSERT(GetHeadingLinkTest("#### `Hello World`", "Marked") ==# "`hello-world`") +call ASSERT(GetHeadingLinkTest("##### _Hello_World_", "Marked") ==# "_hello_world_") +call ASSERT(GetHeadingLinkTest("###### ,", "Marked") ==# ",") +call ASSERT(GetHeadingLinkTest("# ,", "Marked") ==# ",") +call ASSERT(GetHeadingLinkTest("## No additional spaces before / after punctuation in fullwidth form", "Marked") ==# "no-additional-spaces-before-/-after-punctuation-in-fullwidth-form") +call ASSERT(GetHeadingLinkTest("### No additional spaces before/after punctuation in fullwidth form", "Marked") ==# "no-additional-spaces-before/after-punctuation-in-fullwidth-form") +call ASSERT(GetHeadingLinkTest("#### Hello Markdown ", "Marked") ==# "hello-markdown") +call ASSERT(GetHeadingLinkTest("####Heading without a space after the hashes", "Marked") ==# "heading-without-a-space-after-the-hashes") +call ASSERT(GetHeadingLinkTest("### heading with trailing hashes ###", "Marked") ==# "heading-with-trailing-hashes") +call ASSERT(GetHeadingLinkTest("### heading with trailing hashes###", "Marked") ==# "heading-with-trailing-hashes") +call ASSERT(GetHeadingLinkTest("### heading with trailing hashes ends with spaces ### ", "Marked") ==# "heading-with-trailing-hashes-ends-with-spaces") +call ASSERT(GetHeadingLinkTest("### heading with trailing hashes nested with spaces # # # ", "Marked") ==# "heading-with-trailing-hashes-nested-with-spaces-#-#") +call ASSERT(GetHeadingLinkTest("### [vim-markdown-toc](https://github.com/mzlogin/vim-markdown-toc)", "Marked") ==# "[vim-markdown-toc](https://github.com/mzlogin/vim-markdown-toc)") +call ASSERT(GetHeadingLinkTest("### [vim-markdown-toc-again][1]", "Marked") ==# "[vim-markdown-toc-again][1]") +call ASSERT(GetHeadingLinkTest("### ![vim-markdown-toc-img](/path/to/a/png)", "Marked") ==# "![vim-markdown-toc-img](/path/to/a/png)") +call ASSERT(GetHeadingLinkTest("### ![](/path/to/a/png)", "Marked") ==# "![](/path/to/a/png)") +call ASSERT(GetHeadingLinkTest("### 1.1", "Marked") ==# "1.1") +call ASSERT(GetHeadingLinkTest("### heading with some \"special\" \(yes, special\) chars: les caractères unicodes", "Marked") ==# "heading-with-some-\" special\"-\(yes,-special\)-chars:-les-caractères-unicodes") +" }}} + +echo "" . g:passCaseCount . " cases pass, " . g:errorCaseCount . " cases error"