1
+ /**
2
+ * @typedef {import('mdast-util-from-markdown').Extension } FromMarkdownExtension
3
+ * @typedef {import('mdast-util-from-markdown').Transform } FromMarkdownTransform
4
+ * @typedef {import('mdast-util-from-markdown').Handle } FromMarkdownHandle
5
+ * @typedef {import('mdast-util-to-markdown/lib/types.js').Options } ToMarkdownExtension
6
+ * @typedef {import('mdast-util-find-and-replace').ReplaceFunction } ReplaceFunction
7
+ * @typedef {import('mdast-util-find-and-replace').RegExpMatchObject } RegExpMatchObject
8
+ * @typedef {import('mdast-util-find-and-replace').PhrasingContent } PhrasingContent
9
+ */
10
+
1
11
import { ccount } from 'ccount'
2
12
import { findAndReplace } from 'mdast-util-find-and-replace'
3
- import unicodePunctuation from 'micromark/dist/character/unicode-punctuation.js'
4
- import unicodeWhitespace from 'micromark/dist/character/unicode-whitespace.js'
13
+ import { unicodePunctuation , unicodeWhitespace } from 'micromark-util-character'
5
14
6
15
const inConstruct = 'phrasing'
7
16
const notInConstruct = [ 'autolink' , 'link' , 'image' , 'label' ]
8
17
18
+ /** @type {FromMarkdownExtension } */
9
19
export const gfmAutolinkLiteralFromMarkdown = {
10
20
transforms : [ transformGfmAutolinkLiterals ] ,
11
21
enter : {
@@ -22,6 +32,7 @@ export const gfmAutolinkLiteralFromMarkdown = {
22
32
}
23
33
}
24
34
35
+ /** @type {ToMarkdownExtension } */
25
36
export const gfmAutolinkLiteralToMarkdown = {
26
37
unsafe : [
27
38
{
@@ -42,31 +53,39 @@ export const gfmAutolinkLiteralToMarkdown = {
42
53
]
43
54
}
44
55
56
+ /** @type {FromMarkdownHandle } */
45
57
function enterLiteralAutolink ( token ) {
58
+ // @ts -expect-error: `null` is fine.
46
59
this . enter ( { type : 'link' , title : null , url : '' , children : [ ] } , token )
47
60
}
48
61
62
+ /** @type {FromMarkdownHandle } */
49
63
function enterLiteralAutolinkValue ( token ) {
50
64
this . config . enter . autolinkProtocol . call ( this , token )
51
65
}
52
66
67
+ /** @type {FromMarkdownHandle } */
53
68
function exitLiteralAutolinkHttp ( token ) {
54
69
this . config . exit . autolinkProtocol . call ( this , token )
55
70
}
56
71
72
+ /** @type {FromMarkdownHandle } */
57
73
function exitLiteralAutolinkWww ( token ) {
58
74
this . config . exit . data . call ( this , token )
59
75
this . stack [ this . stack . length - 1 ] . url = 'http://' + this . sliceSerialize ( token )
60
76
}
61
77
78
+ /** @type {FromMarkdownHandle } */
62
79
function exitLiteralAutolinkEmail ( token ) {
63
80
this . config . exit . autolinkEmail . call ( this , token )
64
81
}
65
82
83
+ /** @type {FromMarkdownHandle } */
66
84
function exitLiteralAutolink ( token ) {
67
85
this . exit ( token )
68
86
}
69
87
88
+ /** @type {FromMarkdownTransform } */
70
89
function transformGfmAutolinkLiterals ( tree ) {
71
90
findAndReplace (
72
91
tree ,
@@ -78,8 +97,16 @@ function transformGfmAutolinkLiterals(tree) {
78
97
)
79
98
}
80
99
100
+ /**
101
+ * @type {ReplaceFunction }
102
+ * @param {string } _
103
+ * @param {string } protocol
104
+ * @param {string } domain
105
+ * @param {string } path
106
+ * @param {RegExpMatchObject } match
107
+ */
81
108
// eslint-disable-next-line max-params
82
- function findUrl ( $0 , protocol , domain , path , match ) {
109
+ function findUrl ( _ , protocol , domain , path , match ) {
83
110
let prefix = ''
84
111
85
112
// Not an expected previous character.
@@ -102,34 +129,48 @@ function findUrl($0, protocol, domain, path, match) {
102
129
103
130
if ( ! parts [ 0 ] ) return false
104
131
105
- let result = {
132
+ /** @type {PhrasingContent } */
133
+ // @ts -expect-error: `null` is fine.
134
+ const result = {
106
135
type : 'link' ,
107
136
title : null ,
108
137
url : prefix + protocol + parts [ 0 ] ,
109
138
children : [ { type : 'text' , value : protocol + parts [ 0 ] } ]
110
139
}
111
140
112
141
if ( parts [ 1 ] ) {
113
- result = [ result , { type : 'text' , value : parts [ 1 ] } ]
142
+ return [ result , { type : 'text' , value : parts [ 1 ] } ]
114
143
}
115
144
116
145
return result
117
146
}
118
147
119
- function findEmail ( $0 , atext , label , match ) {
148
+ /**
149
+ * @type {ReplaceFunction }
150
+ * @param {string } _
151
+ * @param {string } atext
152
+ * @param {string } label
153
+ * @param {RegExpMatchObject } match
154
+ */
155
+ function findEmail ( _ , atext , label , match ) {
120
156
// Not an expected previous character.
121
157
if ( ! previous ( match , true ) || / [ _ - ] $ / . test ( label ) ) {
122
158
return false
123
159
}
124
160
125
161
return {
126
162
type : 'link' ,
163
+ // @ts -expect-error: `null` is fine.
127
164
title : null ,
128
165
url : 'mailto:' + atext + '@' + label ,
129
166
children : [ { type : 'text' , value : atext + '@' + label } ]
130
167
}
131
168
}
132
169
170
+ /**
171
+ * @param {string } domain
172
+ * @returns {boolean }
173
+ */
133
174
function isCorrectDomain ( domain ) {
134
175
const parts = domain . split ( '.' )
135
176
@@ -148,15 +189,24 @@ function isCorrectDomain(domain) {
148
189
return true
149
190
}
150
191
192
+ /**
193
+ * @param {string } url
194
+ * @returns {[string, string|undefined] }
195
+ */
151
196
function splitUrl ( url ) {
152
- let trail = / [ ! " & ' ) , . : ; < > ? \] } ] + $ / . exec ( url )
197
+ const trailExec = / [ ! " & ' ) , . : ; < > ? \] } ] + $ / . exec ( url )
198
+ /** @type {number } */
153
199
let closingParenIndex
200
+ /** @type {number } */
154
201
let openingParens
202
+ /** @type {number } */
155
203
let closingParens
204
+ /** @type {string|undefined } */
205
+ let trail
156
206
157
- if ( trail ) {
158
- url = url . slice ( 0 , trail . index )
159
- trail = trail [ 0 ]
207
+ if ( trailExec ) {
208
+ url = url . slice ( 0 , trailExec . index )
209
+ trail = trailExec [ 0 ]
160
210
closingParenIndex = trail . indexOf ( ')' )
161
211
openingParens = ccount ( url , '(' )
162
212
closingParens = ccount ( url , ')' )
@@ -172,8 +222,14 @@ function splitUrl(url) {
172
222
return [ url , trail ]
173
223
}
174
224
225
+ /**
226
+ * @param {RegExpMatchObject } match
227
+ * @param {boolean } [email=false]
228
+ * @returns {boolean }
229
+ */
175
230
function previous ( match , email ) {
176
231
const code = match . input . charCodeAt ( match . index - 1 )
232
+
177
233
return (
178
234
( match . index === 0 ||
179
235
unicodeWhitespace ( code ) ||
0 commit comments