@@ -6,25 +6,33 @@ use concat_in_place::strcat;
6
6
use constcat:: concat;
7
7
use phf:: { phf_map, Map } ;
8
8
use rari_types:: fm_types:: { FeatureStatus , PageType } ;
9
+ use rari_types:: globals:: content_translated_root;
9
10
use rari_types:: locale:: Locale ;
10
11
use rari_types:: RariEnv ;
11
- use serde:: Serialize ;
12
12
13
+ use super :: spa_homepage:: {
14
+ featured_articles, featured_contributor, lastet_news, recent_contributions,
15
+ } ;
13
16
use crate :: cached_readers:: blog_files;
14
17
use crate :: error:: DocError ;
15
- use crate :: pages:: json:: { BuiltDocy , HyData , JsonBasicSPA , JsonBlogPost , JsonBlogPostDoc } ;
18
+ use crate :: pages:: json:: {
19
+ BlogIndex , BuiltDocy , HyData , ItemContainer , JsonBasicSPA , JsonBlogPost , JsonBlogPostDoc ,
20
+ JsonHomePageSPA ,
21
+ } ;
16
22
use crate :: pages:: page:: { Page , PageLike , PageReader } ;
17
23
use crate :: pages:: title:: page_title;
18
24
use crate :: pages:: types:: blog:: BlogMeta ;
19
25
20
- #[ derive( Debug , Clone , Serialize ) ]
21
- pub struct BlogIndex {
22
- pub posts : Vec < BlogMeta > ,
26
+ #[ derive( Debug , Clone , Copy ) ]
27
+ pub struct BasicSPA {
28
+ pub only_follow : bool ,
29
+ pub no_indexing : bool ,
23
30
}
24
31
25
- #[ derive( Debug , Clone ) ]
32
+ #[ derive( Debug , Copy , Clone ) ]
26
33
pub enum SPAData {
27
- BlogIndex ( BlogIndex ) ,
34
+ BlogIndex ,
35
+ HomePage ,
28
36
BasicSPA ( BasicSPA ) ,
29
37
}
30
38
@@ -35,8 +43,9 @@ pub struct SPA {
35
43
pub url : String ,
36
44
pub locale : Locale ,
37
45
pub page_type : PageType ,
38
- pub typ : SPAData ,
46
+ pub data : SPAData ,
39
47
pub base_slug : Cow < ' static , str > ,
48
+ pub page_description : Option < & ' static str > ,
40
49
}
41
50
impl SPA {
42
51
pub fn from_url ( url : & str ) -> Option < Page > {
@@ -45,50 +54,46 @@ impl SPA {
45
54
_ => None ,
46
55
}
47
56
}
57
+
48
58
pub fn from_slug ( slug : & str , locale : Locale ) -> Option < Page > {
49
- if let Some ( basic_spa) = BASIC_SPAS . get ( slug) {
50
- return Some ( Page :: SPA ( Arc :: new ( SPA {
51
- page_title : basic_spa. page_title ,
52
- slug : basic_spa. slug ,
53
- url : strcat ! ( "/" locale. as_url_str( ) basic_spa. slug) ,
59
+ BASIC_SPAS . get ( slug) . and_then ( |build_spa| {
60
+ if build_spa. en_us_only && locale != Locale :: EnUs { None } else {
61
+ Some ( Page :: SPA ( Arc :: new ( SPA {
62
+ page_title : build_spa. page_title ,
63
+ slug : build_spa. slug ,
64
+ url : strcat ! ( "/" locale. as_url_str( ) "/" build_spa. slug if build_spa. trailing_slash { "/" } else { "" } ) ,
54
65
locale,
55
66
page_type : PageType :: SPA ,
56
- typ : SPAData :: BasicSPA ( * basic_spa ) ,
67
+ data : build_spa . data ,
57
68
base_slug : Cow :: Owned ( strcat ! ( "/" locale. as_url_str( ) "/" ) ) ,
58
- } ) ) ) ;
59
- }
60
- match ( slug, locale) {
61
- ( "blog" | "blog/" , Locale :: EnUs ) => Some ( Page :: SPA ( Arc :: new ( SPA {
62
- page_title : "MDN Blog" ,
63
- slug : "blog" ,
64
- url : "/en-US/blog/" . to_string ( ) ,
65
- locale : Locale :: EnUs ,
66
- page_type : PageType :: SPA ,
67
- typ : SPAData :: BlogIndex ( BlogIndex {
68
- posts : blog_files ( )
69
- . sorted_meta
70
- . iter ( )
71
- . rev ( )
72
- . map ( BlogMeta :: from)
73
- . map ( |mut m| {
74
- m. links = Default :: default ( ) ;
75
- m
76
- } )
77
- . collect ( ) ,
78
- } ) ,
79
- base_slug : Cow :: Borrowed ( concat ! ( "/" , Locale :: EnUs . as_url_str( ) , "/" ) ) ,
80
- } ) ) ) ,
81
- _ => None ,
82
- }
69
+ page_description : build_spa. page_description ,
70
+ } ) ) ) }
71
+ } )
83
72
}
84
73
85
74
pub fn is_spa ( slug : & str , locale : Locale ) -> bool {
86
- BASIC_SPAS . contains_key ( slug) || matches ! ( ( slug, locale) , ( "blog" | "blog/" , Locale :: EnUs ) )
75
+ BASIC_SPAS
76
+ . get ( slug)
77
+ . map ( |build_spa| locale == Default :: default ( ) || !build_spa. en_us_only )
78
+ . unwrap_or_default ( )
79
+ }
80
+
81
+ pub fn all ( ) -> Vec < ( & ' static & ' static str , Locale ) > {
82
+ BASIC_SPAS
83
+ . entries ( )
84
+ . flat_map ( |( slug, build_spa) | {
85
+ if build_spa. en_us_only || content_translated_root ( ) . is_none ( ) {
86
+ vec ! [ ( slug, Locale :: EnUs ) ]
87
+ } else {
88
+ Locale :: all ( ) . iter ( ) . map ( |locale| ( slug, * locale) ) . collect ( )
89
+ }
90
+ } )
91
+ . collect ( )
87
92
}
88
93
89
94
pub fn as_built_doc ( & self ) -> Result < BuiltDocy , DocError > {
90
- match & self . typ {
91
- SPAData :: BlogIndex ( b ) => Ok ( BuiltDocy :: BlogPost ( Box :: new ( JsonBlogPost {
95
+ match & self . data {
96
+ SPAData :: BlogIndex => Ok ( BuiltDocy :: BlogPost ( Box :: new ( JsonBlogPost {
92
97
doc : JsonBlogPostDoc {
93
98
title : self . title ( ) . to_string ( ) ,
94
99
mdn_url : self . url ( ) . to_owned ( ) ,
@@ -100,18 +105,55 @@ impl SPA {
100
105
url : self . url ( ) . to_owned ( ) ,
101
106
locale : self . locale ( ) ,
102
107
blog_meta : None ,
103
- hy_data : Some ( HyData :: BlogIndex ( b. clone ( ) ) ) ,
108
+ hy_data : Some ( HyData :: BlogIndex ( BlogIndex {
109
+ posts : blog_files ( )
110
+ . sorted_meta
111
+ . iter ( )
112
+ . rev ( )
113
+ . map ( BlogMeta :: from)
114
+ . map ( |mut m| {
115
+ m. links = Default :: default ( ) ;
116
+ m
117
+ } )
118
+ . collect ( ) ,
119
+ } ) ) ,
104
120
page_title : self . title ( ) . to_owned ( ) ,
105
121
..Default :: default ( )
106
122
} ) ) ) ,
107
123
SPAData :: BasicSPA ( basic_spa) => Ok ( BuiltDocy :: BasicSPA ( Box :: new ( JsonBasicSPA {
108
124
slug : self . slug ,
109
125
page_title : self . page_title ,
110
- page_description : basic_spa . page_description ,
126
+ page_description : self . page_description ,
111
127
only_follow : basic_spa. only_follow ,
112
128
no_indexing : basic_spa. no_indexing ,
113
129
url : strcat ! ( self . base_slug. as_ref( ) self . slug) ,
114
130
} ) ) ) ,
131
+ SPAData :: HomePage => Ok ( BuiltDocy :: HomePageSPA ( Box :: new ( JsonHomePageSPA {
132
+ slug : self . slug ,
133
+ page_title : self . page_title ,
134
+ page_description : self . page_description ,
135
+ featured_articles : featured_articles (
136
+ & [
137
+ "/en-US/blog/mdn-scrimba-partnership/" ,
138
+ "/en-US/blog/learn-javascript-console-methods/" ,
139
+ "/en-US/blog/introduction-to-web-sustainability/" ,
140
+ "/en-US/docs/Web/API/CSS_Custom_Highlight_API" ,
141
+ ] ,
142
+ self . locale ,
143
+ ) ?,
144
+ featured_contributor : featured_contributor ( self . locale ) ?,
145
+ latest_news : ItemContainer {
146
+ items : lastet_news ( & [
147
+ "/en-US/blog/mdn-scrimba-partnership/" ,
148
+ "/en-US/blog/mdn-http-observatory-launch/" ,
149
+ "/en-US/blog/mdn-curriculum-launch/" ,
150
+ "/en-US/blog/baseline-evolution-on-mdn/" ,
151
+ ] ) ?,
152
+ } ,
153
+ recent_contributions : ItemContainer {
154
+ items : recent_contributions ( ) ?,
155
+ } ,
156
+ } ) ) ) ,
115
157
}
116
158
}
117
159
}
@@ -184,115 +226,136 @@ impl PageLike for SPA {
184
226
}
185
227
}
186
228
187
- #[ derive( Debug , Clone , Copy , Default ) ]
188
- pub struct BasicSPA {
229
+ #[ derive( Debug , Clone , Copy ) ]
230
+ pub struct BuildSPA {
189
231
pub slug : & ' static str ,
190
232
pub page_title : & ' static str ,
191
- pub page_description : & ' static str ,
192
- pub only_follow : bool ,
193
- pub no_indexing : bool ,
233
+ pub page_description : Option < & ' static str > ,
234
+ pub trailing_slash : bool ,
235
+ pub en_us_only : bool ,
236
+ pub data : SPAData ,
194
237
}
195
238
196
- const DEFAULT_BASIC_SPA : BasicSPA = BasicSPA {
239
+ const DEFAULT_BASIC_SPA : BuildSPA = BuildSPA {
197
240
slug : "" ,
198
241
page_title : "" ,
199
- page_description : "" ,
200
- only_follow : false ,
201
- no_indexing : false ,
242
+ page_description : None ,
243
+ trailing_slash : false ,
244
+ en_us_only : false ,
245
+ data : SPAData :: BasicSPA ( BasicSPA {
246
+ only_follow : false ,
247
+ no_indexing : false ,
248
+ } ) ,
202
249
} ;
203
250
204
251
const MDN_PLUS_TITLE : & str = "MDN Plus" ;
205
252
const OBSERVATORY_TITLE_FULL : & str = "HTTP Observatory | MDN" ;
206
253
207
- const OBSERVATORY_DESCRIPTION : & str =
208
- "Test your site’s HTTP headers, including CSP and HSTS, to find security problems and get actionable recommendations to make your website more secure. Test other websites to see how you compare." ;
254
+ const OBSERVATORY_DESCRIPTION : Option < & str > =
255
+ Some ( "Test your site’s HTTP headers, including CSP and HSTS, to find security problems and get actionable recommendations to make your website more secure. Test other websites to see how you compare." ) ;
209
256
210
- static BASIC_SPAS : Map < & ' static str , BasicSPA > = phf_map ! (
211
- "play" => BasicSPA {
257
+ static BASIC_SPAS : Map < & ' static str , BuildSPA > = phf_map ! (
258
+ "" => BuildSPA {
259
+ slug: "" ,
260
+ page_title: "MDN Web Docs" ,
261
+ page_description: None ,
262
+ trailing_slash: true ,
263
+ data: SPAData :: HomePage ,
264
+ ..DEFAULT_BASIC_SPA
265
+ } ,
266
+ "blog" => BuildSPA {
267
+ slug: "blog" ,
268
+ page_title: "MDN Blog" ,
269
+ page_description: None ,
270
+ trailing_slash: true ,
271
+ en_us_only: true ,
272
+ data: SPAData :: BlogIndex
273
+ } ,
274
+ "play" => BuildSPA {
212
275
slug: "play" ,
213
276
page_title: "Playground | MDN" ,
214
277
..DEFAULT_BASIC_SPA
215
278
} ,
216
- "observatory" => BasicSPA {
279
+ "observatory" => BuildSPA {
217
280
slug: "observatory" ,
218
281
page_title: concat!( "HTTP Header Security Test - " , OBSERVATORY_TITLE_FULL ) ,
219
282
page_description: OBSERVATORY_DESCRIPTION ,
220
283
..DEFAULT_BASIC_SPA
221
284
} ,
222
- "observatory/analyze" => BasicSPA {
285
+ "observatory/analyze" => BuildSPA {
223
286
slug: "observatory/analyze" ,
224
287
page_title: concat!( "Scan results - " , OBSERVATORY_TITLE_FULL ) ,
225
288
page_description: OBSERVATORY_DESCRIPTION ,
226
- no_indexing: true ,
289
+ data : SPAData :: BasicSPA ( BasicSPA { no_indexing: true , only_follow : false } ) ,
227
290
..DEFAULT_BASIC_SPA
228
291
} ,
229
- "observatory/docs/tests_and_scoring" => BasicSPA {
292
+ "observatory/docs/tests_and_scoring" => BuildSPA {
230
293
slug: "observatory/docs/tests_and_scoring" ,
231
294
page_title: concat!( "Tests & Scoring - " , OBSERVATORY_TITLE_FULL ) ,
232
295
page_description: OBSERVATORY_DESCRIPTION ,
233
296
..DEFAULT_BASIC_SPA
234
297
} ,
235
- "observatory/docs/faq" => BasicSPA {
298
+ "observatory/docs/faq" => BuildSPA {
236
299
slug: "observatory/docs/faq" ,
237
300
page_title: concat!( "FAQ - " , OBSERVATORY_TITLE_FULL ) ,
238
301
page_description: OBSERVATORY_DESCRIPTION ,
239
302
..DEFAULT_BASIC_SPA
240
303
} ,
241
- "search" => BasicSPA {
304
+ "search" => BuildSPA {
242
305
slug: "search" ,
243
306
page_title: "Search" ,
244
- only_follow: true ,
307
+ data : SPAData :: BasicSPA ( BasicSPA { only_follow: true , no_indexing : false } ) ,
245
308
..DEFAULT_BASIC_SPA
246
309
} ,
247
- "plus" => BasicSPA {
310
+ "plus" => BuildSPA {
248
311
slug: "plus" ,
249
312
page_title: MDN_PLUS_TITLE ,
250
313
..DEFAULT_BASIC_SPA
251
314
} ,
252
- "plus/ai-help" => BasicSPA {
315
+ "plus/ai-help" => BuildSPA {
253
316
slug: "plus/ai-help" ,
254
317
page_title: concat!( "AI Help | " , MDN_PLUS_TITLE ) ,
255
318
..DEFAULT_BASIC_SPA
256
319
} ,
257
- "plus/collections" => BasicSPA {
320
+ "plus/collections" => BuildSPA {
258
321
slug: "plus/collections" ,
259
322
page_title: concat!( "Collections | " , MDN_PLUS_TITLE ) ,
260
- no_indexing: true ,
323
+ data : SPAData :: BasicSPA ( BasicSPA { no_indexing: true , only_follow : false } ) ,
261
324
..DEFAULT_BASIC_SPA
262
325
} ,
263
- "plus/collections/frequently_viewed" => BasicSPA {
326
+ "plus/collections/frequently_viewed" => BuildSPA {
264
327
slug: "plus/collections/frequently_viewed" ,
265
328
page_title: concat!( "Frequently viewed articles | " , MDN_PLUS_TITLE ) ,
266
- no_indexing: true ,
329
+ data : SPAData :: BasicSPA ( BasicSPA { no_indexing: true , only_follow : false } ) ,
267
330
..DEFAULT_BASIC_SPA
268
331
} ,
269
- "plus/updates" => BasicSPA {
332
+ "plus/updates" => BuildSPA {
270
333
slug: "plus/updates" ,
271
334
page_title: concat!( "Updates | " , MDN_PLUS_TITLE ) ,
272
335
..DEFAULT_BASIC_SPA
273
336
} ,
274
- "plus/settings" => BasicSPA {
337
+ "plus/settings" => BuildSPA {
275
338
slug: "plus/settings" ,
276
339
page_title: concat!( "Settings | " , MDN_PLUS_TITLE ) ,
277
- no_indexing: true ,
340
+ data : SPAData :: BasicSPA ( BasicSPA { no_indexing: true , only_follow : false } ) ,
278
341
..DEFAULT_BASIC_SPA
279
342
} ,
280
- "about" => BasicSPA {
343
+ "about" => BuildSPA {
281
344
slug: "about" ,
282
345
page_title: "About MDN" ,
283
346
..DEFAULT_BASIC_SPA
284
347
} ,
285
- "community" => BasicSPA {
348
+ "community" => BuildSPA {
286
349
slug: "community" ,
287
350
page_title: "Contribute to MDN" ,
288
351
..DEFAULT_BASIC_SPA
289
352
} ,
290
- "advertising" => BasicSPA {
353
+ "advertising" => BuildSPA {
291
354
slug: "advertising" ,
292
355
page_title: "Advertise with us" ,
293
356
..DEFAULT_BASIC_SPA
294
357
} ,
295
- "newsletter" => BasicSPA {
358
+ "newsletter" => BuildSPA {
296
359
slug: "newsletter" ,
297
360
page_title: "Stay Informed with MDN" ,
298
361
..DEFAULT_BASIC_SPA
0 commit comments