@@ -86,6 +86,71 @@ describe('handleBrokenLinks', () => {
86
86
} ) ;
87
87
} ) ;
88
88
89
+ it ( 'accepts valid link with anchor reported with hash prefix' , async ( ) => {
90
+ await testBrokenLinks ( {
91
+ routes : [ { path : '/page1' } , { path : '/page2' } ] ,
92
+ collectedLinks : {
93
+ '/page1' : { links : [ '/page2#page2anchor' ] , anchors : [ ] } ,
94
+ '/page2' : { links : [ ] , anchors : [ '#page2anchor' ] } ,
95
+ } ,
96
+ } ) ;
97
+ } ) ;
98
+
99
+ it ( 'accepts valid links and anchors, sparse arrays' , async ( ) => {
100
+ await testBrokenLinks ( {
101
+ routes : [ { path : '/page1' } , { path : '/page2' } ] ,
102
+ collectedLinks : {
103
+ '/page1' : {
104
+ links : [
105
+ '/page1' ,
106
+ // @ts -expect-error: invalid type on purpose
107
+ undefined ,
108
+ // @ts -expect-error: invalid type on purpose
109
+ null ,
110
+ // @ts -expect-error: invalid type on purpose
111
+ 42 ,
112
+ '/page2' ,
113
+ '/page2#page2anchor1' ,
114
+ '/page2#page2anchor2' ,
115
+ ] ,
116
+ anchors : [ ] ,
117
+ } ,
118
+ '/page2' : {
119
+ links : [ ] ,
120
+ anchors : [
121
+ 'page2anchor1' ,
122
+ // @ts -expect-error: invalid type on purpose
123
+ undefined ,
124
+ // @ts -expect-error: invalid type on purpose
125
+ null ,
126
+ // @ts -expect-error: invalid type on purpose
127
+ 42 ,
128
+ 'page2anchor2' ,
129
+ ] ,
130
+ } ,
131
+ } ,
132
+ } ) ;
133
+ } ) ;
134
+
135
+ it ( 'accepts valid link and anchor to collected pages that are not in routes' , async ( ) => {
136
+ // This tests the edge-case of the 404 page:
137
+ // We don't have a {path: '404.html'} route
138
+ // But yet we collect links/anchors to it and allow linking to it
139
+ await testBrokenLinks ( {
140
+ routes : [ ] ,
141
+ collectedLinks : {
142
+ '/page 1' : {
143
+ links : [ '/page 2#anchor-page-2' ] ,
144
+ anchors : [ 'anchor-page-1' ] ,
145
+ } ,
146
+ '/page 2' : {
147
+ links : [ '/page 1#anchor-page-1' , '/page%201#anchor-page-1' ] ,
148
+ anchors : [ 'anchor-page-2' ] ,
149
+ } ,
150
+ } ,
151
+ } ) ;
152
+ } ) ;
153
+
89
154
it ( 'accepts valid link with querystring + anchor' , async ( ) => {
90
155
await testBrokenLinks ( {
91
156
routes : [ { path : '/page1' } , { path : '/page2' } ] ,
@@ -132,10 +197,75 @@ describe('handleBrokenLinks', () => {
132
197
'/page%202' ,
133
198
'/page%202?age=42' ,
134
199
'/page%202?age=42#page2anchor' ,
200
+
201
+ '/some dir/page 3' ,
202
+ '/some dir/page 3#page3anchor' ,
203
+ '/some%20dir/page%203' ,
204
+ '/some%20dir/page%203#page3anchor' ,
205
+ '/some%20dir/page 3' ,
206
+ '/some dir/page%203' ,
207
+ '/some dir/page%203#page3anchor' ,
135
208
] ,
136
209
anchors : [ ] ,
137
210
} ,
138
211
'/page 2' : { links : [ ] , anchors : [ 'page2anchor' ] } ,
212
+ '/some dir/page 3' : { links : [ ] , anchors : [ 'page3anchor' ] } ,
213
+ } ,
214
+ } ) ;
215
+ } ) ;
216
+
217
+ it ( 'accepts valid link with anchor with spaces and encoding' , async ( ) => {
218
+ await testBrokenLinks ( {
219
+ routes : [ { path : '/page 1' } , { path : '/page 2' } ] ,
220
+ collectedLinks : {
221
+ '/page 1' : {
222
+ links : [
223
+ '/page 1#a b' ,
224
+ '#a b' ,
225
+ '#a%20b' ,
226
+ '#c d' ,
227
+ '#c%20d' ,
228
+
229
+ '/page 2#你好' ,
230
+ '/page%202#你好' ,
231
+ '/page 2#%E4%BD%A0%E5%A5%BD' ,
232
+ '/page%202#%E4%BD%A0%E5%A5%BD' ,
233
+
234
+ '/page 2#schrödingers-cat-principle' ,
235
+ '/page%202#schrödingers-cat-principle' ,
236
+ '/page 2#schr%C3%B6dingers-cat-principle' ,
237
+ '/page%202#schr%C3%B6dingers-cat-principle' ,
238
+ ] ,
239
+ anchors : [ 'a b' , 'c%20d' ] ,
240
+ } ,
241
+ '/page 2' : {
242
+ links : [ '/page 1#a b' , '/page%201#c d' ] ,
243
+ anchors : [ '你好' , '#schr%C3%B6dingers-cat-principle' ] ,
244
+ } ,
245
+ } ,
246
+ } ) ;
247
+ } ) ;
248
+
249
+ it ( 'accepts valid link with empty anchor' , async ( ) => {
250
+ await testBrokenLinks ( {
251
+ routes : [ { path : '/page 1' } , { path : '/page 2' } ] ,
252
+ collectedLinks : {
253
+ '/page 1' : {
254
+ links : [
255
+ '/page 1' ,
256
+ '/page 2' ,
257
+ '/page 1#' ,
258
+ '/page 2#' ,
259
+ '/page 1?age=42#' ,
260
+ '/page 2?age=42#' ,
261
+ '#' ,
262
+ '#' ,
263
+ './page 1#' ,
264
+ './page 2#' ,
265
+ ] ,
266
+ anchors : [ ] ,
267
+ } ,
268
+ '/page 2' : { links : [ ] , anchors : [ ] } ,
139
269
} ,
140
270
} ) ;
141
271
} ) ;
@@ -225,28 +355,6 @@ describe('handleBrokenLinks', () => {
225
355
` ) ;
226
356
} ) ;
227
357
228
- it ( 'rejects valid link with empty broken anchor' , async ( ) => {
229
- await expect ( ( ) =>
230
- testBrokenLinks ( {
231
- routes : [ { path : '/page1' } , { path : '/page2' } ] ,
232
- collectedLinks : {
233
- '/page1' : { links : [ '/page2#' ] , anchors : [ ] } ,
234
- '/page2' : { links : [ ] , anchors : [ ] } ,
235
- } ,
236
- } ) ,
237
- ) . rejects . toThrowErrorMatchingInlineSnapshot ( `
238
- "Docusaurus found broken anchors!
239
-
240
- Please check the pages of your site in the list below, and make sure you don't reference any anchor that does not exist.
241
- Note: it's possible to ignore broken anchors with the 'onBrokenAnchors' Docusaurus configuration, and let the build pass.
242
-
243
- Exhaustive list of all broken anchors found:
244
- - Broken anchor on source page path = /page1:
245
- -> linking to /page2#
246
- "
247
- ` ) ;
248
- } ) ;
249
-
250
358
it ( 'rejects valid link with broken anchor + query-string' , async ( ) => {
251
359
await expect ( ( ) =>
252
360
testBrokenLinks ( {
0 commit comments