Skip to content

Commit 05d6538

Browse files
authored
fix number trickery, add support for Arabic (#88)
ref #87
1 parent 5acf680 commit 05d6538

File tree

4 files changed

+275
-101
lines changed

4 files changed

+275
-101
lines changed

ftplugin/markdown.vim

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -155,33 +155,38 @@ function! s:GetHeadingLevel(headingLine)
155155
return match(a:headingLine, '[^#]')
156156
endfunction
157157

158+
function! s:AppendNumberTrickery(headingLink)
159+
let l:currentNum = 1
160+
let l:newKey = a:headingLink . "-" . l:currentNum
161+
while has_key(g:GFMHeadingIds, l:newKey)
162+
let l:currentNum += 1
163+
let l:newKey = a:headingLink . "-" . l:currentNum
164+
endwhile
165+
return l:newKey
166+
endfunction
167+
158168
function! s:GetHeadingLinkGFM(headingName)
159169
let l:headingLink = tr(a:headingName, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")
160170

161-
" \_^ : start of line
162-
" _\+ : one of more underscore _
163-
" \| : OR
164-
" _\+ : one of more underscore _
165-
" \_$ : end of line
166-
let l:headingLink = substitute(l:headingLink, "\\_^_\\+\\|_\\+\\_$", "", "g")
167171
" Characters that are not alphanumeric, latin1 extended (for accents) and
168-
" chinese/korean chars are removed.
172+
" Chinese/Japanese/Korean/Arabic chars are removed.
173+
" unicode scope can ref https://fuhaoku.net/blocks
169174
" \\%#=0: allow this pattern to use the regexp engine he wants. Having
170175
" `set re=1` in the vimrc could break this behavior. cf. issue #19
171-
let l:headingLink = substitute(l:headingLink, "\\%#=0[^[:alnum:]\u00C0-\u00FF\u0400-\u04ff\u4e00-\u9fbf\u3040-\u309F\u30A0-\u30FF\uAC00-\uD7AF _-]", "", "g")
176+
let l:headingLink = substitute(l:headingLink, "\\%#=0[^[:alnum:]\u00C0-\u00FF\u0400-\u04ff\u0600-\u06ff\u4e00-\u9fbf\u3040-\u309F\u30A0-\u30FF\uAC00-\uD7AF _-]", "", "g")
172177
let l:headingLink = substitute(l:headingLink, " ", "-", "g")
173178

174179
if l:headingLink ==# ""
175180
let l:nullKey = "<null>"
176181
if has_key(g:GFMHeadingIds, l:nullKey)
177-
let g:GFMHeadingIds[l:nullKey] += 1
178-
let l:headingLink = l:headingLink . "-" . g:GFMHeadingIds[l:nullKey]
182+
let l:headingLink = <SID>AppendNumberTrickery(l:headingLink)
183+
let g:GFMHeadingIds[l:headingLink] = 0
179184
else
180185
let g:GFMHeadingIds[l:nullKey] = 0
181186
endif
182187
elseif has_key(g:GFMHeadingIds, l:headingLink)
183-
let g:GFMHeadingIds[l:headingLink] += 1
184-
let l:headingLink = l:headingLink . "-" . g:GFMHeadingIds[l:headingLink]
188+
let l:headingLink = <SID>AppendNumberTrickery(l:headingLink)
189+
let g:GFMHeadingIds[l:headingLink] = 0
185190
else
186191
let g:GFMHeadingIds[l:headingLink] = 0
187192
endif
@@ -240,7 +245,11 @@ function! s:GetHeadingLinkMarked(headingName)
240245
return l:headingLink
241246
endfunction
242247

243-
function! s:GetHeadingName(headingLine)
248+
function! s:GetHeadingName(headingLine, markdownStyle)
249+
if a:markdownStyle ==# s:supportMarkdownStyles[s:MARKED_STYLE_INDEX]
250+
return <SID>GetHeadingNameMarked(a:headingLine)
251+
endif
252+
244253
let l:headingName = substitute(a:headingLine, '^#*\s*', "", "")
245254
let l:headingName = substitute(l:headingName, '\s*#*$', "", "")
246255

@@ -250,6 +259,14 @@ function! s:GetHeadingName(headingLine)
250259
return l:headingName
251260
endfunction
252261

262+
function! s:GetHeadingNameMarked(headingLine)
263+
let l:headingName = substitute(a:headingLine, '^#*\s*', "", "")
264+
let l:headingName = substitute(l:headingName, '\s\+$', "", "g")
265+
let l:headingName = substitute(l:headingName, '\s*#*$', "", "")
266+
267+
return l:headingName
268+
endfunction
269+
253270
function! s:GetHeadingLink(headingName, markdownStyle)
254271
if a:markdownStyle ==# s:supportMarkdownStyles[s:GFM_STYLE_INDEX]
255272
return <SID>GetHeadingLinkGFM(a:headingName)
@@ -263,7 +280,7 @@ function! s:GetHeadingLink(headingName, markdownStyle)
263280
endfunction
264281

265282
function! GetHeadingLinkTest(headingLine, markdownStyle)
266-
let l:headingName = <SID>GetHeadingName(a:headingLine)
283+
let l:headingName = <SID>GetHeadingName(a:headingLine, a:markdownStyle)
267284
return <SID>GetHeadingLink(l:headingName, a:markdownStyle)
268285
endfunction
269286

@@ -304,7 +321,7 @@ function! s:GenTocInner(markdownStyle, isModeline)
304321
endif
305322

306323
for headingLine in l:headingLines
307-
let l:headingName = <SID>GetHeadingName(headingLine)
324+
let l:headingName = <SID>GetHeadingName(headingLine, a:markdownStyle)
308325
" only add line if less than max level and greater than min level
309326
if l:levels[i] <= g:vmt_max_level && l:levels[i] >= g:vmt_min_level
310327
let l:headingIndents = l:levels[i] - l:minLevel

test/GFM.md

Lines changed: 128 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,57 @@
33

44
* [heading1](#heading1)
55
* [heading2](#heading2)
6-
* [chapter 1](#chapter-1)
7-
* [chapter two](#chapter-------two)
8-
* [第三章!](#第三章)
6+
* [chapter 1](#chapter-1)
7+
* [chapter two](#chapter-------two)
8+
* [第三章!](#第三章)
99
* [heading without space behind hashes](#heading-without-space-behind-hashes)
1010
* [heading with trailing hashes](#heading-with-trailing-hashes)
1111
* [heading with trailing hashes nested with spaces #](#heading-with-trailing-hashes-nested-with-spaces-)
1212
* [heading with trailing hashes nested with spaces # #](#heading-with-trailing-hashes-nested-with-spaces--)
1313
* [1.1 heading with dot 2.1](#11-heading-with-dot-21)
1414
* [1.1](#11)
15-
* [heading with some "special" (yes, special) chars: les caractères unicodes](#heading-with-some-special-yes-special-chars-les-caractères-unicodes)
15+
* [heading with some "special" (yes, special) chars: les caractères unicodes](#heading-with-some-special-yes-special-chars-les-caractères-unicodes)
1616
* [heading with Cyrillic Б б](#heading-with-cyrillic-Б-б)
17+
* [Same Level Same Name](#same-level-same-name)
18+
* [Same Level Same Name](#same-level-same-name-1)
19+
* [Different Level Same Name](#different-level-same-name)
20+
* [Different Level Same Name](#different-level-same-name-1)
21+
* [Same Name Differing Caps](#same-name-differing-caps)
22+
* [SAME NAME DIFFERING CAPS](#same-name-differing-caps-1)
23+
* [same name differing caps](#same-name-differing-caps-2)
24+
* [Same Name( )different-Non-»letter° chars](#same-name---different-non-letter-chars)
25+
* [Same Name &^$ different Non letter chars](#same-name--different-non-letter-chars)
26+
* [Same Name but One Has Code](#same-name-but-one-has-code)
27+
* [Same Name `but` One `Has Code`](#same-name-but-one-has-code-1)
28+
* [Ending Number Trickery](#ending-number-trickery)
29+
* [Ending Number Trickery](#ending-number-trickery-1)
30+
* [Ending Number Trickery 1](#ending-number-trickery-1-1)
31+
* [Ending Number Trickery](#ending-number-trickery-2)
32+
* [Ending Number Trickery 2](#ending-number-trickery-2-1)
33+
* [Reverse Order Number Trickery 5](#reverse-order-number-trickery-5)
34+
* [Reverse Order Number Trickery](#reverse-order-number-trickery)
35+
* [Reverse Order Number Trickery 5](#reverse-order-number-trickery-5-1)
36+
* [Reverse Order Number Trickery](#reverse-order-number-trickery-1)
37+
* [Other Ending Number Trickery 1](#other-ending-number-trickery-1)
38+
* [Other Ending Number Trickery](#other-ending-number-trickery)
39+
* [Other Ending Number Trickery](#other-ending-number-trickery-2)
40+
* [Final Ending Number Trickery](#final-ending-number-trickery)
41+
* [Final Ending Number Trickery](#final-ending-number-trickery-1)
42+
* [Final Ending Number Trickery 1](#final-ending-number-trickery-1-1)
43+
* [Final Ending Number Trickery 1 1](#final-ending-number-trickery-1-1-1)
44+
* [Final Ending Number Trickery 1 1](#final-ending-number-trickery-1-1-2)
45+
* [Underscored_heading](#underscored_heading)
46+
* [Multiple__underscores](#multiple__underscores)
47+
* [\_Leading_underscore](#_leading_underscore)
48+
* [_Leading_underscore_without_escape](#_leading_underscore_without_escape)
49+
* [Trailing_underscore\_](#trailing_underscore_)
50+
* [Trailing_underscore_without_escape_](#trailing_underscore_without_escape_)
51+
* [Heading with non-`[a-z]` letters like ß, ا, and 猫](#heading-with-non-a-z-letters-like-ß-ا-and-猫)
52+
* [Heading with a Chinese punctuation mark (specifically '】')](#heading-with-a-chinese-punctuation-mark-specifically-)
53+
* [M̵i̶l̶d̵l̶y̵ ̴Z̸a̴l̶g̶o̵](#M̵i̶l̶d̵l̶y̵ ̴Z̸a̴l̶g̶o̵)
54+
* [Greek letter Mu (Μ)](#greek-letter-mu-)
55+
* [Assorted accent marks like Combining enclosing circle backslash (α⃠) and Combining inverted breve (ȃ)](#assorted-accent-marks-like-combining-enclosing-circle-backslash--and-combining-inverted-breve-ȃ)
56+
* [Emoji in heading 🧟🧛🏻‍♀️](#emoji-in-heading-)
1757

1858
<!-- vim-markdown-toc -->
1959

@@ -33,11 +73,11 @@ not heading2
3373

3474
---
3575

36-
# chapter 1
76+
## chapter 1
3777

38-
# chapter two
78+
## chapter two
3979

40-
# 第三章!
80+
## 第三章!
4181

4282
##heading without space behind hashes
4383

@@ -51,6 +91,86 @@ not heading2
5191

5292
## 1.1
5393

54-
### heading with some "special" (yes, special) chars: les caractères unicodes
94+
## heading with some "special" (yes, special) chars: les caractères unicodes
5595

5696
## heading with Cyrillic Б б
97+
98+
## Same Level Same Name
99+
100+
## Same Level Same Name
101+
102+
## Different Level Same Name
103+
104+
### Different Level Same Name
105+
106+
## Same Name Differing Caps
107+
108+
## SAME NAME DIFFERING CAPS
109+
110+
## same name differing caps
111+
112+
## Same Name( )different-Non-»letter° chars
113+
114+
## Same Name &^$ different Non letter chars
115+
116+
## Same Name but One Has Code
117+
118+
## Same Name `but` One `Has Code`
119+
120+
## Ending Number Trickery
121+
122+
## Ending Number Trickery
123+
124+
## Ending Number Trickery 1
125+
126+
## Ending Number Trickery
127+
128+
## Ending Number Trickery 2
129+
130+
## Reverse Order Number Trickery 5
131+
132+
## Reverse Order Number Trickery
133+
134+
## Reverse Order Number Trickery 5
135+
136+
## Reverse Order Number Trickery
137+
138+
## Other Ending Number Trickery 1
139+
140+
## Other Ending Number Trickery
141+
142+
## Other Ending Number Trickery
143+
144+
## Final Ending Number Trickery
145+
146+
## Final Ending Number Trickery
147+
148+
## Final Ending Number Trickery 1
149+
150+
## Final Ending Number Trickery 1 1
151+
152+
## Final Ending Number Trickery 1 1
153+
154+
## Underscored_heading
155+
156+
## Multiple__underscores
157+
158+
## \_Leading_underscore
159+
160+
## _Leading_underscore_without_escape
161+
162+
## Trailing_underscore\_
163+
164+
## Trailing_underscore_without_escape_
165+
166+
## Heading with non-`[a-z]` letters like ß, ا, and 猫
167+
168+
## Heading with a Chinese punctuation mark (specifically '】')
169+
170+
## M̵i̶l̶d̵l̶y̵ ̴Z̸a̴l̶g̶o̵
171+
172+
## Greek letter Mu (Μ)
173+
174+
## Assorted accent marks like Combining enclosing circle backslash (α⃠) and Combining inverted breve (ȃ)
175+
176+
## Emoji in heading 🧟🧛🏻‍♀️

test/Marked.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* [Section 3.1 Can I use /? || \?](#section-3.1-can-i-use-/?-||-\?)
1515
* [Section 3.2 Test @ and -](#section-3.2-test-@-and--)
1616
* [Section 3.3 Done. Cheer Up~](#section-3.3-done.-cheer-up~)
17+
* [heading with some "special" (yes, special) chars: les caractères unicodes](#heading-with-some-"special"-(yes,-special)-chars:-les-caractères-unicodes)
1718

1819
<!-- vim-markdown-toc -->
1920

@@ -171,3 +172,4 @@ That's all thx.
171172

172173
YES! YOU CAN DO ALL OF ThOSE THINGS!
173174

175+
### heading with some "special" (yes, special) chars: les caractères unicodes

0 commit comments

Comments
 (0)